IBKR runtime for shared us_equity strategy profiles from UsEquityStrategies. Strategy logic, cadence, asset universes, parameters, and research/backtest notes live there.
The runtime carries a structured RuntimeTarget / RUNTIME_TARGET_JSON for the running service identity. Strategy-owned defaults come from UsEquityStrategies; platform variables are only explicit overrides.
Full strategy documentation now lives in UsEquityStrategies. This README focuses on IBKR runtime behavior, profile enablement, deployment, and credentials, and this profile matrix remains the authoritative IBKR enablement source.
The mainline runtime now follows one path only:
main.pyassembles platform inputs intoStrategyContextstrategy_runtime.pyloads the unified strategy entrypointentrypoint.evaluate(ctx)returns a sharedStrategyDecisiondecision_mapper.pymaps that decision into IBKR orders, notifications, and runtime updates
main.py no longer reads private strategy constants or platform-only fields from strategy return payloads.
Supported STRATEGY_PROFILE values
global_etf_rotationrussell_1000_multi_factor_defensivetqqq_growth_incomesoxl_soxx_trend_incometech_communication_pullback_enhancementmega_cap_leader_rotation_top50_balanced
IBKR profile status
| Canonical profile | Display name | Eligible | Enabled | Domain | Runtime note |
|---|---|---|---|---|---|
global_etf_rotation |
Global ETF Rotation | Yes | Yes | us_equity |
enabled weight-mode rotation line |
russell_1000_multi_factor_defensive |
Russell 1000 Multi-Factor | Yes | Yes | us_equity |
defensive stock baseline |
tqqq_growth_income |
TQQQ Growth Income | Yes | Yes | us_equity |
enabled value-mode alternative |
soxl_soxx_trend_income |
SOXL/SOXX Semiconductor Trend Income | Yes | Yes | us_equity |
current IBKR live line |
tech_communication_pullback_enhancement |
Tech/Communication Pullback Enhancement | Yes | Yes | us_equity |
enabled feature-snapshot alternative |
mega_cap_leader_rotation_top50_balanced |
Mega Cap Leader Rotation Top50 Balanced | Yes | Yes | us_equity |
enabled balanced Top50 leader rotation |
Check the current matrix locally:
python3 scripts/print_strategy_profile_status.pySnapshot-backed profiles use upstream artifacts from UsEquitySnapshotPipelines. This runtime only needs the artifact location, for example IBKR_FEATURE_SNAPSHOT_PATH; strategy logic, cadence, feature definitions, and snapshot schema details live in UsEquityStrategies / UsEquitySnapshotPipelines.
Example runtime pointer:
STRATEGY_PROFILE=russell_1000_multi_factor_defensive
IBKR_FEATURE_SNAPSHOT_PATH=/var/data/r1000_feature_snapshot.csvCloud Scheduler (cron chosen from the strategy-layer cadence in `UsEquityStrategies`)
↓ HTTP POST
Cloud Run (Flask: strategy + orchestration)
↓ shared adapter package
QuantPlatformKit (IBKR adapter)
↓ ib_insync TCP
GCE (IB Gateway, always-on)
↓
IBKR Account
Telegram alerts support English/Chinese execution and heartbeat messages. Strategy-specific signal/status fields come from the selected UsEquityStrategies profile; IBKR-specific fields cover order submission, order IDs, account-group context, and runtime state.
The selected ACCOUNT_GROUP is now the runtime identity. Keep broker-specific identity in the account-group config payload, not in Cloud Run env vars.
For IBKR, keep paper as a single account-group entry. If you later add live accounts, split them into separate live groups; do not mix paper and live in one account-group entry.
| Variable | Required | Description |
|---|---|---|
IB_GATEWAY_ZONE |
Optional fallback | GCE zone (for example us-central1-a). Recommended to keep in the selected account-group entry; this env var is only a transition fallback. |
IB_GATEWAY_IP_MODE |
Optional fallback | internal (default) or external. Recommended to keep in the selected account-group entry; this env var is only a transition fallback. |
IBKR_CONNECT_TIMEOUT_SECONDS |
No | IB API handshake timeout in seconds. Defaults to 60; raise only if Gateway remote API startup is consistently slow. |
IBKR_CONNECT_ATTEMPTS |
No | Number of IBKR connection attempts before failing the cycle. Defaults to 3. |
IBKR_CONNECT_RETRY_DELAY_SECONDS |
No | Delay between failed IBKR connection attempts. Defaults to 5. |
IBKR_CLIENT_ID_RETRY_OFFSET |
No | Offset added to the configured ib_client_id on each retry, so a timed-out API handshake can retry with a fresh client id. Defaults to 100. |
STRATEGY_PROFILE |
Yes | Strategy profile selector. Supported us_equity values: global_etf_rotation, russell_1000_multi_factor_defensive, tqqq_growth_income, soxl_soxx_trend_income, tech_communication_pullback_enhancement, mega_cap_leader_rotation_top50_balanced |
ACCOUNT_GROUP |
Yes | Account-group selector. Set explicitly for each deployment. |
IBKR_FEATURE_SNAPSHOT_PATH |
Conditionally required | Required for snapshot-backed profiles such as russell_1000_multi_factor_defensive, tech_communication_pullback_enhancement, and mega_cap_leader_rotation_top50_balanced. Path to the latest feature snapshot file (.csv, .json, .jsonl, .parquet). |
IBKR_STRATEGY_PLUGIN_MOUNTS_JSON |
No | Optional IBKR-side strategy plugin mount JSON. The plugin artifact controls mode; platform config must not set mode. |
IBKR_FRACTIONAL_SHARES_ENABLED |
No | Defaults to false; set true only after verifying fractional order support for this account/API path. |
IBKR_ORDER_QUANTITY_STEP |
No | Explicit order quantity step override; e.g. 1 for whole shares or 0.0001 for fractional sizing. Takes precedence over IBKR_FRACTIONAL_SHARES_ENABLED. |
IBKR_MIN_ORDER_NOTIONAL_USD |
No | Minimum buy notional for fractional sizing; defaults to 50.0. |
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME |
Yes for Cloud Run | Secret Manager secret name for account-group config JSON. Recommended production source. |
IB_ACCOUNT_GROUP_CONFIG_JSON |
No | Local/dev JSON fallback for account-group config. Not recommended for production Cloud Run. |
TELEGRAM_TOKEN |
Yes | Telegram bot token. For Cloud Run, prefer a Secret Manager reference instead of a literal env var. |
GLOBAL_TELEGRAM_CHAT_ID |
Yes | Telegram chat ID used by this service. |
NOTIFY_LANG |
No | en (default) or zh |
The selected account-group entry must provide at least:
ib_gateway_instance_nameib_gateway_modeib_client_id
For the recommended Cloud Run deployment, also include:
ib_gateway_zoneib_gateway_ip_mode(or let it default tointernal)
If you use instance-name resolution with ib_gateway_zone, the Cloud Run runtime service account needs roles/compute.viewer. If you load the payload from Secret Manager, the same runtime service account also needs roles/secretmanager.secretAccessor on ibkr-account-groups.
Recommended shared-config mode
For the current first rollout, keep GitHub / Cloud Run focused on service-level values:
STRATEGY_PROFILE=global_etf_rotation
ACCOUNT_GROUP=paper
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups
GLOBAL_TELEGRAM_CHAT_ID=<telegram-chat-id>
NOTIFY_LANG=zh
# Optional transition fallback only:
IB_GATEWAY_ZONE=us-central1-c
IB_GATEWAY_IP_MODE=internalFor the snapshot-based stock profiles:
STRATEGY_PROFILE=russell_1000_multi_factor_defensive
ACCOUNT_GROUP=paper
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups
IBKR_FEATURE_SNAPSHOT_PATH=/var/data/r1000_feature_snapshot.csv
GLOBAL_TELEGRAM_CHAT_ID=<telegram-chat-id>
NOTIFY_LANG=zhSTRATEGY_PROFILE=tech_communication_pullback_enhancement
ACCOUNT_GROUP=paper
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_DRY_RUN_ONLY=true
# Keep whole-share sizing unless fractional API support has been verified for this account/API path.
# IBKR_FRACTIONAL_SHARES_ENABLED=true
# IBKR_ORDER_QUANTITY_STEP=0.0001
GLOBAL_TELEGRAM_CHAT_ID=<telegram-chat-id>
NOTIFY_LANG=zhSTRATEGY_PROFILE=mega_cap_leader_rotation_top50_balanced
ACCOUNT_GROUP=paper
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups
IBKR_FEATURE_SNAPSHOT_PATH=/var/data/mega_cap_leader_rotation_top50_balanced_feature_snapshot_latest.csv
IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH=/var/manifests/mega_cap_leader_rotation_top50_balanced_feature_snapshot_latest.csv.manifest.json
GLOBAL_TELEGRAM_CHAT_ID=<telegram-chat-id>
NOTIFY_LANG=zhThis shared-config mode is only for the IBKR pair (InteractiveBrokersPlatform + IBKRGatewayManager). It is not meant to become a global secret bundle for unrelated quant repos. Across multiple quant projects, the only broadly reusable runtime settings are usually GLOBAL_TELEGRAM_CHAT_ID and NOTIFY_LANG.
Recommended account-group config payload:
{
"groups": {
"paper": {
"ib_gateway_instance_name": "interactive-brokers-quant-instance",
"ib_gateway_zone": "us-central1-c",
"ib_gateway_mode": "paper",
"ib_gateway_ip_mode": "internal",
"ib_client_id": 1,
"service_name": "interactive-brokers-quant-service",
"account_ids": ["DU1234567"]
}
}
}For live multi-account rollout, keep one Cloud Run service per live account group. Each live group should carry exactly one account_ids value so portfolio reads, pending/fill guards, and submitted IBKR orders are all routed to that account.
See docs/examples/ibkr-account-groups.paper.json for a ready-to-edit starter example, and docs/ibkr_runtime_rollout.md for the exact rollout steps to get ACCOUNT_GROUP=paper running.
Current behavior is fail-fast:
- missing
STRATEGY_PROFILE→ startup error - missing
ACCOUNT_GROUP→ startup error - missing account-group config source → startup error
- missing key fields in the selected group (
ib_gateway_instance_name,ib_gateway_mode,ib_client_id) → startup error
If code deployment still uses Google Cloud Trigger, but you want GitHub to be the single source of truth for runtime env vars, this repo now includes .github/workflows/sync-cloud-run-env.yml. The workflow now also emits RUNTIME_TARGET_JSON, so the control plane carries a structured runtime target alongside the legacy STRATEGY_PROFILE selector.
Recommended setup:
- Repository Variables
ENABLE_GITHUB_ENV_SYNC=trueCLOUD_RUN_REGIONCLOUD_RUN_SERVICETELEGRAM_TOKEN_SECRET_NAME(recommended when Cloud Run already uses Secret Manager forTELEGRAM_TOKEN)STRATEGY_PROFILE(set explicitly to one enabled profile, such assoxl_soxx_trend_income)ACCOUNT_GROUP(recommended:paper)IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME- Optional:
IBKR_STRATEGY_PLUGIN_MOUNTS_JSON GLOBAL_TELEGRAM_CHAT_IDNOTIFY_LANG
- Repository Secrets
TELEGRAM_TOKEN(fallback only whenTELEGRAM_TOKEN_SECRET_NAMEis not set)
- Optional transition Variables
IB_GATEWAY_ZONEIB_GATEWAY_IP_MODE
On every push to main, the workflow updates the existing Cloud Run service with the values above and removes legacy env vars that should now live in the account-group config (IB_CLIENT_ID, IB_GATEWAY_INSTANCE_NAME, IB_GATEWAY_MODE) plus the older transport vars (IB_GATEWAY_HOST, IB_GATEWAY_PORT, TELEGRAM_CHAT_ID). If IB_GATEWAY_ZONE or IB_GATEWAY_IP_MODE are blank in GitHub, the workflow also removes them from Cloud Run to avoid drift.
STRATEGY_PROFILE is resolved from a platform capability matrix plus a rollout allowlist derived from runtime_enabled strategy metadata. The current strategy domain is us_equity: eligible means the platform can run the strategy in theory, while enabled means the current rollout really allows it. ACCOUNT_GROUP selects one account-group config entry, and the service fails fast if that runtime identity is incomplete. RUNTIME_TARGET_JSON carries the structured runtime identity; strategy defaults continue to come from UsEquityStrategies.
Important:
- The workflow only becomes strict when
ENABLE_GITHUB_ENV_SYNC=true. If this variable is unset, the sync job is skipped. When enabled, it resolves the selected profile's snapshot/config requirements fromscripts/print_strategy_profile_status.py --jsoninstead of a hard-coded strategy-name list. - Here "shared config" still only means the IBKR pair (
InteractiveBrokersPlatform+IBKRGatewayManager).TELEGRAM_TOKENandTELEGRAM_TOKEN_SECRET_NAMEremain repository-specific. - If
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAMEis set, the Cloud Run runtime needs Secret Manager access to that secret. - GitHub now authenticates to Google Cloud with OIDC + Workload Identity Federation, so
GCP_SA_KEYis no longer required for this workflow. - If you deploy with
gcloud run deploy --sourceor a Cloud Run source trigger, the staging bucketgs://run-sources-<project>-<region>also needsroles/storage.objectViewerfor the build service account, the deploy service account, and the default compute service account. Missing this binding fails the deploy before Cloud Build starts withstorage.objects.getdenied.
QuantPlatformKitis only a shared dependency; Cloud Run now deploysInteractiveBrokersPlatform.- Recommended Cloud Run service name:
interactive-brokers-quant-service. - For future multi-account rollout, keep one Cloud Run service per
ACCOUNT_GROUP, and let each service select its account-group config at runtime. - If you later rename or move this repository, reselect the GitHub source in Cloud Build / Cloud Run trigger instead of assuming the existing source binding will update itself.
- For the shared deployment model and trigger migration checklist, see
QuantPlatformKit/docs/deployment_model.md.
- GCE: Set up IB Gateway (paper or live) on a GCE instance. Ensure API access is enabled, remote clients are allowed when needed, and use
4001forliveor4002forpaper. - VPC / Subnet: Put Cloud Run and GCE in the same VPC. For cleaner firewall rules, reserve a dedicated subnet for Cloud Run Direct VPC egress.
- Cloud Run: Deploy or update this Flask app with Direct VPC egress. Set
STRATEGY_PROFILE,ACCOUNT_GROUP, andIB_ACCOUNT_GROUP_CONFIG_SECRET_NAME. KeepIB_GATEWAY_ZONE/IB_GATEWAY_IP_MODEonly as transition fallbacks if the selected account-group payload does not already contain them. The workflow emitsRUNTIME_TARGET_JSONto describe the structured deployment target. The runtime service account needsroles/secretmanager.secretAccessorand, for instance-name resolution,roles/compute.viewer.- For Cloud Run source deploy, also grant
roles/storage.objectViewerongs://run-sources-${PROJECT_ID}-${REGION}to the build service account, the deploy service account, and${PROJECT_NUMBER}-compute@developer.gserviceaccount.com.
- For Cloud Run source deploy, also grant
- Firewall: Allow TCP
4001(live) or4002(paper) from the Cloud Run egress subnet CIDR to the GCE instance. - Cloud Scheduler: Create a job that POSTs to the Cloud Run URL. Choose the cron from the strategy-layer cadence in
UsEquityStrategies; daily profiles can still use a near-close weekday schedule such as45 15 * * 1-5inAmerica/New_York. - Optional public-IP mode: Only if you cannot use VPC, set
IB_GATEWAY_IP_MODE=external, expose the GCE public IP deliberately, and restrict source ranges tightly. This is not the default path.
Example deploy/update command:
gcloud run deploy interactive-brokers-quant-service \
--source . \
--region us-central1 \
--service-account ibkr-platform-runtime@PROJECT_ID.iam.gserviceaccount.com \
--concurrency 1 \
--max-instances 1 \
--network default \
--subnet cloudrun-direct-egress \
--vpc-egress private-ranges-only \
--set-env-vars STRATEGY_PROFILE=global_etf_rotation,ACCOUNT_GROUP=paper,IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups,GLOBAL_TELEGRAM_CHAT_ID=123456789,NOTIFY_LANG=zhIf the service already exists and your CI only updates source/image, you can patch networking separately:
gcloud run services update ibkr-quant \
--region us-central1 \
--concurrency 1 \
--max-instances 1 \
--network default \
--subnet cloudrun-direct-egress \
--vpc-egress private-ranges-only \
--update-env-vars IB_GATEWAY_IP_MODE=internalIBKR runtime 负责把共享的 us_equity 策略档位部署到 GCP Cloud Run,并连接 GCE 上的 IB Gateway 执行。策略逻辑、策略频率、标的池、参数和研究/回测说明都放在 UsEquityStrategies;这个仓库只维护 IBKR 运行时、账号组、Gateway 连接、下单和通知。
完整策略说明放在 UsEquityStrategies。这个 README 只保留 IBKR 运行时、profile 启用状态、部署和凭据说明。
当前主线运行路径已经统一为:
main.py负责把平台输入组装成StrategyContextstrategy_runtime.py负责加载统一策略入口entrypoint.evaluate(ctx)返回共享的StrategyDecisiondecision_mapper.py再把决策映射成 IBKR 订单、通知和运行时更新
main.py 已经不再直接读取策略私有常量,也不再依赖策略返回里的平台专属字段。
feature-snapshot 类策略使用 UsEquitySnapshotPipelines 发布的上游 artifact。这个运行时只需要 artifact 的位置,例如 IBKR_FEATURE_SNAPSHOT_PATH;策略逻辑、策略频率、特征定义和 snapshot schema 说明放在 UsEquityStrategies / UsEquitySnapshotPipelines。
Cloud Scheduler(cron 以 `UsEquityStrategies` 的策略层频率为准)
↓ HTTP POST
Cloud Run (Flask: 策略计算 + 编排)
↓ 共享平台适配层
QuantPlatformKit (IBKR adapter)
↓ ib_insync TCP
GCE (IB Gateway 常驻)
↓
IBKR 账户
现在 ACCOUNT_GROUP 就是运行身份选择器。broker 侧身份信息应该放在账号组配置 JSON 里,不要继续把这部分主配置塞回 Cloud Run env。
| 变量 | 必需 | 说明 |
|---|---|---|
IB_GATEWAY_ZONE |
可选过渡项 | GCE zone(如 us-central1-a)。推荐直接放进选中的账号组配置里;这里只保留过渡 fallback。 |
IB_GATEWAY_IP_MODE |
可选过渡项 | internal(默认)或 external。推荐直接放进选中的账号组配置里;这里只保留过渡 fallback。 |
IBKR_CONNECT_TIMEOUT_SECONDS |
否 | IB API 握手超时时间,单位秒。默认 60;只有 Gateway 远程 API 启动持续偏慢时才需要调高。 |
IBKR_CONNECT_ATTEMPTS |
否 | IBKR 连接失败前最多尝试次数。默认 3。 |
IBKR_CONNECT_RETRY_DELAY_SECONDS |
否 | IBKR 连接重试间隔,单位秒。默认 5。 |
IBKR_CLIENT_ID_RETRY_OFFSET |
否 | 每次重试时加到 ib_client_id 上的偏移量,用新的 client id 避开超时握手留下的卡住会话。默认 100。 |
STRATEGY_PROFILE |
是 | 策略档位选择。当前可用的 us_equity 值:global_etf_rotation、russell_1000_multi_factor_defensive、tqqq_growth_income、soxl_soxx_trend_income、tech_communication_pullback_enhancement、mega_cap_leader_rotation_top50_balanced |
ACCOUNT_GROUP |
是 | 账号组选择器,每个部署都要显式设置。 |
IBKR_FEATURE_SNAPSHOT_PATH |
条件必填 | russell_1000_multi_factor_defensive、tech_communication_pullback_enhancement、mega_cap_leader_rotation_top50_balanced 等快照策略需要。指向最新特征快照文件(.csv、.json、.jsonl、.parquet)。 |
IBKR_STRATEGY_PLUGIN_MOUNTS_JSON |
否 | 可选的 IBKR 侧策略插件挂载 JSON。插件 artifact 自带模式;平台配置不要设置 mode。 |
IBKR_FRACTIONAL_SHARES_ENABLED |
否 | 默认 false;只有确认当前账户/API 路径支持碎股单后再设为 true。 |
IBKR_ORDER_QUANTITY_STEP |
否 | 显式覆盖下单数量步进;如 1 表示整数股,0.0001 表示碎股数量步进。优先级高于 IBKR_FRACTIONAL_SHARES_ENABLED。 |
IBKR_MIN_ORDER_NOTIONAL_USD |
否 | 碎股买入的最小名义金额;默认 50.0。 |
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME |
Cloud Run 建议必填 | 账号组配置 JSON 在 Secret Manager 里的密钥名。生产环境推荐使用。 |
IB_ACCOUNT_GROUP_CONFIG_JSON |
否 | 本地开发用的账号组配置 JSON fallback。不建议在生产 Cloud Run 直接使用。 |
TELEGRAM_TOKEN |
是 | Telegram 机器人 Token。Cloud Run 上更推荐走 Secret Manager 引用,不要直接写成明文 env。 |
GLOBAL_TELEGRAM_CHAT_ID |
是 | 这个服务使用的 Telegram Chat ID。 |
NOTIFY_LANG |
否 | en(默认)或 zh |
选中的账号组配置里,至少要有:
ib_gateway_instance_nameib_gateway_modeib_client_id
按当前推荐的 Cloud Run 部署方式,最好再一起放上:
ib_gateway_zoneib_gateway_ip_mode(或者直接走默认internal)
如果你配置了 ib_gateway_zone 让程序通过实例名解析内网 IP,Cloud Run runtime service account 需要 roles/compute.viewer。如果账号组配置来源是 Secret Manager,同一个 runtime service account 还需要对 ibkr-account-groups 具备 roles/secretmanager.secretAccessor。
推荐的共享配置模式
当前第一步,建议让 GitHub / Cloud Run 只维护服务级变量:
STRATEGY_PROFILE=soxl_soxx_trend_income
ACCOUNT_GROUP=paper
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups
GLOBAL_TELEGRAM_CHAT_ID=<telegram-chat-id>
NOTIFY_LANG=zh
# 仅作为过渡 fallback:
IB_GATEWAY_ZONE=us-central1-c
IB_GATEWAY_IP_MODE=internal这里说的“共享配置”只针对 IBKR 这一组系统,也就是 InteractiveBrokersPlatform 和 IBKRGatewayManager 之间共享。它不是让所有 quant 仓库都共用一套 secrets。对多个量化仓库来说,通常只有 GLOBAL_TELEGRAM_CHAT_ID 和 NOTIFY_LANG 适合做跨项目共享。
推荐的账号组配置 JSON:
{
"groups": {
"paper": {
"ib_gateway_instance_name": "interactive-brokers-quant-instance",
"ib_gateway_zone": "us-central1-c",
"ib_gateway_mode": "paper",
"ib_gateway_ip_mode": "internal",
"ib_client_id": 1,
"service_name": "interactive-brokers-quant-service",
"account_ids": ["DU1234567"]
}
}
}仓库里也提供了一个可以直接改的起始样例:docs/examples/ibkr-account-groups.paper.json。如果你要按 ACCOUNT_GROUP=paper 先落地,直接看 docs/ibkr_runtime_rollout.md。
实盘多账户建议一个 UID 对应一个 Cloud Run 服务和一个账号组。每个实盘账号组只放一个 account_ids 值;运行时会用它过滤持仓、pending/fill 检查,并把同一个 UID 写进 IBKR 订单的 order.account。
当前行为改成了 fail-fast:
- 没有
STRATEGY_PROFILE→ 启动直接报错 - 没有
ACCOUNT_GROUP→ 启动直接报错 - 没有账号组配置来源 → 启动直接报错
- 选中的账号组缺少关键字段(
ib_gateway_instance_name、ib_gateway_mode、ib_client_id)→ 启动直接报错
如果代码部署继续走 Google Cloud Trigger,但你想把运行时环境变量统一放在 GitHub 管理,这个仓库现在提供了 .github/workflows/sync-cloud-run-env.yml。
推荐配置方式:
- 仓库级 Variables
ENABLE_GITHUB_ENV_SYNC=trueCLOUD_RUN_REGIONCLOUD_RUN_SERVICETELEGRAM_TOKEN_SECRET_NAME(如果 Cloud Run 上的TELEGRAM_TOKEN已经改成 Secret Manager,建议配置)STRATEGY_PROFILE(显式设置为任一已启用 profile,例如soxl_soxx_trend_income)ACCOUNT_GROUP(建议设为paper)IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME- 可选:
IBKR_STRATEGY_PLUGIN_MOUNTS_JSON GLOBAL_TELEGRAM_CHAT_IDNOTIFY_LANG
- 仓库级 Secrets
TELEGRAM_TOKEN(仅在没设置TELEGRAM_TOKEN_SECRET_NAME时作为 fallback)
- 可选过渡 Variables
IB_GATEWAY_ZONEIB_GATEWAY_IP_MODE
每次 push 到 main 时,这个 workflow 会把上面这些值同步到现有 Cloud Run 服务里,并清掉已经转移到账号组配置里的旧 env(IB_CLIENT_ID、IB_GATEWAY_INSTANCE_NAME、IB_GATEWAY_MODE)以及更早的传输层 env(IB_GATEWAY_HOST、IB_GATEWAY_PORT、TELEGRAM_CHAT_ID)。如果 GitHub 里没有配置 IB_GATEWAY_ZONE 或 IB_GATEWAY_IP_MODE,workflow 也会把 Cloud Run 上这两个旧值一起删除,避免双配置源漂移。
STRATEGY_PROFILE 由平台能力矩阵和从 runtime_enabled 策略元数据派生的 rollout allowlist 一起决定。当前策略域仍是 us_equity:eligible 表示平台理论上能跑,enabled 表示当前 rollout 真正放开。ACCOUNT_GROUP 是严格必填项,并会选中一份账号组配置。运行身份不完整时,服务会直接失败,不再静默回退。
注意:
- 只有在
ENABLE_GITHUB_ENV_SYNC=true时,这个 workflow 才会严格校验并执行同步。没打开时会直接跳过。打开后,它会通过scripts/print_strategy_profile_status.py --json动态解析目标策略需要的 snapshot/config 输入,不再维护硬编码策略名列表。 - 这里说的“共享配置”仍然只针对 IBKR 这一组系统。
TELEGRAM_TOKEN和TELEGRAM_TOKEN_SECRET_NAME都还是这个仓库自己的配置,不建议提升成所有 quant 共用的全局配置。 - 如果设置了
IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME,Cloud Run 运行时还需要有对应 Secret 的访问权限。 - GitHub 现在通过 OIDC + Workload Identity Federation 登录 Google Cloud,这个 workflow 不再需要
GCP_SA_KEY。 - 如果你用
gcloud run deploy --source或 Cloud Run source trigger 部署,还要给 staging bucketgs://run-sources-<project>-<region>补roles/storage.objectViewer,对象包括 build service account、deploy service account、默认 compute service account。少了这层权限,会在 Cloud Build 启动前直接报storage.objects.get denied。
QuantPlatformKit只是共享依赖,不单独部署;Cloud Run 现在部署的是InteractiveBrokersPlatform。- 推荐 Cloud Run 服务名:
interactive-brokers-quant-service。 - 后续如果扩到多账户,建议按
ACCOUNT_GROUP拆成多个 Cloud Run 服务,并让每个服务在运行时选中自己的账号组配置。 - 如果后面改 GitHub 仓库名或再次迁组织,Cloud Build / Cloud Run 里的 GitHub 来源需要重新选择,不要假设旧绑定会自动跟过去。
- 统一部署模型和触发器迁移清单见
QuantPlatformKit/docs/deployment_model.md。
- GCE: 部署 IB Gateway(模拟或实盘),确认 API 已开启、需要远程连接时已允许非 localhost 客户端,并确认
live使用4001、paper使用4002。 - VPC / 子网: 让 Cloud Run 和 GCE 处于同一个 VPC。为了让防火墙规则更干净,建议给 Cloud Run Direct VPC egress 单独准备一个子网。
- Cloud Run: 部署此 Flask 应用时启用 Direct VPC egress。设置
STRATEGY_PROFILE、ACCOUNT_GROUP、IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME;只有在账号组配置里还没放ib_gateway_zone/ib_gateway_ip_mode时,才临时保留IB_GATEWAY_ZONE/IB_GATEWAY_IP_MODE作为过渡 fallback。runtime service account 需要roles/secretmanager.secretAccessor,若走实例名解析,还需要roles/compute.viewer。- 如果使用 Cloud Run source deploy,还要给
gs://run-sources-${PROJECT_ID}-${REGION}这个 bucket 授权roles/storage.objectViewer,对象是 build service account、deploy service account,以及${PROJECT_NUMBER}-compute@developer.gserviceaccount.com。
- 如果使用 Cloud Run source deploy,还要给
- 防火墙: 只允许 Cloud Run 出口子网访问 GCE 的
TCP 4001(live)或TCP 4002(paper)。 - Cloud Scheduler: 创建定时任务,POST 到 Cloud Run URL。cron 频率以
UsEquityStrategies里的策略层 cadence 为准;日频 profile 仍可使用美股临近收盘的工作日计划,例如45 15 * * 1-5(America/New_York 时区)。 - 可选公网模式: 只有在不能走 VPC 时,才设置
IB_GATEWAY_IP_MODE=external,并且要明确开放 GCE 公网 IP,同时严格限制来源 IP 和防火墙规则。
示例部署命令:
gcloud run deploy interactive-brokers-quant-service \
--source . \
--region us-central1 \
--service-account ibkr-platform-runtime@PROJECT_ID.iam.gserviceaccount.com \
--concurrency 1 \
--max-instances 1 \
--network default \
--subnet cloudrun-direct-egress \
--vpc-egress private-ranges-only \
--set-env-vars STRATEGY_PROFILE=global_etf_rotation,ACCOUNT_GROUP=paper,IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME=ibkr-account-groups,GLOBAL_TELEGRAM_CHAT_ID=123456789,NOTIFY_LANG=zh如果服务已经存在,而你们的 CI 只是更新代码/镜像,可以单独补一次网络配置:
gcloud run services update ibkr-quant \
--region us-central1 \
--concurrency 1 \
--max-instances 1 \
--network default \
--subnet cloudrun-direct-egress \
--vpc-egress private-ranges-only \
--update-env-vars IB_GATEWAY_IP_MODE=internal