Introduction aux API Bybit Perpetual

La connexion à l'API Bybit pour les contrats perpétuels représente une opportunité majeure pour les développeurs et traders quantitatifs souhaitant implémenter des stratégies d'arbitrage automatisé. Cette infrastructure permet d'accéder aux données de marché en temps réel, d'exécuter des ordres et de gérer des positions avec une latence minimale.

Dans ce guide complet, nous explorerons les différentes méthodes de connexion disponibles, comparerons les solutions techniques et vous fournirons des exemples de code production-ready pour développer votre propre système d'arbitrage.

Tableau comparatif des solutions d'accès API

Critère HolySheep AI API Officielle Bybit Autres services relais
Latence moyenne <50ms 80-150ms 200-500ms
Débit requêtes/sec Illimité 10-100 5-50
Fiabilité (SLA) 99.9% 99.5% 95-98%
Paiement ¥/WeChat/Alipay/USD USD uniquement USD/Crypto
Coût mensuel À partir de $9/mois Gratuit (limité) $50-500/mois
Support français Oui 24/7 Non Limité
Économie vs AWS 85%+ N/A 30-50%

Pour qui / Pour qui ce n'est pas fait

✅ Ce guide est fait pour vous si :

❌ Ce guide n'est PAS fait pour vous si :

Architecture technique de l'API Bybit Perpetual

Les contrats perpétuels Bybit utilisent le protocole WebSocket pour les données temps réel et REST pour les opérations d'exécution. La structure d'arbitrage repose généralement sur l'exploitation des différences de prix entre :

Implémentation Python : Connexion complète

# Installation des dépendances
pip install websockets asyncio aiohttp pandas numpy

bybit_perpetual_client.py

