Dans cet article, nous allons voir ce qu’est Nautilus Trader et comment l’utiliser. Je me suis penché sur cet outil car je m’étais fixé l’objectif de ré-écrire un bot de trading en Rust avant de m’apercevoir qu’il y avait déjà cette plateforme open source qui existait et qui contient déjà plus de 17 000 commits. Plutôt que de réinventer la roue, l’idée est de voir si je peux m’approprier cet outil bot pour en faire un bot d’arbitage. Cela me permet aussi de me plonger dans un large projet Rust avec bindings pour Python. Et du coup s’il manque des features, ce sera avec grand plaisir que je pourrai les coder.


Présentation

Nautilus Trader n’est pas juste une lib Python écrite en Rust; c’est un peu plus complexe.

C’est une plateforme de trading algorithmique haute performance qui utilise une architecture hybride à trois couches de langages:


1. Rust: Le moteur natif (crates/)

Le workspace Rust contient ~35 crates qui implémentent le cœur du système:

Catégorie Crates
Noyau core, model, common, data, serialization
Trading trading, execution, risk, portfolio, backtest
Infra network, persistence, infrastructure, cryptography
Adapters exchanges binance, bybit, kraken, deribit, okx, dydx, coinbase_intx, tardis, etc.
Binding Python pyo3: le pont vers Python via PyO3

Le crate crates/pyo3/ est la passerelle: il compile une bibliothèque partagée nautilus_pyo3 qui expose les types et fonctions Rust directement en Python.


2. Cython: La couche intermédiaire (fichiers .pyx)

Il y a ~106 fichiers .pyx (Cython) et ~129 fichiers .pxd (déclarations). C’est une couche historique importante qui:

  • Fournit une grande partie de l’API Python publique (stratégies, ordres, instruments, indicateurs, etc.)
  • Appelle le code Rust via FFI/C (headers générés dans nautilus_trader/core/includes/)
  • Implémente certains composants directement en Cython pour la performance
  • Se compile en extensions C (fichiers .so/.pyd) qui se linkent aux bibliothèques statiques Rust

On le voit dans nautilus_trader/core/rust/ qui contient des fichiers .pyx comme model.pyx et common.pyx servant de pont entre Cython et les bibliothèques Rust.


3. Python pur: L’orchestration (fichiers .py)

Du Python classique pour:

  • La configuration et l’orchestration du système
  • Certains adapters de plus haut niveau
  • Les tests

En gros l’architectue du projet se décompose comme ceci:

┌─────────────────────────────────────────────────┐
│              Utilisateur Python                 │
│         (import nautilus_trader)                │
├────────────────────┬────────────────────────────┤
│   Cython (.pyx)    │     Python pur (.py)       │
│  Extensions C/C++  │  Config, orchestration     │
├────────────────────┴────────────────────────────┤
│          FFI (C headers)  &  PyO3               │
├─────────────────────────────────────────────────┤
│              Rust (crates/)                     │
│  Core engine, model, adapters, networking, etc. │
└─────────────────────────────────────────────────┘

L’API utilisateur est en Python, mais que la performance critique est en Rust, et que le Cython sert de ciment (historique) entre les deux.

Le projet migre progressivement de Cython vers Rust/PyO3. Le Cython est la couche historique, et le Rust prend de plus en plus de place. On voit d’ailleurs que les tests ont souvent des versions _pyo3


Il y a 3 catégories d’adapters

1. Adapters Rust + couche Python fine (la majorité)

Ces adapters ont une double implémentation: le gros de la logique est en Rust, avec une couche Python par-dessus.

Adapter Rust (crates/adapters/) Python (nautilus_trader/adapters/)
Binance oui oui
Bybit oui oui
Kraken oui oui
OKX oui oui
Deribit oui oui
dYdX oui oui
Coinbase IntX oui
Databento oui oui
Tardis oui oui
Hyperliquid oui oui
BitMEX oui oui
Architect AX oui
Sandbox oui oui
Blockchain oui oui

Par exemple pour Binance, le code Rust dans crates/adapters/binance/src/futures/data.rs (~1500 lignes) implémente le vrai client de données live (connexions WebSocket, parsing des messages, gestion de l’order book,…). Le code contient même un sous-dossier python/ avec des bindings PyO3 pour exposer certains types (enums, clients HTTP/WebSocket) à Python.

