Navigation
opendeviationbar-py · architecture
🛠 ARCHITECTURE · DELIVERABLE #1 2026-05-09

Pipeline Visualization — End-to-End

Each box has a plain-English summary (yellow italic) and a technical detail block (IN / OUT / Why / When). Read the yellow lines first to understand the flow; drill into the technical detail when you want precision.

Project-invented terms are italicized and link to the glossary. Click any actor box for its source CLAUDE.md. Phase 4 brief: actors-and-edges.md.

What this pipeline does (in plain English)

Crypto and forex markets emit individual trades all day. This system bundles those trades into Open Deviation Bars — special candle-like structures that close when the price moves a fixed percentage from the bar's open price (instead of when a clock ticks). Every bar carries 50+ statistical features.

Two parallel pipelines exist because crypto and forex came online at different times with different broker constraints. They share the algorithm idea but not the code:

🪙 Concrete example — one BTCUSDT trade (illustrative)

A trader buys 0.05 BTC at $60,150.30. Binance assigns aggTrade #2,143,000,000. The current open bar (250 dbps threshold) opened at $60,000.00 — upper breach is $60,150.00.

The trade arrives at STEP 1 via WebSocket → reaches the sidecar at STEP 3 → processor sees $60,150.30 ≥ $60,150.00 = breach, finalizes the bar (open=60,000, close=60,150.30) → bar lands in STEP 5 ClickHouse → reachable by alpha-forge / backtesting / SSE consumers at STEP 6. Total time: sub-second on the live path.

💱 Concrete example — one EURUSD tick (illustrative)

FXView quotes bid 1.08234, ask 1.08236. Open bar (5 dbps threshold) opened at 1.08200 — upper breach ~1.08254.

Tick arrives at STEP 1 → MT5 EA captures it at STEP 2, applies UTC conversion (with 4-signal HALT validating the offset), writes to 3 destinations. Live engine at STEP 4 reads the ring buffer, accumulates ticks, breaches threshold around 1.08245 → bar finalizes via fxview-core's BarBuilder at STEP 5 → lands in ClickHouse at STEP 6opendeviationbar-patterns at STEP 7 mines patterns → validates at STEP 8 → NautilusTrader at STEP 9 sends a real order. Total tick → bar: ~10 sec. Tick → live trading decision: minutes-to-hours.