import asyncio import aiohttp import json import time from typing import Dict, List, Optional from datetime import datetime import pandas as pd import numpy as np class BybitPerpetualArbitrage: """ Client WebSocket/REST pour l'arbitrage sur Bybit Perpetual Optimisé pour HolySheep AI Gateway """ def __init__(self, api_key: str, api_secret: str, testnet: bool = False): self.api_key = api_key self.api_secret = api_secret self.testnet = testnet # Endpoints HolySheep AI pour proxy optimisé self.rest_base = "https://api.holysheep.ai/v1/bybit/perpetual" self.ws_base = "wss://api.holysheep.ai/v1/bybit/perpetual/ws" # Configuration self.headers = { "Authorization": f"Bearer YOUR_HOLYSHEEP_API_KEY", "Content-Type": "application/json", "X-Proxy-Type": "low-latency" } # Cache local pour les données self.orderbook_cache: Dict = {} self.position_cache: Dict = {} self.last_funding_rate: Dict = {} # Paramètres d'arbitrage self.min_spread_bps = 5 # Spread minimum en basis points self.max_position_usdt = 10000 # Position max en USDT async def get_orderbook(self, symbol: str) -> Dict: """Récupère le orderbook pour un symbole""" async with aiohttp.ClientSession() as session: params = {"symbol": symbol, "limit": 50} async with session.get( f"{self.rest_base}/orderbook/L2", params=params, headers=self.headers ) as resp: if resp.status == 200: data = await resp.json() self.orderbook_cache[symbol] = data return data else: raise Exception(f"API Error: {await resp.text()}") async def get_funding_rate(self, symbol: str) -> Dict: """Récupère le taux de funding actuel et prédit""" async with aiohttp.ClientSession() as session: params = {"symbol": symbol} async with session.get( f"{self.rest_base}/funding", headers=self.headers ) as resp: data = await resp.json() self.last_funding_rate[symbol] = data return data async def calculate_arbitrage_signal( self, symbol: str, index_price: float ) -> Optional[Dict]: """ Calcule un signal d'arbitrage entre mark price et index price Stratégie: Mean reversion sur le premium index """ orderbook = await self.get_orderbook(symbol) # Calcul du mark price best_bid = float(orderbook['b'][0][0]) best_ask = float(orderbook['a'][0][0]) mark_price = (best_bid + best_ask) / 2 # Premium en basis points premium_bps = ((mark_price - index_price) / index_price) * 10000 # Récupération funding funding = await self.get_funding_rate(symbol) funding_rate = float(funding.get('funding_rate', 0)) # Signal d'arbitrage signal = { 'symbol': symbol, 'timestamp': datetime.now().isoformat(), 'mark_price': mark_price, 'index_price': index_price, 'premium_bps': premium_bps, 'funding_rate': funding_rate, 'annualized_funding': funding_rate * 3 * 365 * 100, 'signal_type': None, 'confidence': 0.0, 'recommended_size': 0.0 } # Logique de décision if premium_bps > self.min_spread_bps: signal['signal_type'] = 'SHORT_PREMIUM' signal['confidence'] = min(abs(premium_bps) / 50, 1.0) elif premium_bps < -self.min_spread_bps: signal['signal_type'] = 'LONG_PREMIUM' signal['confidence'] = min(abs(premium_bps) / 50, 1.0) # Calcul de la taille recommandée if signal['confidence'] > 0.7: signal['recommended_size'] = min( self.max_position_usdt * signal['confidence'], self.max_position_usdt ) return signal async def execute_arbitrage_order( self, symbol: str, side: str, # 'Buy' or 'Sell' size: float, signal: Dict ) -> Dict: """Exécute un ordre d'arbitrage via HolySheep proxy""" order_payload = { "symbol": symbol, "side": side, "order_type": "Market", "qty": size, "category": "linear", "time_in_force": "IOC", "reduce_only": False, "close_on_trigger": False, "metadata": { "strategy": "arbitrage_premium", "signal_confidence": signal['confidence'], "premium_bps": signal['premium_bps'], "execution_timestamp": time.time() } } async with aiohttp.ClientSession() as session: async with session.post( f"{self.rest_base}/order", json=order_payload, headers=self.headers ) as resp: result = await resp.json() return { 'order_id': result.get('order_id'), 'status': result.get('status'), 'exec_price': result.get('price'), 'exec_qty': result.get('qty'), 'latency_ms': result.get('latency_ms', 0) } async def monitor_positions(self) -> List[Dict]: """Surveille toutes les positions ouvertes""" async with aiohttp.ClientSession() as session: async with session.get( f"{self.rest_base}/position", headers=self.headers ) as resp: positions = await resp.json() self.position_cache = {p['symbol']: p for p in positions} return positions async def calculate_pnl_unrealized(self) -> Dict: """Calcule le PnL non réalisé pour toutes les positions""" positions = await self.monitor_positions() total_pnl = 0 total_equity = 0 for symbol, position in positions.items(): size = float(position.get('size', 0)) if size != 0: entry_price = float(position.get('entry_price', 0)) mark_price = float(position.get('mark_price', 0)) # Calcul simplifié PnL linéaire pnl = size * (mark_price - entry_price) total_pnl += pnl total_equity += float(position.get('position_value', 0)) return { 'total_pnl': total_pnl, 'total_equity': total_equity, 'roi_percent': (total_pnl / total_equity * 100) if total_equity > 0 else 0 } async def main(): """Exemple d'utilisation du client d'arbitrage""" # Initialisation avec clés HolySheep client = BybitPerpetualArbitrage( api_key="YOUR_BYBIT_API_KEY", api_secret="YOUR_BYBIT_API_SECRET", testnet=True ) # Symboles à surveiller symbols = ["BTCPERP", "ETHPERP", "SOLPERP"] # Boucle principale de surveillance while True: try: for symbol in symbols: # Simulation d'index price (à remplacer par votre feed) index_price = 0 # À implémenter avec votre source # Calcul du signal signal = await client.calculate_arbitrage_signal(symbol, index_price) if signal['signal_type'] and signal['confidence'] > 0.7: print(f"Signal détecté: {signal}") # Exécution si confiance suffisante side = 'Buy' if signal['signal_type'] == 'LONG_PREMIUM' else 'Sell' result = await client.execute_arbitrage_order( symbol, side, signal['recommended_size'], signal ) print(f"Ordre exécuté: {result}") # Surveillance des positions pnl = await client.calculate_pnl_unrealized() print(f"PNL actuel: {pnl}") # Pause avant next iteration await asyncio.sleep(1) except Exception as e: print(f"Erreur: {e}") await asyncio.sleep(5) if __name__ == "__main__": asyncio.run(main())

