En tant que développeur indépendant spécialisé dans les systèmes de trading algorithmique depuis maintenant quatre ans, j'ai traversé toutes les étapes possibles de frustration : des APIs qui changent sans préavis, des latences qui ruinent vos stratégies, des coûts qui explosent le budget de développement. Il y a six mois, j'ai reçu un mandat particulièrement stimulant : construire un système de backtesting haute fréquence capable de traiter les données orderbook L2 d'OKX avec une précision au millisecond près. Le défi ? Intégrer ces flux massifs tout en maintenant des coûts d'infrastructure raisonnables — et c'est là que HolySheep AI est devenu mon allié stratégique.

Cas d'Utilisation Concret : Backtesting d'une Stratégie Market-Making

Imaginons que vous développiez une stratégie de market-making sur la paire BTC/USDT d'OKX. Votre système doit :

Sans une architecture adaptée, votre système Python va s'effondrer sous le poids des données. Voici comment structurer cette intégration proprement.

Architecture de l'Intégration OKX L2

1. Configuration de l'Environnement

# Installation des dépendances
pip install okx-sdk pandas numpy asyncio aiohttp

Structure du projet

project/ ├── config/ │ ├── __init__.py │ ├── settings.py # Configuration OKX API │ └── backtest_config.py # Paramètres de backtest ├── data/ │ ├── __init__.py │ ├── okx_connector.py # Connecteur WebSocket OKX │ └── orderbook_manager.py # Gestionnaire de carnet d'ordres ├── backtest/ │ ├── __init__.py │ ├── engine.py # Moteur de backtest │ └── strategy.py # Template de stratégie ├── utils/ │ ├── __init__.py │ └── holysheep_client.py # Client API HolySheep ├── main.py └── requirements.txt

2. Connecteur WebSocket OKX L2

import asyncio
import json
import aiohttp
from datetime import datetime
from typing import Dict, List, Optional
from dataclasses import dataclass, field
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@dataclass
class OrderBookEntry:
    """Représente une entrée du carnet d'ordres L2"""
    price: float
    size: float
    side: str  # 'bid' ou 'ask'
    timestamp: int
    orders_count: int = 1

@dataclass
class OrderBook:
    """Carnet d'ordres L2 complet"""
    symbol: str
    bids: List[OrderBookEntry] = field(default_factory=list)
    asks: List[OrderBookEntry] = field(default_factory=list)
    timestamp: int = 0
    local_timestamp: float = 0.0
    
    def get_mid_price(self) -> float:
        if not self.bids or not self.asks:
            return 0.0
        return (self.bids[0].price + self.asks[0].price) / 2
    
    def get_spread_bps(self) -> float:
        """Calcule le spread en basis points"""
        if not self.bids or not self.asks or self.bids[0].price == 0:
            return 0.0
        return (self.asks[0].price - self.bids[0].price) / self.bids[0].price * 10000

