Skip to content

Commit 71ec0ec

Browse files
authored
docs: add ADR records and guides
docs: add ADR records, developer guide, and data dictionary
2 parents bde4ca0 + c10a4ae commit 71ec0ec

6 files changed

Lines changed: 282 additions & 0 deletions

docs/DATA_DICTIONARY.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Data Dictionary
2+
3+
## Artifact Types
4+
5+
### Feature Snapshots (CSV)
6+
Produced by SnapshotPipelines. Columns vary by strategy profile.
7+
8+
| Column | Type | Description |
9+
|--------|------|-------------|
10+
| symbol | string | Ticker symbol |
11+
| score | float | Composite feature score |
12+
| rank | int | Ranking position (1-based) |
13+
| as_of | date | Snapshot evaluation date |
14+
| momentum_score | float | Momentum factor score |
15+
| quality_score | float | Quality factor score |
16+
| dividend_yield | float | Dividend yield percentage |
17+
18+
### Live Pool (JSON)
19+
Produced by CryptoLivePoolPipelines.
20+
21+
| Field | Type | Description |
22+
|-------|------|-------------|
23+
| symbols | string[] | Ordered list of selected symbols |
24+
| symbol_map | object | Symbol → metadata mapping |
25+
| as_of_date | date | Pool selection date |
26+
| ranking | object[] | Full ranking with scores |
27+
| btc_cycle_indicators | object | BTC cycle metrics |
28+
29+
### Signal Bundle (JSON)
30+
Produced by MarketSignalSources. Schema version: `market_signal_bundle.v1`.
31+
32+
| Field | Type | Description |
33+
|-------|------|-------------|
34+
| signal_bundle | object | Top-level bundle container |
35+
| derived_indicators | object | Computed technical indicators |
36+
| btc_cycle | object | BTC cycle metrics (AHR999, Mayer Multiple) |
37+
| quality_report | object | Data quality assessment |
38+
39+
### Execution Report (JSON)
40+
Produced by platform repos at runtime.
41+
42+
| Field | Type | Description |
43+
|-------|------|-------------|
44+
| run_id | string | Unique execution run identifier |
45+
| strategy_profile | string | Canonical profile name |
46+
| as_of | datetime | Execution timestamp |
47+
| orders | object[] | Submitted orders with status |
48+
| portfolio_snapshot | object | Pre/post execution portfolio state |
49+
| diagnostics | object | Signal details and risk flags |
50+
51+
## Versioning Policy
52+
53+
All artifacts include version metadata:
54+
- `contract_version` — the artifact format version (e.g., `feature_snapshot.v1`)
55+
- `schema_version` — the JSON schema version for structured artifacts
56+
- `generated_at` — ISO 8601 timestamp of artifact creation
57+
- `sha256` — content hash for integrity verification
58+
59+
Version changes require:
60+
1. Increment the version in the producing pipeline
61+
2. Update all consumers before deploying
62+
3. Maintain backward compatibility for one version cycle