CRYPTO TRACK opendeviationbar-py · opendeviationbar_cache · 250/500/750/1000 dbps FOREX TRACK mql5 · fxview_cache · 5/10/25/50 dbps ▸ LANE 1 · SOURCES (where raw data comes from) STEP 1 · C1+C2 Binance data sources (spot only) "Every time someone trades crypto on Binance, we hear about it instantly through their live feed. We also keep daily archives in case we miss anything." IN: (none — source of truth) OUT: aggTrade events {a, p, q, T, m} · 138 trades/sec at peak When: sub-second (WS) · daily ZIPs (Vision archive) STEP 1 · F1 FXView broker (commercial forex) "A commercial forex broker streams us live bid/ask quotes for currency pairs (EUR/USD, GBP/USD, gold, silver). They use European time with daylight saving." IN: (none — source of truth) OUT: MqlTick events {bid, ask, last, volume, time, flags} When: sub-second · 24/5 (closes weekends) ▸ LANE 2 · INGESTION (capture → cache → engine) STEP 2 · C3 Tier-1 Parquet ticks cache "A local copy of every Binance trade ever, on this machine's disk. Saves us from re-downloading the same trades over and over." IN: trades from C2 (Vision ZIP daily seeded by C8) OUT: daily Parquet files · ZSTD-3 · ~5.4× ratio · O(1) has_ticks() STEP 3 · C4 (LIVE ENGINE) opendeviationbar-py sidecar "The live brain. As trades arrive, it watches the price. When the price has moved 0.25% (etc.) from where the current bar started, it 'closes' that bar and writes it to the database, then starts a new bar." IN: aggTrade stream from C1 (live), C2/C3 (resume + gap-fill) OUT: CompletedBar (OHLCV + microstructure + last_agg_trade_id) → C10 Why: primary live writer · owns ≥ resume_tid (per writer-ownership) When: sub-second · breach detection per tick 7 self-healing helpers: Niffler · Charon · Argus · Lethe · Watchdog · Antaeus · Puck (see glossary — each handles one failure mode) STEP 4 · C7 (HISTORICAL ENGINE) Kintsugi (gap reconciler) "When the live engine was offline or had a glitch, gaps appear in the historical record. Kintsugi runs in the background, finds the gaps, re-downloads the missing trades, and computes the missing bars to fill them in." IN: Stathera audit query (tid_delta != 0) + Vision/REST/Parquet OUT: repair bars → C10 (only writes BEFORE resume_tid) When: 60s active polling · 24-worker concurrency · reverse-chronological STEP 2 · F2 MT5 EA (TickCollector.mq5) + Rust tick-writer DLL "MetaTrader runs an Expert Advisor that grabs every quote, converts it from broker-local time to UTC (with safety checks), then hands it to our Rust DLL which writes it to three places at once." IN: MqlTick events from F1 via CopyTicksRange() OUT: UTC-corrected ticks → 3 destinations (F3a Parquet, WAL audit, F3b ring) Why: 4-signal HALT — block writes if broker offset is wrong STEP 3a · F3a (BACKFILL) Parquet tick store "Daily files of every tick — used for re-processing history." OUT: → F5 backfiller STEP 3b · F3b (LIVE) /dev/shm ring buffer "A super-fast in-memory channel where the live engine reads ticks." OUT: → F4 sidecar STEP 4a · F5 (BACKFILL) fxview-backfiller "Re-processes daily files into bars — used for rebuilding history." When: manual / batch tokio multi-symbol parallel STEP 4b · F4 (LIVE ENGINE) fxview-sidecar "The live forex engine. Reads ticks, builds bars, writes to the database." When: sub-second · resume via last_quote_seq SSE :8082 · heartbeat 1s STEP 5 · F6 (SHARED LIB used by F4 + F5) fxview-core (Rust crate, mql5-internal) "The shared bar-building logic. Both the live engine and the backfiller depend on this same code to turn ticks into bars. Independent of the crypto-side opendeviationbar-core — same idea, separate codebase." IN: tick stream (from caller) OUT: CompletedBar (200+ fields) → caller writes to F7 Why: avoids code duplication between live + backfill internals: BarBuilder · ChWriter · PendingQueue · BarRankTrackers CROSS · C8 Tick Cache Seeder "A scheduled job that downloads new daily archive files every 5 minutes, keeping the local cache fresh so Kintsugi never has to wait on a download." CROSS · C9 Heartbeat (6 health checks) "A scheduled job that checks every 5 minutes: is the database reachable? Live engine running? Anything broken? Sends Telegram alert if unhealthy." ▸ LANE 3 · STORAGE (bigblack ClickHouse — two databases, same instance) STEP 5 · C10 ClickHouse · opendeviationbar_cache.open_deviation_bars "The crypto bar database. Big, fast, with multiple safety layers preventing duplicates. Both the live engine (C4) and the gap-filler (C7) write here." IN: bars from C4 (live, ≥ resume_tid) + C7 (historical, < resume_tid) Scale: ~42M bars · 15 symbols × 4 thresholds · partition (sym, threshold) Safety: 5-layer dedup · Redis lock · circuit breaker · skip index STEP 6 · F7 ClickHouse · fxview_cache.forex_bars "The forex bar database. Like the crypto one but separate, with forex-specific bars. Two independent producers write here — bigblack (us) and aws-dev." IN: bars from F4 (live) + F5 (backfill) + aws-dev (cross-region) Scale: ~51.57M bars · 4 symbols × 4 thresholds (5/10/25/50 dbps) Mode: OuroborosMode='week' (Fri 21 UTC → Sun 22 UTC reset) ▸ LANE 4 · CONSUMPTION + EXECUTION (what happens to the bars) STEP 6 · C11 (FAN-OUT) Library consumers (3 pathways) "Other systems use the bars: research frameworks for testing trading ideas, ML pipelines for training models, and live consumers who want fresh bars streamed in real time." a) alpha-forge: OHLCV → panel format via compat/panel.py b) backtesting.py: historical replay via examples/backtesting_integration.py c) SSE consumers: opendeviationbar-client crate (live forming bars) STEP 7 · F8 opendeviationbar-patterns (research lab) "The research lab. Takes the bars and runs evolutionary algorithms + machine learning to discover trading rules. Tries thousands of candidates, weeds out the ones that don't survive rigorous testing." Method: Layer A (Evol WFA + Tautology Dedup) → Layer B (LightGBM) Then: Layer 3 Selector (CPCV + Optuna + conformal) — picks deployable cells Speed: wfo_rs Rust hot-path · 79× speedup over Python STEP 8 · F10 backtesting.py (validation) "Promising rules get re-tested in a realistic simulator with execution costs. If still profitable → live." ConformingStrategy · Triple Barrier F9 (PARALLEL BRANCH) Patterns dashboard "Web dashboard publishing the research findings — researchers review campaigns there." bigblack:8447 · sws + Tailscale STEP 9 · F11 (LIVE) NautilusTrader (production) "Real money on the line. Receives signals from validated rules, sends orders to the broker." custom adapter · drives orders → TERMINAL Broker (live execution) "Orders execute in the live forex market. Loop closes back to F1 for the next quote." ▸ LANE 5 · CROSS-CUTTING INFRASTRUCTURE SHARED INFRA Pueue orchestrator + Telegram alerts (@obdpy_bot) "Pueue is the job queue on bigblack — runs long tasks reliably (Kintsugi, backfills, sweeps). Telegram is how we get failure alerts on our phones." FOREX AUDIT-ONLY Cross-broker triangulation (Dukascopy + Exness) "We compare FXView's data against two other brokers periodically to catch silent timestamp/price errors. Audit-only — does NOT affect the live pipeline." trade events writer ownership boundary at resume_tid historical writes live writes (parallel via C4) live seeds C3 queries tick events backfill live uses lib uses lib writes via ChWriter research consumes bars validate publish port to live orders

