Skip to content

Commit 20bf717

Browse files
committed
Refine runtime target compatibility and validation
1 parent e6c6149 commit 20bf717

24 files changed

Lines changed: 1236 additions & 268 deletions

docs/deployment_model.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
- `QuantPlatformKit` remains the shared platform package and is **not deployed as a runtime service**.
66
- The current runtime repositories (`InteractiveBrokersPlatform`, `CharlesSchwabPlatform`, `LongBridgePlatform`, `BinancePlatform`) are the **transitional deployment units**.
7-
- The **target state** is one deployment repository per broker platform, with strategy behavior selected by configuration such as `STRATEGY_PROFILE`.
7+
- The **target state** is one deployment repository per broker platform, with strategy behavior selected through `RuntimeTarget` / `RUNTIME_TARGET_JSON` and compatibility selectors such as `STRATEGY_PROFILE`.
88
- Strategy or platform repositories should always depend on a fixed `QuantPlatformKit` Git tag instead of `main`.
99

1010
For the live runtime inventory across repositories, projects, services, schedulers, runtime identities, and current secret names, see [`platform_runtime_inventory.md`](./platform_runtime_inventory.md).
@@ -13,6 +13,8 @@ For a cleaner split between shared package code, platform runtime repositories,
1313

1414
For the platform / strategy-domain / configurable-profile matrix, see [`platform_strategy_matrix.md`](./platform_strategy_matrix.md).
1515

16+
For the runtime-target-first control-plane design, see [`runtime_target_architecture.md`](./runtime_target_architecture.md).
17+
1618
## Current state vs target state
1719

1820
### Current transitional state
@@ -149,10 +151,12 @@ Within one broker platform repository, selecting a strategy by configuration is
149151

150152
Recommended selector:
151153

152-
- `STRATEGY_PROFILE`
154+
- `RUNTIME_TARGET_JSON` for structured runtime identity
155+
- `STRATEGY_PROFILE` for compatibility with existing strategy routing
153156

154157
Good examples:
155158

159+
- `RUNTIME_TARGET_JSON={"platform_id":"longbridge",...}`
156160
- `STRATEGY_PROFILE=rotation`
157161
- `STRATEGY_PROFILE=income`
158162
- `STRATEGY_PROFILE=hybrid`
@@ -171,6 +175,7 @@ IBKR should support multiple accounts or account groups under one platform repos
171175

172176
Recommended configuration boundary:
173177

178+
- `RUNTIME_TARGET_JSON`
174179
- `STRATEGY_PROFILE`
175180
- `ACCOUNT_GROUP` or `IB_ACCOUNT_SET`
176181
- `IB_CLIENT_ID` or a deterministic `IB_CLIENT_ID_BASE`
@@ -196,6 +201,7 @@ LongBridge should keep:
196201

197202
The split should always be defined by runtime configuration:
198203

204+
- `RUNTIME_TARGET_JSON`
199205
- `ACCOUNT_REGION=HK|SG`
200206
- `ACCOUNT_PREFIX`
201207
- `SERVICE_NAME`
@@ -213,7 +219,8 @@ Charles Schwab can stay simpler:
213219

214220
- one platform repository
215221
- one or more services only when strategy profiles truly differ
216-
- `STRATEGY_PROFILE` is already part of the current runtime shape
222+
- `RUNTIME_TARGET_JSON` is part of the current runtime shape
223+
- `STRATEGY_PROFILE` remains the compatibility selector
217224

218225
### Binance
219226

@@ -230,7 +237,7 @@ If you rename a repository or move it under a different owner, Cloud Build and C
230237
Recommended migration order:
231238

232239
1. align every runtime repository to the same `QuantPlatformKit` tag
233-
2. finish the platform runtime configuration shape (`STRATEGY_PROFILE`, `ACCOUNT_GROUP`, `ACCOUNT_REGION`, `SERVICE_NAME`)
240+
2. finish the platform runtime configuration shape (`RUNTIME_TARGET_JSON`, `STRATEGY_PROFILE`, `ACCOUNT_GROUP`, `ACCOUNT_REGION`, `SERVICE_NAME`)
234241
3. create or update the new trigger against the target repository
235242
4. confirm the branch is still `main`
236243
5. confirm the target service and region
@@ -262,6 +269,6 @@ Rename affects:
262269