Côté Python, nautilus_trader/adapters/binance/data.py est la couche qui orchestre le tout comme la configuration, les factories, et certains traitements de haut niveau mais qui délègue le travail lourd au Rust.


2. Adapters Python pur (quelques-uns)

Certains adapters n’existent qu’en Python, sans contrepartie Rust:

Adapter Rust Python
Interactive Brokers non oui
Betfair non oui (+ un peu de Cython pour l’orderbook)
Polymarket non oui
dYdX v4 (legacy) non oui

3. Le template Le dossier nautilus_trader/adapters/_template/ contient un squelette Python pour créer de nouveaux adapters. Il est en Python pur:

_template/
├── __init__.py
├── core.py
├── data.py
├── execution.py
└── providers.py

Installation sur OSX

Les bases de données ne sont pas requises pour commencer. Elles sont optionnelles et servent à des cas d’usage spécifiques:

Service Rôle Obligatoire ?
Redis Cache persistant et/ou message bus partagé entre instances Non
PostgreSQL Stockage durable des ordres, positions, instruments Non

Pré-requis

Outil Version Pourquoi
Python 3.12 - 3.14 Runtime principal
Rust (via rustup) 1.93.1 stable Compilation des crates
clang (fourni par Xcode) Compilateur C pour les extensions Cython
uv 0.10.3+ Gestionnaire de packages Python recommandé
Cap’n Proto 1.3.0 Compilation des schémas de sérialisation

# Installation de Rust
curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env
# Ou update 
# rustup update stable

# uv (gestionnaire de packages Python)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Cap'n Proto
brew install capnp

git clone https://github.com/nautechsystems/nautilus_trader
git checkout master
cd nautilus_trader
export PYO3_PYTHON=$(pwd)/.venv/bin/python
make install
# Plus tard pour itérer rapidement: 
# make install-debug
uv run python -c "import nautilus_trader; print(nautilus_trader.__version__)"
# 1.222.0
# uv run python -m pip list

Utilisation basique

Commande Description
make install Build release + install toutes les dépendances
make install-debug Build debug (plus rapide, pour le dev)
make build-debug Recompiler après modification de .rs, .pyx, .pxd
make clean Nettoyer tous les artefacts de build
make format Formater le code Rust et Python
make pre-commit Lancer tous les hooks pre-commit

Organisation des exemples

Le dossier examples/ est organisé autour de 3 environnements d’exécution + un dossier utilitaire:


1. backtest/: Données historiques, exchange simulé

Si on fournit des données historiques, le moteur simule un exchange et exécute une stratégie dessus. Aucune connexion réseau, aucune clé API est nécessaire.

Le pattern est toujours le même: Engine -> Venue -> Instrument -> Data -> Strategy -> Run.

Il y a aussi 11 exemples tutoriels numérotés (example_01 à example_11) qui enseignent chacun un concept:

Exemple Concept enseigné
01 Charger des bars depuis un CSV custom
02 Utiliser les timers de l’horloge
03 Agrégation de bars
04 Utiliser le data catalog
05 Utiliser le portfolio
06 Utiliser le cache
07 Utiliser les indicateurs
08 Indicateurs en cascade
09 Messaging via le message bus
10 Messaging via un Actor (data)
11 Messaging via un Actor (signals)

Chaque tutoriel a un run_example.py (le lanceur) et un strategy.py (la logique de trading).


2. sandbox/: Données live, exécution simulée

C’est un mode hybride. On se connectes à un vrai exchange pour recevoir des données de marché en temps réel, mais les ordres sont exécutés dans un simulateur local. C’est vraiment parfait pour tester une stratégie dans des conditions réelles sans risquer d’argent.

# source binance_spot_futures_sandbox.py

