En tant que développeur specialized dans les infrastructures de trading algorithmique depuis plus de 7 ans, j'ai passé des centaines d'heures à construire des systèmes de surveillance des liquidations sur les exchanges de cryptomonnaies. Le défi principal ? Obtenir des données de liquidation fiables et en temps réel sans exploser son budget API. Aujourd'hui, je vais vous montrer comment créer un système complet de monitoring des liquidations OKX avec l'API Tardis, intégré à HolySheep AI pour l'analyse intelligente des données.
Pourquoi surveiller les liquidations OKX en temps réel ?
Les liquidations forcées sur OKX représentent des signaux capitaux pour les traders algorithmiques. Quando se produce una liquidation massive, le marché subit généralement une pression de vente significative qui peut créer des opportunités de trading ou, au contraire, des risques de liquidation en chaîne (cascade effect). Notre système permettra de :
- Détecter lesflushs de liquidations en moins de 500ms
- Identifier les seuils de liquidations critiques (>$100K en 1 minute)
- Envoyer des alertes multisupport : Telegram, Discord, Webhook
- Analyser les patterns avec l'IA de HolySheep pour prédire les mouvements
- Générer des rapports automatiques pour le backtesting
Architecture du Système
Notre architecture se compose de trois couches distinctes :
- Couche de collecte : API Tardis pour les données brutes de liquidation
- Couche de traitement : Pipeline Python avec filtres et agrégations
- Couche d'analyse : HolySheep AI pour l'interprétation intelligente
Comparatif des Coûts LLM pour l'Analyse de Liquidations
Avant de commencer le code, analysons les coûts réels pour processer 10 millions de tokens par mois d'analyse de liquidations. Voici ma comparaison basée sur les tarifs 2026 vérifiés :
| Modèle | Prix/MTok | 10M tokens/mois | Latence moyenne | Score qualité |
|---|---|---|---|---|
| DeepSeek V3.2 | 0,42 $ | 4,20 $ | <50ms | ★★★★☆ |
| Gemini 2.5 Flash | 2,50 $ | 25,00 $ | 80ms | ★★★★☆ |
| GPT-4.1 | 8,00 $ | 80,00 $ | 120ms | ★★★★★ |
| Claude Sonnet 4.5 | 15,00 $ | 150,00 $ | 150ms | ★★★★★ |
Analyse de mon utilisation personnelle : Pour le monitoring des liquidations, j'utilise principalement DeepSeek V3.2 via HolySheep pour l'analyse routine, et GPT-4.1 pour les rapports hebdomadaires détaillés. L'économie est considérable : environ 75 $ par mois par rapport à Claude Sonnet 4.5 avec une qualité parfaitement adequate.
Pour qui / Pour qui ce n'est pas fait
| ✅ Idéal pour | ❌ Pas adapté pour |
|---|---|
| Traders algorithmiques avec capital >$10K | Débutants sans expérience en trading |
| Institutions nécessitant des rapports合规 | Personnes cherchant des signaux de trading gratuits |
| Développeurs Python intermédiaires | Utilisateurs non techniques sans capacité d'adaptation |
| Market makers souhaitant anticiper la volatilité | Investisseurs long-term qui n'ont pas besoin de données temps réel |
Configuration Initiale et Prérequis
Assurez-vous d'avoir Python 3.10+ installé, ainsi que les dépendances suivantes :
# Installation des dépendances
pip install requests websockets asyncio aiohttp python-dotenv
pip install pandas numpy sqlalchemy
pip install telegram-send discord-webhook
Structure du projet recommandée
project/
├── config/
│ ├── __init__.py
│ ├── settings.py
│ └── .env
├── src/
│ ├── collectors/
│ │ ├── tardis_client.py
│ │ └── okx_liquidation_monitor.py
│ ├── processors/
│ │ └── liquidation_analyzer.py
│ ├── notifiers/
│ │ └── alert_manager.py
│ └── integrations/
│ └── holysheep_ai.py
├── main.py
└── requirements.txt
Connexion à l'API Tardis
L'API Tardis propose des données de liquidations en temps réel avec une latence inférieure à 100ms. Voici mon implémentation complète du client :
# src/collectors/tardis_client.py
import asyncio
import json
import logging
from typing import Dict, List, Optional, Callable
from datetime import datetime
import aiohttp
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class TardisLiquidationClient:
"""
Client WebSocket pour les données de liquidation OKX via Tardis.
Documentation: https://docs.tardis.dev/
"""
def __init__(self, api_key: str, exchanges: List[str] = ["okx"]):
self.api_key = api_key
self.exchanges = exchanges
self.ws_url = "wss://stream.tardis.dev/v1/stream"
self.websocket = None
self.session = None
self.liquidations_buffer: List[Dict] = []
self.callbacks: List[Callable] = []
self.is_connected = False
async def connect(self):
"""Établit la connexion WebSocket à Tardis."""
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
# Subscribe aux channels de liquidations pour OKX
subscribe_message = {
"type": "subscribe",
"channels": [
{
"name": "liquidations",
"exchange": "okx"
}
]
}
try:
self.session = aiohttp.ClientSession(headers=headers)
self.websocket = await self.session.ws_connect(
self.ws_url,
autoping=True,
ping_timeout=30
)
await self.websocket.send_json(subscribe_message)
self.is_connected = True
logger.info("✅ Connecté à l'API Tardis - Liquidations OKX")
except aiohttp.ClientError as e:
logger.error(f"❌ Erreur de connexion Tardis: {e}")
raise
async def disconnect(self):
"""Ferme la connexion proprement."""
if self.websocket:
await self.websocket.close()
if self.session:
await self.session.close()
self.is_connected = False
logger.info("Déconnexion Tardis effectuée")
def register_callback(self, callback: Callable):
"""Enregistre une fonction de callback pour les nouvelles liquidations."""
self.callbacks.append(callback)
async def start_listening(self):
"""Boucle principale d'écoute des messages."""
if not self.is_connected:
await self.connect()
try:
async for msg in self.websocket:
if msg.type == aiohttp.WSMsgType.TEXT:
data = json.loads(msg.data)
await self._process_message(data)
elif msg.type == aiohttp.WSMsgType.ERROR:
logger.error(f"Erreur WebSocket: {msg.data}")
break
except asyncio.CancelledError:
logger.info("Arrêt de l'écoute...")
await self.disconnect()
async def _process_message(self, data: Dict):
"""Traite un message de liquidation entrant."""
if data.get("type") == "liquidation":
liquidation = {
"exchange": data.get("exchange"),
"symbol": data.get("symbol"),
"side": data.get("side"), # "buy" ou "sell"
"price": float(data.get("price", 0)),
"size": float(data.get("size", 0)),
"value_usd": float(data.get("value", 0)),
"timestamp": data.get("timestamp"),
"datetime": datetime.fromtimestamp(
data.get("timestamp", 0) / 1000
).isoformat()
}
self.liquidations_buffer.append(liquidation)
# Appeler tous les callbacks enregistrés
for callback in self.callbacks:
try:
await callback(liquidation)
except Exception as e:
logger.error(f"Erreur callback: {e}")
elif data.get("type") == "subscribed":
logger.info(f"Souscrit au channel: {data.get('channel')}")
async def get_historical(
self,
exchange: str,
symbol: str,
from_ts: int,
to_ts: int
) -> List[Dict]:
"""Récupère les liquidations historiques via l'API REST."""
url = f"https://api.tardis.dev/v1/liquidations/{exchange}"
params = {
"symbol": symbol,
"from": from_ts,
"to": to_ts,
"apiKey": self.api_key
}
async with self.session.get(url, params=params) as resp:
if resp.status == 200:
return await resp.json()
else:
logger.error(f"Erreur API: {resp.status}")
return []
Intégration HolySheep AI pour l'Analyse Intelligente
Maintenant, l'intégration cruciale avec HolySheep AI. S'inscrire ici pour obtenir votre clé API avec 85% d'économie sur les tarifs OpenAI. La latence moyenne est inférieure à 50ms, ce qui est parfait pour notre système de monitoring.
# src/integrations/holysheep_ai.py
import json
import asyncio
from typing import Dict, List, Optional
from datetime import datetime
import requests
class HolySheepAnalyzer:
"""
Client pour l'analyse des liquidations via HolySheep AI.
Tarifs 2026: DeepSeek V3.2 ($0.42/MTok), GPT-4.1 ($8/MTok)
Latence moyenne: <50ms
"""
def __init__(self, api_key: str):
self.api_key = api_key
# ⚠️ Configuration HolySheep - NE PAS utiliser api.openai.com
self.base_url = "https://api.holysheep.ai/v1"
self.model = "deepseek-v3.2" # Modèle économique pour le monitoring
def _build_prompt(self, liquidations: List[Dict], timeframe: str) -> str:
"""Construit le prompt pour l'analyse des liquidations."""
total_value = sum(l.get("value_usd", 0) for l in liquidations)
buy_liquidations = [l for l in liquidations if l.get("side") == "buy"]
sell_liquidations = [l for l in liquidations if l.get("side") == "sell"]
prompt = f"""Analyse des liquidations OKX - Période: {timeframe}
Données brutes:
- Total liquidations: {len(liquidations)}
- Valeur totale: ${total_value:,.2f}
- Long liquidations (buy): {len(buy_liquidations)} (${sum(l.get('value_usd', 0) for l in buy_liquidations):,.2f})
- Short liquidations (sell): {len(sell_liquidations)} (${sum(l.get('value_usd', 0) for l in sell_liquidations):,.2f})
Top 5 liquidations:
{json.dumps(liquidations[:5], indent=2)}
Merci d'analyser:
1. Sentiment du marché (bullish/bearish/neutral)
2. Niveau de risque actuel (faible/moyen/élevé/extrême)
3. Recommandation pour les 30 prochaines minutes
4. watchlist de symboles à surveiller
Réponds en JSON avec les clés: sentiment, risk_level, recommendation, watchlist."""
return prompt
def analyze_liquidations(
self,
liquidations: List[Dict],
timeframe: str = "15 minutes"
) -> Dict:
"""
Analyse un lot de liquidations avec DeepSeek V3.2.
Coût estimé: ~500 tokens × $0.42/MTok = $0.00021
"""
prompt = self._build_prompt(liquidations, timeframe)
payload = {
"model": self.model,
"messages": [
{
"role": "system",
"content": "Tu es un analyste expert en trading de cryptomonnaies. Analyse les données de liquidations avec précision et donne des recommandations actionnables."
},
{
"role": "user",
"content": prompt
}
],
"temperature": 0.3, # Température basse pour des réponses cohérentes
"max_tokens": 500,
"response_format": {"type": "json_object"}
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
try:
response = requests.post(
f"{self.base_url}/chat/completions",
headers=headers,
json=payload,
timeout=5 # Timeout court pour le monitoring
)
if response.status_code == 200:
data = response.json()
content = data["choices"][0]["message"]["content"]
usage = data.get("usage", {})
# Log des coûts pour le suivi
tokens_used = usage.get("total_tokens", 0)
cost = (tokens_used / 1_000_000) * 0.42 # Prix DeepSeek V3.2
return {
"success": True,
"analysis": json.loads(content),
"tokens_used": tokens_used,
"cost_usd": cost,
"latency_ms": data.get("latency_ms", 0)
}
else:
return {
"success": False,
"error": f"HTTP {response.status_code}",
"details": response.text
}
except requests.exceptions.Timeout:
return {"success": False, "error": "Timeout HolySheep"}
except Exception as e:
return {"success": False, "error": str(e)}
async def analyze_liquidations_async(
self,
liquidations: List[Dict],
timeframe: str = "15 minutes"
) -> Dict:
"""Version asynchrone pour une meilleure performance."""
prompt = self._build_prompt(liquidations, timeframe)
payload = {
"model": self.model,
"messages": [
{"role": "system", "content": "Tu es un analyste expert en trading de cryptomonnaies."},
{"role": "user", "content": prompt}
],
"temperature": 0.3,
"max_tokens": 500
}
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
async with aiohttp.ClientSession() as session:
try:
async with session.post(
f"{self.base_url}/chat/completions",
headers=headers,
json=payload,
timeout=aiohttp.ClientTimeout(total=5)
) as resp:
if resp.status == 200:
data = await resp.json()
return {
"success": True,
"analysis": json.loads(
data["choices"][0]["message"]["content"]
),
"tokens_used": data.get("usage", {}).get("total_tokens", 0)
}
else:
return {
"success": False,
"error": f"HTTP {resp.status}"
}
except Exception as e:
return {"success": False, "error": str(e)}
Implémentation Complète du Système d'Alerte
# src/notifiers/alert_manager.py
import asyncio
import logging
from typing import Dict, List, Optional
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from collections import defaultdict
import requests
import json
@dataclass
class AlertConfig:
"""Configuration des alertes."""
telegram_bot_token: Optional[str] = None
telegram_chat_id: Optional[str] = None
discord_webhook_url: Optional[str] = None
webhook_url: Optional[str] = None
# Seuils d'alerte
min_value_usd: float = 10_000 # Alert si > $10K
aggregation_window_sec: int = 60 # Fenêtre d'agrégation
cooldown_sec: int = 300 # 5 min entre alertes similaires
@dataclass
class LiquidationAlert:
"""Représente une alerte de liquidation."""
timestamp: datetime
symbol: str
side: str
value_usd: float
price: float
severity: str # "low", "medium", "high", "critical"
sentiment: str = "unknown"
recommendation: str = ""
class AlertManager:
"""
Gestionnaire centralisé des alertes de liquidation.
"""
def __init__(self, config: AlertConfig):
self.config = config
self.alert_history: List[LiquidationAlert] = []
self.last_alert_time: Dict[str, datetime] = {}
self.pending_alerts: asyncio.Queue = asyncio.Queue()
async def process_liquidation(self, liquidation: Dict):
"""Traite une nouvelle liquidation et génère une alerte si nécessaire."""
value = liquidation.get("value_usd", 0)
symbol = liquidation.get("symbol", "UNKNOWN")
# Déterminer la sévérité
severity = self._calculate_severity(value)
# Créer l'alerte
alert = LiquidationAlert(
timestamp=datetime.fromisoformat(liquidation.get("datetime")),
symbol=symbol,
side=liquidation.get("side"),
value_usd=value,
price=liquidation.get("price"),
severity=severity
)
# Vérifier le cooldown
if self._should_send_alert(symbol, severity):
self.alert_history.append(alert)
await self._send_alert(alert)
self.last_alert_time[symbol] = datetime.now()
def _calculate_severity(self, value_usd: float) -> str:
"""Calcule la sévérité basée sur la valeur."""
if value_usd >= 1_000_000: # > $1M
return "critical"
elif value_usd >= 500_000: # > $500K
return "high"
elif value_usd >= 100_000: # > $100K
return "medium"
else:
return "low"
def _should_send_alert(self, symbol: str, severity: str) -> bool:
"""Vérifie si l'alerte doit être envoyée (cooldown)."""
last_time = self.last_alert_time.get(symbol)
if not last_time:
return True
elapsed = (datetime.now() - last_time).total_seconds()
cooldown_multiplier = 1 if severity == "critical" else 3
return elapsed >= self.config.cooldown_sec * cooldown_multiplier
async def _send_alert(self, alert: LiquidationAlert):
"""Envoie l'alerte sur tous les canaux configurés."""
message = self._format_telegram_message(alert)
tasks = []
# Telegram
if self.config.telegram_bot_token and self.config.telegram_chat_id:
tasks.append(self._send_telegram(message))
# Discord
if self.config.discord_webhook_url:
tasks.append(self._send_discord(alert))
# Webhook personnalisé
if self.config.webhook_url:
tasks.append(self._send_webhook(alert))
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)
def _format_telegram_message(self, alert: LiquidationAlert) -> str:
"""Formate le message pour Telegram."""
emoji = {
"critical": "🚨",
"high": "⚠️",
"medium": "⚡",
"low": "📊"
}.get(alert.severity, "📊")
side_emoji = "🔴" if alert.side == "sell" else "🟢"
return f"""{emoji} ALERTE LIQUIDATION {emoji}
⏰ {alert.timestamp.strftime('%H:%M:%S')}
🪙 Paire: {alert.symbol}
{side_emoji} Type: {alert.side.upper()}
💰 Valeur: ${alert.value_usd:,.2f}
💲 Prix: ${alert.price:,.4f}
📈 Sévérité: {alert.severity.upper()}"""
async def _send_telegram(self, message: str):
"""Envoie via Telegram Bot API."""
url = (
f"https://api.telegram.org/bot{self.config.telegram_bot_token}"
f"/sendMessage"
)
payload = {
"chat_id": self.config.telegram_chat_id,
"text": message,
"parse_mode": "Markdown"
}
try:
response = requests.post(url, json=payload, timeout=10)
return response.json()
except Exception as e:
logging.error(f"Erreur Telegram: {e}")
async def _send_discord(self, alert: LiquidationAlert):
"""Envoie via Discord Webhook."""
color_map = {
"critical": 0xFF0000, # Rouge
"high": 0xFF8800, # Orange
"medium": 0xFFFF00, # Jaune
"low": 0x00FF00 # Vert
}
payload = {
"embeds": [{
"title": f"🚨 Liquidation {alert.symbol}",
"description": f"Type: {alert.side.upper()}",
"color": color_map.get(alert.severity, 0x00FF00),
"fields": [
{
"name": "Valeur",
"value": f"${alert.value_usd:,.2f}",
"inline": True
},
{
"name": "Prix",
"value": f"${alert.price:,.4f}",
"inline": True
},
{
"name": "Sévérité",
"value": alert.severity.upper(),
"inline": True
}
],
"timestamp": alert.timestamp.isoformat()
}]
}
try:
response = requests.post(
self.config.discord_webhook_url,
json=payload,
timeout=10
)
return response.status_code == 204
except Exception as e:
logging.error(f"Erreur Discord: {e}")
async def _send_webhook(self, alert: LiquidationAlert):
"""Envoie vers un webhook personnalisé."""
payload = {
"event": "liquidation",
"data": {
"symbol": alert.symbol,
"side": alert.side,
"value_usd": alert.value_usd,
"price": alert.price,
"severity": alert.severity,
"timestamp": alert.timestamp.isoformat()
}
}
try:
response = requests.post(
self.config.webhook_url,
json=payload,
headers={"Content-Type": "application/json"},
timeout=10
)
return response.ok
except Exception as e:
logging.error(f"Erreur Webhook: {e}")
Fichier Principal de Monitoring
# main.py
import asyncio
import logging
import os
from dotenv import load_dotenv
from src.collectors.tardis_client import TardisLiquidationClient
from src.integrations.holysheep_ai import HolySheepAnalyzer
from src.notifiers.alert_manager import AlertManager, AlertConfig
from collections import defaultdict
from datetime import datetime, timedelta
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
Configuration via variables d'environnement
load_dotenv()
TARDIS_API_KEY = os.getenv("TARDIS_API_KEY")
HOLYSHEEP_API_KEY = os.getenv("HOLYSHEEP_API_KEY")
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
DISCORD_WEBHOOK = os.getenv("DISCORD_WEBHOOK_URL")
class LiquidationMonitor:
"""
Système complet de monitoring des liquidations OKX.
"""
def __init__(self):
self.tardis_client = TardisLiquidationClient(TARDIS_API_KEY)
self.analyzer = HolySheepAnalyzer(HOLYSHEEP_API_KEY)
alert_config = AlertConfig(
telegram_bot_token=TELEGRAM_BOT_TOKEN,
telegram_chat_id=TELEGRAM_CHAT_ID,
discord_webhook_url=DISCORD_WEBHOOK,
min_value_usd=10_000
)
self.alert_manager = AlertManager(alert_config)
# Buffer pour l'analyse périodique
self.liquidation_buffer: list = []
self.buffer_lock = asyncio.Lock()
self.analysis_interval = 300 # 5 minutes
# Statistiques
self.stats = {
"total_processed": 0,
"alerts_sent": 0,
"analysis_count": 0,
"total_cost_usd": 0.0
}
async def on_liquidation(self, liquidation: dict):
"""Callback appelé pour chaque nouvelle liquidation."""
async with self.buffer_lock:
self.liquidation_buffer.append(liquidation)
self.stats["total_processed"] += 1
# Traiter l'alerte
await self.alert_manager.process_liquidation(liquidation)
# Log
logger.info(
f"Liquidation: {liquidation['symbol']} "
f"{liquidation['side']} ${liquidation['value_usd']:,.2f}"
)
async def periodic_analysis(self):
"""Analyse périodique du buffer avec HolySheep AI."""
while True:
await asyncio.sleep(self.analysis_interval)
async with self.buffer_lock:
if not self.liquidation_buffer:
continue
buffer_copy = self.liquidation_buffer.copy()
self.liquidation_buffer.clear()
# Analyse avec HolySheep
logger.info(f"Analyse de {len(buffer_copy)} liquidations...")
result = self.analyzer.analyze_liquidations(
buffer_copy,
timeframe="5 minutes"
)
if result.get("success"):
analysis = result["analysis"]
cost = result.get("cost_usd", 0)
self.stats["total_cost_usd"] += cost
self.stats["analysis_count"] += 1
logger.info(
f"📊 Analyse HolySheep:\n"
f" Sentiment: {analysis.get('sentiment')}\n"
f" Risque: {analysis.get('risk_level')}\n"
f" Coût: ${cost:.6f}\n"
f" Tokens: {result.get('tokens_used')}"
)
# Envoyer l'analyse vers Discord
await self._send_analysis_report(analysis, len(buffer_copy))
else:
logger.error(f"Erreur analyse: {result.get('error')}")
async def _send_analysis_report(self, analysis: dict, count: int):
"""Envoie un rapport d'analyse vers Discord."""
if not DISCORD_WEBHOOK:
return
import requests
payload = {
"embeds": [{
"title": "📊 Rapport d'Analyse des Liquidations",
"description": f"Analyse de {count} liquidations",
"color": 0x8800FF,
"fields": [
{"name": "Sentiment", "value": analysis.get('sentiment', 'N/A'), "inline": True},
{"name": "Niveau de Risque", "value": analysis.get('risk_level', 'N/A'), "inline": True}
],
"fields": analysis.get('fields', []) + [
{
"name": "Recommandation",
"value": analysis.get('recommendation', 'Aucune')[:500]
},
{
"name": "Watchlist",
"value": ", ".join(analysis.get('watchlist', []))
}
],
"timestamp": datetime.now().isoformat()
}]
}
try:
requests.post(DISCORD_WEBHOOK, json=payload, timeout=10)
except Exception as e:
logger.error(f"Erreur envoi rapport: {e}")
async def print_stats(self):
"""Affiche les statistiques périodiquement."""
while True:
await asyncio.sleep(60)
logger.info(
f"📈 Statistiques:\n"
f" Liquidations traitées: {self.stats['total_processed']}\n"
f" Analyses effectuées: {self.stats['analysis_count']}\n"
f" Coût total HolySheep: ${self.stats['total_cost_usd']:.4f}"
)
async def run(self):
"""Point d'entrée principal."""
logger.info("🚀 Démarrage du système de monitoring...")
logger.info(f" HolySheep URL: https://api.holysheep.ai/v1")
logger.info(f" Modèle: DeepSeek V3.2 ($0.42/MTok)")
# Enregistrer le callback
self.tardis_client.register_callback(self.on_liquidation)
# Lancer les tâches
tasks = [
asyncio.create_task(self.tardis_client.start_listening()),
asyncio.create_task(self.periodic_analysis()),
asyncio.create_task(self.print_stats())
]
try:
await asyncio.gather(*tasks)
except asyncio.CancelledError:
logger.info("Arrêt du système...")
await self.tardis_client.disconnect()
if __name__ == "__main__":
monitor = LiquidationMonitor()
asyncio.run(monitor.run())
Configuration .env
# .env - Variables d'environnement
NE PAS commiter ce fichier sur Git !
Clés API
TARDIS_API_KEY=votre_cle_tardis_ici
HOLYSHEEP_API_KEY=votre_cle_holysheep_ici
Telegram (optionnel)
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
TELEGRAM_CHAT_ID=-1001234567890
Discord Webhook (optionnel)
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/xxx/yyy
Seuils personnalisés
MIN_LIQUIDATION_VALUE_USD=10000
ANALYSIS_INTERVAL_SECONDS=300
Erreurs Courantes et Solutions
Erreur 1: "Connection timeout" avec l'API Tardis
Symptôme : Le client se déconnecte après quelques minutes avec des timeouts répétés.
Causes possibles :
- Firewall bloquant les connexions WebSocket sortantes
- Problème de réseau instable
- Rate limiting côté Tardis
Solution :
# src/collectors/tardis_client.py - Ajout de reconnection automatique
class TardisLiquidationClient:
MAX_RECONNECT_ATTEMPTS = 5
RECONNECT_DELAY = 10 # secondes
async def start_listening(self):
"""Boucle principale avec reconnexion automatique."""
attempts = 0
while attempts < self.MAX_RECONNECT_ATTEMPTS:
try:
if not self.is_connected:
await self.connect()
async for msg in self.websocket:
if msg.type == aiohttp.WSMsgType.TEXT:
await self._process_message(json.loads(msg.data))
elif msg.type == aiohttp.WSMsgType.ERROR:
logger.error(f"WebSocket error: {msg.data}")
break
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
attempts += 1
logger.warning(
f"Tentative {attempts}/{self.MAX_RECONNECT_ATTEMPTS} échouée: {e}"
)
if attempts < self.MAX_RECONNECT_ATTEMPTS:
await asyncio.sleep(self.RECONNECT_DELAY)
self.is_connected = False
else:
logger.error("Nombre maximum de tentatives atteint")
raise
Erreur 2: "401 Unauthorized" avec HolySheep AI
Symptôme : Les appels à HolySheep retournent une erreur 401 même avec une clé valide.
Causes possibles :
- Clé API mal formatée ou copiée avec des espaces
- Tentative d'utiliser api.openai.com au lieu de api.holysheep.ai
- Clé expirée ou désactivée
Solution :
# Vérification de la clé et configuration correcte
import os
def validate_holysheep_config():
"""Valide la configuration HolySheep."""
api_key = os.getenv("HOLYSHEEP_API_KEY")
if not api_key:
raise ValueError("HOL