263270
- platform code lives in `QuantPlatformKit`
264271
- one broker platform should map to one deployable runtime repository
265-
- strategy selection can happen inside one broker platform via config like `STRATEGY_PROFILE`
272+
- strategy selection can happen inside one broker platform via config like `RUNTIME_TARGET_JSON` and `STRATEGY_PROFILE`
266273
- LongBridge HK/SG and IBKR multi-account should be modeled as service or trigger splits, not broker-mixing logic
267274
- versions are managed with fixed tags

docs/platform_repo_boundaries.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ The codebase is in a transitional state, so this document is meant to answer a s
1414
1515
For the platform / strategy-domain / configurable-profile matrix, see [`platform_strategy_matrix.md`](./platform_strategy_matrix.md).
1616

17+
For the runtime-target-first architecture and the Bridge / Adapter split, see [`runtime_target_architecture.md`](./runtime_target_architecture.md).
18+
1719
## 1. `QuantPlatformKit`
1820

1921
`QuantPlatformKit` is the shared dependency.
@@ -28,6 +30,7 @@ It should own:
2830
- strategy domain
2931
- strategy profile definition
3032
- platform compatibility rules
33+
- `RuntimeTarget` / `RuntimeAssembly` bridge objects
3134

3235
It should **not** own:
3336

@@ -75,7 +78,9 @@ When a runtime already has a controlled cutover window, prefer removing the old
7578
flat callable entrypoint entirely instead of carrying both shapes in parallel.
7679
Keeping `runtime/config` and legacy one-off call signatures alive at the same
7780
time usually leaks compatibility branches back into execution and notification
78-
code.
81+
code. The shared `RuntimeTarget` / `RuntimeAssembly` bridge exists so
82+
entrypoints can stay thin while runtime identity still flows through logs,
83+
reports, and deployment metadata.
7984

8085
When a dependency already matches a shared interface, entrypoints should adapt
8186
it to the shared port first, for example:

docs/platform_runtime_inventory.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,21 @@ For the platform / strategy-domain / configurable-profile matrix, see [`platform
1616
- GitHub Variables remain the control plane for:
1717
- service names
1818
- regions
19-
- strategy selectors such as `STRATEGY_PROFILE`
19+
- structured runtime selectors such as `RUNTIME_TARGET_JSON`
20+
- compatibility strategy selectors such as `STRATEGY_PROFILE`
2021
- secret selector variables such as `*_SECRET_NAME`
2122
- Secret Manager is the runtime source of truth for sensitive values that Cloud Run services actually consume.
2223
- The US equity Cloud Run env-sync workflows use GitHub OIDC + Workload Identity Federation. `GCP_SA_KEY` is not required for those workflows.
2324
- GitHub Secrets can remain as temporary runtime fallbacks where migration is not fully finished.
2425

2526
## Runtime inventory
2627

27-
| Platform | Repo | Strategy domain | Strategy selector | Runtime model | Project / backend | Runtime unit |
28-
|---|---|---:|---|---|---|---|
29-
| IBKR | `QuantStrategyLab/InteractiveBrokersPlatform` | `us_equity` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | configurable |
30-
| Schwab | `QuantStrategyLab/CharlesSchwabPlatform` | `us_equity` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | `charlesschwabquant` | `charles-schwab-quant-service` |
31-
| LongBridge | `QuantStrategyLab/LongBridgePlatform` | `us_equity` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | configurable |
32-
| Binance | `QuantStrategyLab/BinancePlatform` | `crypto` | `STRATEGY_PROFILE=crypto_leader_rotation` | Oracle Cloud + self-hosted runner | `binancequant` only for Firestore / GCP credentials | GitHub Actions `workflow_dispatch` + self-hosted runner |
28+
| Platform | Repo | Strategy domain | Runtime identity | Strategy selector | Runtime model | Project / backend | Runtime unit |
29+
|---|---|---:|---|---|---|---|---|
30+
| IBKR | `QuantStrategyLab/InteractiveBrokersPlatform` | `us_equity` | `RUNTIME_TARGET_JSON` + `ACCOUNT_GROUP` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | configurable |
31+
| Schwab | `QuantStrategyLab/CharlesSchwabPlatform` | `us_equity` | `RUNTIME_TARGET_JSON` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | `charlesschwabquant` | `charles-schwab-quant-service` |
32+
| LongBridge | `QuantStrategyLab/LongBridgePlatform` | `us_equity` | `RUNTIME_TARGET_JSON` + `ACCOUNT_REGION` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | configurable |
33+
| Binance | `QuantStrategyLab/BinancePlatform` | `crypto` | `RUNTIME_TARGET_JSON` (workflow-local) | `STRATEGY_PROFILE=crypto_leader_rotation` | Oracle Cloud + self-hosted runner | `binancequant` only for Firestore / GCP credentials | GitHub Actions `workflow_dispatch` + self-hosted runner |
3334

3435
## Platform details
3536

docs/platform_strategy_matrix.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ For strategy behavior, research status, and archived backtest evidence, see
1818
- There are currently two strategy domains:
1919
- `us_equity`
2020
- `crypto`
21-
- Runtime repositories already expose `STRATEGY_PROFILE`, but this is **not** a full multi-strategy marketplace yet.
21+
- Runtime repositories now expose `RUNTIME_TARGET_JSON` plus `STRATEGY_PROFILE`; this is **not** a full multi-strategy marketplace yet.
2222
- Today, each US equity platform can switch among the `runtime_enabled` `us_equity` profiles published by `UsEquityStrategies`, subject to each platform's rollout configuration.
2323
- Platform runtime adapters are generated from strategy input/target-mode declarations plus platform capabilities, so new in-contract profiles should not need per-platform allowlist edits.
2424
- The shared contract is in `QuantPlatformKit`; real `us_equity` strategy implementations now live in `UsEquityStrategies`, while platform repositories own runtime adapters and broker execution.
2525

2626
## Platform matrix
2727

28-
| Platform | Repo | Strategy domain | Configurable profile scope | Runtime model | Real switching today? |
29-
|---|---|---|---|---|---|
30-
| IBKR | `QuantStrategyLab/InteractiveBrokersPlatform` | `us_equity` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | Yes - controlled by platform rollout config |
31-
| Charles Schwab | `QuantStrategyLab/CharlesSchwabPlatform` | `us_equity` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | Yes - controlled by platform rollout config |
32-
| LongBridge | `QuantStrategyLab/LongBridgePlatform` | `us_equity` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` per regional service | Cloud Run | Yes - controlled by platform rollout config |
33-
| Binance | `QuantStrategyLab/BinancePlatform` | `crypto` | `crypto_leader_rotation` | Oracle Cloud + self-hosted runner | No - only this profile is supported today |
28+
| Platform | Repo | Strategy domain | Runtime identity | Configurable profile scope | Runtime model | Real switching today? |
29+
|---|---|---|---|---|---|---|
30+
| IBKR | `QuantStrategyLab/InteractiveBrokersPlatform` | `us_equity` | `RUNTIME_TARGET_JSON` + `ACCOUNT_GROUP` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | Yes - controlled by platform rollout config |
31+
| Charles Schwab | `QuantStrategyLab/CharlesSchwabPlatform` | `us_equity` | `RUNTIME_TARGET_JSON` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` | Cloud Run | Yes - controlled by platform rollout config |
32+
| LongBridge | `QuantStrategyLab/LongBridgePlatform` | `us_equity` | `RUNTIME_TARGET_JSON` + `ACCOUNT_REGION` | `STRATEGY_PROFILE=<runtime_enabled us_equity profile>` per regional service | Cloud Run | Yes - controlled by platform rollout config |
33+
| Binance | `QuantStrategyLab/BinancePlatform` | `crypto` | `RUNTIME_TARGET_JSON` (workflow-local) | `crypto_leader_rotation` | Oracle Cloud + self-hosted runner | No - only this profile is supported today |
3434

3535
## What this means right now
3636

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# Runtime Target Architecture
2+
3+
## Goal
4+
5+
Make runtime selection explicit and stable across platforms by separating:
6+
7+
- strategy selection
8+
- platform selection
9+
- account selection
10+
- deployment mode
11+
12+
`STRATEGY_PROFILE` still exists as a compatibility selector, but the running service is now described primarily by `RuntimeTarget` and `RuntimeAssembly`.
13+
14+
## Core idea
15+
16+
The shared control-plane object is `RuntimeTarget`.
17+
18+
It answers:
19+
20+
- which platform is this?
21+
- which strategy implementation is selected?
22+
- is this paper or live?
23+
- which deployment selector is active?
24+
- which account selector is active?
25+
- which service is this bound to?
26+
27+
The runtime target should flow through:
28+
29+
- GitHub env sync
30+
- Cloud Run env
31+
- runtime logs
32+
- reports
33+
- deployment previews
34+
35+
`RuntimeAssembly` is the internal bridge object that carries the deployment identity plus the runtime target into logging, reporting, and platform wiring.
36+
37+
## Design patterns used
38+
39+
### Strategy
40+
41+
`strategy_profile` selects the strategy behavior:
42+
43+
- signal generation
44+
- universe
45+
- cadence
46+
- sizing rules
47+
48+
It must not own broker selection or deployment identity.
49+
50+
### Bridge
51+
52+
Platform and strategy evolve independently.
53+
54+
- strategy axis: `global_etf_rotation`, `tqqq_growth_income`, ...
55+
- platform axis: LongBridge, IBKR, Schwab, PaperSignal
56+
57+
`RuntimeTarget` is the bridge payload that keeps those axes separate.
58+
59+
### Adapter
60+
61+
Each platform still adapts unified ports to broker-specific APIs:
62+
63+
- `ExecutionPort`
64+
- `PortfolioPort`
65+
- `MarketDataPort`
66+
- notification/report adapters
67+
68+
Platform differences stay at the edge.
69+
70+
### Abstract Factory
71+
72+
A runtime factory assembles a runnable service from `RuntimeTarget` and `RuntimeAssembly`:
73+
74+
- runtime config
75+
- broker adapter
76+
- reporting adapter
77+
- notification adapter
78+
- capability validation
79+
80+
### Template Method
81+
82+
GitHub sync and runtime startup follow the same high-level flow:
83+
84+
1. resolve inputs
85+
2. resolve capability
86+
3. build runtime target
87+
4. sync env
88+
5. start service
89+
6. emit report
90+
91+
### Facade
92+
93+
External callers should prefer a small surface:
94+
95+
- `runtime_target`
96+
- `strategy_profile` for compatibility
97+
98+
Do not leak broker-specific wiring into external deployment steps.
99+
100+
## Target module split
101+
102+
### Shared package
103+
104+
`QuantPlatformKit`
105+
106+
Owns:
107+
108+
- `RuntimeTarget`
109+
- runtime config helpers
110+
- shared ports and adapters
111+
- runtime report helpers
112+
- strategy contracts
113+
114+
### Platform runtime repository
115+
116+
Example repositories:
117+
118+
- `LongBridgePlatform`
119+
- `InteractiveBrokersPlatform`
120+
- `CharlesSchwabPlatform`
121+
122+
Own:
123+
124+
- runtime entrypoints
125+
- platform adapters
126+
- deployment sync scripts
127+
- account selection and secret wiring
128+
- platform-specific reporting text
129+
130+
### Strategy repository
131+
132+
Future shared strategy repositories should own:
133+
134+
- reusable strategy math
135+
- platform-independent signal logic
136+
- domain parameters
137+
138+
They should not own:
139+
140+
- Cloud Run entrypoints
141+
- broker auth
142+
- scheduler wiring
143+
- deployment secrets
144+
145+
## RuntimeTarget invariants
146+
147+
- `strategy_profile` is still required for compatibility and strategy routing.
148+
- `platform_id` is required.
149+
- `dry_run_only` determines `execution_mode`.
150+
- `account_selector` is optional and platform-dependent.
151+
- `account_scope` is optional and may mirror region or account-group semantics.
152+
- `service_name` is a deployment identity, not a strategy concept.
153+
154+
## Platform-specific account rules
155+
156+
### LongBridge
157+
158+
- split by region
159+
- `account_scope` can mirror `HK` / `SG`
160+
- `deployment_selector` should reflect the active region
161+
- one service per region is the target shape
162+
163+
### IBKR
164+
165+
- split by account group
166+
- `account_selector` may contain one or more IB account identifiers
167+
- `ACCOUNT_GROUP` stays as the external runtime selector
168+
169+
### Schwab
170+
171+
- typically one service identity
172+
- `account_selector` may stay empty
173+
- `STRATEGY_PROFILE` remains the compatibility selector, not the main control plane
174+
175+
### PaperSignal
176+
177+
- paper/live is controlled by `dry_run_only`
178+
- strategy identity still flows through the same `RuntimeTarget`
179+
180+
## Migration sequence
181+
182+
1. keep `STRATEGY_PROFILE` working
183+
2. emit `RuntimeTarget` in runtime settings and reports
184+
3. emit `RUNTIME_TARGET_JSON` in GitHub env sync
185+
4. move docs and previews to runtime-target-first wording
186+
5. keep `strategy_profile` only as internal compatibility input
187+
6. keep `RuntimeAssembly` as the internal bridge for entrypoints and reports
188+
7. extract more shared orchestration once the target model is stable
189+
190+
## Practical rule
191+
192+
If a piece of code answers:
193+
194+
- "which broker runtime is this?"
195+
- "which account or region is active?"
196+
- "is this paper or live?"
197+
198+
then it belongs in the runtime target / runtime config layer, not in strategy code.

0 commit comments

Comments
 (0)