data_clients={
    "BINANCE_FUTURES": BinanceDataClientConfig(  # <-- Données RÉELLES de Binance
        // ...
    ),
    "BINANCE_SPOT": BinanceDataClientConfig(     # <-- Données RÉELLES de Binance
        // ...
    ),
},
exec_clients={
    "BINANCE_FUTURES": SandboxExecutionClientConfig(  # <-- Exécution SIMULÉE
        venue="BINANCE_FUTURES",
        starting_balances=["10_000 USDC", "0.005 BTC"],
    ),
    "BINANCE_SPOT": SandboxExecutionClientConfig(     # <-- Exécution SIMULÉE
        venue="BINANCE_SPOT",
        starting_balances=["1_000 USDC", "0.001 BTC"],
    ),
},

3. live/: Données live, exécution live

Dans cette section, c’est du vrai trading. C’est Organisé par exchange, chaque sous-dossier contient typiquement:

  • Un data tester (*_data_tester.py) qui se connecte et affiche les données reçues, sans trader
  • Un exec tester (*_exec_tester.py) qui teste le passage d’ordres réels
  • Des stratégies (*_ema_cross.py, *_market_maker.py, etc.) qui sont des exemples complets.

Indicateur disponibles

Moyennes mobiles

Indicateur Abréviation Description
SimpleMovingAverage SMA Moyenne arithmétique sur une fenêtre glissante
ExponentialMovingAverage EMA Moyenne exponentielle: pondère davantage les données récentes
DoubleExponentialMovingAverage DEMA Double exponentielle: réduit encore le retard
WeightedMovingAverage WMA Moyenne pondérée linéairement
HullMovingAverage HMA Hull: très réactive avec peu de lag
AdaptiveMovingAverage AMA Kaufman: s’adapte au bruit du marché
WilderMovingAverage RMA Wilder: utilisée dans le calcul du RSI
VariableIndexDynamicAverage VIDYA Variable: s’ajuste dynamiquement à la volatilité
LinearRegression LR Régression linéaire glissante
VolumeWeightedAveragePrice VWAP Prix moyen pondéré par le volume

Momentum

Indicateur Abréviation Description
RelativeStrengthIndex RSI Force relative: détection des zones de surachat/survente
MovingAverageConvergenceDivergence MACD Convergence/divergence de moyennes mobiles
BollingerBands BB Bandes de volatilité autour d’une moyenne mobile
Stochastics STOCH Oscillateur stochastique (%K, %D)
CommodityChannelIndex CCI Mesure l’écart du prix par rapport à sa moyenne statistique
ChandeMomentumOscillator CMO Oscillateur de momentum de Chande
RateOfChange ROC Taux de variation en pourcentage
AroonOscillator AROON Détection de tendance et de sa force
ArcherMovingAveragesTrends AMAT Identification de tendance par croisement de moyennes
DirectionalMovement DM Mouvement directionnel (ADX, +DI, -DI)
PsychologicalLine PSL Pourcentage de bougies haussières sur une fenêtre
Swings Détection de points hauts et bas (swing points)
Bias Écart relatif du prix par rapport à une moyenne mobile

Volatilité

Indicateur Abréviation Description
AverageTrueRange ATR Mesure de la volatilité moyenne
DonchianChannel DC Canal basé sur le plus haut/bas des N dernières périodes
KeltnerChannel KC Canal basé sur l’EMA ± un multiple de l’ATR
KeltnerPosition KP Position relative du prix dans le canal de Keltner
VolatilityRatio VR Ratio entre la volatilité récente et historique
VerticalHorizontalFilter VHF Filtre qui distingue tendance et range
RelativeVolatilityIndex RVI Index de volatilité relative

Volume

Indicateur Abréviation Description
OnBalanceVolume OBV Volume cumulé pondéré par la direction du prix
KlingerVolumeOscillator KVO Oscillateur de flux monétaire de Klinger
Pressure Mesure de la pression acheteuse vs vendeuse

Ratio et analyse

Indicateur Abréviation Description
EfficiencyRatio ER Ratio d’efficience de Kaufman (signal/bruit)
SpreadAnalyzer Analyse du spread bid-ask
BookImbalanceRatio Ratio de déséquilibre du carnet d’ordres

Divers

Indicateur Abréviation Description
FuzzyCandlesticks Classification des bougies par logique floue (fuzzy logic)

Ichimoku est absent 😢


Analyse d’exemples

