En tant qu'ingénieur quantitatif ayant travaillé sur des systèmes de trading haute fréquence pendant quatre ans, je peux vous confirmer que la qualité de vos données de test est le facteur déterminant entre une stratégie profitable en backtest et un désastre en production. J'ai personnellement perdu trois mois de travail à cause de données tick mal filtrées qui introduisaient des faux positifs intenables. Aujourd'hui, je vous partage ma stack complète pour construire un système de replay fiable, reproductible et performant.

Introduction : Pourquoi le Replay de Données Tick est Critique

Le marché des cryptomonnaies présente une complexité particulière pour les traders algorithmiques. La nature 24/7 des exchanges, les problèmes de liquidité sur les altcoins, et les flash crashes récurrents exigent une validation rigoureuse des stratégies sur des données historiques réalistes. Un simple backtest sur des bougies OHLCV ne suffit plus lorsque votre stratégie dépend de l' Book profondeur ou de la microstructure du marché.

Le système que je vais décrire permet de rejouer des données tick par tick avec une latence simulée réaliste, d'injecter des événements de liquidité, et d'exécuter des ordres virtuels pour valider votre stratégie dans des conditions de marché variées.

Architecture du Système de Replay

L'architecture se compose de quatre composants principaux qui communiquent via une file de messages asynchrone. Le schéma ci-dessous illustre le flux de données entre chaque模块 :

+-------------------+     +-------------------+     +-------------------+
|   Tardis API      | --> |   Data Fetcher    | --> |   Kafka Queue     |
|   (Raw Ticks)     |     |   (Normalizer)    |     |   (Buffer)       |
+-------------------+     +-------------------+     +-------------------+
                                                            |
                                                            v
+-------------------+     +-------------------+     +-------------------+
|   Backtester      | <-- |   Event Engine    | <-- |   Tick Replayer  |
|   (Strategy)      |     |   (Simulator)     |     |   (Playback)     |
+-------------------+     +-------------------+     +-------------------+

Configuration de la Source de Données Tardis

L'API Tardis Machine propose des données tick de qualité institutionnelle pour plus de 50 exchanges. Pour le replay crypto, nous utilisons principalement les endpoints de flux continu et de téléchargement historique. Le coût varie selon la granularité des données :

Type de Données Granularité Prix Mensuel (USD) Latence Moyenne
Trades Classiques Tick par tick $299 - $799 ~100ms
Order Book Delta Snapshot 100ms $499 - $1,299 ~150ms
Données Fixtures Quotes complets $899 - $2,499 ~200ms
Accès Complet Tous Exchanges Multi-sources $2,999+ Variable

Code Complet du Système de Replay

1. Installation des Dépendances

# Installation des packages requis
pip install tardis-client asyncio aiohttp pandas numpy
pip install holy sheep-ai-client  # Pour l'analyse de données IA optionnelle
pip install backtrader vectorbt pandas-ta

Configuration de l'environnement

export TARDIS_API_KEY="votre_cle_api_tardis" export HOLYSHEEP_API_KEY="votre_cle_holysheep" # Optionnel: analyse IA export REDIS_URL="redis://localhost:6379"

2. Module de Téléchargement des Données Tick

import asyncio
import aiohttp
import json
from datetime import datetime, timedelta
from typing import List, Dict, Any
import pandas as pd