class OKXL2Connector:
    """
    Connecteur WebSocket pour les données orderbook L2 d'OKX.
    Documentation: https://www.okx.com/docs-v5/
    """
    
    WS_URL = "wss://ws.okx.com:8443/ws/v5/public"
    
    def __init__(self, symbol: str = "BTC-USDT-SWAP"):
        self.symbol = symbol
        self.orderbook = OrderBook(symbol=symbol)
        self._running = False
        self._ws = None
        self._session = None
        self._buffer = []  # Buffer pour le backtesting
        self._message_count = 0
        self._last_stats_time = datetime.now()
        
    def _format_symbol(self) -> str:
        """Convertit le symbole au format OKX (ex: BTC-USDT-SWAP -> BTC-USDT-SWAP)"""
        return self.symbol
    
    async def connect(self) -> None:
        """Établit la connexion WebSocket"""
        self._session = aiohttp.ClientSession()
        self._ws = await self._session.ws_connect(self.WS_URL)
        self._running = True
        
        # Souscription au flux L2
        subscribe_msg = {
            "op": "subscribe",
            "args": [{
                "channel": "books",
                "instId": self._format_symbol()
            }]
        }
        await self._ws.send_json(subscribe_msg)
        logger.info(f"Souscrit au flux L2 pour {self.symbol}")
        
    async def _parse_orderbook_update(self, data: dict) -> Optional[OrderBook]:
        """Parse une mise à jour du carnet d'ordres"""
        try:
            if "data" not in data:
                return None
                
            for update in data["data"]:
                # Extraction des bids et asks
                bids_raw = update.get("bids", [])
                asks_raw = update.get("asks", [])
                timestamp = int(update.get("ts", 0))
                
                bids = [
                    OrderBookEntry(
                        price=float(b[0]),
                        size=float(b[1]),
                        side="bid",
                        timestamp=timestamp,
                        orders_count=int(b[2]) if len(b) > 2 else 1
                    )
                    for b in bids_raw
                ]
                
                asks = [
                    OrderBookEntry(
                        price=float(a[0]),
                        size=float(a[1]),
                        side="ask",
                        timestamp=timestamp,
                        orders_count=int(a[2]) if len(a[2]) > 2 else 1
                    )
                    for a in asks_raw
                ]
                
                # Mise à jour incrémentale ou snapshot
                if update.get("action") == "snapshot":
                    self.orderbook.bids = bids
                    self.orderbook.asks = asks
                else:
                    # Mise à jour incrémentale
                    self._apply_incremental_update(bids, asks)
                
                self.orderbook.timestamp = timestamp
                self.orderbook.local_timestamp = datetime.now().timestamp()
                
                # Stockage pour le backtest
                self._buffer.append({
                    "timestamp": timestamp,
                    "orderbook": OrderBook(
                        symbol=self.symbol,
                        bids=list(self.orderbook.bids),
                        asks=list(self.orderbook.asks),
                        timestamp=timestamp
                    )
                })
                
                self._message_count += 1
                
        except Exception as e:
            logger.error(f"Erreur de parsing: {e}")
            
        return self.orderbook
    
    def _apply_incremental_update(self, bids: List[OrderBookEntry], 
                                  asks: List[OrderBookEntry]) -> None:
        """Applique les mises à jour incrémentales au carnet"""
        for bid in bids:
            if bid.size == 0:
                # Suppression
                self.orderbook.bids = [
                    b for b in self.orderbook.bids 
                    if abs(b.price - bid.price) > 1e-8
                ]
            else:
                # Insertion ou mise à jour
                found = False
                for i, b in enumerate(self.orderbook.bids):
                    if abs(b.price - bid.price) < 1e-8:
                        self.orderbook.bids[i] = bid
                        found = True
                        break
                if not found:
                    self.orderbook.bids.append(bid)
        
        # Même logique pour les asks
        for ask in asks:
            if ask.size == 0:
                self.orderbook.asks = [
                    a for a in self.orderbook.asks 
                    if abs(a.price - ask.price) > 1e-8
                ]
            else:
                found = False
                for i, a in enumerate(self.orderbook.asks):
                    if abs(a.price - ask.price) < 1e-8:
                        self.orderbook.asks[i] = ask
                        found = True
                        break
                if not found:
                    self.orderbook.asks.append(ask)
        
        # Tri et limitation
        self.orderbook.bids.sort(key=lambda x: x.price, reverse=True)
        self.orderbook.asks.sort(key=lambda x: x.price)
        self.orderbook.bids = self.orderbook.bids[:25]  # Top 25 bids
        self.orderbook.asks = self.orderbook.asks[:25]  # Top 25 asks
    
    async def listen(self, callback=None) -> None:
        """Boucle principale d'écoute"""
        await self.connect()
        
        while self._running:
            msg = await self._ws.receive()
            
            if msg.type == aiohttp.WSMsgType.TEXT:
                data = json.loads(msg.data)
                orderbook = await self._parse_orderbook_update(data)
                
                if callback and orderbook:
                    await callback(orderbook)
                    
            elif msg.type == aiohttp.WSMsgType.ERROR:
                logger.error(f"Erreur WebSocket: {msg.data}")
                break
                
            # Logging des statistiques
            now = datetime.now()
            if (now - self._last_stats_time).seconds >= 10:
                elapsed = (now - self._last_stats_time).seconds
                rate = self._message_count / elapsed if elapsed > 0 else 0
                logger.info(f"Messages/seconde: {rate:.1f}, Buffer: {len(self._buffer)}")
                self._message_count = 0
                self._last_stats_time = now
                
    def stop(self) -> None:
        """Arrête la connexion"""
        self._running = False
        
    def get_buffer(self) -> List[dict]:
        """Retourne le buffer de données pour le backtest"""
        return self._buffer
    
    async def close(self) -> None:
        """Ferme proprement la connexion"""
        self.stop()
        if self._ws:
            await self._ws.close()
        if self._session:
            await self._session.close()