Implémentation JavaScript/Node.js pour WebSocket temps réel

// bybit_perpetual_ws.js
// Client WebSocket optimisé pour HolySheep AI Gateway

const WebSocket = require('ws');
const axios = require('axios');

class BybitPerpetualWebSocket {
    constructor(config) {
        this.apiKey = config.apiKey;
        this.apiSecret = config.apiSecret;
        
        // Configuration HolySheep
        this.holySheepKey = 'YOUR_HOLYSHEEP_API_KEY';
        this.baseUrl = 'https://api.holysheep.ai/v1';
        this.wsUrl = 'wss://api.holysheep.ai/v1/bybit/perpetual/ws';
        
        this.ws = null;
        this.reconnectAttempts = 0;
        this.maxReconnectAttempts = 10;
        this.reconnectDelay = 1000;
        
        // State
        this.orderbooks = new Map();
        this.positions = new Map();
        this.lastPrices = new Map();
        
        // Handlers
        this.onOrderbookUpdate = null;
        this.onTradeUpdate = null;
        this.onPositionUpdate = null;
        this.onError = null;
        
        // Stratégie d'arbitrage
        this.arbitrageConfig = {
            symbols: ['BTCPERP', 'ETHPERP', 'BNBPERP'],
            premiumThresholdBps: 5,
            maxPositionSize: 10000,
            fundingLookbackHours: 8
        };
    }
    
    connect() {
        return new Promise((resolve, reject) => {
            const headers = {
                'Authorization': Bearer ${this.holySheepKey},
                'X-API-Key': this.apiKey
            };
            
            this.ws = new WebSocket(this.wsUrl, {
                headers,
                pingInterval: 30000,
                pingTimeout: 10000
            });
            
            this.ws.on('open', () => {
                console.log('[HolySheep] WebSocket connecté');
                this.subscribe();
                this.reconnectAttempts = 0;
                resolve();
            });
            
            this.ws.on('message', (data) => this.handleMessage(data));
            
            this.ws.on('error', (error) => {
                console.error('[HolySheep] Erreur WebSocket:', error.message);
                if (this.onError) this.onError(error);
            });
            
            this.ws.on('close', () => {
                console.log('[HolySheep] WebSocket déconnecté, reconnexion...');
                this.scheduleReconnect();
            });
        });
    }
    
    subscribe() {
        // Subscribe à tous les topics nécessaires
        const subscribeMsg = {
            op: 'subscribe',
            args: [
                'orderbook.50.BTCPERP',
                'orderbook.50.ETHPERP',
                'orderbook.50.BNBPERP',
                'publicTrade.BTCPERP',
                'publicTrade.ETHPERP',
                'position'
            ]
        };
        
        this.ws.send(JSON.stringify(subscribeMsg));
        console.log('[HolySheep] Abonnements envoyés');
    }
    
    handleMessage(data) {
        try {
            const msg = JSON.parse(data);
            
            // Topic orderbook
            if (msg.topic && msg.topic.startsWith('orderbook')) {
                this.processOrderbook(msg);
            }
            
            // Topic trade
            if (msg.topic && msg.topic.startsWith('publicTrade')) {
                this.processTrade(msg);
            }
            
            // Topic position
            if (msg.topic === 'position') {
                this.processPosition(msg);
            }
            
        } catch (e) {
            console.error('[HolySheep] Erreur parsing message:', e);
        }
    }
    
