Série Algo Trading — De 100K au Million — Partie 5 sur 12

Exécution & Market Microstructure

Système d'exécution multi-marchés : OMS, routage intelligent, TWAP/VWAP, slippage control, gestion des horaires US/EU/APAC, et monitoring des fills en temps réel.

Smart Routing Multi-Timezone TWAP/VWAP Fill Analysis
Algo Trading — De 100K au Million5/12
MicrostructureOMSAlgos ExecMulti-MarchésSlippageMonitoring
Market microstructure — Ce qui se passe vraiment

Comprendre la microstructure pour mieux exécuter

La microstructure des marchés étudie comment les prix se forment tick par tick. Pour un trader algo, la comprendre est la différence entre perdre 0.5% par trade en slippage (catastrophique sur 1000 trades/an) et gagner 0.05% en execution alpha.

Le carnet d'ordres — L'anatomie d'un marché

Spread, depth, et market impact

  • Bid-Ask Spread : Coût minimum d'un aller-retour. Sur les large-caps US : 1-3 bps. Sur les small-caps EU : 20-50 bps.
  • Book Depth : Volume disponible aux 5 meilleurs niveaux. Détermine combien on peut acheter sans impacter le prix.
  • Market Impact : Le slippage causé par notre propre ordre. Modèle standard : Impact = σ × √(Q/V) où Q = taille de l'ordre, V = volume quotidien moyen.
  • Résilience : Vitesse à laquelle le carnet se regarnit après un trade. Les actions très liquides se regarnissent en secondes.

Impact de marché par type d'actif

Type d'actifADV typiqueSpread moyenImpact pour $10KImpact pour $50KFenêtre d'exécution
US Large-Cap (AAPL, MSFT)$5B+1-2 bps~0 bps~0 bpsMarket order OK
US Mid-Cap ($5-30B)$100-500M3-8 bps1-2 bps3-5 bpsLimit order
US Small-Cap ($1-5B)$10-100M10-30 bps3-5 bps10-20 bpsTWAP 30min
EU Large-Cap (ASML, SAP)€200M-1B5-15 bps2-5 bps5-10 bpsLimit order
EU Mid-Cap€20-200M15-40 bps5-10 bps15-30 bpsTWAP 1h
APAC (TSE, HKEX)Variable10-30 bps3-8 bps10-25 bpsTWAP adaptatif
ETF (SPY, QQQ)$20B+1 bps~0 bps~0 bpsMarket order OK

La règle des 1% ADV

Ne jamais placer un ordre représentant plus de 1% du volume quotidien moyen (ADV) d'une action en un seul bloc. Au-delà de ce seuil, le market impact devient significatif et potentiellement détectable par les prédateurs HFT. Pour notre portefeuille de 100K€ démarrant, cette contrainte est rarement atteinte sur les large-caps mais critique sur les small-caps EU.

Order Management System (OMS)

OMS — Le système nerveux de l'exécution

L'OMS est le composant qui transforme les signaux du méta-allocateur en ordres réels envoyés au broker. Il gère le cycle de vie complet d'un ordre : création, validation, envoi, suivi, fill, et reporting.

Architecture de l'OMS

claude -p "Implémente l'OMS dans execution/oms.py :

from enum import Enum
from dataclasses import dataclass
from datetime import datetime
import asyncio

class OrderStatus(Enum):
    PENDING = 'pending'          # Créé, en attente de validation
    VALIDATED = 'validated'      # Passé les checks pre-trade
    SUBMITTED = 'submitted'      # Envoyé au broker
    PARTIAL_FILL = 'partial'     # Partiellement exécuté
    FILLED = 'filled'            # Entièrement exécuté
    CANCELLED = 'cancelled'      # Annulé (par nous ou par le broker)
    REJECTED = 'rejected'        # Rejeté par le broker
    EXPIRED = 'expired'          # TTL dépassé sans fill

class OrderType(Enum):
    MARKET = 'MKT'
    LIMIT = 'LMT'
    LIMIT_ON_CLOSE = 'LOC'       # Exécuté au prix de clôture
    ADAPTIVE = 'IBALGO:Adaptive' # Algo IBKR natif (patient/urgent)
    TWAP = 'TWAP'                # Notre implémentation
    VWAP = 'VWAP'                # Notre implémentation