Legend & how to read

📐 Layout

Two columns by track (CRYPTO left, FOREX right). Five rows by function (Sources → Ingestion → Storage → Execution → Cross-cutting). Read top-to-bottom within each column.

📖 Inside each box

  • Yellow italic — plain-English summary (what this does)
  • IN: / OUT: — what data flows in & out
  • Why: / When: / etc. — technical specifics in monospace

Read the yellow lines first to understand the flow. Drill into the technical lines for precision.

🎨 Color codes (per function)

  • blue — sources
  • cyan — caches
  • green — processing engines
  • orange — storage
  • purple — consumers + execution
  • slate dashed — cross-cutting

↪ Arrow types

  • Solid bold — primary data flow on the hot path
  • Dashed — secondary or parallel path (live-vs-backfill, dashboard publish)
  • Dotted — library dependency (F4/F5 use F6 shared crate)

All arrows are 90°-orthogonal (Manhattan routing). No diagonals.

🔢 Step numbering

Each box has a STEP badge. Crypto reaches STEP 6, Forex reaches STEP 9 (deeper because of the live/backfill split + research/validation/execution chain). Cross-cutting boxes have CROSS · IDs instead of step numbers.

🔗 Hyperlinks

Every actor box links to its source CLAUDE.md. Project-invented terms (Kintsugi, Stathera, Puck, OuroborosMode, fxview-core, etc.) link to their canonical entries in the glossary.