Files
ai-exchange/tests/unit/test_model_trust_service.py
T
2026-05-08 21:01:09 +08:00

86 lines
4.0 KiB
Python

from datetime import datetime, timezone
import os
import unittest
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://user:pass@localhost:5432/ai_ict_test")
from src.services.trust import ModelTrustService
from src.services.trust.model_trust_service import build_model_buckets
class ModelTrustServiceTests(unittest.TestCase):
def test_build_summary_classifies_models(self) -> None:
service = ModelTrustService(
backtest_repository=_BacktestRepo(
[
{
"model_code": "OSOK",
"candidate_model_code": "OSOK",
"summary": {
"quality_gate": {"passed": True},
"executed_expectancy_r": 0.6,
"session_performance": {
"LONDON": {"executed_expectancy_r": 0.8, "framework_execution_rate": 0.9, "risk_violation_count": 0}
},
},
},
{
"model_code": "REAL_TRADE_IMPORT",
"candidate_model_code": "REAL_TRADE_IMPORT",
"summary": {"quality_gate": {"passed": False}, "executed_expectancy_r": -0.2},
},
]
),
journal_repository=_JournalRepo(
[
{"model_code": "OSOK", "framework_execution": True, "out_of_model_trade": False, "risk_violation": False, "real_trade_detected": True},
{"model_code": "OSOK", "framework_execution": True, "out_of_model_trade": False, "risk_violation": False, "real_trade_detected": True},
{"model_code": "OSOK", "framework_execution": True, "out_of_model_trade": False, "risk_violation": False, "real_trade_detected": True},
{"model_code": "OSOK", "framework_execution": True, "out_of_model_trade": False, "risk_violation": False, "real_trade_detected": True},
{"model_code": "OSOK", "framework_execution": False, "out_of_model_trade": False, "risk_violation": False, "real_trade_detected": True},
{"model_code": "REAL_TRADE_IMPORT", "framework_execution": False, "out_of_model_trade": True, "risk_violation": True, "real_trade_detected": True},
]
),
)
payload = service.build_summary(instrument_id=1)
self.assertIn("OSOK", payload["whitelist"])
self.assertIn("REAL_TRADE_IMPORT", payload["blacklist"])
self.assertIn("REAL_TRADE_IMPORT", payload["analysis_only_list"])
self.assertIn("OSOK", payload["decision_support_list"])
self.assertIn("OSOK", payload["execution_candidate_list"])
self.assertTrue(payload["models"][0]["score"] >= payload["models"][1]["score"])
def test_build_model_buckets_creates_observe_bucket_when_samples_are_small(self) -> None:
buckets = build_model_buckets(
backtest_runs=[{"model_code": "OSOK", "candidate_model_code": "OSOK", "summary": {"quality_gate": {"passed": True}, "executed_expectancy_r": 0.2}}],
journal_entries=[{"model_code": "OSOK", "framework_execution": True, "out_of_model_trade": False, "risk_violation": False, "real_trade_detected": False}],
)
self.assertEqual(buckets["OSOK"].classification, "observe")
self.assertIn("sample_size_small", buckets["OSOK"].reasons)
self.assertTrue(buckets["OSOK"].analysis_only_allowed)
self.assertTrue(buckets["OSOK"].decision_support_allowed)
self.assertFalse(buckets["OSOK"].execution_allowed)
class _BacktestRepo:
def __init__(self, rows):
self.rows = rows
def fetch_recent_backtest_run_rows(self, instrument_id: int, limit: int = 20):
return list(self.rows)
class _JournalRepo:
def __init__(self, rows):
self.rows = rows
def fetch_weekly_journal_entries(self, **kwargs):
return list(self.rows)
if __name__ == "__main__":
unittest.main()