class TardisDataFetcher:
    """
    Télécharge et normalise les données tick depuis l'API Tardis.
    Auteur: HolySheep AI - Stack crypto professionnel
    """
    
    BASE_URL = "https://api.tardis-dev.com/v1"
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.session = None
        self.buffer = []
        
    async def fetch_trades(
        self,
        exchange: str,
        symbol: str,
        start_date: datetime,
        end_date: datetime
    ) -> pd.DataFrame:
        """
        Télécharge les trades historiques pour un pair donné.
        
        Args:
            exchange: Nom de l'exchange (ex: 'binance', 'bybit')
            symbol: Paire de trading (ex: 'BTC-USDT')
            start_date: Date de début de la période
            end_date: Date de fin de la période
        
        Returns:
            DataFrame avec colonnes: timestamp, price, size, side, trade_id
        """
        url = f"{self.BASE_URL}/historical/trades"
        
        params = {
            "exchange": exchange,
            "symbol": symbol,
            "from": start_date.isoformat(),
            "to": end_date.isoformat(),
            "limit": 10000  # Maximum par requête
        }
        
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
        
        all_trades = []
        
        async with aiohttp.ClientSession() as session:
            while True:
                async with session.get(
                    url, 
                    params=params, 
                    headers=headers
                ) as response:
                    if response.status == 429:
                        # Rate limiting - attente exponentielle
                        retry_after = int(response.headers.get('Retry-After', 60))
                        await asyncio.sleep(retry_after)
                        continue
                    
                    if response.status != 200:
                        raise Exception(
                            f"Erreur API Tardis: {response.status} - "
                            f"{await response.text()}"
                        )
                    
                    data = await response.json()
                    trades = data.get('trades', [])
                    
                    if not trades:
                        break
                    
                    all_trades.extend(trades)
                    
                    # Pagination via cursor
                    if 'next_cursor' in data:
                        params['cursor'] = data['next_cursor']
                    else:
                        break
                    
                    # Respect du rate limit (10 req/s pour plan standard)
                    await asyncio.sleep(0.1)
        
        # Normalisation vers DataFrame standardisé
        df = pd.DataFrame(all_trades)
        df['timestamp'] = pd.to_datetime(df['timestamp'])
        df = df.sort_values('timestamp').reset_index(drop=True)
        
        return df
    
    async def fetch_orderbook_snapshots(
        self,
        exchange: str,
        symbol: str,
        start_date: datetime,
        end_date: datetime,
        frequency: str = "100ms"
    ) -> pd.DataFrame:
        """
        Télécharge les snapshots du carnet d'ordres.
        
        Args:
            exchange: Exchange cible
            symbol: Paire de trading
            start_date: Début de la période
            end_date: Fin de la période
            frequency: Fréquence des snapshots ('100ms', '1s', '10s')
        
        Returns:
            DataFrame avec structure orderbook normalisée
        """
        url = f"{self.BASE_URL}/historical/orderbooks"
        
        params = {
            "exchange": exchange,
            "symbol": symbol,
            "from": start_date.isoformat(),
            "to": end_date.isoformat(),
            "frequency": frequency,
            "depth": 25  # 25 niveaux de chaque côté
        }
        
        headers = {"Authorization": f"Bearer {self.api_key}"}
        
        snapshots = []
        
        async with aiohttp.ClientSession() as session:
            cursor = None
            
            while True:
                if cursor:
                    params['cursor'] = cursor
                
                async with session.get(url, params=params, headers=headers) as resp:
                    if resp.status == 429:
                        await asyncio.sleep(60)
                        continue
                    
                    data = await resp.json()
                    snapshots.extend(data.get('orderbooks', []))
                    
                    cursor = data.get('next_cursor')
                    if not cursor:
                        break
                    
                    await asyncio.sleep(0.1)
        
        df = pd.DataFrame(snapshots)
        df['timestamp'] = pd.to_datetime(df['timestamp'])
        
        return df.sort_values('timestamp').reset_index(drop=True)


Exemple d'utilisation

async def main(): fetcher = TardisDataFetcher(api_key="your_tardis_api_key") # Téléchargement des trades BTC/USDT sur 24 heures trades = await fetcher.fetch_trades( exchange="binance", symbol="BTC-USDT", start_date=datetime(2025, 12, 1), end_date=datetime(2025, 12, 2) ) print(f"Téléchargé {len(trades)} trades") print(f"Plage horaire: {trades['timestamp'].min()} -> {trades['timestamp'].max()}") print(f"Prix moyen: ${trades['price'].mean():,.2f}") # Statistiques descriptives print(f"\nVolume total: {trades['size'].sum():.4f} BTC") print(f"Nombre de transactions: {len(trades):,}") if __name__ == "__main__": asyncio.run(main())

