docs: add production pipeline wiring design (6 tasks)

Wire existing components into end-to-end pipeline: 5 missing inference
adapters, 10-model registration, market data feeding, integration test,
Docker build validation, and CI pipeline triage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-02-23 14:43:22 +01:00
parent ae225b0e31
commit d268a9dca8

View File

@@ -0,0 +1,155 @@
# Production Pipeline Wiring — Design
**Date:** 2026-02-23
**Status:** Approved
**Goal:** Connect existing components into a working end-to-end pipeline, prove it with an integration test, and validate Docker/CI infrastructure.
**Non-overlap:** Trading-universe handles data acquisition/organization. This work handles service-layer plumbing, integration testing, and infrastructure validation.
## Problem
The ML ensemble (10 models), conviction gates (7 gates), feature extraction (51-dim), and paper trading executor all exist and pass unit tests independently. But they are not wired together in the production service:
1. **5 of 10 models lack inference adapters** — TGGN, TLOB, KAN, xLSTM, Diffusion have trainable adapters but no `ModelInferenceAdapter` impl for the ensemble coordinator
2. **Market data doesn't feed the ensemble**`EnsembleCoordinator::update_market_data()` exists but nobody calls it during service startup
3. **No end-to-end test** proving the critical path works: OHLCV → features → ensemble → gates → paper trade
4. **Docker builds unvalidated** against the current 37-crate workspace
5. **CI pipelines likely stale** — 30+ workflows, many reference old structure
## Architecture
```
CURRENT (disconnected)
┌──────────┐ ┌──────────┐ ┌──────┐ ┌───────┐
│ MarketGen │ │ Features │ │ 5/10 │ │ Paper │
│ (exists) │ │ (exists) │ │Models │ │Trading│
└──────────┘ └──────────┘ └──────┘ └───────┘
✗ not wired ✗ not fed ✗ 5 missing ✗ not connected
TARGET (wired)
MarketGen ──→ update_market_data() ──→ 51-dim features
EnsembleCoordinator (10 models)
7 Conviction Gates
PaperTradingExecutor
```
## Task 1: Create 5 Missing Inference Adapters
**Files:** `ml/src/ensemble/adapters/{tggn,tlob,kan,xlstm,diffusion}.rs`
Each adapter follows the exact pattern of the existing 5 (DQN, PPO, TFT, Mamba2, Liquid):
| Model | Adapter Name | Input | Notes |
|-------|-------------|-------|-------|
| TGGN | `TggnInferenceAdapter` | 51-dim | Graph neural network, uses adjacency matrix |
| TLOB | `TlobInferenceAdapter` | 51-dim | Transformer for limit order book |
| KAN | `KanInferenceAdapter` | 51-dim | B-spline activations |
| xLSTM | `XlstmInferenceAdapter` | 51-dim | sLSTM + mLSTM blocks, sequence buffer |
| Diffusion | `DiffusionInferenceAdapter` | 51-dim | DDPM/DDIM denoising, multi-step |
Each implements `ModelInferenceAdapter` trait:
- `fn predict(&self, features: &FeatureVector) -> MLResult<EnsemblePrediction>`
- `fn model_id(&self) -> &str`
- `fn model_type(&self) -> ModelType`
Register all 5 in `ml/src/ensemble/adapters/mod.rs`.
~100-150 lines per adapter, ~500-750 lines total.
**Tests:** 3 tests per adapter (creation, prediction range, determinism) — same pattern as existing adapters.
## Task 2: Register All 10 Models in main.rs
**File:** `services/trading_service/src/main.rs`
Add registration blocks for TGGN, TLOB, KAN, xLSTM, Diffusion following the existing pattern (match on adapter creation, wrap in `InferenceAdapterBridge`, call `register_loaded_model`).
Initial weights (equal across 10):
| Model | Weight |
|-------|--------|
| DQN | 0.10 |
| PPO | 0.10 |
| TFT | 0.10 |
| Mamba2 | 0.10 |
| Liquid | 0.10 |
| TGGN | 0.10 |
| TLOB | 0.10 |
| KAN | 0.10 |
| xLSTM | 0.10 |
| Diffusion | 0.10 |
~100 lines of registration code.
## Task 3: Wire Market Data → EnsembleCoordinator
**File:** `services/trading_service/src/main.rs`
The test/DBN market data generators already exist as modules (`test_market_data_generator`, `dbn_market_data_generator`). Wire one as a background task that:
1. Spawns a tokio task after ensemble coordinator initialization
2. Reads from the configured market data source (test generator for dev, DBN for staging)
3. Calls `ensemble_coordinator.update_market_data(symbol, price, volume, timestamp)` on each bar
4. Logs warmup progress (bars received vs ~51 required for feature extraction)
~50 lines of wiring code. The generators already handle data production — this is just the connection.
## Task 4: End-to-End Integration Test
**File:** `services/trading_service/tests/e2e_pipeline_test.rs`
Single `#[tokio::test(flavor = "multi_thread")]` that proves the critical path:
1. Create `EnsembleCoordinator` with all 10 real candle adapters (untrained, random weights)
2. Feed 60 synthetic OHLCV bars via `update_market_data()` (warmup period)
3. Call `fetch_features_for_symbol()` — assert 51 real features, no NaN/Inf, no all-zeros
4. Call `predict()` — assert `EnsembleDecision` returns with:
- `action` is Buy/Sell/Hold
- `confidence` in [0.0, 1.0]
- `model_votes` has entries from all 10 models
- Conviction gate results are populated
5. Feed decision to `PaperTradingExecutor` — assert paper order generated (or HOLD from gate rejection)
No external dependencies (no PostgreSQL, no QuestDB, no Docker). Pure in-process test.
~150 lines.
## Task 5: Docker Build Validation
**Files:** All 6 Dockerfiles + `Dockerfile.foxhunt-build`
For each service:
1. `docker build -t foxhunt-<service>:test -f services/<service>/Dockerfile .`
2. Fix any compilation failures (missing system deps, stale paths)
3. Verify the binary starts and health check passes: `docker run --rm foxhunt-<service>:test --help` or equivalent
Services:
- `trading_service` (primary)
- `api_gateway`
- `ml_training_service`
- `backtesting_service`
- `trading_agent_service`
- `broker_gateway_service`
Fix-only — no new Dockerfiles.
## Task 6: CI Pipeline Triage
**Directory:** `.github/workflows/`
1. Identify the 3 essential workflows: build (`ci.yml`), test (`test.yml`), lint/clippy (`compilation-guard.yml` or `build.yml`)
2. Validate each uses `SQLX_OFFLINE=true`, correct Rust toolchain, correct workspace paths
3. Fix broken steps (missing env vars, wrong cache keys, outdated actions)
4. Delete obvious duplicates (e.g., `comprehensive-testing.yml` vs `comprehensive_testing.yml`)
5. Ensure at least build + test + clippy pass on `main` branch
Fix-only — no new workflows.
## Constraints
- Build: `SQLX_OFFLINE=true cargo check --workspace`
- Test: `SQLX_OFFLINE=true cargo test -p <crate> --lib`
- Clippy: `#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::indexing_slicing)]`
- No overlap with `feat/trading-universe-data-org` branch (data acquisition, universe definition, cache structure)
- RTX 3050 Ti 4GB — adapter configs must use small hidden dims (32-64)