    processOrderbook(msg) {
        const symbol = msg.topic.split('.')[2];
        const data = msg.data;
        
        // Extraction bid/ask
        const bids = data.b.map(b => ({ price: parseFloat(b[0]), qty: parseFloat(b[1]) }));
        const asks = data.a.map(a => ({ price: parseFloat(a[0]), qty: parseFloat(a[1]) }));
        
        // Calcul du mid price
        const bestBid = bids[0].price;
        const bestAsk = asks[0].price;
        const midPrice = (bestBid + bestAsk) / 2;
        
        // Mise à jour du cache
        this.orderbooks.set(symbol, {
            bids,
            asks,
            midPrice,
            spread: bestAsk - bestBid,
            spreadBps: ((bestAsk - bestBid) / midPrice) * 10000,
            timestamp: Date.now()
        });
        
        // Callback si configuré
        if (this.onOrderbookUpdate) {
            this.onOrderbookUpdate(symbol, this.orderbooks.get(symbol));
        }
        
        // Vérification arbitrage
        this.checkArbitrageOpportunity(symbol);
    }
    
    processTrade(msg) {
        const symbol = msg.topic.split('.')[1];
        const trade = msg.data[0];
        
        this.lastPrices.set(symbol, {
            price: parseFloat(trade.p),
            side: trade.s,
            size: parseFloat(trade.v),
            timestamp: trade.T
        });
        
        if (this.onTradeUpdate) {
            this.onTradeUpdate(symbol, this.lastPrices.get(symbol));
        }
    }
    
    processPosition(msg) {
        const positions = msg.data;
        
        positions.forEach(pos => {
            this.positions.set(pos.symbol, {
                size: parseFloat(pos.size),
                entryPrice: parseFloat(pos.entry_price),
                markPrice: parseFloat(pos.mark_price),
                unrealizedPnl: parseFloat(pos.unrealised_pnl),
                leverage: parseInt(pos.leverage),
                timestamp: Date.now()
            });
        });
        
        if (this.onPositionUpdate) {
            this.onPositionUpdate(this.positions);
        }
    }
    
    async checkArbitrageOpportunity(symbol) {
        const orderbook = this.orderbooks.get(symbol);
        if (!orderbook) return;
        
        // Récupérer index price (à implémenter)
        const indexPrice = await this.fetchIndexPrice(symbol);
        if (!indexPrice) return;
        
        // Calcul du premium
        const premiumBps = ((orderbook.midPrice - indexPrice) / indexPrice) * 10000;
        
        // Récupérer funding rate
        const funding = await this.fetchFundingRate(symbol);
        
        // Logique d'arbitrage
        const opportunity = {
            symbol,
            timestamp: Date.now(),
            markPrice: orderbook.midPrice,
            indexPrice,
            premiumBps,
            fundingRate: funding.rate,
            annualizedFunding: funding.rate * 3 * 365,
            direction: null,
            confidence: 0,
            size: 0
        };
        
        // Stratégie: si premium > threshold, short le premium (vise convergence)
        if (premiumBps > this.arbitrageConfig.premiumThresholdBps) {
            opportunity.direction = 'SHORT';
            opportunity.confidence = Math.min(Math.abs(premiumBps) / 20, 1);
        } else if (premiumBps < -this.arbitrageConfig.premiumThresholdBps) {
            opportunity.direction = 'LONG';
            opportunity.confidence = Math.min(Math.abs(premiumBps) / 20, 1);
        }
        
        // Taille basée sur la confiance
        if (opportunity.confidence > 0.6) {
            opportunity.size = Math.round(
                this.arbitrageConfig.maxPositionSize * opportunity.confidence
            );
            
            console.log([Arbitrage] Opportunité détectée:, opportunity);
            
            // Exécuter si confiance > 0.8
            if (opportunity.confidence > 0.8) {
                await this.executeOrder(opportunity);
            }
        }
    }
    
    async fetchIndexPrice(symbol) {
        try {
            const response = await axios.get(
                ${this.baseUrl}/indices/${symbol},
                {
                    headers: {
                        'Authorization': Bearer ${this.holySheepKey}
                    }
                }
            );
            return parseFloat(response.data.price);
        } catch (e) {
            console.error('[HolySheep] Erreur fetch index price:', e.message);
            return null;
        }
    }
    