3. Intégration HolySheep pour l'Analyse IA

Ici intervient la magie HolySheep. Pour analyser les patterns de liquidité et détecter les anomalies dans votre carnet d'ordres, j'utilise leur API avec DeepSeek V3.2 — le modèle le plus économique du marché à seulement 0,42 $ par million de tokens. Le taux de change avantageux (¥1 = $1) rend le service encore plus accessible.

 aiohttp.ClientSession:
        """Lazy initialization de la session HTTP"""
        if self._session is None or self._session.closed:
            self._session = aiohttp.ClientSession(
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json"
                },
                timeout=aiohttp.ClientTimeout(total=10)
            )
        return self._session
    
    async def analyze_liquidity_pattern(
        self, 
        orderbook_data: Dict,
        context: Optional[str] = None
    ) -> Dict:
        """
        Analyse les patterns de liquidité via DeepSeek V3.2.
        
        Args:
            orderbook_data: Données du carnet d'ordres
            context: Contexte additionnel (volatilité, actualité...)
            
        Returns:
            Analyse structurée avec recommandations
        """
        prompt = self._build_liquidity_prompt(orderbook_data, context)
        
        session = await self._get_session()
        
        payload = {
            "model": "deepseek-v3.2",
            "messages": [
                {
                    "role": "system",
                    "content": """Tu es un analyste quantitatif expert en carnet d'ordres.
Réponds en JSON avec les champs: 
- liquidite_score (0-100)
- imbalance_ratio (rapport bid/ask)
- recommendations (liste de conseils)
- risk_factors (liste des risques identifiés)"""
                },
                {
                    "role": "user", 
                    "content": prompt
                }
            ],
            "temperature": 0.3,
            "max_tokens": 500
        }
        
        try:
            async with session.post(
                f"{self.BASE_URL}/chat/completions",
                json=payload
            ) as response:
                if response.status != 200:
                    error_text = await response.text()
                    raise Exception(f"API Error {response.status}: {error_text}")
                
                result = await response.json()
                content = result["choices"][0]["message"]["content"]
                
                # Parsing JSON de la réponse
                return json.loads(content)
                
        except Exception as e:
            return {
                "error": str(e),
                "liquidite_score": 50,
                "imbalance_ratio": 1.0,
                "recommendations": ["Vérifier la connexion API"],
                "risk_factors": ["Erreur de connexion"]
            }
    
    def _build_liquidity_prompt(self, orderbook_data: Dict, 
                                 context: Optional[str]) -> str:
        """Construit le prompt pour l'analyse"""
        symbol = orderbook_data.get("symbol", "UNKNOWN")
        bids = orderbook_data.get("bids", [])[:10]
        asks = orderbook_data.get("asks", [])[:10]
        
        bids_str = "\n".join([
            f"  Prix {b['price']} | Taille {b['size']}" 
            for b in bids
        ])
        asks_str = "\n".join([
            f"  Prix {a['price']} | Taille {a['size']}" 
            for a in asks
        ])
        
        prompt = f"""Analyse du carnet d'ordres pour {symbol}:

BIDS (Achats):
{bids_str}

ASKS (Ventes):
{asks_str}

"""
        if context:
            prompt += f"Contexte: {context}\n"
            
        prompt += """
Donne une analyse quantitative de la liquidité et des risques.
"""
        return prompt
    
    async def batch_analyze(
        self, 
        orderbook_samples: List[Dict],
        batch_size: int = 10
    ) -> List[Dict]:
        """
        Analyse un batch de snapshots orderbook.
        Optimisé pour le post-backtesting.
        
        Args:
            orderbook_samples: Liste de snapshots orderbook
            batch_size: Nombre de requêtes parallèles
            
        Returns:
            Liste des analyses
        """
        results = []
        
        for i in range(0, len(orderbook_samples), batch_size):
            batch = orderbook_samples[i:i+batch_size]
            
            # Requêtes parallèles
            tasks = [
                self.analyze_liquidity_pattern(sample)
                for sample in batch
            ]
            
            batch_results = await asyncio.gather(*tasks, return_exceptions=True)
            results.extend(batch_results)
            
            # Rate limiting doux
            if i + batch_size < len(orderbook_samples):
                await asyncio.sleep(0.1)
        
        return results
    
    async def generate_backtest_report(
        self,
        backtest_results: Dict,
        holysheep_api_key: str
    ) -> str:
        """
        Génère un rapport d'analyse post-backtest avec l'IA.
        Utilise DeepSeek V3.2 pour une analyse approfondie.
        
        Returns:
            Rapport HTML formaté
        """
        session = await self._get_session()
        
        summary_prompt = f"""Génère un rapport de backtest détaillé:

Performance:
- Sharpe Ratio: {backtest_results.get('sharpe_ratio', 0):.2f}
- Drawdown Max: {backtest_results.get('max_drawdown', 0)*100:.1f}%
- Return Total: {backtest_results.get('total_return', 0)*100:.1f}%
- Win Rate: {backtest_results.get('win_rate', 0)*100:.1f}%

Métriques:
- Nb Trades: {backtest_results.get('num_trades', 0)}
- PnL Moyen: ${backtest_results.get('avg_pnl', 0):.2f}
- Volatilité: {backtest_results.get('volatility', 0)*100:.2f}%

Fournis une analyse approfondie et des recommandations.
Réponds en français, format HTML.
"""
        
        payload = {
            "model": "deepseek-v3.2",
            "messages": [
                {"role": "system", "content": "Tu es un analyste quantitatif expert."},
                {"role": "user", "content": summary_prompt}
            ],
            "temperature": 0.5,
            "max_tokens": 1000
        }
        
        try:
            async with session.post(
                f"{self.BASE_URL}/chat/completions",
                json=payload
            ) as response:
                result = await response.json()
                return result["choices"][0]["message"]["content"]
        except Exception as e:
            return f"

