From 3f6fa9ecfe4ae5092ffd1c01c9729b2c4fec2442 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Thu, 4 Jun 2026 01:50:34 +0800 Subject: [PATCH] Bump strategy package pins and HK runtime profiles --- .github/workflows/ci.yml | 2 +- .github/workflows/sync-cloud-run-env.yml | 2 +- ...r_global_etf_rotation.rollback.env.example | 2 +- ...on_pullback_enhancement.dryrun.env.example | 11 ----- ...unication_pullback_enhancement.env.example | 11 ----- ...ion_pullback_enhancement.paper.env.example | 11 ----- docs/hk_equity_runtime.md | 14 +++---- notifications/telegram.py | 12 +++--- requirements.txt | 6 +-- scripts/build_cloud_run_env_sync_plan.py | 2 +- scripts/print_strategy_profile_status.py | 2 +- scripts/print_strategy_switch_env_plan.py | 2 +- tests/test_execution_service.py | 2 +- tests/test_notifications.py | 12 +++--- tests/test_request_handling.py | 6 +-- tests/test_runtime_config_support.py | 40 +++++++++---------- tests/test_strategy_runtime.py | 8 ++-- tests/test_sync_cloud_run_env_workflow.sh | 2 +- 18 files changed, 57 insertions(+), 90 deletions(-) delete mode 100644 configs/paper_tech_communication_pullback_enhancement.dryrun.env.example delete mode 100644 configs/paper_tech_communication_pullback_enhancement.env.example delete mode 100644 configs/paper_tech_communication_pullback_enhancement.paper.env.example diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8bf47d..8771282 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: assert CallableNotificationPort assert CallablePortfolioPort assert resolve_canonical_profile("mega_cap_leader_rotation_top50_balanced") == "mega_cap_leader_rotation_top50_balanced" - assert resolve_hk_canonical_profile("hk_listed_global_etf_rotation") == "hk_listed_global_etf_rotation" + assert resolve_hk_canonical_profile("hk_global_etf_tactical_rotation") == "hk_global_etf_tactical_rotation" PY - name: Install editable shared repositories diff --git a/.github/workflows/sync-cloud-run-env.yml b/.github/workflows/sync-cloud-run-env.yml index c975399..1b3c2ce 100644 --- a/.github/workflows/sync-cloud-run-env.yml +++ b/.github/workflows/sync-cloud-run-env.yml @@ -200,7 +200,7 @@ jobs: json.dumps( { "platform_id": "ibkr", - "strategy_profile": "hk_listed_global_etf_rotation", + "strategy_profile": "hk_global_etf_tactical_rotation", "deployment_selector": os.environ["ACCOUNT_GROUP_VALUE"], "account_scope": os.environ["ACCOUNT_GROUP_VALUE"], "execution_mode": "paper", diff --git a/configs/paper_global_etf_rotation.rollback.env.example b/configs/paper_global_etf_rotation.rollback.env.example index 012b3ce..a163afb 100644 --- a/configs/paper_global_etf_rotation.rollback.env.example +++ b/configs/paper_global_etf_rotation.rollback.env.example @@ -4,7 +4,7 @@ ACCOUNT_GROUP=default IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups GLOBAL_TELEGRAM_CHAT_ID= NOTIFY_LANG=zh -# remove if previously set for tech_communication_pullback_enhancement: +# remove if previously set by a snapshot-backed strategy: # IBKR_FEATURE_SNAPSHOT_PATH # IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH # IBKR_STRATEGY_CONFIG_PATH diff --git a/configs/paper_tech_communication_pullback_enhancement.dryrun.env.example b/configs/paper_tech_communication_pullback_enhancement.dryrun.env.example deleted file mode 100644 index 36605d8..0000000 --- a/configs/paper_tech_communication_pullback_enhancement.dryrun.env.example +++ /dev/null @@ -1,11 +0,0 @@ -# IBKR paper runtime switch: tech_communication_pullback_enhancement (dry-run) -STRATEGY_PROFILE=tech_communication_pullback_enhancement -ACCOUNT_GROUP=default -IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups -IBKR_FEATURE_SNAPSHOT_PATH=/var/data/tech_communication_pullback_enhancement_feature_snapshot_latest.csv -IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH=/var/manifests/tech_communication_pullback_enhancement_feature_snapshot_latest.csv.manifest.json -# IBKR_STRATEGY_CONFIG_PATH is optional; the bundled canonical default is used when unset. -IBKR_RECONCILIATION_OUTPUT_PATH=/var/log/ibkr_tech_communication_pullback_enhancement_reconciliation.json -IBKR_DRY_RUN_ONLY=true -GLOBAL_TELEGRAM_CHAT_ID= -NOTIFY_LANG=zh diff --git a/configs/paper_tech_communication_pullback_enhancement.env.example b/configs/paper_tech_communication_pullback_enhancement.env.example deleted file mode 100644 index b3efdfa..0000000 --- a/configs/paper_tech_communication_pullback_enhancement.env.example +++ /dev/null @@ -1,11 +0,0 @@ -# IBKR paper runtime switch: tech_communication_pullback_enhancement -STRATEGY_PROFILE=tech_communication_pullback_enhancement -ACCOUNT_GROUP=default -IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups -IBKR_FEATURE_SNAPSHOT_PATH=/var/data/tech_communication_pullback_enhancement_feature_snapshot_latest.csv -IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH=/var/manifests/tech_communication_pullback_enhancement_feature_snapshot_latest.csv.manifest.json -# IBKR_STRATEGY_CONFIG_PATH is optional; the bundled canonical default is used when unset. -IBKR_RECONCILIATION_OUTPUT_PATH=/var/log/ibkr_tech_communication_pullback_enhancement_reconciliation.json -IBKR_DRY_RUN_ONLY=true -GLOBAL_TELEGRAM_CHAT_ID= -NOTIFY_LANG=zh diff --git a/configs/paper_tech_communication_pullback_enhancement.paper.env.example b/configs/paper_tech_communication_pullback_enhancement.paper.env.example deleted file mode 100644 index 14a558e..0000000 --- a/configs/paper_tech_communication_pullback_enhancement.paper.env.example +++ /dev/null @@ -1,11 +0,0 @@ -# IBKR paper runtime switch: tech_communication_pullback_enhancement (paper ordering) -STRATEGY_PROFILE=tech_communication_pullback_enhancement -ACCOUNT_GROUP=default -IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups -IBKR_FEATURE_SNAPSHOT_PATH=/var/data/tech_communication_pullback_enhancement_feature_snapshot_latest.csv -IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH=/var/manifests/tech_communication_pullback_enhancement_feature_snapshot_latest.csv.manifest.json -# IBKR_STRATEGY_CONFIG_PATH is optional; the bundled canonical default is used when unset. -IBKR_RECONCILIATION_OUTPUT_PATH=/var/log/ibkr_tech_communication_pullback_enhancement_reconciliation.json -IBKR_DRY_RUN_ONLY=false -GLOBAL_TELEGRAM_CHAT_ID= -NOTIFY_LANG=zh diff --git a/docs/hk_equity_runtime.md b/docs/hk_equity_runtime.md index 70c5616..5dbdb62 100644 --- a/docs/hk_equity_runtime.md +++ b/docs/hk_equity_runtime.md @@ -14,7 +14,7 @@ QuantStrategyLab 现有平台仓库里,能接入港股股票交易的平台是 ## 运行时设计 -本仓库只做券商运行时能力,不把港股策略逻辑硬编码进平台。当前已接入 `HkEquityStrategies` 的港股 profile 元数据,平台可选港股 profile 只暴露 `runtime_enabled` 的 `hk_listed_global_etf_rotation`。`hk_blue_chip_leader_rotation` 是 snapshot 架构占位,`hk_index_mean_reversion`、`hk_etf_regime_rotation` 是 `market_history` 研究候选,均留在研究/快照仓库,不进入平台可选列表。Cloud Run 通过 `RUNTIME_TARGET_JSON` / `STRATEGY_PROFILE` 选择当前运行策略。整体沿用美股策略的架构: +本仓库只做券商运行时能力,不把港股策略逻辑硬编码进平台。当前已接入 `HkEquityStrategies` 的港股 profile 元数据,平台可选港股 profile 只暴露 `runtime_enabled` 的 `hk_global_etf_tactical_rotation`。`hk_blue_chip_leader_rotation` 是 snapshot 架构占位,`hk_index_mean_reversion`、`hk_etf_regime_rotation` 是 `market_history` 研究候选,均留在研究/快照仓库,不进入平台可选列表。Cloud Run 通过 `RUNTIME_TARGET_JSON` / `STRATEGY_PROFILE` 选择当前运行策略。整体沿用美股策略的架构: 1. [`HkEquityStrategies`](https://github.com/QuantStrategyLab/HkEquityStrategies) 提供非 snapshot `hk_equity` 策略 profile、运行入口和 IBKR runtime adapter。 2. [`HkEquitySnapshotPipelines`](https://github.com/QuantStrategyLab/HkEquitySnapshotPipelines) 发布 snapshot-backed profile 的 `_feature_snapshot_latest.csv`、manifest、ranking 和 release summary。 @@ -28,12 +28,12 @@ QuantStrategyLab 现有平台仓库里,能接入港股股票交易的平台是 | Profile | Domain | Inputs | Target mode | Snapshot manifest | Status | | --- | --- | --- | --- | --- | --- | -| `hk_listed_global_etf_rotation` | `hk_equity` | `market_history` | `weight` | not required | runtime-enabled; platform-selectable | +| `hk_global_etf_tactical_rotation` | `hk_equity` | `market_history` | `weight` | not required | runtime-enabled; platform-selectable | | `hk_blue_chip_leader_rotation` | `hk_equity` | `feature_snapshot` | `weight` | required | snapshot scaffold; not platform-selectable | | `hk_index_mean_reversion` | `hk_equity` | `market_history` | `weight` | not required | research/backtest only; not platform-selectable | | `hk_etf_regime_rotation` | `hk_equity` | `market_history` | `weight` | not required | research/backtest only; not platform-selectable | -`scripts/print_strategy_profile_status.py` 只显示平台可选 profile,因此只会列出 `hk_listed_global_etf_rotation` 这一条港股 profile。其他港股候选继续保留在研究文档和 snapshot pipeline,不应该出现在 Cloud Run switch plan 里。 +`scripts/print_strategy_profile_status.py` 只显示平台可选 profile,因此只会列出 `hk_global_etf_tactical_rotation` 这一条港股 profile。其他港股候选继续保留在研究文档和 snapshot pipeline,不应该出现在 Cloud Run switch plan 里。 未来启用 snapshot-backed profile 后的最小策略配置示例;这些 profile 晋级为 `runtime_enabled` 前不会出现在平台可选列表: @@ -76,7 +76,7 @@ IBKR_MARKET_DATA_SYMBOL_SUFFIX=.HK ```bash python scripts/print_strategy_switch_env_plan.py \ - --profile hk_listed_global_etf_rotation \ + --profile hk_global_etf_tactical_rotation \ --dry-run-only \ --deployment-selector hk-verify \ --account-scope hk-verify \ @@ -87,7 +87,7 @@ python scripts/print_strategy_switch_env_plan.py \ 这个命令只打印计划。输出会显式包含: -- `RUNTIME_TARGET_JSON`:`strategy_profile=hk_listed_global_etf_rotation`、`dry_run_only=true`、`execution_mode=paper`。 +- `RUNTIME_TARGET_JSON`:`strategy_profile=hk_global_etf_tactical_rotation`、`dry_run_only=true`、`execution_mode=paper`。 - `IBKR_DRY_RUN_ONLY=true` 和 `IBKR_MARKET=HK` / `XHKG` / `SEHK` / `HKD` / `.HK`。 - `remove_if_present`:清理 snapshot/config 相关环境变量,因为该 profile 直接使用 `market_history`。 - `dry_run_plan`:检查 HK 行情权限、SEHK/HKD 映射、整数股和 lot-size、HKD 现金口径、通知和 runtime report。 @@ -99,7 +99,7 @@ python scripts/print_strategy_switch_env_plan.py \ 仓库的 `Deploy Cloud Run` workflow 支持手动 `workflow_dispatch` 目标 `hk-verify`。这个目标会设置或更新独立港股 dry-run 服务: - `CLOUD_RUN_SERVICE=interactive-brokers-hk-verify-service`(可通过输入改名) -- `STRATEGY_PROFILE=hk_listed_global_etf_rotation` +- `STRATEGY_PROFILE=hk_global_etf_tactical_rotation` - `ACCOUNT_GROUP=hk-verify` - `RUNTIME_TARGET_JSON.execution_mode=paper`、`dry_run_only=true` - `IBKR_DRY_RUN_ONLY=true` @@ -147,5 +147,5 @@ gh workflow run sync-cloud-run-env.yml \ - IBKR 港股实盘依赖账户权限、行情权限、Gateway 登录账户可见账号和交易许可;平台配置无法替代这些权限。 - 不同 IBKR 账户或区域对港股 symbol 格式可能有差异,首批上线前需要用 dry-run 和小范围 symbol 做实盘连接验证。 - `XHKG` 是否可用取决于部署环境里的 `pandas_market_calendars` 版本;如不可用,可用 `IBKR_MARKET_CALENDAR` 临时覆盖。 -- `hk_listed_global_etf_rotation` 已在策略包 `runtime_enabled`,可由 IBKR HK Cloud Run 通过运行时环境选择;`hk_blue_chip_leader_rotation`、`hk_index_mean_reversion`、`hk_etf_regime_rotation` 仍不进入平台可选列表。 +- `hk_global_etf_tactical_rotation` 已在策略包 `runtime_enabled`,可由 IBKR HK Cloud Run 通过运行时环境选择;`hk_blue_chip_leader_rotation`、`hk_index_mean_reversion`、`hk_etf_regime_rotation` 仍不进入平台可选列表。 - 港股 `market_history` profile 运行后,需要持续用 IBKR HK 行情 feed 对 `02800`、`03033`、`02822`、`02840`、`03110`、`03188`、`02834`、`03175` 做行情、价差、lot-size 和订单预览/执行结果复核。 diff --git a/notifications/telegram.py b/notifications/telegram.py index 707f4e4..b35e91b 100644 --- a/notifications/telegram.py +++ b/notifications/telegram.py @@ -139,9 +139,9 @@ "strategy_name_qqq_tech_enhancement": "科技通信回调增强", "strategy_name_mega_cap_leader_rotation_top50_balanced": "Mega Cap Top50 平衡龙头轮动", "strategy_name_nasdaq_sp500_smart_dca": "纳斯达克 / 标普智能定投", - "strategy_name_hk_listed_global_etf_rotation": "港股上市全球 ETF 轮动", - "strategy_name_hk_high_dividend_low_vol_trend": "港股高股息低波趋势", - "strategy_name_hk_low_vol_dividend_quality": "港股低波股息质量", + "strategy_name_hk_global_etf_tactical_rotation": "港股全球 ETF 战术轮动", + "strategy_name_hk_dividend_gold_defensive_rotation": "港股股息黄金防守轮动", + "strategy_name_hk_low_vol_dividend_quality_snapshot": "港股低波股息质量快照", "strategy_name_tqqq_growth_income": "TQQQ 增长收益", "strategy_name_soxl_soxx_trend_income": "SOXL/SOXX 半导体趋势收益", }, @@ -280,9 +280,9 @@ "strategy_name_qqq_tech_enhancement": "Tech/Communication Pullback Enhancement", "strategy_name_mega_cap_leader_rotation_top50_balanced": "Mega Cap Leader Rotation Top50 Balanced", "strategy_name_nasdaq_sp500_smart_dca": "Nasdaq/S&P 500 Smart DCA", - "strategy_name_hk_listed_global_etf_rotation": "HK-listed Global ETF Rotation", - "strategy_name_hk_high_dividend_low_vol_trend": "HK High Dividend Low-Volatility Trend", - "strategy_name_hk_low_vol_dividend_quality": "HK Low-Volatility Dividend Quality", + "strategy_name_hk_global_etf_tactical_rotation": "HK Global ETF Tactical Rotation", + "strategy_name_hk_dividend_gold_defensive_rotation": "HK Dividend-Gold Defensive Rotation", + "strategy_name_hk_low_vol_dividend_quality_snapshot": "HK Low-Vol Dividend Quality Snapshot", "strategy_name_tqqq_growth_income": "TQQQ Growth Income", "strategy_name_soxl_soxx_trend_income": "SOXL/SOXX Semiconductor Trend Income", }, diff --git a/requirements.txt b/requirements.txt index 4793e51..390cd83 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ flask gunicorn -quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@v0.7.36 -us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@v0.7.50 -hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@hk-low-vol-dividend-quality-20260603 +quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@v0.7.37 +us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@v0.7.52 +hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@v0.4.3 pandas numpy requests diff --git a/scripts/build_cloud_run_env_sync_plan.py b/scripts/build_cloud_run_env_sync_plan.py index e0cd04a..6b2a37e 100644 --- a/scripts/build_cloud_run_env_sync_plan.py +++ b/scripts/build_cloud_run_env_sync_plan.py @@ -34,7 +34,7 @@ def _should_add_local_src(candidate: Path) -> bool: return _has_catalog_marker( candidate, "hk_equity_strategies", - "hk_listed_global_etf_rotation", + "hk_global_etf_tactical_rotation", ) return True diff --git a/scripts/print_strategy_profile_status.py b/scripts/print_strategy_profile_status.py index 613f8a1..88f9dcf 100644 --- a/scripts/print_strategy_profile_status.py +++ b/scripts/print_strategy_profile_status.py @@ -31,7 +31,7 @@ def _should_add_local_src(candidate: Path) -> bool: return _has_catalog_marker( candidate, "hk_equity_strategies", - "hk_listed_global_etf_rotation", + "hk_global_etf_tactical_rotation", ) return True diff --git a/scripts/print_strategy_switch_env_plan.py b/scripts/print_strategy_switch_env_plan.py index f0178d2..1b92936 100644 --- a/scripts/print_strategy_switch_env_plan.py +++ b/scripts/print_strategy_switch_env_plan.py @@ -32,7 +32,7 @@ def _should_add_local_src(candidate: Path) -> bool: return _has_catalog_marker( candidate, "hk_equity_strategies", - "hk_listed_global_etf_rotation", + "hk_global_etf_tactical_rotation", ) return True diff --git a/tests/test_execution_service.py b/tests/test_execution_service.py index 1db04f2..0fa8665 100644 --- a/tests/test_execution_service.py +++ b/tests/test_execution_service.py @@ -276,7 +276,7 @@ def accountValues(self): order_intent_cls=OrderIntent, translator=translate, strategy_symbols=["02834", "03110"], - strategy_profile="hk_listed_global_etf_rotation", + strategy_profile="hk_global_etf_tactical_rotation", account_group="paper-hk", service_name="ibkr-hk-paper", signal_metadata=_signal_metadata( diff --git a/tests/test_notifications.py b/tests/test_notifications.py index bdbe712..70cb73e 100644 --- a/tests/test_notifications.py +++ b/tests/test_notifications.py @@ -84,12 +84,12 @@ def test_strategy_display_name_translates_new_live_profiles(): assert en_name("mega_cap_leader_rotation_top50_balanced") == "Mega Cap Leader Rotation Top50 Balanced" assert zh_name("nasdaq_sp500_smart_dca") == "纳斯达克 / 标普智能定投" assert en_name("nasdaq_sp500_smart_dca") == "Nasdaq/S&P 500 Smart DCA" - assert zh_name("hk_listed_global_etf_rotation") == "港股上市全球 ETF 轮动" - assert en_name("hk_listed_global_etf_rotation") == "HK-listed Global ETF Rotation" - assert zh_name("hk_high_dividend_low_vol_trend") == "港股高股息低波趋势" - assert en_name("hk_high_dividend_low_vol_trend") == "HK High Dividend Low-Volatility Trend" - assert zh_name("hk_low_vol_dividend_quality") == "港股低波股息质量" - assert en_name("hk_low_vol_dividend_quality") == "HK Low-Volatility Dividend Quality" + assert zh_name("hk_global_etf_tactical_rotation") == "港股全球 ETF 战术轮动" + assert en_name("hk_global_etf_tactical_rotation") == "HK Global ETF Tactical Rotation" + assert zh_name("hk_dividend_gold_defensive_rotation") == "港股股息黄金防守轮动" + assert en_name("hk_dividend_gold_defensive_rotation") == "HK Dividend-Gold Defensive Rotation" + assert zh_name("hk_low_vol_dividend_quality_snapshot") == "港股低波股息质量快照" + assert en_name("hk_low_vol_dividend_quality_snapshot") == "HK Low-Vol Dividend Quality Snapshot" def test_supported_strategy_profiles_have_translated_names(): diff --git a/tests/test_request_handling.py b/tests/test_request_handling.py index 25651a8..8d4e3a6 100644 --- a/tests/test_request_handling.py +++ b/tests/test_request_handling.py @@ -428,7 +428,7 @@ def test_cycle_report_summary_counts_dry_run_order_previews(strategy_module): def test_notification_delivery_log_summary_records_sent_dry_run_without_raw_text(strategy_module): payload = strategy_module._build_notification_delivery_log_for_report( platform="interactive_brokers", - strategy_profile="hk_low_vol_dividend_quality", + strategy_profile="hk_low_vol_dividend_quality_snapshot", run_id="run-001", dry_run=True, orders_previewed_count=2, @@ -446,7 +446,7 @@ def test_notification_delivery_log_summary_records_sent_dry_run_without_raw_text assert payload["notification_event_type"] == "hk_snapshot_live_enablement_dry_run" assert payload["notification_correlation_id"] == "run-001" assert payload["locales"] == ["en", "zh-Hans"] - assert payload["profile"] == "hk_low_vol_dividend_quality" + assert payload["profile"] == "hk_low_vol_dividend_quality_snapshot" assert payload["platform"] == "interactive_brokers" assert payload["orders_previewed"] == 2 assert payload["notification_redacts_sensitive_fields"] is True @@ -456,7 +456,7 @@ def test_notification_delivery_log_summary_records_sent_dry_run_without_raw_text def test_notification_delivery_log_summary_stays_empty_without_sent_event(strategy_module): payload = strategy_module._build_notification_delivery_log_for_report( platform="interactive_brokers", - strategy_profile="hk_low_vol_dividend_quality", + strategy_profile="hk_low_vol_dividend_quality_snapshot", run_id="run-001", dry_run=True, orders_previewed_count=2, diff --git a/tests/test_runtime_config_support.py b/tests/test_runtime_config_support.py index 653d75d..b2da74d 100644 --- a/tests/test_runtime_config_support.py +++ b/tests/test_runtime_config_support.py @@ -62,9 +62,9 @@ "russell_1000_multi_factor_defensive", "soxl_soxx_trend_income", "tqqq_growth_income", - "hk_high_dividend_low_vol_trend", - "hk_listed_global_etf_rotation", - "hk_low_vol_dividend_quality", + "hk_dividend_gold_defensive_rotation", + "hk_global_etf_tactical_rotation", + "hk_low_vol_dividend_quality_snapshot", } ) HK_DISABLED_PROFILES = frozenset( @@ -599,14 +599,14 @@ def test_load_platform_runtime_settings_rejects_disabled_hk_profiles(monkeypatch def test_load_platform_runtime_settings_accepts_runtime_enabled_hk_global_etf_rotation(monkeypatch): - monkeypatch.setenv("RUNTIME_TARGET_JSON", runtime_target_json("hk_listed_global_etf_rotation")) + monkeypatch.setenv("RUNTIME_TARGET_JSON", runtime_target_json("hk_global_etf_tactical_rotation")) monkeypatch.setenv("ACCOUNT_GROUP", "hk-live") monkeypatch.setenv("IB_ACCOUNT_GROUP_CONFIG_JSON", MINIMAL_HK_GROUP_JSON) settings = load_platform_runtime_settings(project_id_resolver=lambda: "project-1") - assert settings.strategy_profile == "hk_listed_global_etf_rotation" - assert settings.strategy_display_name == "HK-listed Global ETF Rotation" + assert settings.strategy_profile == "hk_global_etf_tactical_rotation" + assert settings.strategy_display_name == "HK Global ETF Tactical Rotation" assert settings.strategy_domain == "hk_equity" assert settings.strategy_target_mode == "weight" assert settings.market == HK_MARKET @@ -700,9 +700,9 @@ def test_platform_profile_status_matrix_matches_current_ibkr_rollout(): assert by_profile["nasdaq_sp500_smart_dca"]["display_name"] == "Nasdaq/S&P 500 Smart DCA" assert by_profile["nasdaq_sp500_smart_dca"]["eligible"] is True assert by_profile["nasdaq_sp500_smart_dca"]["enabled"] is True - assert by_profile["hk_listed_global_etf_rotation"] == { - "canonical_profile": "hk_listed_global_etf_rotation", - "display_name": "HK-listed Global ETF Rotation", + assert by_profile["hk_global_etf_tactical_rotation"] == { + "canonical_profile": "hk_global_etf_tactical_rotation", + "display_name": "HK Global ETF Tactical Rotation", "domain": "hk_equity", "eligible": True, "enabled": True, @@ -750,7 +750,7 @@ def test_print_strategy_profile_status_json_matches_registry(): assert by_profile["mega_cap_leader_rotation_top50_balanced"]["requires_strategy_config_path"] is False for profile in ("hk_blue_chip_leader_rotation", "hk_index_mean_reversion", "hk_etf_regime_rotation"): assert profile not in by_profile - for profile in ("hk_listed_global_etf_rotation",): + for profile in ("hk_global_etf_tactical_rotation",): assert by_profile[profile]["profile_group"] == "direct_runtime_inputs" assert by_profile[profile]["input_mode"] == "market_history" assert by_profile[profile]["requires_snapshot_artifacts"] is False @@ -773,10 +773,10 @@ def test_print_strategy_profile_status_table_contains_expected_headers(): assert "input_mode" in result.stdout assert "requires_snapshot_artifacts" in result.stdout assert "global_etf_rotation" in result.stdout - assert "hk_listed_global_etf_rotation" in result.stdout + assert "hk_global_etf_tactical_rotation" in result.stdout assert "Mega Cap Leader Rotation Top50 Balanced" in result.stdout assert "Tech/Communication Pullback Enhancement" not in result.stdout - assert "HK-listed Global ETF Rotation" in result.stdout + assert "HK Global ETF Tactical Rotation" in result.stdout assert "TQQQ Growth Income" in result.stdout assert "hk_blue_chip_leader_rotation" not in result.stdout assert "hk_index_mean_reversion" not in result.stdout @@ -824,7 +824,7 @@ def test_print_strategy_switch_env_plan_for_hk_global_etf_dry_run(): sys.executable, str(SWITCH_PLAN_SCRIPT_PATH), "--profile", - "hk_listed_global_etf_rotation", + "hk_global_etf_tactical_rotation", "--dry-run-only", "--deployment-selector", "hk-verify", @@ -843,7 +843,7 @@ def test_print_strategy_switch_env_plan_for_hk_global_etf_dry_run(): plan = json.loads(result.stdout) assert plan["platform"] == "ibkr" - assert plan["canonical_profile"] == "hk_listed_global_etf_rotation" + assert plan["canonical_profile"] == "hk_global_etf_tactical_rotation" assert plan["domain"] == HK_EQUITY_DOMAIN assert plan["runtime_target"]["dry_run_only"] is True assert plan["runtime_target"]["execution_mode"] == "paper" @@ -1055,13 +1055,13 @@ def test_print_strategy_switch_env_plan_for_mega_cap_top50_balanced_profile(): assert plan["hints"]["feature_snapshot_filename"] == "mega_cap_leader_rotation_top50_balanced_feature_snapshot_latest.csv" -def test_print_strategy_switch_env_plan_for_hk_low_vol_dividend_quality_profile(): +def test_print_strategy_switch_env_plan_for_hk_low_vol_dividend_quality_snapshot_profile(): result = subprocess.run( [ sys.executable, str(SWITCH_PLAN_SCRIPT_PATH), "--profile", - "hk_low_vol_dividend_quality", + "hk_low_vol_dividend_quality_snapshot", "--dry-run-only", "--deployment-selector", "hk-verify", @@ -1077,17 +1077,17 @@ def test_print_strategy_switch_env_plan_for_hk_low_vol_dividend_quality_profile( ) plan = json.loads(result.stdout) - assert plan["canonical_profile"] == "hk_low_vol_dividend_quality" + assert plan["canonical_profile"] == "hk_low_vol_dividend_quality_snapshot" assert plan["enabled"] is True assert plan["profile_group"] == "snapshot_backed" assert plan["input_mode"] == "feature_snapshot" - assert plan["snapshot_contract_version"] == "hk_low_vol_dividend_quality.factor_snapshot.v1" + assert plan["snapshot_contract_version"] == "hk_low_vol_dividend_quality_snapshot.factor_snapshot.v1" assert plan["set_env"]["IBKR_DRY_RUN_ONLY"] == "true" assert plan["set_env"]["IBKR_FEATURE_SNAPSHOT_PATH"] == "" assert plan["set_env"]["IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH"] == "" - assert plan["hints"]["feature_snapshot_filename"] == "hk_low_vol_dividend_quality_factor_snapshot_latest.csv" + assert plan["hints"]["feature_snapshot_filename"] == "hk_low_vol_dividend_quality_snapshot_factor_snapshot_latest.csv" assert plan["hints"]["feature_snapshot_manifest_filename"] == ( - "hk_low_vol_dividend_quality_factor_snapshot_latest.csv.manifest.json" + "hk_low_vol_dividend_quality_snapshot_factor_snapshot_latest.csv.manifest.json" ) diff --git a/tests/test_strategy_runtime.py b/tests/test_strategy_runtime.py index 3e1a1aa..050303a 100644 --- a/tests/test_strategy_runtime.py +++ b/tests/test_strategy_runtime.py @@ -549,9 +549,9 @@ def test_hk_direct_market_history_runtime_materializes_loader(monkeypatch): class FakeEntrypoint: manifest = StrategyManifest( - profile="hk_listed_global_etf_rotation", + profile="hk_global_etf_tactical_rotation", domain="hk_equity", - display_name="HK-listed Global ETF Rotation", + display_name="HK Global ETF Tactical Rotation", description="test", required_inputs=frozenset({"market_history"}), default_config={"universe_symbols": ("02800", "02834")}, @@ -578,7 +578,7 @@ def close_loader(ib, symbol, **_kwargs): status_icon="🇭🇰", runtime_policy=StrategyRuntimePolicy(signal_effective_after_trading_days=1), ), - runtime_settings=_build_runtime_settings(profile="hk_listed_global_etf_rotation"), + runtime_settings=_build_runtime_settings(profile="hk_global_etf_tactical_rotation"), runtime_config={}, merged_runtime_config={"universe_symbols": ("02800", "02834")}, status_icon="🇭🇰", @@ -587,7 +587,7 @@ def close_loader(ib, symbol, **_kwargs): monkeypatch.setattr( strategy_runtime_module, "_requires_materialized_market_history", - lambda profile: profile == "hk_listed_global_etf_rotation", + lambda profile: profile == "hk_global_etf_tactical_rotation", ) runtime.evaluate( diff --git a/tests/test_sync_cloud_run_env_workflow.sh b/tests/test_sync_cloud_run_env_workflow.sh index aaa8924..9082005 100644 --- a/tests/test_sync_cloud_run_env_workflow.sh +++ b/tests/test_sync_cloud_run_env_workflow.sh @@ -19,7 +19,7 @@ grep -Fq 'target:' "$workflow_file" grep -Fq 'default: hk-verify' "$workflow_file" grep -Fq 'INPUT_DEPLOY_IMAGE: ${{ inputs.deploy_image }}' "$workflow_file" grep -Fq 'Apply HK verify-only dispatch defaults' "$workflow_file" -grep -Fq '"strategy_profile": "hk_listed_global_etf_rotation"' "$workflow_file" +grep -Fq '"strategy_profile": "hk_global_etf_tactical_rotation"' "$workflow_file" grep -Fq 'echo "IBKR_DRY_RUN_ONLY=true"' "$workflow_file" grep -Fq 'echo "IBKR_MARKET=HK"' "$workflow_file" grep -Fq 'echo "IBKR_MARKET_EXCHANGE=SEHK"' "$workflow_file"