@dataclass
class Order:
    id: str                      # UUID unique
    symbol: str                  # e.g. 'AAPL' ou 'ASML-AMS'
    side: str                    # 'BUY' ou 'SELL'
    quantity: int                # Nombre d'actions
    order_type: OrderType
    limit_price: float | None    # None pour MARKET
    strategy: str                # Stratégie source
    urgency: str                 # 'low', 'medium', 'high', 'emergency'
    ttl_minutes: int             # Time-to-live avant expiration
    max_participation_rate: float # Max % du volume (ex: 0.05 = 5%)
    created_at: datetime
    status: OrderStatus = OrderStatus.PENDING
    filled_qty: int = 0
    avg_fill_price: float = 0.0
    slippage_bps: float = 0.0

class OrderManagementSystem:
    '''Gestionnaire du cycle de vie des ordres.

    Pre-trade checks (validate()):
    1. Position finale respecte les contraintes de portefeuille ?
    2. Taille de l'ordre < 1% de l'ADV ?
    3. Marché ouvert pour ce symbole ?
    4. Pas de duplication (même symbole+side dans les 5 dernières minutes) ?
    5. Capital disponible suffisant (cash + sells en cours) ?
    6. Pas de trading halt sur ce symbole ?

    Routing logic (route()):
    - Large-cap + urgence low: LIMIT au mid-price, TTL 2h
    - Large-cap + urgence high: ADAPTIVE (IBKR algo)
    - Small-cap: TWAP sur 30-60min
    - Clôture (dernier 30min): LOC
    - Emergency (circuit-breaker): MARKET immédiat

    Fill management:
    - Partial fills: relancer avec le residual
    - Unfilled après TTL: annuler + alerter si > 20% unfilled
    - Amélioration de prix: logger le positive slippage

    Post-trade reporting:
    - Slippage = (fill_price - decision_price) / decision_price × 10000 bps
    - Stocker dans fills.parquet pour analyse
    '''
"

Pre-trade Risk Checks — Les garde-fous en temps réel

CheckConditionAction si échecSeverité
Position maxPosition résultante > 10% NAVRéduire la tailleHard block
ADV limitOrdre > 1% de l'ADVDécouper en TWAPAuto-fix
Marché ouvertBourse fermée ou pre/post-marketQueue pour prochaine ouvertureSoft delay
DuplicationMême symbole+side en < 5minRejeter + alerteHard block
CapitalCash insuffisant pour l'achatRejeter + alerteHard block
Trading haltSymbole en halt (SEC, LULD)Queue pour repriseHard block
Fat fingerTaille > 5× la taille moyenne historiqueRejeter + alerte DiscordHard block
Prix aberrantLimit price > ±5% du mid-priceRejeter + alerteHard block
Algorithmes d'exécution

TWAP, VWAP, et Adaptive — 3 algos pour 3 situations

1. TWAP — Time-Weighted Average Price

Le TWAP découpe un gros ordre en tranches égales exécutées à intervalles réguliers. Idéal pour les actions moyennement liquides où on veut minimiser le market impact.

claude -p "Implémente un TWAPExecutor dans execution/algos/twap.py :

class TWAPExecutor:
    '''Exécution TWAP avec gestion des partial fills.

    Paramètres:
    - total_qty: quantité totale à exécuter
    - duration_minutes: durée totale (ex: 30min, 60min)
    - n_slices: nombre de tranches (ex: 10)
    - order_type_per_slice: LIMIT au mid-price avec offset
    - max_participation: max % du volume par tranche

    Algorithme:
    1. Calculer interval = duration / n_slices
    2. slice_qty = total_qty / n_slices (arrondi)
    3. Toutes les `interval` minutes:
       a. Calculer le mid-price actuel
       b. Placer un LIMIT à mid-price + offset (0 pour buy, -0 pour sell)
       c. TTL = interval - 10sec (cancel avant prochaine tranche)
       d. Si partial fill, accumuler le residual
    4. Dernière tranche: envoyer tout le residual en ADAPTIVE

    Anti-gaming:
    - Ajouter un jitter aléatoire de ±20% sur l'interval
    - Varier la taille des tranches (±30%) pour être moins prédictible
    - Ne pas exécuter si le spread > 2× le spread médian (marché stressé)
    '''
"

2. VWAP — Volume-Weighted Average Price

Le VWAP adapte la taille des tranches au profil de volume intraday. Plus de volume en open et close → plus grosses tranches à ces moments. Objectif : battre le VWAP du jour.

