From 611ec3b7f58cd57b6298fd7128eb231badc9992a Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Mon, 1 Jun 2026 19:15:01 +0800 Subject: [PATCH] Hide HK research and snapshot scaffolds from IBKR status --- .github/workflows/ci.yml | 2 +- docs/hk_equity_runtime.md | 16 +++++----- strategy_registry.py | 4 ++- tests/test_runtime_config_support.py | 46 ++++++---------------------- 4 files changed, 22 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67347ef..e8bf47d 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_blue_chip_leader_rotation") == "hk_blue_chip_leader_rotation" + assert resolve_hk_canonical_profile("hk_listed_global_etf_rotation") == "hk_listed_global_etf_rotation" PY - name: Install editable shared repositories diff --git a/docs/hk_equity_runtime.md b/docs/hk_equity_runtime.md index 097e74a..ea90604 100644 --- a/docs/hk_equity_runtime.md +++ b/docs/hk_equity_runtime.md @@ -14,9 +14,9 @@ QuantStrategyLab 现有平台仓库里,能接入港股股票交易的平台是 ## 运行时设计 -本仓库只做券商运行时能力,不把港股策略逻辑硬编码进平台。当前已接入 `HkEquityStrategies` 的港股 profile 元数据:`hk_blue_chip_leader_rotation` 是架构占位,`hk_index_mean_reversion`、`hk_etf_regime_rotation` 是 `market_history` 研究候选,`hk_listed_global_etf_rotation` 已 runtime-enabled。生产 Cloud Run 仍保持原策略,除非单独变更 `RUNTIME_TARGET_JSON` / `STRATEGY_PROFILE`。整体沿用美股策略的架构: +本仓库只做券商运行时能力,不把港股策略逻辑硬编码进平台。当前已接入 `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`。整体沿用美股策略的架构: -1. [`HkEquityStrategies`](https://github.com/QuantStrategyLab/HkEquityStrategies) 提供 `hk_equity` 策略 profile、运行入口和 IBKR runtime adapter。 +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。 3. 非 snapshot profile 使用平台 market-data feed 提供的 `market_history`,不需要 snapshot artifact。 4. 平台仓库通过 `RUNTIME_TARGET_JSON`、snapshot/config 路径和平台 market scope 读取策略输入。 @@ -28,10 +28,12 @@ QuantStrategyLab 现有平台仓库里,能接入港股股票交易的平台是 | Profile | Domain | Inputs | Target mode | Snapshot manifest | Status | | --- | --- | --- | --- | --- | --- | -| `hk_blue_chip_leader_rotation` | `hk_equity` | `feature_snapshot` | `weight` | required | eligible but disabled | -| `hk_index_mean_reversion` | `hk_equity` | `market_history` | `weight` | not required | eligible but disabled | -| `hk_etf_regime_rotation` | `hk_equity` | `market_history` | `weight` | not required | eligible but disabled | -| `hk_listed_global_etf_rotation` | `hk_equity` | `market_history` | `weight` | not required | runtime-enabled; not deployed by default | +| `hk_listed_global_etf_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 里。 未来启用 snapshot-backed profile 后的最小策略配置示例;当前不要写入 Cloud Run: @@ -145,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,但生产 Cloud Run 仍保持原配置;`hk_blue_chip_leader_rotation`、`hk_index_mean_reversion`、`hk_etf_regime_rotation` 仍未启用,不要写入生产 Cloud Run。 +- `hk_listed_global_etf_rotation` 已在策略包 runtime-enabled,但生产 Cloud Run 仍保持原配置;`hk_blue_chip_leader_rotation`、`hk_index_mean_reversion`、`hk_etf_regime_rotation` 不进入平台可选列表,不要写入生产 Cloud Run。 - 港股 `market_history` profile 投入生产前,需要先用 IBKR HK 行情 feed 对 `02800`、`03033`、`02822`、`02840`、`03110`、`03188`、`02834`、`03175` 做 dry-run 校验,不提交真实订单。 diff --git a/strategy_registry.py b/strategy_registry.py index f22bd98..cdefd65 100644 --- a/strategy_registry.py +++ b/strategy_registry.py @@ -105,7 +105,7 @@ def describe_platform_runtime_requirements(profile: str | None, *, platform_id: ), supported_capabilities=frozenset({"broker_client"}), ) -ELIGIBLE_STRATEGY_PROFILES = derive_eligible_profiles_for_platform( +_STRUCTURALLY_ELIGIBLE_STRATEGY_PROFILES = derive_eligible_profiles_for_platform( STRATEGY_CATALOG, capability_matrix=PLATFORM_CAPABILITY_MATRIX, runtime_adapter_loader=lambda profile: get_platform_runtime_adapter( @@ -113,6 +113,8 @@ def describe_platform_runtime_requirements(profile: str | None, *, platform_id: platform_id=IBKR_PLATFORM, ), ) +# Keep research-only and snapshot-scaffold HK profiles out of platform switch/status output. +ELIGIBLE_STRATEGY_PROFILES = _STRUCTURALLY_ELIGIBLE_STRATEGY_PROFILES & IBKR_ROLLOUT_ALLOWLIST IBKR_ENABLED_PROFILES = derive_enabled_profiles_for_platform( STRATEGY_CATALOG, capability_matrix=PLATFORM_CAPABILITY_MATRIX, diff --git a/tests/test_runtime_config_support.py b/tests/test_runtime_config_support.py index 1c57994..24e5c03 100644 --- a/tests/test_runtime_config_support.py +++ b/tests/test_runtime_config_support.py @@ -73,7 +73,7 @@ "hk_etf_regime_rotation", } ) -EXPECTED_IBKR_PROFILES = EXPECTED_IBKR_ENABLED_PROFILES | HK_DISABLED_PROFILES +EXPECTED_IBKR_PROFILES = EXPECTED_IBKR_ENABLED_PROFILES def runtime_target_json( @@ -701,30 +701,6 @@ 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_blue_chip_leader_rotation"] == { - "canonical_profile": "hk_blue_chip_leader_rotation", - "display_name": "HK Blue Chip Leader Rotation", - "domain": "hk_equity", - "eligible": True, - "enabled": False, - "platform": "ibkr", - } - assert by_profile["hk_index_mean_reversion"] == { - "canonical_profile": "hk_index_mean_reversion", - "display_name": "HK Index Mean Reversion", - "domain": "hk_equity", - "eligible": True, - "enabled": False, - "platform": "ibkr", - } - assert by_profile["hk_etf_regime_rotation"] == { - "canonical_profile": "hk_etf_regime_rotation", - "display_name": "HK ETF Regime Rotation", - "domain": "hk_equity", - "eligible": True, - "enabled": False, - "platform": "ibkr", - } assert by_profile["hk_listed_global_etf_rotation"] == { "canonical_profile": "hk_listed_global_etf_rotation", "display_name": "HK-listed Global ETF Rotation", @@ -733,6 +709,8 @@ def test_platform_profile_status_matrix_matches_current_ibkr_rollout(): "enabled": True, "platform": "ibkr", } + for profile in HK_DISABLED_PROFILES: + assert profile not in by_profile def test_print_strategy_profile_status_json_matches_registry(): @@ -774,12 +752,9 @@ def test_print_strategy_profile_status_json_matches_registry(): assert by_profile["mega_cap_leader_rotation_top50_balanced"]["input_mode"] == "feature_snapshot" assert by_profile["mega_cap_leader_rotation_top50_balanced"]["requires_snapshot_artifacts"] is True assert by_profile["mega_cap_leader_rotation_top50_balanced"]["requires_strategy_config_path"] is False - assert by_profile["hk_blue_chip_leader_rotation"]["profile_group"] == "snapshot_backed" - assert by_profile["hk_blue_chip_leader_rotation"]["input_mode"] == "feature_snapshot" - assert by_profile["hk_blue_chip_leader_rotation"]["requires_snapshot_artifacts"] is True - assert by_profile["hk_blue_chip_leader_rotation"]["requires_snapshot_manifest_path"] is True - assert by_profile["hk_blue_chip_leader_rotation"]["requires_strategy_config_path"] is False - for profile in ("hk_index_mean_reversion", "hk_etf_regime_rotation", "hk_listed_global_etf_rotation"): + 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",): 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 @@ -802,16 +777,13 @@ 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_blue_chip_leader_rotation" in result.stdout - assert "hk_index_mean_reversion" in result.stdout - assert "hk_etf_regime_rotation" in result.stdout assert "hk_listed_global_etf_rotation" in result.stdout assert "Tech/Communication Pullback Enhancement" in result.stdout - assert "HK Blue Chip Leader Rotation" in result.stdout - assert "HK Index Mean Reversion" in result.stdout - assert "HK ETF Regime Rotation" in result.stdout assert "HK-listed Global ETF 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 + assert "hk_etf_regime_rotation" not in result.stdout def test_print_strategy_switch_env_plan_for_tqqq_growth_income():