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
16 changes: 8 additions & 8 deletions .github/workflows/build-hk-low-vol-snapshot-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ on:
profile:
description: "HK snapshot profile to build."
required: true
default: hk_low_vol_dividend_quality
default: hk_low_vol_dividend_quality_snapshot
type: choice
options:
- hk_low_vol_dividend_quality
- hk_low_vol_dividend_quality_snapshot
data_source_mode:
description: "Source used to generate the factor snapshot."
required: true
Expand Down Expand Up @@ -49,12 +49,12 @@ on:
artifact_dir:
description: "Artifact output directory inside HkEquitySnapshotPipelines."
required: false
default: data/output/hk_low_vol_dividend_quality
default: data/output/hk_low_vol_dividend_quality_snapshot
type: string
gcs_prefix:
description: "Optional GCS prefix for validated runtime artifacts."
required: false
default: gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality
default: gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality_snapshot
type: string
execute_publish:
description: "Actually upload validated artifacts to GCS. false only prints the publish plan."
Expand Down Expand Up @@ -141,7 +141,7 @@ jobs:
set -euo pipefail

case "${PROFILE}" in
hk_low_vol_dividend_quality) ;;
hk_low_vol_dividend_quality_snapshot) ;;
*)
echo "Unsupported HK snapshot profile: ${PROFILE}" >&2
exit 1
Expand Down Expand Up @@ -205,8 +205,8 @@ jobs:
generated_dir="data/input/generated/${PROFILE}"
artifact_dir="${ARTIFACT_DIR_INPUT:-data/output/${PROFILE}}"
mkdir -p "${generated_dir}" "${artifact_dir}"
snapshot_uri="${GCS_PREFIX%/}/hk_low_vol_dividend_quality_factor_snapshot_latest.csv"
manifest_uri="${GCS_PREFIX%/}/hk_low_vol_dividend_quality_factor_snapshot_latest.csv.manifest.json"
snapshot_uri="${GCS_PREFIX%/}/hk_low_vol_dividend_quality_snapshot_factor_snapshot_latest.csv"
manifest_uri="${GCS_PREFIX%/}/hk_low_vol_dividend_quality_snapshot_factor_snapshot_latest.csv.manifest.json"
{
echo "artifact_dir=${SNAPSHOT_REPO_DIR}/${artifact_dir}"
echo "generated_input_dir=${SNAPSHOT_REPO_DIR}/${generated_dir}"
Expand Down Expand Up @@ -390,7 +390,7 @@ jobs:
echo "Suggested longbridge-hk environment values for dry-run runtime:"
echo
echo "\`\`\`bash"
echo "STRATEGY_PROFILE=hk_low_vol_dividend_quality"
echo "STRATEGY_PROFILE=hk_low_vol_dividend_quality_snapshot"
echo "LONGBRIDGE_DRY_RUN_ONLY=true"
echo "LONGBRIDGE_FEATURE_SNAPSHOT_PATH=${{ steps.build.outputs.snapshot_gcs_uri }}"
echo "LONGBRIDGE_FEATURE_SNAPSHOT_MANIFEST_PATH=${{ steps.build.outputs.manifest_gcs_uri }}"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ jobs:

assert CallableNotificationPort
assert CallablePortfolioPort
assert resolve_canonical_profile("tech_communication_pullback_enhancement") == "tech_communication_pullback_enhancement"
assert resolve_hk_canonical_profile("hk_listed_global_etf_rotation") == "hk_listed_global_etf_rotation"
assert resolve_canonical_profile("mega_cap_leader_rotation_top50_balanced") == "mega_cap_leader_rotation_top50_balanced"
assert resolve_hk_canonical_profile("hk_global_etf_tactical_rotation") == "hk_global_etf_tactical_rotation"
PY

- name: Install editable shared repositories
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sync-cloud-run-env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ jobs:
json.dumps(
{
"platform_id": "longbridge",
"strategy_profile": "hk_listed_global_etf_rotation",
"strategy_profile": "hk_global_etf_tactical_rotation",
"deployment_selector": "hk-verify",
"account_scope": "hk-verify",
"execution_mode": "paper",
Expand Down
30 changes: 15 additions & 15 deletions docs/hk_equity_runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -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` 策略定义、运行入口和 LongBridge runtime adapter。
2. [`HkEquitySnapshotPipelines`](https://github.com/QuantStrategyLab/HkEquitySnapshotPipelines) 产出 snapshot-backed profile 的特征快照、manifest、ranking 和 release summary。
Expand All @@ -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` 前不会出现在平台可选列表:

Expand Down Expand Up @@ -73,7 +73,7 @@ LONGBRIDGE_TRADING_CURRENCY=HKD

```bash
python scripts/print_strategy_switch_env_plan.py \
--profile hk_listed_global_etf_rotation \
--profile hk_global_etf_tactical_rotation \
--account-region hk \
--dry-run-only \
--deployment-selector hk-verify \
Expand All @@ -84,25 +84,25 @@ 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`。
- `ACCOUNT_REGION=HK`、`ACCOUNT_PREFIX=HK`、`LONGBRIDGE_DRY_RUN_ONLY=true`。
- `LONGBRIDGE_MARKET=HK` / `XHKG` / `Asia/Hong_Kong` / `.HK` / `HKD`。
- `remove_if_present`:清理 snapshot/config 相关环境变量,因为该 profile 直接使用 `market_history`。
- `dry_run_plan`:检查 HK 行情权限、`.HK` / HKD 映射、整数股和 lot-size、HKD 现金口径、dry-run 订单预览、通知和 runtime report。

打印计划不会直接修改服务配置;只有执行 Cloud Run env 更新/部署命令才会改变服务。

## 生成 `hk_low_vol_dividend_quality` snapshot artifacts
## 生成 `hk_low_vol_dividend_quality_snapshot` snapshot artifacts

`hk_low_vol_dividend_quality` 是 snapshot-backed 策略,Cloud Run 切到这个 profile 前必须先有经过校验的 feature snapshot 和 manifest。`LongBridgePlatform` 提供一个手动桥接 workflow,使用本仓库已经允许的 `longbridge-hk` WIF 发布 artifact。默认数据源是 `public_yfinance_staging`,不依赖 LongBridge 历史行情权限;如果账号已开通对应 HK market-data entitlement,也可以切到 `longbridge_openapi_staging`。
`hk_low_vol_dividend_quality_snapshot` 是 snapshot-backed 策略,Cloud Run 切到这个 profile 前必须先有经过校验的 feature snapshot 和 manifest。`LongBridgePlatform` 提供一个手动桥接 workflow,使用本仓库已经允许的 `longbridge-hk` WIF 发布 artifact。默认数据源是 `public_yfinance_staging`,不依赖 LongBridge 历史行情权限;如果账号已开通对应 HK market-data entitlement,也可以切到 `longbridge_openapi_staging`。

手动生成并只打印 GCS 发布计划:

```bash
gh workflow run build-hk-low-vol-snapshot-artifacts.yml \
--repo QuantStrategyLab/LongBridgePlatform \
-f snapshot_ref=main \
-f profile=hk_low_vol_dividend_quality \
-f profile=hk_low_vol_dividend_quality_snapshot \
-f data_source_mode=public_yfinance_staging \
-f allow_research_defaults=false \
-f execute_publish=false
Expand All @@ -114,20 +114,20 @@ gh workflow run build-hk-low-vol-snapshot-artifacts.yml \
gh workflow run build-hk-low-vol-snapshot-artifacts.yml \
--repo QuantStrategyLab/LongBridgePlatform \
-f snapshot_ref=main \
-f profile=hk_low_vol_dividend_quality \
-f profile=hk_low_vol_dividend_quality_snapshot \
-f data_source_mode=public_yfinance_staging \
-f allow_research_defaults=false \
-f gcs_prefix=gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality \
-f gcs_prefix=gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality_snapshot \
-f execute_publish=true
```

发布后,HK dry-run runtime 需要至少配置:

```bash
STRATEGY_PROFILE=hk_low_vol_dividend_quality
STRATEGY_PROFILE=hk_low_vol_dividend_quality_snapshot
LONGBRIDGE_DRY_RUN_ONLY=true
LONGBRIDGE_FEATURE_SNAPSHOT_PATH=gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality/hk_low_vol_dividend_quality_factor_snapshot_latest.csv
LONGBRIDGE_FEATURE_SNAPSHOT_MANIFEST_PATH=gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality/hk_low_vol_dividend_quality_factor_snapshot_latest.csv.manifest.json
LONGBRIDGE_FEATURE_SNAPSHOT_PATH=gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality_snapshot/hk_low_vol_dividend_quality_snapshot_factor_snapshot_latest.csv
LONGBRIDGE_FEATURE_SNAPSHOT_MANIFEST_PATH=gs://qsl-runtime-logs-interactivebrokersquant/strategy-artifacts/hk_equity/hk_low_vol_dividend_quality_snapshot/hk_low_vol_dividend_quality_snapshot_factor_snapshot_latest.csv.manifest.json
```

注意:`allow_research_defaults=true` 只允许做研究 smoke,不允许发布到 GCS,也不能作为 live-enable 证据。public yfinance 数据源用于让 snapshot artifact 生成和券商执行解耦;它仍需要按策略证据包记录数据源、生成时间和 broker dry-run 结果。
Expand All @@ -137,7 +137,7 @@ LONGBRIDGE_FEATURE_SNAPSHOT_MANIFEST_PATH=gs://qsl-runtime-logs-interactivebroke
仓库的 `Deploy Cloud Run` workflow 支持手动 `workflow_dispatch` 目标 `hk-verify`。这个目标只启用 HK matrix deployment,PAPER / SG 会跳过,并设置或更新独立港股 dry-run 服务:

- `CLOUD_RUN_SERVICE=longbridge-quant-hk-verify-service`(可通过输入改名)
- `STRATEGY_PROFILE=hk_listed_global_etf_rotation`
- `STRATEGY_PROFILE=hk_global_etf_tactical_rotation`
- `ACCOUNT_REGION=HK`、`ACCOUNT_PREFIX=HK`
- `RUNTIME_TARGET_JSON.execution_mode=paper`、`dry_run_only=true`
- `LONGBRIDGE_DRY_RUN_ONLY=true`
Expand Down Expand Up @@ -177,6 +177,6 @@ gh workflow run sync-cloud-run-env.yml \
## 风险和注意事项

- `XHKG` 是否可用取决于部署环境里的 `pandas_market_calendars` 版本;如不可用,可用 `LONGBRIDGE_MARKET_CALENDAR` 临时覆盖。
- `hk_listed_global_etf_rotation` 已在策略包 `runtime_enabled`,可由 LongBridge HK Cloud Run 通过运行时环境选择;`hk_blue_chip_leader_rotation`、`hk_index_mean_reversion`、`hk_etf_regime_rotation` 仍不进入平台可选列表。
- `hk_global_etf_tactical_rotation` 已在策略包 `runtime_enabled`,可由 LongBridge HK Cloud Run 通过运行时环境选择;`hk_blue_chip_leader_rotation`、`hk_index_mean_reversion`、`hk_etf_regime_rotation` 仍不进入平台可选列表。
- 港股 `market_history` profile 运行后,需要持续用 LongBridge HK 行情 feed 对 `02800`、`03033`、`02822`、`02840`、`03110`、`03188`、`02834`、`03175` 做行情、价差、lot-size 和订单预览/执行结果复核。
- LongBridge 下单仍保持整数股规则;如果未来港股策略涉及碎股或特殊交易单位,需要在策略层明确 lot-size 约束后再扩展。
6 changes: 0 additions & 6 deletions notifications/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,8 @@
"strategy_name_tech_communication_pullback_enhancement": "科技通信回调增强",
"strategy_name_qqq_tech_enhancement": "科技通信回调增强",
"strategy_name_mega_cap_leader_rotation_top50_balanced": "Mega Cap Top50 平衡龙头轮动",
"strategy_name_hk_listed_global_etf_rotation": "港股上市全球 ETF 轮动",
"strategy_name_hk_global_etf_tactical_rotation": "港股全球 ETF 战术轮动",
"strategy_name_hk_high_dividend_low_vol_trend": "港股高股息低波趋势",
"strategy_name_hk_dividend_gold_defensive_rotation": "港股股息黄金防守轮动",
"strategy_name_hk_low_vol_dividend_quality": "港股低波股息质量",
"strategy_name_hk_low_vol_dividend_quality_snapshot": "港股低波股息质量快照",
"strategy_plugin_line": "🧩 插件:{plugin} | 状态:{route} | 提醒:{action}",
"strategy_plugin_alert_subject": "🚨 策略插件告警:{plugin} | {route}",
Expand Down Expand Up @@ -224,11 +221,8 @@
"strategy_name_tech_communication_pullback_enhancement": "Tech/Communication Pullback Enhancement",
"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_hk_listed_global_etf_rotation": "HK-listed Global ETF Rotation",
"strategy_name_hk_global_etf_tactical_rotation": "HK Global ETF Tactical Rotation",
"strategy_name_hk_high_dividend_low_vol_trend": "HK High Dividend Low-Volatility Trend",
"strategy_name_hk_dividend_gold_defensive_rotation": "HK Dividend-Gold Defensive Rotation",
"strategy_name_hk_low_vol_dividend_quality": "HK Low-Volatility Dividend Quality",
"strategy_name_hk_low_vol_dividend_quality_snapshot": "HK Low-Vol Dividend Quality Snapshot",
"strategy_plugin_line": "🧩 Plugin: {plugin} | status: {route} | notice: {action}",
"strategy_plugin_alert_subject": "🚨 Strategy plugin alert: {plugin} | {route}",
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -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-runtime-adapter-kwargs
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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove stale tech-profile smoke check

With this new pin, the Smoke import pinned shared packages step in .github/workflows/ci.yml lines 61-72 still runs resolve_canonical_profile("tech_communication_pullback_enhancement") against the package installed from requirements.txt before the editable checkout, but us-equity-strategies v0.7.52 removed that profile from its strategy catalog. PR/push CI will fail in that smoke step whenever it installs this requirements file; update the workflow assertion or keep the old pin until the smoke check is aligned.

Useful? React with 👍 / 👎.

hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@v0.4.3
pandas
requests
pytz
Expand Down
2 changes: 1 addition & 1 deletion scripts/print_strategy_profile_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion scripts/print_strategy_switch_env_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions tests/test_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ def test_supported_strategy_profiles_have_translated_names(self):
en_name = build_strategy_display_name(build_translator("en"))
self.assertEqual(zh_name("global_etf_confidence_vol_gate"), "全球 ETF 置信波动门控")
self.assertEqual(en_name("global_etf_confidence_vol_gate"), "Global ETF Confidence Vol Gate")
self.assertEqual(zh_name("hk_listed_global_etf_rotation"), "港股上市全球 ETF 轮动")
self.assertEqual(en_name("hk_listed_global_etf_rotation"), "HK-listed Global ETF Rotation")
self.assertEqual(zh_name("hk_high_dividend_low_vol_trend"), "港股高股息低波趋势")
self.assertEqual(en_name("hk_high_dividend_low_vol_trend"), "HK High Dividend Low-Volatility Trend")
self.assertEqual(zh_name("hk_global_etf_tactical_rotation"), "港股全球 ETF 战术轮动")
self.assertEqual(en_name("hk_global_etf_tactical_rotation"), "HK Global ETF Tactical Rotation")
self.assertEqual(zh_name("hk_dividend_gold_defensive_rotation"), "港股股息黄金防守轮动")
self.assertEqual(en_name("hk_dividend_gold_defensive_rotation"), "HK Dividend-Gold Defensive Rotation")

for profile in SUPPORTED_STRATEGY_PROFILES:
self.assertNotEqual(zh_name(profile), profile)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_rebalance_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def test_execute_rebalance_cycle_hk_dry_run_uses_hk_suffix_without_broker_submit
estimated_symbols = []
prices = {"02800.HK": 30.0, "03033.HK": 20.0}
plan = _build_plan(
strategy_profile="hk_listed_global_etf_rotation",
strategy_profile="hk_global_etf_tactical_rotation",
strategy_symbols=("02800", "03033"),
risk_symbols=("02800", "03033"),
targets={"02800": 90000.0, "03033": 70000.0},
Expand Down
Loading