docs/DEVELOPER_GUIDE.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# QuantStrategyLab Developer Guide
2+
3+
## Overview
4+
5+
QuantStrategyLab is a multi-market quantitative trading platform spanning 28 repositories. This guide helps new developers understand the system and start contributing.
6+
7+
## Repository Map
8+
9+
### Layer 1: Shared Foundation
10+
| Repo | Purpose |
11+
|------|---------|
12+
| **QuantPlatformKit** | Core shared library: domain models, broker adapters, cloud abstraction, notifications, risk, backtest, data versioning |
13+
| **QuantRuntimeSettings** | Runtime configuration center: JSON Schema, strategy switch console (JS/Cloudflare Workers) |
14+
15+
### Layer 2: Strategy Packages
16+
| Repo | Market | Strategies |
17+
|------|--------|-----------|
18+
| **UsEquityStrategies** | US Equity | ETF rotation, Smart DCA, leader rotation, leveraged combos |
19+
| **HkEquityStrategies** | HK Equity | Global ETF rotation, dividend quality, combo |
20+
| **CnEquityStrategies** | CN A-shares | Industry ETF rotation, dividend quality, combo |
21+
| **CryptoStrategies** | Crypto | BTC DCA, trend rotation, live pool rotation, combo |
22+
23+
### Layer 3: Data Pipelines
24+
| Repo | Produces |
25+
|------|----------|
26+
| **UsEquitySnapshotPipelines** | Feature snapshots, rankings, backtest summaries for US equity strategies |
27+
| **HkEquitySnapshotPipelines** | Factor snapshots, live-enablement evidence for HK strategies |
28+
| **CnEquitySnapshotPipelines** | A-share factor snapshots via AkShare |
29+
| **CryptoLivePoolPipelines** | Monthly live pool selection with ML ranking |
30+
| **MarketSignalSources** | BTC cycle indicators, daily technicals, US equity context |
31+
| **ResearchSignalContextPipelines** | Research-grade market context artifacts |
32+
33+
### Layer 4: Execution Platforms
34+
| Repo | Broker | Deployment |
35+
|------|--------|-----------|
36+
| **InteractiveBrokersPlatform** | IBKR | Cloud Run (Flask) |
37+
| **LongBridgePlatform** | LongBridge | Cloud Run (Flask) |
38+
| **CharlesSchwabPlatform** | Schwab | Cloud Run (Flask) |
39+
| **FirstradePlatform** | Firstrade | Cloud Run (Flask) |
40+
| **BinancePlatform** | Binance | VPS (CLI) |
41+
| **QmtPlatform** | QMT (paper) | Cloud Run (Flask) |
42+
43+
### Layer 5: Operations & Research
44+
| Repo | Purpose |
45+
|------|---------|
46+
| **IBKRGatewayManager** | IBKR gateway VM lifecycle (Docker + TOTP) |
47+
| **SchwabTokenAutoRefresher** | Schwab OAuth token refresh (Playwright) |
48+
| **CodexAuditBridge** | AI audit gateway (Claude/GPT/Codex) |
49+
| **QuantStrategyPlugins** | Sidecar risk plugins (regime, crisis, macro) |
50+
| **QuantAdvisorResearch** | Advisory research publishing |
51+
| **PoliticalEventTrackingResearch** | Political event RSS tracking |
52+
53+
## Development Workflow
54+
55+
1. **Create feature branch**: `git checkout -b feat/description`
56+
2. **Make changes**: Follow existing code patterns
57+
3. **Run checks**: `ruff check . && pytest tests/ -q`
58+
4. **Commit**: `type(scope): description` format
59+
5. **Push and create PR**: CI must pass before merge
60+
6. **Merge**: PR merged with `admin` flag, branch deleted
61+
62+
## Key Patterns
63+
64+
### Strategy Interface
65+
All strategies expose:
66+
```python
67+
PROFILE_NAME: str
68+
build_target_weights(...) → (weights_dict, ranked_frame, metadata)
69+
compute_signals(...) → (weights, signal_desc, is_emergency, status_desc, diagnostics)
70+
extract_managed_symbols(...) → tuple[str, ...]
71+
```
72+
73+
### Catalog Pattern
74+
Every strategy package has a `catalog.py` with standardized accessor functions:
75+
`get_strategy_definitions()`, `get_strategy_catalog()`, `get_runtime_enabled_profiles()`
76+
77+
### Broker Adapter
78+
Platform repos implement broker-specific adapters conforming to QPK's `MarketDataPort`, `PortfolioPort`, `ExecutionPort` protocols.
79+
80+
### Dependency Pinning
81+
All repos pin QPK via `QPK_PIN`. Run `python scripts/check_qpk_pin_consistency.py` to verify.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# ADR 0001: Record Architecture Decisions
2+
3+
**Date**: 2026-06-30
4+
**Status**: Accepted
5+
6+
## Context
7+
8+
QuantStrategyLab operates 28 repositories across 5 layers (shared libs → strategies → pipelines → platforms → ops). Architectural choices have been made incrementally without formal documentation. This ADR establishes the practice of recording architecture decisions and serves as the template for all future ADRs.
9+
10+
## Decision
11+
12+
All significant architectural decisions will be recorded as Architecture Decision Records (ADRs) in this directory (`docs/adr/`). Each ADR follows the format: Context → Decision → Consequences.
13+
14+
## Template
15+
16+
```markdown
17+
# ADR NNNN: <title>
18+
19+
**Date**: YYYY-MM-DD
20+
**Status**: Proposed | Accepted | Deprecated | Superseded
21+
22+
## Context
23+
What is the issue that we're seeing that is motivating this decision or change?
24+
25+
## Decision
26+
What is the change that we're proposing and/or doing?
27+
28+
## Consequences
29+
What becomes easier or more difficult to do because of this change?
30+
```
31+
32+
## Consequences
33+
34+
- **Positive**: Future contributors can understand *why* the system is structured as it is
35+
- **Positive**: New team members can onboard by reading ADRs chronologically
36+
- **Negative**: Maintaining ADRs requires discipline; stale ADRs must be marked as deprecated
37+
- **Neutral**: ADRs are immutable once accepted; changes require a new ADR with "Supersedes" reference
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# ADR 0002: Merge Combo Strategy Repos Into Domain Strategy Packages
2+
3+
**Date**: 2026-06-30
4+
**Status**: Accepted
5+
6+
## Context
7+
8+
The organization had 4 standalone "combo" repositories (QuantUsComboStrategies, QuantHkComboStrategies, QuantCnComboStrategies, QuantCryptoComboStrategies) each containing 1-2 strategy files that were thin wrappers combining sub-strategies from the main domain packages (UsEquityStrategies, HkEquityStrategies, CnEquityStrategies, CryptoStrategies). Version 0.1.0, 2-3 commits each.
9+
10+
This created:
11+
- 4 near-empty repos requiring separate CI, testing, and dependency management
12+
- Duplicated catalog/manifest/entrypoint boilerplate
13+
- `crypto_equity_combo` duplicated in both CryptoStrategies and QuantCryptoComboStrategies
14+
- Platform repos importing from two packages for the same domain
15+
16+
## Decision
17+
18+
Merge all combo strategies into their parent domain strategy packages:
19+
20+
| Combo Repo | Merged Into |
21+
|-----------|------------|
22+
| QuantUsComboStrategies | UsEquityStrategies |
23+
| QuantHkComboStrategies | HkEquityStrategies |
24+
| QuantCnComboStrategies | CnEquityStrategies |
25+
| QuantCryptoComboStrategies | CryptoStrategies |
26+
27+
The original combo repos were converted to backward-compatible re-export wrappers that import from the parent domain package.
28+
29+
## Consequences
30+
31+
- **Positive**: 4 fewer repos to maintain (CI, deps, tests)
32+
- **Positive**: `crypto_equity_combo` now has a single source of truth
33+
- **Positive**: Catalog entries for combo profiles live alongside their sub-strategies
34+
- **Negative**: Platform repos had pre-existing tests that imported from the old combo locations — required updates to `runtime_adapters.py`, `combo_entrypoints.py`, and test expectations
35+
- **Negative**: Re-export wrappers create a transitional dependency that will be removed once platform repos update their imports
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# ADR 0003: QPK_PIN Dependency Consistency Mechanism
2+
3+
**Date**: 2026-06-30
4+
**Status**: Accepted
5+
6+
## Context
7+
8+
The organization uses git-based dependencies (`quant-platform-kit @ git+https://...@<sha>`) across 15+ repos. When QPK changes, every dependent repo must manually update its pin. This has caused repeated deployment failures:
9+
10+
- Pip `ResolutionImpossible` errors when strategy repos declare QPK@SHA_A but platforms pin QPK@SHA_B
11+
- Cloud Run `ImportError` when Docker images are built with mismatched QPK versions
12+
- Manual cascading updates across strategy → platform repos
13+
14+
Three separate incidents occurred during a single day of development due to SHA drift.
15+
16+
## Decision
17+
18+
Introduce `QPK_PIN` as the single source of truth for which QPK commit all dependent repos should reference:
19+
20+
1. **QPK_PIN file** in QPK repo root — contains only the canonical QPK commit SHA
21+
2. **Auto-update workflow** (`update-qpk-pin.yml`) — runs on every push to QPK main, writes the current HEAD SHA to QPK_PIN
22+
3. **Consistency check script** (`check_qpk_pin_consistency.py`) — validates all git-based QPK references in a repo match QPK_PIN, with optional `--fix` mode for automatic updates
23+
24+
Dependent repos add a CI step that curls the QPK_PIN file and runs the check script.
25+
26+
## Consequences
27+
28+
- **Positive**: Single source of truth prevents SHA drift
29+
- **Positive**: CI catches mismatches before they reach deployment
30+
- **Positive**: `--fix` mode enables automated dependency updates
31+
- **Negative**: Requires QPK GitHub Actions to have push permission to main
32+
- **Negative**: Dependent repos must add the consistency check to their CI
33+
- **Neutral**: The pin file itself is a simple text file; no new infrastructure required
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# ADR 0004: Unify Platform Strategy Loader via QPK Shared Module
2+
3+
**Date**: 2026-06-30
4+
**Status**: Accepted
5+
6+
## Context
7+
8+
Four Cloud Run-based platform repos (InteractiveBrokersPlatform, LongBridgePlatform, CharlesSchwabPlatform, FirstradePlatform) each contained an identical `strategy_loader.py` implementing a 3-function pattern:
9+
10+
```python
11+
def load_strategy_definition(raw_profile)
12+
def load_strategy_entrypoint_for_profile(raw_profile)
13+
def load_strategy_runtime_adapter_for_profile(raw_profile)
14+
```
15+
16+
This created a Shotgun Surgery anti-pattern: any change to the strategy loading contract required updating 4 repos with identical code.
17+
18+
## Decision
19+
20+
Extract the shared strategy loading logic into `quant_platform_kit.common.platform_runner.loader`:
21+
22+
- `load_strategy_definition()` — resolves a profile string to a `StrategyDefinition`
23+
- `load_strategy_entrypoint_for_profile()` — loads the entrypoint with runtime adapter
24+
- `load_strategy_runtime_adapter_for_profile()` — loads the runtime adapter
25+
26+
Each platform repo retains a thin `strategy_loader.py` wrapper that delegates to the QPK module, customizing only the `platform_id` constant.
27+
28+
## Consequences
29+
30+
- **Positive**: Single implementation to maintain and test
31+
- **Positive**: Adding a new platform requires only a one-line platform_id constant change
32+
- **Negative**: Required updating all 4 platform repos simultaneously
33+
- **Negative**: Initially caused `ModuleNotFoundError` on Cloud Run because Docker images had older QPK without the `platform_runner.loader` module — resolved by rebuilding images after QPK SHA sync
34+
- **Neutral**: The 3-function API remains unchanged; existing callers are unaffected

0 commit comments

Comments
 (0)