Erreur génération rapport: {e}

" async def close(self) -> None: """Ferme la session HTTP""" if self._session and not self._session.closed: await self._session.close()

--- Exemple d'utilisation ---

async def main(): # Initialisation holysheep = HolySheepAnalysisClient( api_key="YOUR_HOLYSHEEP_API_KEY" # Remplacez par votre clé ) # Analyse d'un snapshot sample_orderbook = { "symbol": "BTC-USDT-SWAP", "bids": [ {"price": 67450.50, "size": 2.5}, {"price": 67449.00, "size": 1.8}, {"price": 67448.50, "size": 3.2} ], "asks": [ {"price": 67451.00, "size": 1.2}, {"price": 67452.00, "size": 2.1}, {"price": 67453.50, "size": 0.9} ] } # Analyse avec IA analysis = await holysheep.analyze_liquidity_pattern( sample_orderbook, context="Volatilité élevée suite aux annonces Fed" ) print(f"Score liquidité: {analysis.get('liquidite_score', 'N/A')}") print(f"Recommandations: {analysis.get('recommendations', [])}") await holysheep.close() if __name__ == "__main__": asyncio.run(main())

4. Moteur de Backtesting

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

logger = logging.getLogger(__name__)

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

class OrderType(Enum):
    MARKET = "market"
    LIMIT = "limit"

@dataclass
class Trade:
    """Représente une transaction exécutée"""
    timestamp: int
    side: OrderSide
    price: float
    size: float
    fee: float
    fee_tier: str = "taker"
    
    @property
    def value(self) -> float:
        return self.price * self.size
    
    @property
    def total_cost(self) -> float:
        return self.value + self.fee if self.side == OrderSide.BUY else self.value + self.fee

@dataclass
class Position:
    """Position ouverte"""
    entry_price: float
    size: float
    entry_time: int
    side: OrderSide

@dataclass
class BacktestStats:
    """Statistiques de performance"""
    total_return: float = 0.0
    sharpe_ratio: float = 0.0
    max_drawdown: float = 0.0
    win_rate: float = 0.0
    num_trades: int = 0
    avg_pnl: float = 0.0
    volatility: float = 0.0
    pnl_history: List[float] = field(default_factory=list)

class BacktestEngine:
    """
    Moteur de backtesting haute performance pour données orderbook L2.
    Supporte les frais maker/taker, le slippage et l'exécution réaliste.
    """
    
    # Frais OKX (exemple pour tier VIP 0)
    MAKER_FEE = 0.0002  # 0.02%
    TAKER_FEE = 0.0005  # 0.05%
    
    def __init__(
        self,
        initial_capital: float = 100000.0,
        max_position_pct: float = 0.1,
        slippage_bps: float = 1.0
    ):
        self.initial_capital = initial_capital
        self.capital = initial_capital
        self.max_position_pct = max_position_pct
        self.slippage_bps = slippage_bps
        
        self.position: Optional[Position] = None
        self.trades: List[Trade] = []
        self.equity_curve: List[float] = []
        self.daily_returns: List[float] = []
        
        self.current_time: int = 0
        self._last_equity = initial_capital
        
    def execute_order(
        self,
        side: OrderSide,
        price: float,
        size: float,
        order_type: OrderType = OrderType.MARKET,
        limit_price: Optional[float] = None
    ) -> Optional[Trade]:
        """Exécute un ordre avec prise en compte du slippage et des frais"""
        
        if size <= 0:
            return None
            
        # Calcul du prix d'exécution avec slippage
        if order_type == OrderType.MARKET:
            if side == OrderSide.BUY:
                exec_price = price * (1 + self.slippage_bps / 10000)
            else:
                exec_price = price * (1 - self.slippage_bps / 10000)
        else:
            exec_price = limit_price if limit_price else price
            
        # Calcul des frais
        fee = exec_price * size * self.TAKER_FEE
        fee_tier = "taker"
        
        trade = Trade(
            timestamp=self.current_time,
            side=side,
            price=exec_price,
            size=size,
            fee=fee,
            fee_tier=fee_tier
        )
        
        # Mise à jour du capital et position
        if side == OrderSide.BUY:
            self.capital -= trade.total_cost
            if self.position is None:
                self.position = Position(
                    entry_price=exec_price,
                    size=size,
                    entry_time=self.current_time,
                    side=side
                )
            else:
                # Averaging
                total_size = self.position.size + size
                self.position.entry_price = (
                    (self.position.entry_price * self.position.size + exec_price * size) 
                    / total_size
                )
                self.position.size = total_size
                
        else:  # SELL
            self.capital += (trade.value - trade.fee)
            self.position = None
            
        self.trades.append(trade)
        return trade
    
    def update_equity(self, current_price: float) -> float:
        """Met à jour l'equity curve avec le prix mark-to-market"""
        
        # Calcul de la valeur actuelle du portfolio
        portfolio_value = self.capital
        
        if self.position:
            if self.position.side == OrderSide.BUY:
                unrealized_pnl = (current_price - self.position.entry_price) * self.position.size
            else:
                unrealized_pnl = (self.position.entry_price - current_price) * self.position.size
            portfolio_value += unrealized_pnl
            
        self.equity_curve.append(portfolio_value)
        
        # Calcul du return quotidien
        if len(self.equity_curve) > 1:
            daily_return = (portfolio_value - self._last_equity) / self._last_equity
            self.daily_returns.append(daily_return)
            
        self._last_equity = portfolio_value
        return portfolio_value
    
    def process_orderbook_snapshot(
        self,
        orderbook,
        strategy_func: Callable,
        **strategy_params
    ) -> None:
        """Traite un snapshot du carnet d'ordres via la stratégie"""
        
        self.current_time = orderbook.timestamp
        
        # Mise à jour de l'equity
        mid_price = orderbook.get_mid_price()
        if mid_price > 0:
            self.update_equity(mid_price)
            
        # Exécution de la stratégie
        signal = strategy_func(
            orderbook=orderbook,
            position=self.position,
            capital=self.capital,
            **strategy_params
        )
        
        if signal:
            action = signal.get("action")
            size_pct = signal.get("size_pct", self.max_position_pct)
            max_size = self.capital * size_pct / mid_price if mid_price > 0 else 0
            
            if action == "buy" and self.position is None:
                self.execute_order(OrderSide.BUY, mid_price, max_size)
            elif action == "sell" and self.position is not None:
                self.execute_order(OrderSide.SELL, mid_price, self.position.size)
    
    def get_stats(self) -> BacktestStats:
        """Calcule les statistiques finales de backtest"""
        
        if not self.equity_curve:
            return BacktestStats()
            
        equity = np.array(self.equity_curve)
        returns = np.diff(equity) / equity[:-1]
        
        # Métriques de base
        total_return = (equity[-1] - self.initial_capital) / self.initial_capital
        
        # Sharpe Ratio (annualisé, 假设252 jours de trading)
        if len(returns) > 0 and np.std(returns) > 0:
            sharpe_ratio = np.mean(returns) / np.std(returns) * np.sqrt(252)
        else:
            sharpe_ratio = 0.0
            
        # Maximum Drawdown
        cummax = np.maximum.accumulate(equity)
        drawdowns = (cummax - equity) / cummax
        max_drawdown = np.max(drawdowns)
        
        # Win Rate
        pnl_list = []
        for trade in self.trades:
            if trade.side == OrderSide.SELL and self.trades.index(trade) > 0:
                # Trouver le trade d'achat correspondant
                for i in range(len(pnl_list)-1, -1, -1):
                    if pnl_list[i] == 0:
                        # Calculer PnL approximatif
                        pnl_list[i] = trade.value
                        break
                        
        winning_trades = sum(1 for p in pnl_list if p > 0)
        num_trades = len([t for t in self.trades if t.side == OrderSide.SELL])
        win_rate = winning_trades / num_trades if num_trades > 0 else 0
        
        # Volatilité annualisée
        volatility = np.std(returns) * np.sqrt(252) if len(returns) > 0 else 0
        
        # PnL moyen par trade
        avg_pnl = (equity[-1] - self.initial_capital) / num_trades if num_trades > 0 else 0
        
        return BacktestStats(
            total_return=total_return,
            sharpe_ratio=sharpe_ratio,
            max_drawdown=max_drawdown,
            win_rate=win_rate,
            num_trades=num_trades,
            avg_pnl=avg_pnl,
            volatility=volatility,
            pnl_history=pnl_list
        )
    
    def generate_report(self) -> Dict:
        """Génère un rapport complet de backtest"""
        
        stats = self.get_stats()
        
        return {
            "configuration": {
                "capital_initial": self.initial_capital,
                "capital_final": self.equity_curve[-1] if self.equity_curve else self.initial_capital,
                "max_position_pct": self.max_position_pct,
                "slippage_bps": self.slippage_bps
            },
            "performance": {
                "return_total": f"{stats.total_return*100:.2f}%",
                "sharpe_ratio": f"{stats.sharpe_ratio:.2f}",
                "max_drawdown": f"{stats.max_drawdown*100:.2f}%",
                "win_rate": f"{stats.win_rate*100:.1f}%",
                "volatilite": f"{stats.volatility*100:.2f}%",
                "nb_trades": stats.num_trades,
                "pnl_moyen": f"${stats.avg_pnl:.2f}"
            },
            "frais_totaux": {
                "total": f"${sum(t.fee for t in self.trades):.2f}",
                "avg_par_trade": f"${np.mean([t.fee for t in self.trades]):.3f}" if self.trades else "$0"
            },
            "equity_curve": self.equity_curve,
            "trades": [
                {
                    "time": t.timestamp,
                    "side": t.side.value,
                    "price": t.price,
                    "size": t.size,
                    "fee": t.fee
                }
                for t in self.trades
            ]
        }