Voici la description des exemples de 4 exchanges dans examples/live/:

Binance (7 fichiers)

Fichier Stratégie Description
binance_data_tester.py DataTester Connexion data-only, affiche quotes/trades/bars/book. Pas de trading.
binance_spot_ema_cross.py EMACross Croisement EMA 10/20 sur ETHUSDT Spot, ordres de 0.010 ETH
binance_futures_testnet_ema_cross.py EMACross Même stratégie mais sur Futures testnet (ETHUSDT-PERP), mode hedging
binance_spot_ema_cross_bracket_algo.py EMACrossBracketAlgo + TWAP EMA cross avec ordres bracket (TP/SL basés sur ATR) et exécution TWAP
binance_spot_exec_tester.py ExecTester Test de passage d’ordres (limit post-only, market IOC). Pas de stratégie.
binance_spot_testnet_exec_tester.py ExecTester Idem sur testnet
binance_futures_testnet_exec_tester.py ExecTester Idem sur Futures testnet
binance_spot_and_futures_market_maker.py VolatilityMarketMaker x2 Market making sur Spot ET Futures simultanément (2 exchanges, 2 stratégies)

Bybit (8 fichiers)

Fichier Stratégie Description
bybit_data_tester.py DataTester Data-only (LINEAR ou INVERSE)
bybit_ema_cross.py EMACross EMA 10/20 sur ETHUSDT-LINEAR
bybit_ema_cross_bracket_algo.py EMACrossBracketAlgo + TWAP EMA cross avec bracket orders et TWAP
bybit_ema_cross_stop_entry.py EMACrossStopEntry EMA cross avec entrée par stop order et trailing stop ATR
bybit_ema_cross_with_trailing_stop.py EMACrossTrailingStop EMA cross avec trailing stop en basis points
bybit_exec_tester.py ExecTester Test d’exécution (SPOT/LINEAR/INVERSE/OPTION)
bybit_options_data_collector.py BybitOptionsDataCollector Collecte les données d’options BTC en parquet
bybit_request_custom_endpoint.py RequestDemoStrategy Démo de requête custom (ticker) toutes les 10s

OKX (3 fichiers)

Fichier Stratégie Description
okx_data_tester.py DataTester Spot + Swap, quotes/trades/mark/funding
okx_exec_tester.py ExecTester SPOT/MARGIN/SWAP/FUTURES/OPTION
okx_spot_swap_quoter.py SpotSwapQuoter Quote ETH-USDT Spot et ETH-USDT-SWAP simultanément (2 instruments, 1 exchange)

Interactive Brokers (8 fichiers)

Fichier Stratégie Description
connect_with_dockerized_gateway.py SubscribeStrategy Connexion via IB Gateway Docker, SPY/ES/CL/EUR.USD
connect_with_tws.py SubscribeStrategy Connexion via TWS local
contract_download.py Script utilitaire Télécharge les définitions d’instruments (NSE NIFTY50)
historical_download.py Script utilitaire Télécharge des données historiques AAPL en parquet
with_databento_client.py SubscribeStrategy Données via Databento + exécution via IB (2 sources)
notebooks/bracket_order_example.py Bracket order Ordre bracket sur ES futures avec OCO TP/SL
notebooks/oca_group_example.py OCA group Groupe OCA (One-Cancels-All) sur ES
notebooks/spread_example.py SpreadTestStrategy Calendar spread ES ou options spread, multi-leg

Voilà c’est tout pour cette première analyse. Je vais maintenant creuser du côté du coeur en Rust, du côté de l’arbitrage (en Python et surtout en Rust pour maximiser la latence), des screeners basiques pour trouver des cadeaux à trader et je vais peut être voir si je ne peux pas contribuer sur la création d’un indicateur ou stratégie avec Ichimoku. J’écrirais sans doute un autre article sur cet outil prochainement car je passe énormément de temps sur le sujet du trading chaque semaine et je ne documente jamais. Je ne suis pas trader pro mais je regarde presque quotidiennement depuis 4 ou 5 ans des vidéos d’analyse technique et je passe très régulièrement des trades sur des CEX. Bref pouvoir combiner 2 passions (Dev avec Rust + Python & trading) c’est top.