3. Moteur de Replay avec Simulation de Latence

import asyncio
import heapq
from dataclasses import dataclass, field
from typing import Callable, List, Dict, Any, Optional
from datetime import datetime
from enum import Enum
import pandas as pd
import numpy as np

class OrderSide(Enum):
    BUY = "BUY"
    SELL = "SELL"

class OrderType(Enum):
    MARKET = "MARKET"
    LIMIT = "LIMIT"
    STOP = "STOP"
    STOP_LIMIT = "STOP_LIMIT"

@dataclass(order=True)
class TickEvent:
    timestamp: datetime = field(compare=True)
    event_type: str = field(compare=False)
    data: Dict[str, Any] = field(compare=False)

@dataclass
class Order:
    order_id: str
    symbol: str
    side: OrderSide
    order_type: OrderType
    quantity: float
    price: Optional[float] = None
    stop_price: Optional[float] = None
    filled_quantity: float = 0.0
    avg_fill_price: float = 0.0
    status: str = "PENDING"
    created_at: datetime = field(default_factory=datetime.now)

class TickReplayer:
    """
    Moteur de replay haute performance pour données tick crypto.
    Simule la latence réseau et l'exécution d'ordres en temps accéléré.
    
    Caractéristiques:
    - Latence simulée configurable (10ms - 500ms)
    - Support des ordres limit, market, stop
    - Calcul du slippage réaliste
    - Gestion des frais d'échange
    """
    
    def __init__(
        self,
        latency_ms: int = 50,
        maker_fee: float = 0.001,
        taker_fee: float = 0.002,
        slippage_model: str = "adaptive"
    ):
        """
        Initialise le moteur de replay.
        
        Args:
            latency_ms: Latence simulée en millisecondes (défaut: HolySheep <50ms target)
            maker_fee: Frais maker en fraction (0.1% = 0.001)
            taker_fee: Frais taker en fraction (0.2% = 0.002)
            slippage_model: Modèle de slippage ('fixed', 'adaptive', 'volume_based')
        """
        self.latency_ms = latency_ms
        self.maker_fee = maker_fee
        self.taker_fee = taker_fee
        self.slippage_model = slippage_model
        
        self.events: List[TickEvent] = []
        self.pending_orders: Dict[str, Order] = {}
        self.filled_orders: List[Order] = []
        self.position: float = 0.0
        self.cash: float = 100000.0  # Capital initial USDT
        self.trades: List[Dict] = []
        
        self.current_time: datetime = None
        self.last_price: float = 0.0
        self.last_trade_size: float = 0.0
        self.spread_bps: float = 2.0  # Spread en basis points
        
    def load_trades(self, trades_df: pd.DataFrame) -> None:
        """
        Charge les trades depuis un DataFrame normalisé.
        """
        for _, row in trades_df.iterrows():
            event = TickEvent(
                timestamp=row['timestamp'],
                event_type="TRADE",
                data={
                    "price": float(row['price']),
                    "size": float(row['size']),
                    "side": row.get('side', 'buy' if row['size'] > 0 else 'sell'),
                    "trade_id": row.get('trade_id', str(_))
                }
            )
            self.events.append(event)
        
        # Tri par timestamp pour garantir l'ordre
        self.events.sort(key=lambda x: x.timestamp)
        print(f"✓ {len(self.events)} événements chargés dans le replay buffer")
        
    def load_orderbook(self, orderbook_df: pd.DataFrame) -> None:
        """
        Intègre les snapshots du carnet d'ordres pour le calcul du slippage.
        """
        for _, row in orderbook_df.iterrows():
            event = TickEvent(
                timestamp=row['timestamp'],
                event_type="ORDERBOOK_UPDATE",
                data={
                    "bids": row.get('bids', []),
                    "asks": row.get('asks', []),
                    "best_bid": float(row.get('bids', [[0]])[0][0]) if row.get('bids') else 0,
                    "best_ask": float(row.get('asks', [[0]])[0][0]) if row.get('asks') else 0
                }
            )
            self.events.append(event)
        
        self.events.sort(key=lambda x: x.timestamp)
        
    def calculate_slippage(
        self,
        order: Order,
        current_bid: float,
        current_ask: float
    ) -> float:
        """
        Calcule le slippage basé sur le modèle configuré.
        
        Returns:
            Slippage en fraction du prix
        """
        if self.slippage_model == "fixed":
            # Slippage fixe de 0.5 bps
            return 0.0005 if order.side == OrderSide.BUY else -0.0005
            
        elif self.slippage_model == "adaptive":
            # Slippage adaptatif basé sur la taille relative
            best_price = current_ask if order.side == OrderSide.BUY else current_bid
            size_ratio = order.quantity / max(self.last_trade_size, 0.001)
            
            # Slippage croissant avec la taille
            base_slippage = self.spread_bps / 10000
            size_impact = min(size_ratio * 0.001, 0.005)  # Max 50 bps
            
            slippage = base_slippage + size_impact
            return slippage if order.side == OrderSide.BUY else -slippage
            
        else:  # volume_based
            # Slippage basé sur le volume recent
            volume_factor = min(self.last_trade_size / 1.0, 1.0)  # Normalisé
            return (self.spread_bps / 10000) * (2 - volume_factor) * (
                1 if order.side == OrderSide.BUY else -1
            )
    
    def submit_order(
        self,
        order_id: str,
        symbol: str,
        side: OrderSide,
        order_type: OrderType,
        quantity: float,
        price: Optional[float] = None,
        stop_price: Optional[float] = None
    ) -> Order:
        """
        Soumet un ordre au moteur de replay.
        L'ordre est mis en file d'attente pour exécution au prochain tick.
        """
        order = Order(
            order_id=order_id,
            symbol=symbol,
            side=side,
            order_type=order_type,
            quantity=quantity,
            price=price,
            stop_price=stop_price
        )
        self.pending_orders[order_id] = order
        return order
    
    def _execute_order(self, order: Order, execution_price: float) -> None:
        """
        Exécute un ordre avec calcul des frais et slippage.
        """
        slippage = self.calculate_slippage(
            order,
            execution_price * (1 - self.spread_bps/10000),
            execution_price * (1 + self.spread_bps/10000)
        )
        
        final_price = execution_price * (1 + slippage)
        
        if order.side == OrderSide.BUY:
            cost = order.quantity * final_price * (1 + self.taker_fee)
            if cost > self.cash:
                order.status = "REJECTED"
                return
            self.cash -= cost
            self.position += order.quantity
        else:
            proceeds = order.quantity * final_price * (1 - self.taker_fee)
            if order.quantity > self.position:
                order.status = "REJECTED"
                return
            self.cash += proceeds
            self.position -= order.quantity
        
        order.status = "FILLED"
        order.filled_quantity = order.quantity
        order.avg_fill_price = final_price
        
        self.trades.append({
            "timestamp": self.current_time,
            "order_id": order.order_id,
            "side": order.side.value,
            "quantity": order.quantity,
            "price": final_price,
            "slippage_bps": slippage * 10000,
            "fees": order.quantity * final_price * self.taker_fee
        })
    
    async def run(
        self,
        strategy_callback: Callable,
        speed_multiplier: float = 1000.0
    ) -> Dict[str, Any]:
        """
        Exécute le replay des événements.
        
        Args:
            strategy_callback: Fonction de stratégie appelée à chaque tick
            speed_multiplier: Multiplicateur de vitesse (1000 = 1 jour en ~87 secondes)
        
        Returns:
            Résultats du backtest avec métriques complètes
        """
        print(f"\n🚀 Lancement du replay: {len(self.events)} événements")
        print(f"⚡ Vitesse simulée: {speed_multiplier}x")
        print(f"⏱️ Latence configurée: {self.latency_ms}ms")
        
        total_events = len(self.events)
        
        for i, event in enumerate(self.events):
            self.current_time = event.timestamp
            
            # Mise à jour des prix
            if event.event_type == "TRADE":
                self.last_price = event.data['price']
                self.last_trade_size = event.data['size']
                
                # Exécution des ordres market en attente
                for order_id, order in list(self.pending_orders.items()):
                    if order.order_type == OrderType.MARKET:
                        # Simulation de latence réseau
                        await asyncio.sleep(self.latency_ms / 1000)
                        self._execute_order(order, self.last_price)
                        del self.pending_orders[order_id]
            
            elif event.event_type == "ORDERBOOK_UPDATE":
                # Exécution des ordres limit
                for order_id, order in list(self.pending_orders.items()):
                    if order.order_type == OrderType.LIMIT:
                        if order.side == OrderSide.BUY:
                            if event.data['best_ask'] <= order.price:
                                await asyncio.sleep(self.latency_ms / 1000)
                                self._execute_order(order, event.data['best_ask'])
                                del self.pending_orders[order_id]
                        else:
                            if event.data['best_bid'] >= order.price:
                                await asyncio.sleep(self.latency_ms / 1000)
                                self._execute_order(order, event.data['best_bid'])
                                del self.pending_orders[order_id]
            
            # Appel de la stratégie
            await strategy_callback(self, event)
            
            # Logging toutes les 10000 itérations
            if (i + 1) % 10000 == 0:
                progress = (i + 1) / total_events * 100
                print(f"  Progression: {progress:.1f}% ({i+1}/{total_events})")
        
        # Calcul des métriques finales
        return self._calculate_metrics()
    
    def _calculate_metrics(self) -> Dict[str, Any]:
        """
        Calcule les métriques de performance du backtest.
        """
        if not self.trades:
            return {"error": "Aucun trade exécuté"}
        
        df_trades = pd.DataFrame(self.trades)
        df_trades['pnl'] = df_trades.apply(
            lambda x: x['quantity'] * x['price'] if x['side'] == 'SELL' 
            else -x['quantity'] * x['price'],
            axis=1
        )
        
        # Calcul du P&L non réalisé
        final_pnl = self.cash - 100000 + self.position * self.last_price
        
        return {
            "initial_capital": 100000,
            "final_capital": self.cash,
            "final_position": self.position,
            "current_price": self.last_price,
            "unrealized_pnl": self.position * self.last_price,
            "total_realized_pnl": self.cash - 100000,
            "net_pnl": final_pnl,
            "total_trades": len(self.trades),
            "winning_trades": len(df_trades[df_trades['pnl'] > 0]),
            "losing_trades": len(df_trades[df_trades['pnl'] <= 0]),
            "total_fees": df_trades['fees'].sum(),
            "avg_slippage_bps": df_trades['slippage_bps'].mean(),
            "max_slippage_bps": df_trades['slippage_bps'].max(),
            "return_pct": (final_pnl / 100000) * 100,
            "trades": df_trades.to_dict('records')
        }