--- Exemple de stratégie simple ---

def simple_midprice_strategy( orderbook, position: Optional[Position], capital: float, imbalance_threshold: float = 0.1, spread_threshold: float = 5.0 ) -> Optional[Dict]: """ Stratégie simple basée sur le prix moyen et l'imbalance du livre. Achète quand: - Le spread est faible (< spread_threshold bps) - L'imbalance est en faveur des bids (plus de volume acheteur) Vends quand: - Position existante et profit > 0.1% - Ou l'imbalance se retourne """ if not orderbook.bids or not orderbook.asks: return None mid_price = orderbook.get_mid_price() spread_bps = orderbook.get_spread_bps() # Calcul de l'imbalance bid_volume = sum(b.size for b in orderbook.bids[:10]) ask_volume = sum(a.size for a in orderbook.asks[:10]) total_volume = bid_volume + ask_volume if total_volume > 0: imbalance = (bid_volume - ask_volume) / total_volume else: imbalance = 0 # Logique de trading if position is None: # Chercher une opportunité d'achat if spread_bps < spread_threshold and imbalance > imbalance_threshold: return { "action": "buy", "size_pct": 0.05, "reason": f"Imbalance={imbalance:.2f}, Spread={spread_bps:.1f}bps" } else: # Vérifier si on doit vendre current_pnl_pct = (mid_price - position.entry_price) / position.entry_price if current_pnl_pct > 0.001: # Profit > 0.1% return { "action": "sell", "size_pct": 1.0, "reason": f"Profit={current_pnl_pct*100:.2f}%" } elif imbalance < -imbalance_threshold: return { "action": "sell", "size_pct": 1.0, "reason": f"Imbalance négative={imbalance:.2f}" } return None