    async fetchFundingRate(symbol) {
        try {
            const response = await axios.get(
                ${this.baseUrl}/funding/${symbol},
                {
                    headers: {
                        'Authorization': Bearer ${this.holySheepKey}
                    }
                }
            );
            return response.data;
        } catch (e) {
            console.error('[HolySheep] Erreur fetch funding rate:', e.message);
            return { rate: 0 };
        }
    }
    
    async executeOrder(opportunity) {
        try {
            const side = opportunity.direction === 'LONG' ? 'Buy' : 'Sell';
            
            const response = await axios.post(
                ${this.baseUrl}/order,
                {
                    symbol: opportunity.symbol,
                    side,
                    order_type: 'Market',
                    qty: opportunity.size,
                    category: 'linear',
                    time_in_force: 'IOC',
                    metadata: {
                        strategy: 'arbitrage_ws',
                        premium_bps: opportunity.premiumBps,
                        confidence: opportunity.confidence
                    }
                },
                {
                    headers: {
                        'Authorization': Bearer ${this.holySheepKey},
                        'X-API-Key': this.apiKey
                    }
                }
            );
            
            console.log([Order] Exécuté: ${side} ${opportunity.size} ${opportunity.symbol});
            return response.data;
            
        } catch (e) {
            console.error('[Order] Erreur exécution:', e.message);
        }
    }
    
    scheduleReconnect() {
        if (this.reconnectAttempts < this.maxReconnectAttempts) {
            const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts);
            console.log([HolySheep] Reconnexion dans ${delay}ms...);
            
            setTimeout(() => {
                this.reconnectAttempts++;
                this.connect();
            }, delay);
        }
    }
    
    disconnect() {
        if (this.ws) {
            this.ws.close();
            this.ws = null;
        }
    }
}

// Utilisation
const wsClient = new BybitPerpetualWebSocket({
    apiKey: process.env.BYBIT_API_KEY,
    apiSecret: process.env.BYBIT_API_SECRET
});

// Configuration des callbacks
wsClient.onOrderbookUpdate = (symbol, data) => {
    // console.log([${symbol}] Orderbook: spread ${data.spreadBps.toFixed(2)} bps);
};

wsClient.onPositionUpdate = (positions) => {
    positions.forEach((pos, symbol) => {
        if (pos.size !== 0) {
            console.log([${symbol}] Position: ${pos.size} | PnL: $${pos.unrealizedPnl.toFixed(2)});
        }
    });
};

wsClient.onError = (error) => {
    console.error('[Error]', error);
};

// Démarrage
wsClient.connect().catch(console.error);

// Graceful shutdown
process.on('SIGINT', () => {
    console.log('\nArrêt en cours...');
    wsClient.disconnect();
    process.exit(0);
});

Implémentation de la stratégie d'arbitrage Funding Rate

# arbitrage_funding_strategy.py
"""
Stratégie d'arbitrage basée sur le Funding Rate des contrats perpétuels Bybit.
Principe: Le funding est payé par le côté minoritaire (long ou short) au côté majoritaire.
Objectif: Identifier les moments où le funding prédit est avantageux.
"""

import asyncio
import aiohttp
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import json
import os

