|
| 1 | +# QuantStrategyLab Architecture |
| 2 | + |
| 3 | +> Investing involves risk. This document describes system architecture only, not investment advice. |
| 4 | +
|
| 5 | +## Layer Model |
| 6 | + |
| 7 | +``` |
| 8 | +┌─────────────────────────────────────────────────────────┐ |
| 9 | +│ EXECUTION LAYER │ |
| 10 | +│ SchwabPlatform │ IBKRPlatform │ LongBridgePlatform │ |
| 11 | +│ BinancePlatform │ FirstradePlatform │ |
| 12 | +│ (Cloud Run) │ (Cloud Run) │ (GitHub Actions+VPS) │ |
| 13 | +├─────────────────────────────────────────────────────────┤ |
| 14 | +│ STRATEGY LAYER │ |
| 15 | +│ UsEquityStrategies │ HkEquityStrategies │ |
| 16 | +│ CnEquityStrategies │ CryptoStrategies │ |
| 17 | +│ QuantUsComboStrategies │ QuantHkComboStrategies │ |
| 18 | +│ (pip wheels, version-pinned in requirements.txt) │ |
| 19 | +├─────────────────────────────────────────────────────────┤ |
| 20 | +│ SNAPSHOT LAYER │ |
| 21 | +│ UsEquitySnapshotPipelines │ HkEquitySnapshotPipelines │ |
| 22 | +│ CnEquitySnapshotPipelines │ CryptoLivePoolPipelines │ |
| 23 | +│ (GCS artifacts, consumed by execution layer) │ |
| 24 | +├─────────────────────────────────────────────────────────┤ |
| 25 | +│ INFRASTRUCTURE LAYER │ |
| 26 | +│ QuantPlatformKit │ QuantRuntimeSettings │ |
| 27 | +│ QuantStrategyPlugins │ MarketSignalSources │ |
| 28 | +│ (shared contracts, adapters, runtime tooling) │ |
| 29 | +└─────────────────────────────────────────────────────────┘ |
| 30 | +``` |
| 31 | + |
| 32 | +## Data Flow |
| 33 | + |
| 34 | +``` |
| 35 | +Strategy Definition (pip package) |
| 36 | + → Strategy Catalog (STRATEGY_CATALOG) |
| 37 | + → Platform Capability Matrix (can this platform run it?) |
| 38 | + → Snapshot Pipeline (generates artifacts → GCS) |
| 39 | + → Runtime Adapter (loads strategy entrypoint) |
| 40 | + → Platform Execution (fetch data → compute → submit orders) |
| 41 | + → Execution Report (GCS + structured log) |
| 42 | + → Monitor Dispatch (probe + dry-run checks) |
| 43 | +``` |
| 44 | + |
| 45 | +## Configuration Single Source of Truth |
| 46 | + |
| 47 | +Every platform service has ONE canonical config entry-point: |
| 48 | + |
| 49 | +``` |
| 50 | +RUNTIME_TARGET_JSON = { |
| 51 | + "platform_id": "...", |
| 52 | + "strategy_profile": "...", |
| 53 | + "execution_mode": "live" | "paper", |
| 54 | + "dry_run_only": true | false, |
| 55 | + "account_scope": "...", |
| 56 | + "scheduler": { |
| 57 | + "main_time": "45 15 * * *", |
| 58 | + "precheck_time": "45 9 * * *", |
| 59 | + "probe_time": "35 9,15 * * *", |
| 60 | + "timezone": "America/New_York" |
| 61 | + } |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +**All other config values that reference strategy/platform names derive from this.** The auto-sync layer (config-sync) corrects stale references on startup. |
| 66 | + |
| 67 | +## Design Patterns |
| 68 | + |
| 69 | +### 1. Strategy Registry Pattern |
| 70 | + |
| 71 | +Each platform has a `strategy_registry.py` that: |
| 72 | +- Imports shared strategy catalogs from pip packages |
| 73 | +- Merges multiple catalogs (US + HK + Combo) |
| 74 | +- Filters strategies through a capability matrix |
| 75 | +- Routes to the correct runtime adapter |
| 76 | + |
| 77 | +``` |
| 78 | +profile → domain check → adapter lookup → StrategyRuntimeAdapter |
| 79 | +``` |
| 80 | + |
| 81 | +### 2. Runtime Adapter Pattern |
| 82 | + |
| 83 | +Every strategy exposes a `StrategyRuntimeAdapter` via `get_platform_runtime_adapter(profile, platform_id)`. The adapter declares: |
| 84 | +- `available_inputs` — what data the strategy needs |
| 85 | +- `managed_symbols_extractor` — symbols to monitor |
| 86 | +- `runtime_policy` — execution timing contract |
| 87 | + |
| 88 | +### 3. Config Auto-Sync Pattern |
| 89 | + |
| 90 | +At module load time, the `config-sync` layer: |
| 91 | +1. Reads `STRATEGY_PROFILE` from `RUNTIME_TARGET_JSON` |
| 92 | +2. Scans plugin mount JSON → corrects stale `strategy` fields |
| 93 | +3. Scans monitor target JSON → corrects stale `strategy_profile` fields |
| 94 | +4. Logs `[config-sync]` messages for each correction |
| 95 | + |
| 96 | +**Result**: User only changes `RUNTIME_TARGET_JSON`. Everything else auto-aligns. |
| 97 | + |
| 98 | +### 4. Single Source of Truth Pattern |
| 99 | + |
| 100 | +- `RUNTIME_TARGET_JSON` = canonical strategy+platform assignment |
| 101 | +- `STRATEGY_PROFILE` env var = DEPRECATED (removed) |
| 102 | +- Plugin mount `strategy` field = auto-synced to match |
| 103 | +- Monitor target `strategy_profile` = auto-synced to match |
| 104 | + |
| 105 | +### 5. Execution Timing Pattern |
| 106 | + |
| 107 | +Strategies declare `signal_effective_after_trading_days` and `execution_timing_contract` in their runtime policy. The platform: |
| 108 | +- Checks market calendar before execution |
| 109 | +- Respects the timing contract (next_trading_day, etc.) |
| 110 | +- Uses `execution_dedup_enabled` for multi-day windows (monthly DCA) |
| 111 | + |
| 112 | +## Naming Conventions |
| 113 | + |
| 114 | +| Type | Convention | Example | |
| 115 | +|---|---|---| |
| 116 | +| Platform ID | lowercase, underscores | `schwab`, `interactive_brokers`, `longbridge` | |
| 117 | +| Strategy Profile | lowercase, underscores | `soxl_soxx_trend_income` | |
| 118 | +| Domain | lowercase, underscores | `us_equity`, `hk_equity`, `quant_combo` | |
| 119 | +| Repo Name | PascalCase for platforms, camelCase for packages | `CharlesSchwabPlatform`, `us-equity-strategies` | |
| 120 | +| Pip Package | lowercase-hyphenated | `us-equity-strategies`, `quant-us-combo-strategies` | |
| 121 | +| Python Package | lowercase_underscores | `us_equity_strategies`, `quant_us_combo_strategies` | |
| 122 | +| GCP Service | lowercase-hyphenated | `charles-schwab-quant-service` | |
| 123 | +| Scheduler Job | `{platform}-{strategy}-{type}` | `schwab-soxl-main`, `ibkr-u16608560-precheck` | |
| 124 | + |
| 125 | +## Scheduler Rules |
| 126 | + |
| 127 | +| Market | Calendar | Timezone | Execution Window | Cron | |
| 128 | +|---|---|---|---|---| |
| 129 | +| US Equity | NASDAQ | `America/New_York` | 3:45 PM ET | `45 15 * * *` | |
| 130 | +| HK Equity | XHKG | `Asia/Hong_Kong` | 3:45 PM HKT | `45 15 * * *` | |
| 131 | +| A-Share | XSHG | `Asia/Shanghai` | 2:45 PM CST | `45 14 * * *` | |
| 132 | +| Crypto | 24/7 | UTC | N/A | GitHub Actions `schedule` | |
| 133 | + |
| 134 | +**Rule**: Scheduler timezone = **market** timezone, not service region. |
| 135 | + |
| 136 | +## Adding a New Platform |
| 137 | + |
| 138 | +1. Create platform repo from the closest existing template |
| 139 | +2. Implement `strategy_registry.py`: |
| 140 | + - Import shared catalogs, merge them |
| 141 | + - Define `PLATFORM_CAPABILITY_MATRIX` |
| 142 | + - Define `*_EXCLUDED_LIVE_PROFILES` |
| 143 | + - Implement `get_platform_runtime_adapter(profile, platform_id)` |
| 144 | +3. Implement `runtime_config_support.py`: |
| 145 | + - Define `PlatformRuntimeSettings` dataclass |
| 146 | + - REQUIRED fields FIRST, default fields AFTER (Python dataclass rule) |
| 147 | + - Implement `load_platform_runtime_settings()` |
| 148 | +4. Implement broker adapters, market data ports, execution ports |
| 149 | +5. Add `main.py` with Flask routes (`/run`, `/dry-run`, `/probe`, `/health`, `/monitor-dispatch`) |
| 150 | +6. Add Cloud Scheduler jobs (or GitHub Actions for self-hosted) |
| 151 | +7. Add `.env.example` with all required env vars |
| 152 | +8. Add to `MONITOR_DISPATCH_TARGETS_JSON` for cross-platform monitoring |
| 153 | + |
| 154 | +## Adding a New Strategy |
| 155 | + |
| 156 | +1. Add strategy definition to the appropriate shared catalog pip package |
| 157 | +2. Set `compatible_platforms` in the catalog |
| 158 | +3. Set `runtime_enabled_profiles` for rollout |
| 159 | +4. Implement `get_platform_runtime_adapter(profile, platform_id)` in the runtime_adapters module |
| 160 | +5. Each platform auto-discovers it via `derive_enabled_profiles_for_platform()` |
| 161 | +6. To deploy: update `RUNTIME_TARGET_JSON.strategy_profile` on the target service |
| 162 | + |
| 163 | +## Adding a New Plugin |
| 164 | + |
| 165 | +1. Add plugin definition to `STRATEGY_PLUGIN_MOUNTS_JSON` |
| 166 | +2. The `strategy` field auto-syncs to match `RUNTIME_TARGET_JSON.strategy_profile` |
| 167 | +3. Plugin signals are consumed by the strategy entrypoint |
| 168 | + |
| 169 | +## Deployment Safety |
| 170 | + |
| 171 | +1. `python scripts/check_required_env.py --platform=<id>` — validate env vars |
| 172 | +2. `python scripts/validate_platform_consistency.py` — validate catalog vs registry |
| 173 | +3. Deploy to Cloud Run with `--clear-base-image` |
| 174 | +4. Verify `/health` returns 200 with no module errors |
| 175 | +5. Trigger `/dry-run` via Scheduler — verify execution report |
| 176 | +6. Enable live execution only after dry-run passes |
| 177 | + |
| 178 | +## Version History |
| 179 | + |
| 180 | +| Version | Date | Changes | |
| 181 | +|---|---|---| |
| 182 | +| 1.0 | 2026-06-30 | Initial architecture document | |
0 commit comments