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 :
- Vous êtes développeur Python/JavaScript avec des bases en trading algorithmique
- Vous souhaitez construire un système d'arbitrage entre les contrats perpétuels Bybit et d'autres exchanges
- Vous avez besoin d'une latence inférieure à 100ms pour vos stratégies haute fréquence
- Vous cherchez une infrastructure fiable avec support en français et paiement en ¥
- Vous voulez éviter les limitations de l'API officielle Bybit (rate limits, fiabilité)
- Vous êtes trader quantitatif ou fund cherchant à industrialiser vos stratégies
❌ Ce guide n'est PAS fait pour vous si :
- Vous êtes débutant absolu en programmation ou en trading
- Vous cherchez uniquement des signaux de trading sans infrastructure technique
- Vous préférez utiliser des plateformes no-code pour votre trading
- Vous n'avez pas de capital minimum pour couvrir les positions et frais
- Vous n'acceptez pas le risque inhérent au trading de cryptomonnaies
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 :
- Le prix index (basé sur les exchanges sous-jacents) et le prix mark (prix du contrat)
- Le spread entre contrats sur différents expiry (calendar spread)
- Les inefficiences entre Bybit et d'autres exchanges (spatial arbitrage)
- Le funding rate et ses variations prévisibles
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}%