Trading Framework — Multi-Strategy Backtesting Engine

A systems-design and backtesting framework where the same strategy code runs unchanged across backtest, paper, and live modes, with pluggable strategies, pluggable venues, and a layered risk engine.
PythonasyncioSQLAlchemyasyncpgAlembicPostgreSQLRedisPolarsNumPyFastAPIWebSocketsNuxtNuxtUITypeScriptDockerpyright2026

Overview

This project is a framework for designing, backtesting, and operating automated trading strategies — the engineering focus is the architecture, not any single strategy. Its central goal is that a strategy written once runs unchanged in three modes: backtest against historical data, paper trading against live data with simulated fills, and live execution. The same code path everywhere removes the usual gap between what was tested and what runs, which is where most automated-trading mistakes originate.

Pluggable Architecture

The system is built around small, protocol-based abstractions so each part can be swapped independently. A Strategy emits signals and reacts to fills and ticks. A Venue adapter exposes a uniform interface over a specific broker or exchange (listing instruments, submitting and cancelling orders, and streaming fills). A RiskRule is a pluggable gate that can approve, modify, or block an order. Because these are clean interfaces rather than tangled inheritance, new strategies, venues, and risk rules can be added without touching the core.

Unified Backtest, Paper, and Live Execution

All three execution modes share one Strategy interface and differ only in their context. In backtest, an accelerated clock replays historical data and a slippage model simulates fills. In paper mode, a real-time clock and live data drive a simulated venue. In live mode, the same logic submits real orders. A strategy receives a context that abstracts the clock, the data source, persistent state, bankroll, and positions — so it never needs to know which mode it is running in. This is the framework's defining design property.

Risk Engine

Risk is enforced in layers, independent of strategy logic. A kill switch can halt all trading instantly. Drawdown circuit breakers trip at per-strategy and global thresholds. Per-strategy capital limits cap exposure. A database-level uniqueness constraint on a strategy's deduplication key makes duplicate orders structurally impossible rather than merely unlikely. All monetary values use exact decimal arithmetic — never floating point — to avoid rounding errors in financial calculations.

Worker Topology and Data Flow

The system runs as cooperating asynchronous workers that communicate only through Postgres and Redis — there are no direct service-to-service calls. Strategy workers publish signals to per-venue Redis Streams; a risk-and-execution worker reads them, applies the risk rules, builds orders, and submits them; venue-filler workers hold long-lived streams to reconcile fills and update positions. State flows through the database and the streams, which makes the system observable, restartable, and crash-recoverable. The codebase uses Alembic migrations from day one and is checked under strict pyright typing.

Dashboard

A Nuxt frontend built on Nuxt UI provides a real-time monitoring and control surface over a FastAPI backend, streaming live events over WebSockets. From the dashboard, per-strategy capital allocations and overrides can be adjusted safely, and the state of strategies, orders, positions, and risk decisions is visible at a glance.

Built with Nuxt UI & Three.js © 2026