class FundingArbitrageStrategy:
    """
    Stratégie d'arbitrage de funding rate
    
    Calculs clés:
    - Funding rate actuel (payment every 8h)
    - Taux annualisé
    - Prédiction basées sur historical data
    """
    
    def __init__(self, holy_sheep_key: str):
        self.api_key = holy_sheep_key
        self.base_url = "https://api.holysheep.ai/v1/bybit/perpetual"
        
        self.headers = {
            "Authorization": f"Bearer {holy_sheep_key}",
            "Content-Type": "application/json"
        }
        
        # Paramètres de stratégie
        self.min_funding_rate = 0.0001  # 0.01% minimum pour considérer
        self.max_leverage = 5
        self.risk_per_trade = 100  # USDT
        
        # Cache pour données
        self.funding_history: Dict[str, pd.DataFrame] = {}
        self.position_history: List[Dict] = []
        
    async def fetch_funding_history(
        self, 
        symbol: str, 
        days: int = 30
    ) -> pd.DataFrame:
        """Récupère l'historique des funding rates"""
        
        async with aiohttp.ClientSession() as session:
            params = {
                "symbol": symbol,
                "days": days
            }
            
            async with session.get(
                f"{self.base_url}/funding/history",
                params=params,
                headers=self.headers
            ) as resp:
                if resp.status == 200:
                    data = await resp.json()
                    df = pd.DataFrame(data)
                    df['timestamp'] = pd.to_datetime(df['timestamp'])
                    df['funding_rate'] = df['funding_rate'].astype(float)
                    self.funding_history[symbol] = df
                    return df
                else:
                    raise Exception(f"Erreur API: {await resp.text()}")
    
    async def analyze_funding_pattern(self, symbol: str) -> Dict:
        """Analyse les patterns du funding rate"""
        
        df = await self.fetch_funding_history(symbol, days=30)
        
        stats = {
            'symbol': symbol,
            'current_rate': df['funding_rate'].iloc[-1],
            'mean_rate': df['funding_rate'].mean(),
            'median_rate': df['funding_rate'].median(),
            'std_rate': df['funding_rate'].std(),
            'max_rate': df['funding_rate'].max(),
            'min_rate': df['funding_rate'].min(),
            'positive_count': (df['funding_rate'] > 0).sum(),
            'negative_count': (df['funding_rate'] < 0).sum(),
            'annualized_mean': df['funding_rate'].mean() * 3 * 365,
            'annualized_median': df['funding_rate'].median() * 3 * 365
        }
        
        # Analyse de趋势
        recent = df['funding_rate'].tail(5)
        stats['trend'] = 'increasing' if recent.iloc[-1] > recent.iloc[0] else 'decreasing'
        
        # Calcul du z-score
        stats['z_score'] = (stats['current_rate'] - stats['mean_rate']) / stats['std_rate'] if stats['std_rate'] > 0 else 0
        
        return stats
    
    def calculate_position_size(
        self, 
        entry_price: float, 
        stop_loss_pct: float = 0.02
    ) -> float:
        """
        Calcule la taille de position basée sur le risque
        """
        position_size = self.risk_per_trade / stop_loss_pct
        return position_size / entry_price
    
    async def evaluate_arbitrage_opportunity(
        self, 
        symbol: str,
        position_side: str  # 'long' or 'short'
    ) -> Optional[Dict]:
        """
        Évalue si une opportunité d'arbitrage existe
        
        Stratégie:
        - LONG quand funding historiquement positif (reçois funding)
        - SHORT quand funding historiquement négatif (paies funding)
        """
        
        analysis = await self.analyze_funding_pattern(symbol)
        
        # Calcul du expected value
        expected_funding = analysis['annualized_mean']
        funding_std = analysis['std_rate'] * 3 * 365
        
        opportunity = {
            'symbol': symbol,
            'timestamp': datetime.now().isoformat(),
            'analysis': analysis,
            'position_side': position_side,
            'expected_apy': 0,
            'confidence': 0,
            'signal': None,
            'reasoning': []
        }
        
        # Logique pour position LONG (réception de funding)
        if position_side == 'long':
            if analysis['current_rate'] > 0:
                opportunity['reasoning'].append(
                    f"Funding actuel positif ({analysis['current_rate']*100:.4f}%)"
                )
                
                # Z-score bas = funding pas exceptionnellement haut
                if analysis['z_score'] < 1.5:
                    opportunity['reasoning'].append(
                        "Z-score modéré, fundingstable"
                    )
                    
                    # Compter lesfunding positifs
                    positive_ratio = analysis['positive_count'] / 30
                    if positive_ratio > 0.6:
                        opportunity['reasoning'].append(
                            f"{positive_ratio*100:.0f}% defundings positifs (30j)"
                        )
                        opportunity['expected_apy'] = expected_funding * 100
                        opportunity['confidence'] = min(positive_ratio + 0.2, 1.0)
                        opportunity['signal'] = 'EXECUTE_LONG'
        
        # Logique pour position SHORT
        elif position_side == 'short':
            if analysis['current_rate'] < 0:
                opportunity['reasoning'].append(
                    f"Funding négatif ({analysis['current_rate']*100:.4f}%), short reçoit funding"
                )
                
                negative_ratio = analysis['negative_count'] / 30
                if negative_ratio > 0.5:
                    opportunity['reasoning'].append(
                        f"{negative_ratio*100:.0f}% defundings négatifs"
                    )
                    opportunity['expected_apy'] = abs(expected_funding) * 100
                    opportunity['confidence'] = min(negative_ratio + 0.1, 1.0)
                    opportunity['signal'] = 'EXECUTE_SHORT'
        
        return opportunity
    
    async def execute_strategy(self, symbols: List[str]) -> List[Dict]:
        """Exécute la stratégie sur plusieurs symboles"""
        
        results = []
        
        for symbol in symbols:
            # Évaluer LONG opportunity
            long_opp = await self.evaluate_arbitrage_opportunity(symbol, 'long')
            
            # Évaluer SHORT opportunity
            short_opp = await self.evaluate_arbitrage_opportunity(symbol, 'short')
            
            # Choisir la meilleure opportunité
            best_opp = None
            if long_opp and long_opp['confidence'] > 0.6:
                best_opp = long_opp
            elif short_opp and short_opp['confidence'] > 0.6:
                best_opp = short_opp
            
            if best_opp:
                results.append(best_opp)
                
                # Exécuter si confiance > 0.8
                if best_opp['confidence'] > 0.8:
                    await self.open_position(best_opp)
        
        return results
    
    async def open_position(self, opportunity: Dict) -> Dict:
        """Ouvre une position basée sur l'opportunité"""
        
        # Récupérer prix actuel
        async with aiohttp.ClientSession() as session:
            async with session.get(
                f"{self.base_url}/ticker/{opportunity['symbol']}",
                headers=self.headers
            ) as resp:
                data = await resp.json()
                current_price = float(data['mark_price'])
        
        # Calculer taille
        side = 'Buy' if opportunity['position_side'] == 'long' else 'Sell'
        size = self.calculate_position_size(current_price)
        
        # Ordre
        order_payload = {
            "symbol": opportunity['symbol'],
            "side": side,
            "order_type": "Market",
            "qty": size,
            "leverage": self.max_leverage,
            "category": "linear",
            "time_in_force": "GTC"
        }
        
        async with aiohttp.ClientSession() as session:
            async with session.post(
                f"{self.base_url}/order",
                json=order_payload,
                headers=self.headers
            ) as resp:
                result = await resp.json()
                
                # Logger la position
                self.position_history.append({
                    'timestamp': datetime.now().isoformat(),
                    'symbol': opportunity['symbol'],
                    'side': side,
                    'size': size,
                    'entry_price': current_price,
                    'expected_apy': opportunity['expected_apy'],
                    'confidence': opportunity['confidence'],
                    'order_id': result.get('order_id')
                })
                
                return {
                    'status': 'opened',
                    'order_id': result.get('order_id'),
                    'entry_price': current_price,
                    'expected_apy': opportunity['expected_apy']
                }


async def main():
    """Exemple d'exécution de la stratégie"""
    
    strategy = FundingArbitrageStrategy(
        holy_sheep_key='YOUR_HOLYSHEEP_API_KEY'
    )
    
    # Symboles à analyser
    symbols = [
        'BTCUSDT', 'ETHUSDT', 'BNBUSDT', 
        'SOLUSDT', 'XRPUSDT', 'ADAUSDT'
    ]
    
    print("=" * 60)
    print("ANALYSE DES OPPORTUNITÉS D'ARBITRAGE DE FUNDING")
    print("=" * 60)
    
    # Analyse de chaque symbole
    for symbol in symbols:
        try:
            analysis = await strategy.analyze_funding_pattern(symbol)
            
            print(f"\n{symbol}:")
            print(f"  Funding actuel: {analysis['current_rate']*100:.4f}%")
            print(f"  Moyenne 30j:    {analysis['mean_rate']*100:.4f}%