claude -p "Implémente un VWAPExecutor dans execution/algos/vwap.py :

class VWAPExecutor:
    '''Exécution VWAP basée sur le profil de volume historique.

    1. Charger le profil de volume intraday moyen (30 jours)
       → volume_pct[i] = volume_bucket_i / total_daily_volume
    2. Pour chaque bucket de 5 minutes:
       target_qty[i] = total_qty × volume_pct[i]
    3. Placer les tranches proportionnellement
    4. Tracking: calculer le VWAP réalisé vs VWAP marché

    Le volume profile est typiquement en U:
    - 9:30-10:00 (US): 15-20% du volume
    - 10:00-15:30: 50-60% (réparti uniformément)
    - 15:30-16:00: 20-25% du volume

    Avantage vs TWAP: meilleur prix moyen en marché normal
    Inconvénient: prédictible si quelqu'un connaît notre profil cible
    '''
"

3. IBKR Adaptive Algo — Pour l'urgence

Interactive Brokers fournit un algorithme Adaptive natif qui ajuste dynamiquement entre passive (limit) et aggressive (market) selon les conditions. On l'utilise pour les ordres urgents.

claude -p "Implémente l'IBKRAdaptiveRouter dans execution/algos/adaptive.py :

class IBKRAdaptiveRouter:
    '''Wrapper pour l'algo Adaptive d'IBKR via ib_insync.

    Modes:
    - Patient: commence passif (limit au bid/ask), escalade si non-fill
    - Normal: mix 50/50 passif/agressif
    - Urgent: commence agressif, remplit au plus vite

    Mapping urgence → mode IBKR:
    - urgency='low' → Patient, TTL=4h
    - urgency='medium' → Normal, TTL=1h
    - urgency='high' → Urgent, TTL=15min
    - urgency='emergency' → MARKET (pas d'algo)
    '''

    async def execute(self, order: Order) -> Fill:
        from ib_insync import IB, Stock, LimitOrder, MarketOrder
        # Créer le contrat IBKR
        contract = Stock(order.symbol, exchange, currency)
        # Qualifier le contrat
        await self.ib.qualifyContractsAsync(contract)
        # Créer l'ordre avec algo params
        ib_order = LimitOrder(
            order.side, order.quantity, order.limit_price,
            algoStrategy='Adaptive',
            algoParams=[TagValue('adaptivePriority', priority)]
        )
        trade = self.ib.placeOrder(contract, ib_order)
        # Monitor fills...
"

Comparaison des algos d'exécution

AlgoCas d'usageSlippage typiqueFill ratePrédictibilité
Market OrderEmergency uniquement5-50 bps100%N/A
Limit OrderLarge-caps, pas d'urgence-2 à +5 bps60-80%Faible
TWAPMid/small-caps, gros ordres2-10 bps90-95%Moyenne
VWAPLarge-caps, benchmark VWAP1-5 bps95%Élevée
IBKR AdaptiveUrgence moyenne à haute3-15 bps95-99%Faible
LOC (Limit on Close)Rebalancement fin de journée1-3 bps99%Aucune
Exécution multi-marchés

Trading sur 3 fuseaux horaires — US, Europe, APAC

Notre univers couvre 3 régions, chacune avec ses horaires, ses conventions, et ses particularités. Le scheduler d'exécution doit orchestrer tout cela de manière fluide.

Horaires des marchés

MarchéOuverture (UTC)Fermeture (UTC)Pre-marketCurrencySettlement
NYSE / NASDAQ14:3021:0010:00-14:30USDT+1
Euronext Paris08:0016:3007:15-08:00EURT+2
Xetra (Francfort)08:0016:3007:30-08:00EURT+2
LSE (Londres)08:0016:30GBPT+1
TSE (Tokyo)00:0006:00JPYT+2
HKEX (Hong Kong)01:3008:0001:00-01:30HKDT+2
ASX (Sydney)00:0006:00AUDT+2

Le scheduler d'exécution multi-marché

claude -p "Implémente le MultiMarketScheduler dans execution/scheduler.py :

