|
| 1 | +# US equity cross-platform strategy spec |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +All US equity strategies should be written once and be portable across the three |
| 6 | +current broker runtimes: |
| 7 | + |
| 8 | +- `ibkr` |
| 9 | +- `schwab` |
| 10 | +- `longbridge` |
| 11 | + |
| 12 | +This document defines the contract new strategies must follow, and the migration |
| 13 | +target existing strategies should converge to. |
| 14 | + |
| 15 | +## Scope |
| 16 | + |
| 17 | +This spec applies to: |
| 18 | + |
| 19 | +- `QuantPlatformKit` |
| 20 | +- `UsEquityStrategies` |
| 21 | +- the US equity runtime repositories that consume them |
| 22 | + |
| 23 | +It does **not** define broker authentication, Cloud Run wiring, scheduler |
| 24 | +behavior, or Telegram wording beyond the shared runtime contract. |
| 25 | + |
| 26 | +## Design rule |
| 27 | + |
| 28 | +Strategy code must stay platform-agnostic. |
| 29 | + |
| 30 | +In practice that means: |
| 31 | + |
| 32 | +1. strategy repos declare required inputs and strategy metadata |
| 33 | +2. platform repos build those inputs from broker/runtime data |
| 34 | +3. strategy repos return a standard `StrategyDecision` |
| 35 | +4. platform repos translate the resulting `AllocationIntent` into broker-native |
| 36 | + execution |
| 37 | + |
| 38 | +Strategy code must not branch on broker platform. |
| 39 | + |
| 40 | +## Mandatory layers |
| 41 | + |
| 42 | +### 1. Strategy definition layer |
| 43 | + |
| 44 | +Each US equity profile must declare: |
| 45 | + |
| 46 | +- canonical profile name |
| 47 | +- display metadata |
| 48 | +- `target_mode` |
| 49 | +- `required_inputs` |
| 50 | +- supported platforms |
| 51 | +- entrypoint definition |
| 52 | + |
| 53 | +### 2. Runtime adapter layer |
| 54 | + |
| 55 | +Each supported platform must expose a `StrategyRuntimeAdapter` for that profile. |
| 56 | + |
| 57 | +The adapter may define: |
| 58 | + |
| 59 | +- available inputs |
| 60 | +- available capabilities |
| 61 | +- portfolio input name |
| 62 | +- artifact validation expectations |
| 63 | +- temporary migration metadata |
| 64 | + |
| 65 | +The adapter must **not** leak broker order sequencing back into strategy logic. |
| 66 | + |
| 67 | +### 3. Platform input builder layer |
| 68 | + |
| 69 | +Platforms are responsible for assembling normalized inputs. Strategy code only |
| 70 | +consumes the normalized inputs it asked for. |
| 71 | + |
| 72 | +### 4. Execution translation layer |
| 73 | + |
| 74 | +Platforms must translate the unified allocation intent into their own native |
| 75 | +execution style: |
| 76 | + |
| 77 | +- `ibkr`: native `weight` |
| 78 | +- `schwab`: native `value` |
| 79 | +- `longbridge`: native `value` |
| 80 | + |
| 81 | +Strategies must not implement broker-specific execution transforms themselves. |
| 82 | + |
| 83 | +## Canonical required inputs |
| 84 | + |
| 85 | +New US equity strategies must choose from this canonical input vocabulary: |
| 86 | + |
| 87 | +- `market_history` |
| 88 | +- `benchmark_history` |
| 89 | +- `portfolio_snapshot` |
| 90 | +- `derived_indicators` |
| 91 | +- `feature_snapshot` |
| 92 | + |
| 93 | +Current legacy input names may still exist during migration, but new profiles |
| 94 | +should use the canonical names from day one. Platform repos may keep temporary |
| 95 | +mapping shims until all live profiles are migrated. |
| 96 | + |
| 97 | +### Input intent |
| 98 | + |
| 99 | +- `market_history`: broad instrument history used for ranking, rotation, or risk |
| 100 | + checks |
| 101 | +- `benchmark_history`: dedicated benchmark history such as `QQQ` or `SPY` |
| 102 | +- `portfolio_snapshot`: current holdings, cash, market value, and account state |
| 103 | +- `derived_indicators`: precomputed regime or indicator bundle owned by the |
| 104 | + platform runtime |
| 105 | +- `feature_snapshot`: validated artifact-backed cross-sectional feature dataset |
| 106 | + |
| 107 | +## Strategy outputs |
| 108 | + |
| 109 | +US equity strategies must return: |
| 110 | + |
| 111 | +- `StrategyDecision` |
| 112 | +- `AllocationIntent` derived from that decision |
| 113 | + |
| 114 | +Broker-specific order payloads, notification rows, UI layout fields, and service |
| 115 | +state writes must stay in the platform repository. |
| 116 | + |
| 117 | +### Target mode |
| 118 | + |
| 119 | +Each strategy must declare exactly one `target_mode`: |
| 120 | + |
| 121 | +- `weight` |
| 122 | +- `value` |
| 123 | + |
| 124 | +Mixed output modes inside one profile are not allowed. |
| 125 | + |
| 126 | +The strategy picks the semantic target mode. Platform repos are responsible for |
| 127 | +translating that mode when their native execution model differs. |
| 128 | + |
| 129 | +## Artifact contract |
| 130 | + |
| 131 | +If a strategy depends on artifacts such as feature snapshots, it must declare a |
| 132 | +stable contract: |
| 133 | + |
| 134 | +- artifact type |
| 135 | +- schema version |
| 136 | +- freshness rule |
| 137 | +- optional manifest/checksum rule |
| 138 | + |
| 139 | +The platform runtime owns: |
| 140 | + |
| 141 | +- artifact transport |
| 142 | +- artifact storage path or URI |
| 143 | +- freshness validation |
| 144 | +- runtime injection into `StrategyContext` |
| 145 | + |
| 146 | +The strategy layer must not assume broker-local files or service-specific paths. |
| 147 | + |
| 148 | +## Three-platform support rule |
| 149 | + |
| 150 | +For new US equity strategy profiles, the default expectation is: |
| 151 | + |
| 152 | +- `ibkr` adapter present |
| 153 | +- `schwab` adapter present |
| 154 | +- `longbridge` adapter present |
| 155 | + |
| 156 | +If one platform is intentionally unsupported, the PR must include an explicit |
| 157 | +reason and the profile must remain `eligible=false` there until the gap is |
| 158 | +closed. |
| 159 | + |
| 160 | +## Eligible vs enabled |
| 161 | + |
| 162 | +These two states must stay separate: |
| 163 | + |
| 164 | +- `eligible`: the platform can run the profile in theory |
| 165 | +- `enabled`: the current rollout actually turns it on |
| 166 | + |
| 167 | +Eligibility should be derived from the contract: |
| 168 | + |
| 169 | +- domain match |
| 170 | +- target mode support or translation support |
| 171 | +- required inputs available |
| 172 | +- runtime adapter present |
| 173 | +- capability requirements met |
| 174 | + |
| 175 | +Rollout allowlists should only control `enabled`. |
| 176 | + |
| 177 | +## Definition of done for a new strategy |
| 178 | + |
| 179 | +A new US equity strategy is not ready until it has: |
| 180 | + |
| 181 | +1. metadata and canonical profile registration |
| 182 | +2. manifest and entrypoint |
| 183 | +3. explicit `target_mode` |
| 184 | +4. canonical `required_inputs` |
| 185 | +5. runtime adapters for the intended platforms |
| 186 | +6. allocation-contract tests |
| 187 | +7. platform adapter tests |
| 188 | +8. at least one dry-run smoke path per enabled platform |
| 189 | + |
| 190 | +## Review checklist |
| 191 | + |
| 192 | +Reviewers should reject a new strategy PR if any of these are true: |
| 193 | + |
| 194 | +- strategy code branches on platform id |
| 195 | +- strategy code reads broker env vars directly |
| 196 | +- strategy output includes broker-specific order fields |
| 197 | +- a new ad-hoc required input name is introduced without updating this spec |
| 198 | +- `target_mode` is missing or mixed |
| 199 | +- artifact-dependent logic skips schema or freshness checks |
| 200 | + |
| 201 | +## Migration notes for current profiles |
| 202 | + |
| 203 | +Current live profiles can migrate incrementally, but the end state should be: |
| 204 | + |
| 205 | +- `global_etf_rotation`: portable through normalized history inputs plus |
| 206 | + weight/value translation |
| 207 | +- `hybrid_growth_income`: portable through benchmark/portfolio inputs plus |
| 208 | + value/weight translation |
| 209 | +- `semiconductor_rotation_income`: portable through indicator/account-state |
| 210 | + inputs plus value/weight translation |
| 211 | +- `russell_1000_multi_factor_defensive`: portable through standardized |
| 212 | + `feature_snapshot` artifact delivery |
| 213 | +- `tech_pullback_cash_buffer`: portable through standardized `feature_snapshot` |
| 214 | + artifact delivery |
| 215 | + |
| 216 | +New profiles should target the end state immediately instead of adding more |
| 217 | +one-off runtime contracts. |
0 commit comments