66
77import pytest
88
9+ ROOT = Path (__file__ ).resolve ().parents [1 ]
10+ QPK_SRC = ROOT .parent / "QuantPlatformKit" / "src"
11+ UES_SRC = ROOT .parent / "UsEquityStrategies" / "src"
12+ HES_SRC = ROOT .parent / "HkEquityStrategies" / "src"
13+ for candidate in (ROOT , QPK_SRC , UES_SRC , HES_SRC ):
14+ if candidate .exists () and str (candidate ) not in sys .path :
15+ sys .path .insert (0 , str (candidate ))
16+
917from runtime_config_support import (
1018 DEFAULT_MARKET ,
1119 DEFAULT_MARKET_CALENDAR ,
5967EXPECTED_IBKR_ENABLED_PROFILES = frozenset (
6068 {
6169 "global_etf_rotation" ,
70+ "ibit_smart_dca" ,
71+ "nasdaq_sp500_smart_dca" ,
6272 "russell_top50_leader_rotation" ,
6373 "soxl_soxx_trend_income" ,
6474 "tqqq_growth_income" ,
75+ "us_equity_combo" ,
76+ "us_equity_combo_leveraged" ,
6577 "hk_global_etf_tactical_rotation" ,
6678 "hk_low_vol_dividend_quality_snapshot" ,
6779 }
@@ -106,7 +118,7 @@ def test_load_platform_runtime_settings_requires_strategy_profile(monkeypatch):
106118 monkeypatch .setenv ("IB_ACCOUNT_GROUP_CONFIG_JSON" , MINIMAL_GROUP_JSON )
107119 monkeypatch .delenv ("RUNTIME_TARGET_JSON" , raising = False )
108120
109- with pytest .raises (EnvironmentError , match = "RUNTIME_TARGET_JSON is required " ):
121+ with pytest .raises (EnvironmentError , match = "RUNTIME_TARGET_JSON" ):
110122 load_platform_runtime_settings (project_id_resolver = lambda : "project-1" )
111123
112124
@@ -541,7 +553,7 @@ def test_load_platform_runtime_settings_reads_income_layer_overrides(monkeypatch
541553 assert settings .income_layer_max_ratio == 0.25
542554
543555
544- def test_ibit_smart_dca_profile_is_rejected_on_ibkr (monkeypatch ):
556+ def test_ibit_smart_dca_profile_is_loaded_on_ibkr (monkeypatch ):
545557 monkeypatch .setenv ("RUNTIME_TARGET_JSON" , runtime_target_json ("ibit_smart_dca" ))
546558 monkeypatch .setenv ("ACCOUNT_GROUP" , "paper" )
547559 monkeypatch .setenv ("IB_ACCOUNT_GROUP_CONFIG_JSON" , MINIMAL_GROUP_JSON )
@@ -552,8 +564,11 @@ def test_ibit_smart_dca_profile_is_rejected_on_ibkr(monkeypatch):
552564 monkeypatch .setenv ("IBIT_ZSCORE_EXIT_RISK_OFF_EXPOSURE" , "0.25" )
553565 monkeypatch .setenv ("IBIT_ZSCORE_EXIT_ALLOW_OUTSIDE_EXECUTION_WINDOW" , "true" )
554566
555- with pytest .raises (ValueError , match = "Unsupported STRATEGY_PROFILE='ibit_smart_dca'" ):
556- load_platform_runtime_settings (project_id_resolver = lambda : "project-1" )
567+ settings = load_platform_runtime_settings (project_id_resolver = lambda : "project-1" )
568+
569+ assert settings .strategy_profile == "ibit_smart_dca"
570+ assert settings .ibit_zscore_exit_enabled is True
571+ assert settings .ibit_zscore_exit_mode == "live"
557572
558573
559574def test_load_platform_runtime_settings_rejects_invalid_income_layer_enabled (monkeypatch ):
@@ -723,13 +738,14 @@ def test_load_platform_runtime_settings_accepts_tqqq_growth_income(monkeypatch):
723738 assert settings .strategy_target_mode == "value"
724739
725740
726- def test_load_platform_runtime_settings_rejects_nasdaq_sp500_smart_dca (monkeypatch ):
741+ def test_load_platform_runtime_settings_accepts_nasdaq_sp500_smart_dca (monkeypatch ):
727742 monkeypatch .setenv ("RUNTIME_TARGET_JSON" , runtime_target_json ("nasdaq_sp500_smart_dca" ))
728743 monkeypatch .setenv ("ACCOUNT_GROUP" , "paper" )
729744 monkeypatch .setenv ("IB_ACCOUNT_GROUP_CONFIG_JSON" , MINIMAL_GROUP_JSON )
730745
731- with pytest .raises (ValueError , match = "Unsupported STRATEGY_PROFILE='nasdaq_sp500_smart_dca'" ):
732- load_platform_runtime_settings (project_id_resolver = lambda : "project-1" )
746+ settings = load_platform_runtime_settings (project_id_resolver = lambda : "project-1" )
747+
748+ assert settings .strategy_profile == "nasdaq_sp500_smart_dca"
733749
734750
735751def test_load_platform_runtime_settings_rejects_legacy_qqq_tech_alias (monkeypatch ):
@@ -758,6 +774,7 @@ def test_platform_profile_status_matrix_matches_current_ibkr_rollout():
758774 assert by_profile ["global_etf_rotation" ] == {
759775 "canonical_profile" : "global_etf_rotation" ,
760776 "display_name" : "Global ETF Rotation" ,
777+ "display_name_zh" : "全球ETF轮动" ,
761778 "domain" : "us_equity" ,
762779 "eligible" : True ,
763780 "enabled" : True ,
@@ -769,11 +786,12 @@ def test_platform_profile_status_matrix_matches_current_ibkr_rollout():
769786 assert by_profile ["tqqq_growth_income" ]["display_name" ] == "TQQQ Growth Income"
770787 assert by_profile ["tqqq_growth_income" ]["eligible" ] is True
771788 assert by_profile ["tqqq_growth_income" ]["enabled" ] is True
772- assert "nasdaq_sp500_smart_dca" not in by_profile
773- assert "ibit_smart_dca" not in by_profile
789+ assert "nasdaq_sp500_smart_dca" in by_profile
790+ assert "ibit_smart_dca" in by_profile
774791 assert by_profile ["hk_global_etf_tactical_rotation" ] == {
775792 "canonical_profile" : "hk_global_etf_tactical_rotation" ,
776793 "display_name" : "HK Global ETF Tactical Rotation" ,
794+ "display_name_zh" : "港股ETF战术轮动" ,
777795 "domain" : "hk_equity" ,
778796 "eligible" : True ,
779797 "enabled" : True ,
@@ -814,11 +832,11 @@ def test_print_strategy_profile_status_json_matches_registry():
814832 assert by_profile ["global_etf_rotation" ]["requires_snapshot_artifacts" ] is True
815833 assert by_profile ["global_etf_rotation" ]["requires_snapshot_manifest_path" ] is True
816834 assert by_profile ["global_etf_rotation" ]["requires_strategy_config_path" ] is False
817- assert "nasdaq_sp500_smart_dca" not in by_profile
818- assert "ibit_smart_dca" not in by_profile
835+ assert "nasdaq_sp500_smart_dca" in by_profile
836+ assert "ibit_smart_dca" in by_profile
819837 assert "tech_communication_pullback_enhancement" not in by_profile
820838 assert by_profile ["russell_top50_leader_rotation" ]["profile_group" ] == "snapshot_backed"
821- assert by_profile ["russell_top50_leader_rotation" ]["display_name_zh" ] == "罗素 Top50 领涨轮动 "
839+ assert by_profile ["russell_top50_leader_rotation" ]["display_name_zh" ] == "罗素Top50领涨 "
822840 assert by_profile ["russell_top50_leader_rotation" ]["input_mode" ] == "feature_snapshot"
823841 assert by_profile ["russell_top50_leader_rotation" ]["requires_snapshot_artifacts" ] is True
824842 assert by_profile ["russell_top50_leader_rotation" ]["requires_strategy_config_path" ] is False
@@ -849,7 +867,7 @@ def test_print_strategy_profile_status_table_contains_expected_headers():
849867 assert "global_etf_rotation" in result .stdout
850868 assert "hk_global_etf_tactical_rotation" in result .stdout
851869 assert "Russell Top50 Leader Rotation" in result .stdout
852- assert "罗素 Top50 领涨轮动 " in result .stdout
870+ assert "罗素Top50领涨 " in result .stdout
853871 assert "Tech/Communication Pullback Enhancement" not in result .stdout
854872 assert "HK Global ETF Tactical Rotation" in result .stdout
855873 assert "TQQQ Growth Income" in result .stdout
0 commit comments