class MultiMarketScheduler:
    '''Orchestre l'exécution sur 3 fuseaux horaires.

    Timeline quotidienne (UTC):
    ─────────────────────────────────────────────
    00:00  │ TSE/ASX ouvrent → Exécuter ordres APAC
    01:30  │ HKEX ouvre → Exécuter ordres HK
    06:00  │ TSE/ASX ferment → Réconcilier APAC
    08:00  │ EU ouvre → Exécuter ordres Europe
    14:30  │ US ouvre → Exécuter ordres US
    16:30  │ EU ferme → Réconcilier Europe
    20:00  │ Pipeline allocation (MetaAllocator)
    21:00  │ US ferme → Réconcilier US
    21:30  │ Post-trade reporting + Discord summary
    ─────────────────────────────────────────────

    Pour chaque marché:
    1. Attendre l'ouverture
    2. Attendre 15min (éviter la volatilité d'ouverture)
    3. Exécuter les ordres par priorité (high → low)
    4. Pour les gros ordres: TWAP sur la session
    5. 30min avant la fermeture: convertir les unfilled en LOC
    6. Réconcilier: vérifier fills, calculer slippage, logger

    Gestion du FX:
    - Comptes IBKR multi-devises (USD, EUR, GBP, JPY, HKD, AUD)
    - Pas de conversion FX automatique (IBKR gère le margin)
    - Si cash EUR insuffisant pour achat EU: alerter (pas de FX auto)
    '''
"

Gestion des jours fériés et événements spéciaux

ÉvénementImpactAction du scheduler
Jour férié USNYSE/NASDAQ fermésSkip ordres US, exécuter EU/APAC normalement
Jour férié EUEuronext/Xetra fermésSkip ordres EU, exécuter US/APAC normalement
FOMC announcementVolatilité extrême 14:00 UTCSuspendre les ordres US 13:30-15:00 UTC
NFP (premier vendredi)Spike de volume 12:30 UTCRéduire la participation rate de 50%
Earnings du tickerGap potentielNe pas exécuter avant l'annonce
Triple witchingVolume anormal, spreads élargisBasculer tout en TWAP, réduire taille
Circuit breakerMarché halt 15minPause automatique, reprise après halt
Slippage control & Transaction Cost Analysis

Mesurer et réduire les coûts de transaction

Le slippage est l'ennemi silencieux du trader algo. Sur 1000 trades/an, même 5 bps de slippage par trade = 5% de rendement perdu. La Transaction Cost Analysis (TCA) est le processus de mesure et d'optimisation continue.

Décomposition du coût total d'un trade

ComposanteTypique US large-capTypique EU mid-capTypique APAC small-cap
Commission broker0.5 bps1.0 bps2.0 bps
Half-spread1.0 bps8.0 bps15.0 bps
Market impact0.5 bps5.0 bps12.0 bps
Timing cost2.0 bps3.0 bps5.0 bps
Opportunity cost1.0 bps3.0 bps5.0 bps
Total one-way5.0 bps20.0 bps39.0 bps
Total round-trip10.0 bps40.0 bps78.0 bps

Implementation du TCA

claude -p "Implémente un TransactionCostAnalyzer dans execution/tca.py :

class TransactionCostAnalyzer:
    '''Analyse post-trade de chaque fill.

    Pour chaque fill, calculer:
    1. Slippage vs decision_price (prix au moment du signal)
    2. Slippage vs arrival_price (prix à la soumission de l'ordre)
    3. Slippage vs VWAP (benchmark standard)
    4. Implementation Shortfall = decision_price → fill_price (total cost)

    Stockage: fills.parquet avec colonnes:
    [timestamp, symbol, side, qty, fill_price, decision_price,
     arrival_price, vwap_benchmark, slippage_bps, commission,
     market_impact_estimate, algo_used, strategy, region]

    Reporting hebdomadaire (dimanche):
    - Slippage moyen par algo (TWAP vs VWAP vs Adaptive vs Market)
    - Slippage moyen par région (US vs EU vs APAC)
    - Slippage moyen par taille d'ordre (déciles)
    - Top 10 fills les plus coûteux (investigation)
    - Trend du slippage sur les 4 dernières semaines

    Si slippage moyen > 2× la target:
    → Alerte Discord + ajuster les algos automatiquement
    '''
"

Optimisation continue du slippage

Feedback loop d'optimisation

