Rust für Trading-Bots: Memory-Safety und Performance.
Rust ist die Sprache, die in der Backend-Welt der letzten zehn Jahre die kompromisslose Performance-Nische besetzt hat — ohne den scharfkantigen Werkzeugkasten von C++. Für Trading-Bots, die ihre Latenz in Mikrosekunden zählen und keinen GC-Pause-Pixie-Dust vertragen, ist Rust ernsthaft eine Option geworden. Hier ist meine Sicht aus der Praxis.
Was Rust für Trading-Code attraktiv macht.
- Kein Garbage-Collector: deterministische Ausführungszeiten. In Java oder Go kann eine GC-Pause Mikrosekunden bis Millisekunden reißen — in Rust gibt es das schlicht nicht.
- Memory-Safety durch Borrow-Checker: keine Use-After-Free, keine Double-Free, keine Data-Races. Bugs, die in C++ Stunden in einem Debugger kosten, werden in Rust beim Kompilieren erschlagen.
- Concurrency ohne Data-Races:
SendundSyncsind Trait-Bounds, die der Compiler durchsetzt. Wer thread-sicher schreiben will, wird vom Typsystem gezwungen — nicht ermahnt. - Performance auf C++-Niveau: in Benchmarks gegen Python typisch 10–50× schneller, bei I/O-lastigen Aufgaben mit tokio oft besser als naive Python-asyncio-Implementierungen.
- Tooling:
cargoist das Build- und Dependency-System, das jeder Sprache zu wünschen wäre. Tests, Docs, Linter (clippy), Formatter — alles eingebaut.
Trading-Bot-Ökosystem in Rust.
- tokio: das De-facto-Async-Runtime. WebSockets, HTTP, TCP — alles läuft hierüber.
- tungstenite / tokio-tungstenite: reife WebSocket-Bibliotheken.
- reqwest: HTTP-Client für REST-API-Calls gegen Broker.
- serde / serde_json: Serialisierung — schnell, typsicher, mit klaren Fehlern.
- nautilus_trader (Rust-Kern): das ehrgeizigste Open-Source-Trading-Framework mit Rust-Engine und Python-Bindings. Reif genug für ernste Setups, anspruchsvoll im Onboarding.
- barter-rs: modulares Rust-Framework speziell für Krypto-Trading-Bots. Klar strukturiert, aktiv gepflegt.
- Hummingbot: nicht in Rust geschrieben (Python), aber konzeptionell vorbildhaft. Wer Marketmaking-Logik studieren will, lernt hier.
Konkretes Beispiel: Binance-WebSocket-Ingestion.
Ein minimaler, produktionsnaher Verbraucher, der den Trade-Stream eines Symbols abonniert, JSON parst und in einen Channel schiebt. Sie sehen die Grundbausteine — tokio, tungstenite, serde:
use futures_util::StreamExt;
use serde::Deserialize;
use tokio::sync::mpsc;
use tokio_tungstenite::connect_async;
#[derive(Debug, Deserialize)]
struct Trade {
#[serde(rename = "p")] price: String,
#[serde(rename = "q")] qty: String,
#[serde(rename = "T")] ts_ms: u64,
}
async fn run(symbol: &str, tx: mpsc::Sender<Trade>) -> anyhow::Result<()> {
let url = format!("wss://stream.binance.com:9443/ws/{}@trade",
symbol.to_lowercase());
let (mut ws, _) = connect_async(url).await?;
while let Some(msg) = ws.next().await {
let msg = msg?;
if let Ok(text) = msg.into_text() {
if let Ok(t) = serde_json::from_str::<Trade>(&text) {
tx.send(t).await.ok();
}
}
}
Ok(())
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let (tx, mut rx) = mpsc::channel::<Trade>(1024);
tokio::spawn(run("btcusdt", tx));
while let Some(t) = rx.recv().await {
println!("{} @ {} ({})", t.qty, t.price, t.ts_ms);
}
Ok(())
}
Diese 30 Zeilen halten in der Praxis tausende Trade-Messages pro Sekunde aus, ohne
zu kleckern. Ein analoger Python-Konsument mit websockets und
asyncio ist ebenfalls schnell genug für die meisten Anwendungen — aber
Rust gibt Ihnen das ruhige Gewissen, dass das Programm auch unter Last vorhersagbar
bleibt und dass kein Speicherproblem über Wochen leise wächst.
Performance, ehrlich gemessen.
Für die Bot-Komponenten, die ich in beiden Sprachen umgesetzt habe (Orderbook- Aggregator, Feature-Berechnung über rolling Windows, Order-Router), liegt Rust real beim 10–50× von Python. Drei Beispiele:
- Orderbook-Update aus Diff-Stream: Python (mit
sortedcontainers) etwa 8 µs pro Update. Rust (BTreeMap) etwa 0,3 µs. Faktor ~25. - EMA über rolling Window von 200 Symbolen, 100 Ticks/s: Python ohne Tricks ~12 % CPU. Rust ~0,4 % CPU. Faktor ~30.
- Round-Trip-Latenz bei Order-Sendung: Sprachunterschied wird durch Netzwerk dominiert. Hier sind 0,5–1 ms Differenz drin, was bei den meisten Strategien irrelevant ist — bei reinem HFT entscheidet es.
Was Rust schmerzhaft macht.
- Lernkurve: der Borrow-Checker ist unterrichtsreif. Sie kämpfen die ersten Wochen weniger mit dem Problem als mit der Sprache. Nach drei Monaten kehrt sich das um — der Compiler wird Ihr bester Freund.
- Iteration langsamer: Compile-Zeiten von 30 Sekunden bis zu mehreren Minuten sind normal. Verglichen mit einer Python-REPL fühlt sich das initial wie ein Rückschritt an.
- Bibliotheks-Lücken: technisches Analyse-Toolkit, ML-Modelle, Backtest-Engines sind in Rust dünner gesät als in Python. Wer
scikit-learnbraucht, ist in Python besser aufgehoben. - Talentmarkt: gute Rust-Entwickler kosten mehr und sind schwerer zu finden. Für eine Trading-Boutique mit drei Leuten ist das eine echte Erwägung.
Wann Rust für Trading-Bots wirklich lohnt.
- Latenz ist Wettbewerbsfaktor. HFT, Marketmaking, Latency-Arbitrage — alles unter ~1 ms Round-Trip. Hier ist Rust (oder C++) die Wahl, kein Python.
- Datenpipeline mit hohem Durchsatz. Marktdaten-Ingestion mit zehntausenden Messages pro Sekunde, persistente Schreib-Pfade in TimescaleDB oder Parquet, ohne dass die Server-CPU schwitzt.
- Long-running Services mit kritischer Stabilität. Order-Router, Risiko-Gatekeeper, Position-Recovery-Service nach Crashes — alles, was niemals leise kaputtgehen darf.
- Co-Location-Setups, in denen jeder Mikrosekunden-Gewinn nachweisbar in P&L umrechenbar ist.
Meine Praxis: Rust für Pipelines, Python für Strategien.
Ich nutze Rust dort, wo Stabilität und Durchsatz im Vordergrund stehen — typisch sind Marktdaten-Ingestoren, die WebSocket-Streams konsumieren, normalisieren und in eine TimescaleDB oder einen Parquet-Store schieben. Diese Komponenten laufen jahrelang ohne Eingriff, und das ist genau das Versprechen, das Rust einlöst.
Die Strategie-Logik selbst — Signal-Berechnung, ML-Modelle, Backtest-Setups, Forschung — bleibt bei mir in Python. Pandas, PyTorch, scikit-learn, das ganze Notebook-Tooling ist dort, wo Iteration und Datenexploration gewinnen, schlicht überlegen.
Die Schnittstelle zwischen beiden Welten ist heute kein Schmerzpunkt mehr. Drei Optionen, die in der Praxis funktionieren:
- PyO3 + maturin: Rust-Bibliothek mit Python-Bindings. Die rechenintensive Funktion kommt aus Rust, der Aufruf aus Python.
- Message-Bus: Rust-Service publiziert auf Redis Streams oder NATS, Python-Strategie konsumiert.
- Arrow / Parquet: Rust schreibt Marktdaten als Arrow, Python liest dieselben Dateien ohne Konvertierung.
Konkretes Einstiegs-Setup.
# Rust installieren
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Projekt
cargo new trading-ingest
cd trading-ingest
# Cargo.toml — die wichtigsten Crates
# [dependencies]
# tokio = { version = "1", features = ["full"] }
# tokio-tungstenite = { version = "0.21", features = ["native-tls"] }
# futures-util = "0.3"
# serde = { version = "1", features = ["derive"] }
# serde_json = "1"
# anyhow = "1"
cargo run --release
Empfehlung.
Wenn Sie heute einen Trading-Bot von null aufbauen und Ihre Strategien im Sekunden- bis Minuten-Bereich operieren: bleiben Sie bei Python. Wenn Ihre Strategien Mikrosekunden zählen, Ihre Datenpipeline aus dem Leim geht oder Ihr System nachts crasht und Sie das zum dritten Mal bemerken: dann ist Rust für die kritischen Komponenten der nächste ernsthafte Schritt — nicht als Religionswechsel, sondern als gezielte Aufrüstung.
Sie überlegen, kritische Komponenten Ihres Trading-Stacks nach Rust zu ziehen? Erstgespräch buchen — wir identifizieren, was sich wirklich lohnt und was Aufwand ohne Ertrag wäre.