Why Not Python? The Case for Rust in Trading

Python dominates quantitative finance. Libraries like pandas, NumPy, and zipline make backtesting accessible to anyone. So why did we build FerroQuant in Rust?

The answer is production latency. Python is excellent for research and prototyping, but when you need to process 1000+ symbols simultaneously with sub-second signal generation, the Global Interpreter Lock (GIL) becomes a bottleneck. Rust gives us true parallelism with zero-cost abstractions — the compiler optimizes away all the safety checks at compile time, producing binaries that run as fast as hand-written C.

FerroQuant's signal engine processes tick-level data from 16 WebSocket shards simultaneously, calculates 16 RSI periods across 4 timeframes for each symbol, and emits signals in under 100 milliseconds. In Python, the same workload takes 3-5 seconds with multiprocessing overhead.

Memory Safety Without Garbage Collection

Financial systems cannot afford unpredictable pauses. Java and Go use garbage collectors that can introduce latency spikes of 10-100ms — an eternity when markets move in milliseconds.

Rust's ownership system eliminates garbage collection entirely. Memory is freed deterministically when variables go out of scope. This means FerroQuant's signal engines maintain consistent latency even under peak load (market opens, high-volatility events, flash crashes).

The ownership model also prevents entire classes of bugs that plague trading systems: use-after-free (accessing deallocated market data), data races (two threads modifying position state simultaneously), and buffer overflows (processing malformed exchange messages). These bugs are caught at compile time, not in production during a market crash.

The Architecture: Axum, Tokio, and WebSocket Shards

FerroQuant's stack is built on the Tokio async runtime with Axum for HTTP/WebSocket handling. The architecture splits into:

- 16 WebSocket shards per market (Futures + Spot = 32 shards) connected to Binance, each handling ~30 symbols - An indicator daemon that reads raw candle data from Parquet files and calculates RSI, MACD, Bollinger Bands, and other indicators across 16 periods - Signal engines (one per market) that consume indicator data and emit trade signals using 165+ strategies - A dashboard server (Axum) that serves the web interface, REST API, and SSE streams

All components communicate through Redis for real-time data and PostgreSQL for persistent state. The entire system runs on a single server, processing 1000+ symbols across 4 markets with a memory footprint under 2GB.

Backtesting at Scale: 7 Years of Tick-Level Data

Our backtesting engine processes 7 years of historical data stored in Hive-partitioned Parquet files — roughly 50GB of tick-level candle data across Binance Futures, Spot, OANDA Forex, and OANDA Commodities.

Rust's performance makes walk-forward validation practical. Each strategy is optimized on a training window, then validated on an unseen test window, repeated across the entire 7-year dataset. This prevents overfitting — a strategy must prove itself on data it has never seen.

A full walk-forward validation across all 165 strategies for a single symbol takes approximately 45 seconds in Rust. The equivalent Python implementation (using vectorized pandas operations) takes 12-15 minutes. This 20x speedup means we can re-optimize all symbols overnight instead of running for days.

Getting Started with Rust for Trading

If you are coming from Python, the learning curve for Rust is steep but rewarding. Start with these resources:

1. The Rust Book (doc.rust-lang.org/book/) — the official tutorial 2. Tokio tutorial (tokio.rs/tokio/tutorial) — for async programming 3. Axum examples (github.com/tokio-rs/axum/tree/main/examples) — for web server patterns

For data processing, the key Rust crates are: polars (DataFrame operations, similar to pandas), arrow and parquet (columnar data), and duckdb (embedded analytical SQL). For exchange connectivity, use tungstenite for WebSockets and reqwest for REST APIs.

FerroQuant is proof that Rust is production-ready for algorithmic trading. The safety guarantees, performance characteristics, and growing ecosystem make it the best choice for systems that need to be both fast and reliable.