System design
Architecture.
AURA splits into a live trading service and a walk-forward parameter optimizer — sharing a codebase, never sharing an event loop or a database write path. Below: the per-cycle lifecycle, the risk gating sequence, and the optimization loop that promotes parameters into production.
- 01
Data ingestion
A coverage-aware provider chain (historical archive → multiple tail feeds → CoinGecko fallback) merges into a per-symbol Parquet cache. Freshness short-circuits and provider-lookback padding stabilize backtests without hammering live APIs.
- 02
Signal generation
Universe is regenerated daily under a momentum / SMA / drawdown screen. A composite scoring function ranks candidates; robust voting across multiple historical offsets favours stable rank over single-snapshot noise. A two-cycle regime hysteresis suppresses bull / sideways / bear flips at the boundary.
- 03
Risk management
Three concentric gates — a kill-switch on rolling drawdown, per-position stop-loss / take-profit, and a portfolio-level cost-benefit check — must clear before any capital moves. The sync guard prevents phantom kill-switch trips when a transient broker error returns an empty position set.
- 04
Execution engine
A fully synchronous, single-threaded loop builds intents from the rebalance plan, hashes each into a deterministic clientOrderId for idempotent retries, and routes them through CCXT to Binance Spot. Sell-clamp logic retries on transient balance-fetch failures rather than aborting the sell.
- 05
Logging & persistence
Every cycle writes events, intents, orders, and snapshots to embedded SQLite. Permanent diagnostic logs ([BOOT], [RISK_TICK], [SL_CHECK], [SYNC_GUARD]) surface any silent regression in journalctl alone. Stop-loss reachability is preserved across restarts via entry-price recovery from snapshots.
Diagram · 01
Per-cycle lifecycle.
Data flows left to right through the score → regime → selector → portfolio → risk-gate → execute pipeline. Every cycle ends in SQLite. The risk gate is non-bypassable.
Diagram · 02
Risk gating sequence.
Three sequential gates between any candidate position and the exchange. A failure at any gate either liquidates (kill-switch), exits the position (SL/TP), or holds (cost-benefit).
Diagram · 03
Walk-forward optimization loop.
Four staged grids, successive-halving budgets, and a benchmark-aware promotion gate. Parameters reach the live trader only after beating both Gold and SPY across the validation slate.
Invariants
Four properties we never compromise on.
- Determinism
- Same inputs → same plan. No threading, no event loops, no async surprises.
- Idempotency
- clientOrderId hashing means a retry after an ambiguous failure cannot double-fill.
- Crash safety
- Boot reconciliation refreshes any broker-acknowledged order whose fill callback was lost.
- Hot reload
- Risk thresholds and selector weights can be tuned between cycles without a service restart.
A more detailed internal reference, including module-level wiring and incident history,
lives in ARCHITECTURE.md at the repository root.