Split launch readiness levels
This commit is contained in:
@@ -138,11 +138,13 @@ class ApiServerRoutingTests(unittest.TestCase):
|
||||
status, payload = route_request(
|
||||
"/trading/launch-readiness",
|
||||
{"instrument_id": ["1"], "timeframe": ["5m"]},
|
||||
dependencies={"trading_launch_readiness": lambda **kwargs: {"assisted_trading_ready": False, "timeframe": kwargs["timeframe"]}},
|
||||
dependencies={"trading_launch_readiness": lambda **kwargs: {"analysis_only_ready": True, "decision_support_ready": False, "real_trade_loop_ready": False, "assisted_trading_ready": True, "timeframe": kwargs["timeframe"]}},
|
||||
)
|
||||
|
||||
self.assertEqual(status, 200)
|
||||
self.assertFalse(payload["assisted_trading_ready"])
|
||||
self.assertTrue(payload["assisted_trading_ready"])
|
||||
self.assertTrue(payload["analysis_only_ready"])
|
||||
self.assertFalse(payload["decision_support_ready"])
|
||||
self.assertEqual(payload["timeframe"], "5m")
|
||||
|
||||
def test_routes_trading_broker_state(self) -> None:
|
||||
|
||||
@@ -20,10 +20,28 @@ class LaunchReadinessServiceTests(unittest.TestCase):
|
||||
with patch("src.services.readiness.launch_readiness_service.get_trading_runtime_service", return_value=_RuntimeService()):
|
||||
payload = service.build_summary(instrument_id=1, timeframe="1m")
|
||||
|
||||
self.assertFalse(payload["assisted_trading_ready"])
|
||||
self.assertIn("real_trade_sample_verified", payload["blocking_reasons"])
|
||||
self.assertTrue(payload["analysis_only_ready"])
|
||||
self.assertTrue(payload["assisted_trading_ready"])
|
||||
self.assertFalse(payload["real_trade_loop_ready"])
|
||||
self.assertIn("real_trade_sample_verified", payload["warning_reasons"])
|
||||
self.assertFalse(payload["real_live_ready"])
|
||||
|
||||
def test_build_summary_keeps_decision_support_false_when_only_blacklist_models_exist(self) -> None:
|
||||
service = LaunchReadinessService(
|
||||
market_state_service=_MarketStateService(),
|
||||
broker_read_model_service=_BrokerReadService(),
|
||||
weekly_review_service=_WeeklyReviewService(),
|
||||
trust_service=_BlacklistOnlyTrustService(),
|
||||
live_readiness_service=_LiveReadinessService(),
|
||||
)
|
||||
|
||||
with patch("src.services.readiness.launch_readiness_service.get_trading_runtime_service", return_value=_RuntimeService()):
|
||||
payload = service.build_summary(instrument_id=1, timeframe="1m")
|
||||
|
||||
self.assertTrue(payload["analysis_only_ready"])
|
||||
self.assertFalse(payload["decision_support_ready"])
|
||||
self.assertIn("trust_model_available", payload["warning_reasons"])
|
||||
|
||||
|
||||
class _MarketState:
|
||||
freshness = type("Freshness", (), {"code": "market_data_fresh"})()
|
||||
@@ -63,7 +81,26 @@ class _WeeklyReviewService:
|
||||
|
||||
class _TrustService:
|
||||
def build_summary(self, **kwargs):
|
||||
return {"whitelist": ["OSOK"], "observe_list": [], "blacklist": []}
|
||||
return {
|
||||
"whitelist": ["OSOK"],
|
||||
"observe_list": [],
|
||||
"blacklist": [],
|
||||
"analysis_only_list": ["OSOK"],
|
||||
"decision_support_list": ["OSOK"],
|
||||
"execution_candidate_list": ["OSOK"],
|
||||
}
|
||||
|
||||
|
||||
class _BlacklistOnlyTrustService:
|
||||
def build_summary(self, **kwargs):
|
||||
return {
|
||||
"whitelist": [],
|
||||
"observe_list": [],
|
||||
"blacklist": ["SWEEP_MSS_FVG"],
|
||||
"analysis_only_list": ["SWEEP_MSS_FVG"],
|
||||
"decision_support_list": [],
|
||||
"execution_candidate_list": [],
|
||||
}
|
||||
|
||||
|
||||
class _LiveReadinessService:
|
||||
|
||||
@@ -47,6 +47,9 @@ class ModelTrustServiceTests(unittest.TestCase):
|
||||
|
||||
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:
|
||||
@@ -57,6 +60,9 @@ class ModelTrustServiceTests(unittest.TestCase):
|
||||
|
||||
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:
|
||||
|
||||
@@ -186,7 +186,7 @@ class RuntimeScriptJsonTests(unittest.TestCase):
|
||||
self.assertEqual(payload["timeframe"], "5m")
|
||||
|
||||
def test_run_launch_readiness_outputs_json(self) -> None:
|
||||
service = type("Service", (), {"build_summary": lambda self, instrument_id, timeframe: {"instrument_id": instrument_id, "timeframe": timeframe, "assisted_trading_ready": False, "real_live_ready": False, "blocking_reasons": ["real_trade_sample_verified"]}})()
|
||||
service = type("Service", (), {"build_summary": lambda self, instrument_id, timeframe: {"instrument_id": instrument_id, "timeframe": timeframe, "analysis_only_ready": True, "decision_support_ready": False, "real_trade_loop_ready": False, "assisted_trading_ready": True, "real_live_ready": False, "blocking_reasons": [], "warning_reasons": ["real_trade_sample_verified"]}})()
|
||||
output = io.StringIO()
|
||||
with patch("scripts.run_launch_readiness.LaunchReadinessService", return_value=service), contextlib.redirect_stdout(output):
|
||||
exit_code = run_launch_readiness.main(
|
||||
@@ -194,7 +194,7 @@ class RuntimeScriptJsonTests(unittest.TestCase):
|
||||
)
|
||||
|
||||
payload = json.loads(output.getvalue())
|
||||
self.assertEqual(exit_code, 2)
|
||||
self.assertEqual(exit_code, 0)
|
||||
self.assertEqual(payload["instrument_id"], 2)
|
||||
self.assertEqual(payload["timeframe"], "5m")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user