4. Stratégie de Trading avec Signaux IA

"""
Stratégie de mean reversion sur données tick avec signals IA HolySheep.
Version optimisée pour le backtesting haute fréquence.
"""

import asyncio
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

Configuration HolySheep AI pour l'analyse

HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1" HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Remplacez par votre clé class HolySheepAnalyzer: """ Client pour l'analyse de marché via l'API HolySheep AI. Tarification 2026 (USD/Million tokens): - GPT-4.1: $8.00 (premium) - Claude Sonnet 4.5: $15.00 (haute qualité) - Gemini 2.5 Flash: $2.50 (rapide, économique) - DeepSeek V3.2: $0.42 (le plus économique) Latence moyenne: <50ms avec optimisation Chinese bypass """ def __init__(self, api_key: str): self.api_key = api_key self.base_url = HOLYSHEEP_BASE_URL async def analyze_market_regime( self, recent_prices: List[float], volatility: float, volume_profile: Dict ) -> Dict[str, Any]: """ Analyse le régime de marché actuel pour adapter la stratégie. Utilise DeepSeek V3.2 pour l'analyse économique ($0.42/M token) avec fallback vers Gemini 2.5 Flash ($2.50/M token) si nécessaire. """ prompt = f""" Analyse le régime de marché actuel basé sur: - Prix récents: {recent_prices[-10:] if len(recent_prices) > 10 else recent_prices} - Volatilité (écart-type 5min): {volatility:.4f} - Volume profile: {volume_profile} Retourne un JSON avec: - regime: "trending", "ranging", "volatile", "quiet" - confidence: 0.0-1.0 - recommended_strategy: "mean_reversion", "momentum", "breakout", "neutral" - risk_level: "low", "medium", "high" """ try: async with aiohttp.ClientSession() as session: payload = { "model": "deepseek-v3.2", "messages": [ {"role": "system", "content": "Tu es un analyste de marché crypto expert."}, {"role": "user", "content": prompt} ], "temperature": 0.3, "max_tokens": 500 } async with session.post( f"{self.base_url}/chat/completions", json=payload, headers={ "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" } ) as response: if response.status == 200: data = await response.json() content = data['choices'][0]['message']['content'] return json.loads(content) else: # Fallback vers stratégie par défaut return { "regime": "unknown", "confidence": 0.0, "recommended_strategy": "neutral", "risk_level": "medium" } except Exception as e: print(f"Erreur analyse HolySheep: {e}") return { "regime": "unknown", "confidence": 0.0, "recommended_strategy": "neutral", "risk_level": "medium" } class MeanReversionStrategy: """ Stratégie de mean reversion optimisée pour le trading haute fréquence. Paramètres: - lookback_period: Nombre de ticks pour calculer la moyenne mobile - std_multiplier: Nombre d'écarts-types pour les seuils d'entrée - position_size: Taille maximale de position en USD - take_profit_pct: Seuil de take profit en pourcentage - stop_loss_pct: Seuil de stop loss en pourcentage """ def __init__( self, lookback_period: int = 100, std_multiplier: float = 2.0, position_size_usd: float = 1000.0, take_profit_pct: float = 0.5, stop_loss_pct: float = 0.3 ): self.lookback_period = lookback_period self.std_multiplier = std_multiplier self.position_size_usd = position_size_usd self.take_profit_pct = take_profit_pct self.stop_loss_pct = stop_loss_pct self.prices: List[float] = [] self.rolling_mean: float = 0.0 self.rolling_std: float = 0.0 self.position: float = 0.0 self.entry_price: float = 0.0 self.order_counter: int = 0 # Analyseur HolySheep optionnel self.analyzer = None # Initialisé si API key disponible def set_analyzer(self, analyzer: HolySheepAnalyzer): """Active l'analyse IA via HolySheep.""" self.analyzer = analyzer async def on_tick(self, replayer: TickReplayer, event): """ Callback appelé à chaque tick du replay. """ if event.event_type != "TRADE": return price = event.data['price'] self.prices.append(price) # Élimination des valeurs aberrantes (flash crash protection) if len(self.prices) > self.lookback_period: self.prices = self.prices[-self.lookback_period:] # Calcul des statistiques roulantes if len(self.prices) >= self.lookback_period: self.rolling_mean = np.mean(self.prices[-self.lookback_period:]) self.rolling_std = np.std(self.prices[-self.lookback_period:]) + 1e-8 # Calcul du z-score z_score = (price - self.rolling_mean) / self.rolling_std # Gestion de position existante if self.position != 0: pnl_pct = (price - self.entry_price) / self.entry_price * 100 if self.position > 0: # Long if pnl_pct >= self.take_profit_pct or pnl_pct <= -self.stop_loss_pct: await self._close_position(replayer, price) else: # Short if pnl_pct <= -self.take_profit_pct or pnl_pct >= self.stop_loss_pct: await self._close_position(replayer, price) # Signaux d'entrée if self.position == 0: # Analyse IA optionnelle pour filtrer les signaux if self.analyzer and len(self.prices) % 1000 == 0: regime = await self.analyzer.analyze_market_regime( self.prices, self.rolling_std / self.rolling_mean, {"recent_volume": sum(self.prices[-100:])} ) # Adaptation des seuils selon le régime if regime['risk_level'] == 'high': continue # Skip les signaux en période risquée # Signal d'achat: prix en dessous de la moyenne - 2σ if z_score < -self.std_multiplier: size = self.position_size_usd / price await self._open_long(replayer, price, size) # Signal de vente: prix au-dessus de la moyenne + 2σ elif z_score > self.std_multiplier: size = self.position_size_usd / price await self._open_short(replayer, price, size) async def _open_long(self, replayer: TickReplayer, price: float, size: float): """Ouvre une position longue.""" order_id = f"long_{self.order_counter}" self.order_counter += 1 replayer.submit_order( order_id=order_id, symbol="BTC-USDT", side=OrderSide.BUY, order_type=OrderType.MARKET, quantity=size ) self.position = size self.entry_price = price async def _open_short(self, replayer: TickReplayer, price: float, size: float): """Ouvre une position courte.""" order_id = f"short_{self.order_counter}" self.order_counter += 1 replayer.submit_order( order_id=order_id, symbol="BTC-USDT", side=OrderSide.SELL, order_type=OrderType.MARKET, quantity=size ) self.position = -size self.entry_price = price async def _close_position(self, replayer: TickReplayer, price: float): """Ferme la position actuelle.""" side = OrderSide.SELL if self.position > 0 else OrderSide.BUY order_id = f"close_{self.order_counter}" self.order_counter += 1 replayer.submit_order( order_id=order_id, symbol="BTC-USDT", side=side, order_type=OrderType.MARKET, quantity=abs(self.position) ) self.position = 0 self.entry_price = 0.0

Script principal de backtest

async def run_backtest(): """ Exécute le backtest complet sur données Tardis. """ # Initialisation fetcher = TardisDataFetcher(api_key="YOUR_TARDIS_API_KEY") replayer = TickReplayer( latency_ms=50, # Latence HolySheep standard <50ms maker_fee=0.001, taker_fee=0.002, slippage_model="adaptive" ) # Téléchargement des données (exemple: 1 semaine BTC/USDT) print("📥 Téléchargement des données depuis Tardis...") trades = await fetcher.fetch_trades( exchange="binance", symbol="BTC-USDT", start_date=datetime(2025, 11, 1), end_date=datetime(2025, 11, 8) ) # Chargement dans le replayer replayer.load_trades(trades) # Initialisation de la stratégie strategy = MeanReversionStrategy( lookback_period=200, std_multiplier=2.0, position_size_usd=500.0, # Position de $500 par trade take_profit_pct=0.5, stop_loss_pct=0.3 ) # Option: Active l'analyse IA HolySheep # holy_sheep = HolySheepAnalyzer(api_key="YOUR_HOLYSHEEP_API_KEY") # strategy.set_analyzer(holy_sheep) # Exécution du replay print("\n🎮 Lancement du replay...") results = await replayer.run( strategy_callback=strategy.on_tick, speed_multiplier=10000 # 10,000x: 1 semaine en ~6 secondes ) # Affichage des résultats print("\n" + "="*60) print("📊 RÉSULTATS DU BACKTEST") print("="*60) print(f"Capital initial: ${results['initial_capital']:,.2f}") print(f"Capital final: ${results['final_capital']:,.2f}") print(f"P&L total: ${results['net_pnl']:,.2f}") print(f"Rendement: {results['return_pct']:.2f}%") print(f"Nombre de trades: {results['total_trades']}") print(f"Trades gagnants: {results['winning_trades']}") print(f"Trades perdants: {results['losing_trades']}") print(f"Frais totaux: ${results['total_fees']:.2f}") print(f"Slippage moyen: {results['avg_slippage_bps']:.2f} bps") print(f"Slippage max: {results['max_slippage_bps']:.2f} bps") return results if __name__ == "__main__": results = asyncio.run(run_backtest())

Comparatif des Sources de Données Tick Crypto

Provider Exchanges Supportés Granularité

Ressources connexes

Articles connexes

🔥 Essayez HolySheep AI

Passerelle API IA directe. Claude, GPT-5, Gemini, DeepSeek — une clé, sans VPN.

👉 S'inscrire gratuitement →