--- Script principal ---

async def run_backtest(): from okx_connector import OKXL2Connector # Collecte des données (30 minutes) connector = OKXL2Connector(symbol="BTC-USDT-SWAP") print("Collecte des données orderbook...") await connector.listen() # Simulation de durée de collecte await asyncio.sleep(1800) # 30 minutes connector.stop() # Initialisation du moteur engine = BacktestEngine( initial_capital=50000.0, max_position_pct=0.1, slippage_bps=1.0 ) # Exécution du backtest print("Exécution du backtest...") buffer = connector.get_buffer() for snapshot in buffer: engine.process_orderbook_snapshot( orderbook=snapshot["orderbook"], strategy_func=simple_midprice_strategy, imbalance_threshold=0.15, spread_threshold=3.0 ) # Génération du rapport report = engine.generate_report() print("\n=== RAPPORT DE BACKTEST ===") print(f"Return Total: {report['performance']['return_total']}") print(f"Sharpe Ratio: {report['performance']['sharpe_ratio']}") print(f"Max Drawdown: {report['performance']['max_drawdown']}") print(f"Nombre de Trades: {report['performance']['nb_trades']}") print(f"Frais Totaux: {report['frais_totaux']['total']}") await connector.close() return report if __name__ == "__main__": report = asyncio.run(run_backtest())

Comparatif : HolySheep vs Alternatives pour l'Analyse IA

Ressources connexes

Articles connexes

🔥 Essayez HolySheep AI

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

👉 S'inscrire gratuitement →