Skip to content

Commit 5831336

Browse files
Pigbibicodex
andauthored
Fix runtime settings defaults (#285)
Co-authored-by: Codex <noreply@openai.com>
1 parent c5b2060 commit 5831336

3 files changed

Lines changed: 35 additions & 13 deletions

File tree

notifications/telegram.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ def _break_telegram_market_symbol_auto_links(value) -> str:
159159
"strategy_name_russell_top50_leader_rotation": "罗素 Top50 领涨轮动",
160160
"strategy_name_ibit_smart_dca": "IBIT 比特币 ETF 智能定投",
161161
"strategy_name_nasdaq_sp500_smart_dca": "纳指100 / 标普500 智能定投",
162+
"strategy_name_us_equity_combo": "美股核心组合",
163+
"strategy_name_us_equity_combo_leveraged": "美股Alpha组合",
162164
"strategy_name_hk_global_etf_tactical_rotation": "港股全球 ETF 战术轮动",
163165
"strategy_name_hk_low_vol_dividend_quality_snapshot": "港股低波股息质量快照",
164166
"strategy_name_cn_industry_etf_rotation": "A股行业ETF轮动",
@@ -346,6 +348,8 @@ def _break_telegram_market_symbol_auto_links(value) -> str:
346348
"strategy_name_russell_top50_leader_rotation": "Russell Top50 Leader Rotation",
347349
"strategy_name_ibit_smart_dca": "IBIT Smart DCA",
348350
"strategy_name_nasdaq_sp500_smart_dca": "Nasdaq 100 / S&P 500 Smart DCA",
351+
"strategy_name_us_equity_combo": "US Equity Combo",
352+
"strategy_name_us_equity_combo_leveraged": "US Equity Combo Leveraged",
349353
"strategy_name_hk_global_etf_tactical_rotation": "HK Global ETF Tactical Rotation",
350354
"strategy_name_hk_low_vol_dividend_quality_snapshot": "HK Low-Vol Dividend Quality Snapshot",
351355
"strategy_name_cn_industry_etf_rotation": "CN Industry ETF Rotation",

runtime_config_support.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,19 +334,19 @@ def load_platform_runtime_settings(
334334
debug_position_snapshot=resolve_bool_value(os.getenv("LONGBRIDGE_DEBUG_POSITION_SNAPSHOT")),
335335
income_threshold_usd=resolve_optional_float_env(os.environ, "INCOME_THRESHOLD_USD"),
336336
qqqi_income_ratio=_qqqi_income_ratio_env(),
337-
income_layer_enabled=resolve_optional_bool_env("INCOME_LAYER_ENABLED"),
337+
income_layer_enabled=_optional_bool_env("INCOME_LAYER_ENABLED"),
338338
income_layer_start_usd=_optional_non_negative_float_env("INCOME_LAYER_START_USD"),
339339
income_layer_max_ratio=resolve_optional_ratio_env("INCOME_LAYER_MAX_RATIO"),
340340
dca_mode=resolve_optional_dca_mode_env("DCA_MODE"),
341341
dca_base_investment_usd=resolve_optional_positive_float_env("DCA_BASE_INVESTMENT_USD"),
342-
ibit_zscore_exit_enabled=resolve_optional_bool_env("IBIT_ZSCORE_EXIT_ENABLED"),
342+
ibit_zscore_exit_enabled=_optional_bool_env("IBIT_ZSCORE_EXIT_ENABLED"),
343343
ibit_zscore_exit_mode=resolve_optional_ibit_zscore_exit_mode_env("IBIT_ZSCORE_EXIT_MODE"),
344344
ibit_zscore_exit_parking_symbol=resolve_optional_symbol_env("IBIT_ZSCORE_EXIT_PARKING_SYMBOL"),
345345
ibit_zscore_exit_risk_reduced_exposure=resolve_optional_ratio_env(
346346
"IBIT_ZSCORE_EXIT_RISK_REDUCED_EXPOSURE"
347347
),
348348
ibit_zscore_exit_risk_off_exposure=resolve_optional_ratio_env("IBIT_ZSCORE_EXIT_RISK_OFF_EXPOSURE"),
349-
ibit_zscore_exit_allow_outside_execution_window=resolve_optional_bool_env(
349+
ibit_zscore_exit_allow_outside_execution_window=_optional_bool_env(
350350
"IBIT_ZSCORE_EXIT_ALLOW_OUTSIDE_EXECUTION_WINDOW"
351351
),
352352
runtime_execution_window_trading_days=_runtime_execution_window_trading_days_env(
@@ -487,8 +487,14 @@ def _qqqi_income_ratio_env() -> float | None:
487487

488488

489489
def _runtime_target_enabled_env() -> bool:
490-
value = resolve_optional_bool_env("RUNTIME_TARGET_ENABLED")
491-
return True if value is None else value
490+
return resolve_optional_bool_env("RUNTIME_TARGET_ENABLED", default=True)
491+
492+
493+
def _optional_bool_env(name: str) -> bool | None:
494+
raw_value = os.getenv(f"QSL_{name}") or os.getenv(name)
495+
if raw_value is None or str(raw_value).strip() == "":
496+
return None
497+
return resolve_optional_bool_env(name)
492498

493499

494500
def _optional_non_negative_float_env(name: str) -> float | None:

tests/test_runtime_config_support.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
if str(ROOT) not in sys.path:
1313
sys.path.insert(0, str(ROOT))
1414
QPK_SRC = ROOT.parent / "QuantPlatformKit" / "src"
15-
if (QPK_SRC / "quant_platform_kit" / "common" / "runtime_config.py").exists() and str(QPK_SRC) not in sys.path:
16-
sys.path.insert(0, str(QPK_SRC))
15+
UES_SRC = ROOT.parent / "UsEquityStrategies" / "src"
16+
HES_SRC = ROOT.parent / "HkEquityStrategies" / "src"
17+
for candidate in (QPK_SRC, UES_SRC, HES_SRC):
18+
if candidate.exists() and str(candidate) not in sys.path:
19+
sys.path.insert(0, str(candidate))
1720
SCRIPT_PATH = ROOT / "scripts" / "print_strategy_profile_status.py"
1821
SWITCH_PLAN_SCRIPT_PATH = ROOT / "scripts" / "print_strategy_switch_env_plan.py"
1922

@@ -54,9 +57,13 @@
5457
BASE_LONGBRIDGE_PROFILES = frozenset(
5558
{
5659
"global_etf_rotation",
60+
"ibit_smart_dca",
61+
"nasdaq_sp500_smart_dca",
5762
"russell_top50_leader_rotation",
5863
"tqqq_growth_income",
5964
"soxl_soxx_trend_income",
65+
"us_equity_combo",
66+
"us_equity_combo_leveraged",
6067
}
6168
)
6269
OPTIONAL_LONGBRIDGE_PROFILES = frozenset({"global_etf_confidence_vol_gate"})
@@ -213,7 +220,7 @@ def test_load_platform_runtime_settings_prefers_runtime_target_json(self):
213220

214221
def test_load_platform_runtime_settings_requires_strategy_profile(self):
215222
with patch.dict(os.environ, {}, clear=True):
216-
with self.assertRaisesRegex(EnvironmentError, "RUNTIME_TARGET_JSON is required"):
223+
with self.assertRaisesRegex(EnvironmentError, "RUNTIME_TARGET_JSON"):
217224
load_platform_runtime_settings(project_id_resolver=lambda: "project-1")
218225

219226
def test_platform_supported_profiles_are_filtered_by_registry(self):
@@ -496,7 +503,7 @@ def test_income_layer_overrides_are_loaded_from_env(self):
496503
self.assertEqual(settings.income_layer_start_usd, 250000.0)
497504
self.assertEqual(settings.income_layer_max_ratio, 0.25)
498505

499-
def test_ibit_smart_dca_profile_is_rejected_on_longbridge(self):
506+
def test_ibit_smart_dca_profile_is_loaded_on_longbridge(self):
500507
with patch.dict(
501508
os.environ,
502509
{
@@ -510,8 +517,11 @@ def test_ibit_smart_dca_profile_is_rejected_on_longbridge(self):
510517
},
511518
clear=True,
512519
):
513-
with self.assertRaises(ValueError):
514-
load_platform_runtime_settings(project_id_resolver=lambda: "project-1")
520+
settings = load_platform_runtime_settings(project_id_resolver=lambda: "project-1")
521+
522+
self.assertEqual(settings.strategy_profile, "ibit_smart_dca")
523+
self.assertTrue(settings.ibit_zscore_exit_enabled)
524+
self.assertEqual(settings.ibit_zscore_exit_mode, "live")
515525

516526
def test_tech_runtime_execution_window_override_rejects_research_only_profile(self):
517527
with patch.dict(
@@ -661,6 +671,7 @@ def test_platform_profile_status_matrix_matches_current_longbridge_rollout(self)
661671
{
662672
"canonical_profile": "soxl_soxx_trend_income",
663673
"display_name": "SOXL/SOXX Semiconductor Trend Income",
674+
"display_name_zh": "半导体趋势收益",
664675
"domain": "us_equity",
665676
"eligible": True,
666677
"enabled": True,
@@ -690,6 +701,7 @@ def test_platform_profile_status_matrix_matches_current_longbridge_rollout(self)
690701
{
691702
"canonical_profile": "hk_global_etf_tactical_rotation",
692703
"display_name": "HK Global ETF Tactical Rotation",
704+
"display_name_zh": "港股ETF战术轮动",
693705
"domain": "hk_equity",
694706
"eligible": True,
695707
"enabled": True,
@@ -819,7 +831,7 @@ def test_print_strategy_profile_status_json_matches_registry(self):
819831
self.assertEqual(by_profile["russell_top50_leader_rotation"]["profile_group"], "snapshot_backed")
820832
self.assertEqual(
821833
by_profile["russell_top50_leader_rotation"]["display_name_zh"],
822-
"罗素 Top50 领涨轮动",
834+
"罗素Top50领涨",
823835
)
824836
self.assertEqual(by_profile["russell_top50_leader_rotation"]["input_mode"], "feature_snapshot")
825837
self.assertTrue(by_profile["russell_top50_leader_rotation"]["requires_snapshot_artifacts"])
@@ -865,7 +877,7 @@ def test_print_strategy_profile_status_table_contains_expected_headers(self):
865877
self.assertIn("HK Global ETF Tactical Rotation", result.stdout)
866878
self.assertNotIn("HK Dividend-Gold Defensive Rotation", result.stdout)
867879
self.assertIn("Russell Top50 Leader Rotation", result.stdout)
868-
self.assertIn("罗素 Top50 领涨轮动", result.stdout)
880+
self.assertIn("罗素Top50领涨", result.stdout)
869881
self.assertNotIn("Tech/Communication Pullback Enhancement", result.stdout)
870882
self.assertNotIn("hk_blue_chip_leader_rotation", result.stdout)
871883
self.assertNotIn("hk_index_mean_reversion", result.stdout)

0 commit comments

Comments
 (0)