Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions scripts/build_runtime_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@


DEFAULT_ARTIFACT_BUCKET_URI = "gs://qsl-runtime-logs-shared"
# Keep this list limited to strategy-scope artifacts that the publisher
# currently produces. QPK may parse broader explicit mounts for forward
# compatibility, but auto mode must not generate missing latest_signal paths.
MARKET_REGIME_CONTROL_PROFILES = frozenset(
{
"tqqq_growth_income",
"global_etf_rotation",
"russell_top50_leader_rotation",
"soxl_soxx_trend_income",
}
)
IBIT_ZSCORE_EXIT_STRATEGY_PROFILE = "ibit_smart_dca"
Expand Down
45 changes: 36 additions & 9 deletions tests/test_runtime_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ def test_plugin_mount_schema_version_is_rendered_for_platform_parser(self):
assignments["SCHWAB_STRATEGY_PLUGIN_MOUNTS_JSON"],
)

def test_auto_market_regime_control_profiles_cover_published_strategy_artifacts(self):
strategy_profiles = {
item["profile"]
for item in json.loads(
(ROOT / "web/strategy-switch-console/strategy-profiles.example.json").read_text(encoding="utf-8")
)
}
published_strategy_artifact_profiles = {
"tqqq_growth_income",
"soxl_soxx_trend_income",
}

self.assertLessEqual(published_strategy_artifact_profiles, strategy_profiles)
self.assertEqual(published_strategy_artifact_profiles, build_runtime_switch.MARKET_REGIME_CONTROL_PROFILES)

def test_assignment_payload_can_redact_values(self):
_, target = self.load_target("examples/targets/longbridge/sg.example.json")
assignment = next(
Expand Down Expand Up @@ -300,8 +315,6 @@ def test_build_switch_target_defaults_schwab_repository_scope(self):
"live",
"--strategy-profile",
"soxl_soxx_trend_income",
"--plugin-mode",
"none",
]
)

Expand All @@ -313,12 +326,15 @@ def test_build_switch_target_defaults_schwab_repository_scope(self):
self.assertNotIn("environment", target["github"])
self.assertEqual(target["runtime_target"]["service_name"], "charles-schwab-quant-service")
self.assertEqual(assignments["SCHWAB_DRY_RUN_ONLY"], "false")
plugin_payload = json.loads(assignments["SCHWAB_STRATEGY_PLUGIN_MOUNTS_JSON"])
self.assertEqual(plugin_payload["strategy_plugins"][0]["plugin"], "market_regime_control")
self.assertEqual(
json.loads(assignments["SCHWAB_STRATEGY_PLUGIN_MOUNTS_JSON"]),
{"strategy_plugins": []},
plugin_payload["strategy_plugins"][0]["signal_path"],
"gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/"
"soxl_soxx_trend_income/plugins/market_regime_control/latest_signal.json",
)

def test_build_switch_target_clears_plugin_mounts_for_unmounted_strategy(self):
def test_build_switch_target_auto_mounts_market_regime_control_for_soxl(self):
parser = build_runtime_switch.build_parser()
args = parser.parse_args(
[
Expand All @@ -335,9 +351,12 @@ def test_build_switch_target_clears_plugin_mounts_for_unmounted_strategy(self):
assignments = {item.name: item.value for item in runtime_settings.build_assignments(target)}

self.assertEqual(assignments["STRATEGY_PROFILE"], "soxl_soxx_trend_income")
plugin_payload = json.loads(assignments["LONGBRIDGE_STRATEGY_PLUGIN_MOUNTS_JSON"])
self.assertEqual(plugin_payload["strategy_plugins"][0]["plugin"], "market_regime_control")
self.assertEqual(
json.loads(assignments["LONGBRIDGE_STRATEGY_PLUGIN_MOUNTS_JSON"]),
{"strategy_plugins": []},
plugin_payload["strategy_plugins"][0]["signal_path"],
"gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/"
"soxl_soxx_trend_income/plugins/market_regime_control/latest_signal.json",
)

def test_build_switch_target_defaults_firstrade_repository_scope(self):
Expand Down Expand Up @@ -828,7 +847,7 @@ def test_build_switch_target_can_clear_preserved_ibkr_reserved_cash_fields(self)
self.assertEqual(selected["IBKR_MIN_RESERVED_CASH_USD"], "")
self.assertEqual(selected["IBKR_RESERVED_CASH_RATIO"], "")

def test_build_switch_target_patches_ibkr_service_targets_with_empty_plugin_mounts(self):
def test_build_switch_target_patches_ibkr_service_targets_with_soxl_plugin_mounts(self):
existing = {
"targets": [
{
Expand Down Expand Up @@ -885,7 +904,15 @@ def test_build_switch_target_patches_ibkr_service_targets_with_empty_plugin_moun
selected = patched["targets"][0]

self.assertEqual(selected["runtime_target"]["strategy_profile"], "soxl_soxx_trend_income")
self.assertEqual(selected["IBKR_STRATEGY_PLUGIN_MOUNTS_JSON"], {"strategy_plugins": []})
self.assertEqual(
selected["IBKR_STRATEGY_PLUGIN_MOUNTS_JSON"]["strategy_plugins"][0]["plugin"],
"market_regime_control",
)
self.assertEqual(
selected["IBKR_STRATEGY_PLUGIN_MOUNTS_JSON"]["strategy_plugins"][0]["signal_path"],
"gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/"
"soxl_soxx_trend_income/plugins/market_regime_control/latest_signal.json",
)


if __name__ == "__main__":
Expand Down