Chaque semaine, le système analyse les fills de la semaine et ajuste automatiquement :

  • Seuil TWAP vs Limit : Si les limits sont souvent unfilled sur un ticker, basculer en TWAP
  • Durée TWAP : Si le slippage TWAP est élevé, allonger la durée (30min → 60min)
  • Participation rate : Réduire si le market impact est détectable
  • Timing : Éviter les premiers 15min pour les tickers à volatilité d'ouverture
  • Jours à éviter : Certains tickers ont un slippage anormal les lundis ou vendredis
Monitoring temps réel de l'exécution

Dashboard de monitoring et alertes Discord

L'exécution doit être monitorée en temps réel. Le dashboard couvre 3 dimensions : les ordres en cours, les positions résultantes, et la santé du système.

Alertes Discord pour l'exécution

AlerteTriggerUrgenceAction requise
🔴 Ordre rejetéBroker rejette l'ordreHauteInvestiguer la raison
🟡 Fill lent< 50% filled après 50% du TTLMoyenneConsidérer escalade (ADAPTIVE)
🔴 Slippage excessifSlippage > 20 bps sur un fillHauteReview le ticker/algo
🟡 Connection perdueDéconnexion IBKR > 30secHauteAuto-reconnect, vérifier ordres
🔴 Position divergencePosition IBKR ≠ position interneCritiqueStop trading, réconcilier
🟢 Exécution complèteTous les ordres du jour filledInfoAucune (confirmation)
🟡 Unfilled significatif> 20% des ordres non exécutésMoyenneAjuster les algos pour demain
claude -p "Implémente les alertes Discord d'exécution dans execution/alerts.py :

class ExecutionAlertManager:
    '''Envoie des alertes Discord formatées pour chaque événement d'exécution.

    Utilise discord.py webhook pour envoyer des embeds riches:

    Embed fill:
    ┌────────────────────────────────────────┐
    │ ✅ FILL: AAPL BUY 150 @ $182.34      │
    │ Slippage: +1.2 bps vs VWAP            │
    │ Algo: TWAP (30min, 8 slices)          │
    │ Stratégie: CS_Momentum                 │
    │ Region: US │ Commission: $0.75         │
    └────────────────────────────────────────┘

    Embed daily summary (21:30 UTC):
    ┌────────────────────────────────────────┐
    │ 📊 EXECUTION SUMMARY - 2026-02-28     │
    │ Orders: 24 submitted, 22 filled, 2 LOC│
    │ Fill rate: 91.7%                       │
    │ Avg slippage: 3.2 bps (target: 5 bps) │
    │ Best: ASML -1.5 bps (saved €12)       │
    │ Worst: 7203.T +18.2 bps (cost €45)    │
    │ Total commission: $18.50               │
    │ Net execution cost: $67.30 (4.1 bps)  │
    └────────────────────────────────────────┘
    '''
"

Réconciliation de position

La réconciliation est non-négociable

Après chaque session de marché, le système compare les positions internes (notre base de données) avec les positions réelles chez IBKR. Toute divergence → arrêt immédiat du trading + alerte Discord critique. Les causes typiques :

  • Corporate action : split, merge, spin-off non détecté
  • Fill manqué : notre callback n'a pas reçu le fill (réseau)
  • Double submission : bug qui envoie le même ordre 2 fois
  • Annulation broker : IBKR annule un fill (très rare mais possible)

La réconciliation automatique est lancée 3 fois par jour : après fermeture de chaque marché.

Prochaine étape — Stratégies Momentum Cross-Region

L'infrastructure est maintenant complète : data pipeline, alpha factors, portfolio construction, et exécution. Il est temps de construire nos premières stratégies de production. La Partie 6 couvre les 4 stratégies momentum — le moteur principal du portefeuille en régime Risk-On.

Points clés de cette partie

  • Market impact modèle : Impact = σ × √(Q/V), ne jamais dépasser 1% ADV
  • OMS complet : 8 pre-trade checks, cycle de vie PENDING → FILLED
  • 3 algos d'exécution : TWAP (mid-caps), VWAP (large-caps), Adaptive (urgent)
  • Multi-marchés : Scheduler UTC couvrant APAC → EU → US, gestion FX multi-devises
  • TCA systématique : Mesure du slippage sur 5 dimensions, feedback loop hebdomadaire
  • Monitoring temps réel : Alertes Discord granulaires + daily summary
  • Réconciliation : 3× par jour, toute divergence = stop trading immédiat
Partie suivante Stratégies Momentum Cross-Region →
Algo Trading — De 100K au Million5/12