Vous souhaitez accéder aux données d'ordre de marché (orderbooks) historiques de Binance avec une granularité tick par tick ? Vous voulez analyser les carnets d'ordres passés pour backtester vos stratégies de trading ou comprendre le comportement du marché à un moment précis ? Vous êtes au bon endroit.
Dans ce tutoriel complet, je vais vous guider pas à pas depuis l'inscription jusqu'à l'obtention de vos premières données d'orderbook historiques. Pas de prérequis techniques avancés : si vous savez ce qu'est Python et que vous avez envie d'apprendre, ce guide est fait pour vous. En tant qu'ingénieur quantitatif ayant travaillé sur des données de marché pendant 8 ans, je vais vous expliquer les concepts de manière accessible tout en vous fournissant du code production-ready.
Pourquoi Tardis.dev pour les données d'orderbooks Binance ?
Binance ne stocke pas historiquement les snapshots d'orderbooks complets avec une granularité tick par tick. Les données L2 (niveau 2) sont disponibles en temps réel via le websocket, mais pour l'historique, il faut passer par des agrégateurs spécialisés.
Tardis.dev se positionne comme l'un des fournisseurs les plus fiables avec :
- Couverture historique à partir de 2019 pour les principaux symboles
- Données tick-by-tick pour les trades et snapshots d'orderbook
- Format normalisé JSON, facile à parser
- Latence de l'API inférieure à 200ms pour les requêtes
- Prix start à $49/mois pour l'accès basique
Pour qui / pour qui ce n'est pas fait
| ✅ Idéal pour | ❌ Moins adapté pour |
|---|---|
| Traders algorithmiques en backtesting | Traders haute fréquence (latence >100ms) |
| Chercheurs en finance quantitative | Applications temps réel critiques |
| Étudiants en finance ou data science | Gratuit pour toujours (abonnement requis) |
| Data scientists analysant le marché crypto | Couverture de tous les exchanges (limité à Binance, OKX, Bybit) |
Configuration initiale : Installation de Python et des dépendances
Étape 1 : Vérifier votre version de Python
Ouvrez votre terminal (sur Windows, utilisez PowerShell ou l'invite de commandes) et tapez :
python --version
ou
python3 --version
Vous devriez voir quelque chose comme Python 3.9.0 ou supérieur. Si vous obtenez une erreur, téléchargez Python sur python.org/downloads.
Étape 2 : Créer un environnement virtuel (recommandé)
# Créer le dossier du projet
mkdir tardis-orderbook-tutorial
cd tardis-orderbook-tutorial
Créer un environnement virtuel
python -m venv venv
Activer l'environnement (Windows PowerShell)
.\venv\Scripts\Activate.ps1
Activer l'environnement (macOS/Linux)
source venv/bin/activate
Étape 3 : Installer les bibliothèques nécessaires
pip install requests pandas pyarrow
Ces trois bibliothèques serviront à :
- requests : pour effectuer les appels HTTP à l'API
- pandas : pour manipuler et analyser les données tabulaires
- pyarrow : pour sauvegarder les données en format Parquet (plus performant que CSV)
Obtention de la clé API Tardis.dev
Inscription et configuration
- Rendez-vous sur tardis.dev
- Cliquez sur "Sign Up" et créez un compte avec votre email
- Connectez-vous et allez dans "API Keys" dans le menu latéral
- Générez une nouvelle clé API
- Copiez cette clé et conservez-la précieusement (elle ne s'affiche qu'une fois)
⚠️ Important : Ne partagez jamais votre clé API publiquement. Ne la commitez pas sur GitHub. Utilisez des variables d'environnement.
Récupérer les données d'Orderbook Historiques
Comprendre la structure des données
Un orderbook (carnet d'ordres) contient deux côtés :
- Bids (ordres d'achat) : prix auxquels les acheteurs sont prêts à payer
- Asks (ordres de vente) : prix auxquels les vendeurs sont prêts à vendre
Chaque entrée contient :
- price : le niveau de prix
- size : la quantité disponible à ce prix
Code complet : Récupérer un orderbook historique
Créez un fichier nommé get_orderbook.py et collez le code suivant :
import requests
import pandas as pd
import os
from datetime import datetime, timedelta
============================================
CONFIGURATION
============================================
TARDIS_API_KEY = os.getenv("TARDIS_API_KEY", "VOTRE_CLE_API_ICI")
EXCHANGE = "binance"
SYMBOL = "btcusdt"
DATA_TYPE = "orderbook" # Options: "orderbook", "trades", "bookTicker"
Dates : récupérer les données d'il y a 1 heure
end_date = datetime.utcnow() - timedelta(hours=1)
start_date = end_date - timedelta(minutes=30) # 30 minutes de données
============================================
FONCTION D'APPEL API
============================================
def fetch_tardis_data(exchange, symbol, data_type, start_date, end_date):
"""
Récupère les données historiques depuis l'API Tardis.dev
Args:
exchange: Nom de l'exchange (ex: 'binance')
symbol: Symbole de trading (ex: 'btcusdt')
data_type: Type de données ('orderbook', 'trades', 'bookTicker')
start_date: Date de début (datetime)
end_date: Date de fin (datetime)
Returns:
list: Liste des données récupérées
"""
base_url = f"https://api.tardis.dev/v1/{exchange}/{symbol}/{data_type}"
params = {
"from": int(start_date.timestamp()),
"to": int(end_date.timestamp()),
"limit": 1000 # Maximum par requête
}
headers = {
"Authorization": f"Bearer {TARDIS_API_KEY}"
}
all_data = []
has_more = True
offset = 0
print(f"📥 Récupération des {data_type} pour {symbol} sur {exchange}")
print(f" Période : {start_date} → {end_date}")
while has_more:
params["offset"] = offset
response = requests.get(base_url, params=params, headers=headers)
if response.status_code == 200:
data = response.json()
if isinstance(data, list):
all_data.extend(data)
print(f" ✓ Requête {offset//1000 + 1} : {len(data)} records récupérés")
else:
print(f" ⚠️ Réponse inattendue: {type(data)}")
break
# Vérifier s'il y a plus de données
if len(data) < 1000:
has_more = False
else:
offset += 1000
elif response.status_code == 429:
print(" ⏳ Rate limit atteint, attente de 60 secondes...")
time.sleep(60)
else:
print(f" ❌ Erreur {response.status_code}: {response.text}")
break
return all_data
============================================
EXÉCUTION PRINCIPALE
============================================
if __name__ == "__main__":
import time
print("=" * 50)
print("Récupération Orderbook Binance - Tardis.dev")
print("=" * 50)
# Récupérer les données
orderbook_data = fetch_tardis_data(
exchange=EXCHANGE,
symbol=SYMBOL,
data_type=DATA_TYPE,
start_date=start_date,
end_date=end_date
)
print(f"\n📊 Total records récupérés : {len(orderbook_data)}")
# Convertir en DataFrame pandas
if orderbook_data:
df = pd.DataFrame(orderbook_data)
print(f"\n📋 Colonnes disponibles : {list(df.columns)}")
print(f"\n🔍 Aperçu des 5 premières lignes :")
print(df.head())
# Sauvegarder en CSV
output_file = f"orderbook_{SYMBOL}_{start_date.strftime('%Y%m%d_%H%M%S')}.csv"
df.to_csv(output_file, index=False)
print(f"\n💾 Données sauvegardées dans : {output_file}")
else:
print("\n⚠️ Aucune donnée récupérée")
Comprendre la pagination
Si vous demandez une longue période, l'API retourne les données par lots de 1000 enregistrements maximum. Le paramètre offset permet de paginer à travers les résultats.
# Exemple de pagination avec gestion des erreurs
import time
def fetch_all_orderbooks_with_pagination():
all_data = []
offset = 0
batch_size = 1000
max_retries = 3
while True:
retries = 0
while retries < max_retries:
try:
response = requests.get(
f"https://api.tardis.dev/v1/binance/btcusdt/orderbook",
params={"from": start_ts, "to": end_ts, "limit": batch_size, "offset": offset},
headers={"Authorization": f"Bearer {TARDIS_API_KEY}"},
timeout=30
)
if response.status_code == 200:
data = response.json()
if not data:
return all_data
all_data.extend(data)
offset += batch_size
break
elif response.status_code == 429:
wait_time = int(response.headers.get("Retry-After", 60))
print(f"Attente {wait_time}s...")
time.sleep(wait_time)
else:
print(f"Erreur: {response.status_code}")
return all_data
except Exception as e:
retries += 1
print(f"Tentative {retries} échouée: {e}")
time.sleep(5 * retries)
if retries >= max_retries:
print("Max retries atteint")
break
# Protection rate limit
time.sleep(0.1)
return all_data
Analyser et visualiser les Orderbooks
Calculer le prix moyen pondéré par le volume (VWAP)
import pandas as pd
import matplotlib.pyplot as plt
def analyze_orderbook_depth(df):
"""
Analyse la profondeur du carnet d'ordres
Args:
df: DataFrame contenant les données d'orderbook
Returns:
dict: Métriques d'analyse
"""
# Supposer que la structure est : timestamp, bids, asks
# Chaque bid/ask est une liste de [prix, taille]
results = {
"best_bid": None,
"best_ask": None,
"spread": None,
"spread_percent": None,
"bid_depth_1pct": 0,
"ask_depth_1pct": 0
}
# Analyser le premier snapshot (le plus récent)
if len(df) > 0:
first_row = df.iloc[0]
if "bids" in first_row and "asks" in first_row:
bids = first_row["bids"]
asks = first_row["asks"]
if bids and asks:
best_bid = float(bids[0][0])
best_ask = float(asks[0][0])
results["best_bid"] = best_bid
results["best_ask"] = best_ask
results["spread"] = best_ask - best_bid
results["spread_percent"] = (results["spread"] / best_bid) * 100
# Calculer la profondeur sur 1%
mid_price = (best_bid + best_ask) / 2
threshold_1pct = mid_price * 0.01
for price, size in bids:
if float(price) >= best_bid - threshold_1pct:
results["bid_depth_1pct"] += float(size)
for price, size in asks:
if float(price) <= best_ask + threshold_1pct:
results["ask_depth_1pct"] += float(size)
return results
Utilisation
if orderbook_data:
df = pd.DataFrame(orderbook_data)
metrics = analyze_orderbook_depth(df)
print("📊 Métriques du Carnet d'Ordres")
print("=" * 40)
print(f"Meilleur Bid : ${metrics['best_bid']:,.2f}")
print(f"Meilleur Ask : ${metrics['best_ask']:,.2f}")
print(f"Spread : ${metrics['spread']:,.2f} ({metrics['spread_percent']:.4f}%)")
print(f"Depth Bid 1% : {metrics['bid_depth_1pct']:.4f} BTC")
print(f"Depth Ask 1% : {metrics['ask_depth_1pct']:.4f} BTC")
Gestion des dates et fuseaux horaires
⚠️ Point critique : L'API Tardis.dev utilise les timestamps Unix en secondes ou millisecondes. Assurez-vous de bien convertir vos dates.
from datetime import datetime, timezone
def parse_date_for_tardis(date_string, timezone_str="UTC"):
"""
Convertit une date string en timestamp Unix pour l'API
Formats supportés : YYYY-MM-DD, YYYY-MM-DD HH:MM:SS, ISO 8601
"""
formats = [
"%Y-%m-%d %H:%M:%S",
"%Y-%m-%d",
"%Y-%m-%dT%H:%M:%SZ",
"%Y-%m-%dT%H:%M:%S.%fZ"
]
for fmt in formats:
try:
dt = datetime.strptime(date_string, fmt)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
return int(dt.timestamp())
except ValueError:
continue
raise ValueError(f"Format de date non reconnu: {date_string}")
Exemples d'utilisation
print(parse_date_for_tardis("2024-01-15"))
print(parse_date_for_tardis("2024-01-15 14:30:00"))
print(parse_date_for_tardis("2024-01-15T14:30:00Z"))
Optimisation des performances
Cache local et requêtes incrémentales
import json
import os
from pathlib import Path
class TardisCache:
"""Gestionnaire de cache pour les données Tardis.dev"""
def __init__(self, cache_dir="tardis_cache"):
self.cache_dir = Path(cache_dir)
self.cache_dir.mkdir(exist_ok=True)
def _get_cache_key(self, exchange, symbol, data_type, start_ts, end_ts):
return f"{exchange}_{symbol}_{data_type}_{start_ts}_{end_ts}.json"
def get_cached(self, exchange, symbol, data_type, start_ts, end_ts):
"""Récupère les données depuis le cache si disponibles"""
cache_key = self._get_cache_key(exchange, symbol, data_type, start_ts, end_ts)
cache_file = self.cache_dir / cache_key
if cache_file.exists():
print(f"📦 Cache hit: {cache_key}")
with open(cache_file, "r") as f:
return json.load(f)
return None
def save_cached(self, exchange, symbol, data_type, start_ts, end_ts, data):
"""Sauvegarde les données dans le cache"""
cache_key = self._get_cache_key(exchange, symbol, data_type, start_ts, end_ts)
cache_file = self.cache_dir / cache_key
with open(cache_file, "w") as f:
json.dump(data, f)
print(f"💾 Cache sauvegardé: {cache_file}")
Tarification et ROI
| Plan | Prix | Limites | Cas d'usage idéal |
|---|---|---|---|
| Free Trial | $0 | 7 jours, 100k messages | Tests initiaux, POC |
| Starter | $49/mois | 10M messages/mois | Backtesting occasionnel |
| Professional | $299/mois | 100M messages/mois | Trading algorithmique actif |
| Enterprise | Sur devis | Illimité + support dédié | Firms de trading, recherche |
Analyse coût-bénéfice
Pour un trader algorithmique effectuant 50 backtests par mois :
- Coût en temps : ~2h/backtest en collectant manuellement = 100h/mois
- Gain avec Tardis : ~5min/requête = 4h/mois
- ROI temps : 96h économisées = $2400+ de valeur (au tarif freelance $25/h)
Pourquoi choisir HolySheep pour vos besoins IA
Si vous travaillez sur des projets de trading algorithmique, vous aurez inévitablement besoin d'appels IA pour :
- Générer du code de stratégie automatiquement
- Analyser les patterns de marché avec des modèles de langage
- Créer des rapports de performance
- Automatiser la documentation
HolySheep AI offre des avantages distincts pour les développeurs de trading :
| Caractéristique | HolySheep AI | Concurrents |
|---|---|---|
| DeepSeek V3.2 | $0.42 / 1M tokens | $1+ / 1M tokens |
| Gemini 2.5 Flash | $2.50 / 1M tokens | $3.50+ / 1M tokens |
| Paiement | WeChat Pay, Alipay, ¥ | Carte uniquement USD |
| Latence API | <50ms | 150-300ms |
| Crédits gratuits | ✅ Inclus | ❌ Rarement |
Avec le taux ¥1 = $1, l'économie est de 85%+ compared aux providers occidentaux pour les mêmes modèles.
S'inscrire ici pour accéder à des tarifs préférentiels en yuan avec les mêmes modèles occidentaux.
Erreurs courantes et solutions
Erreur 401 : Clé API invalide ou manquante
# ❌ ERREUR : Response 401 {"error": "Unauthorized"}
Cause : Clé API absente ou malformée
✅ SOLUTION 1 : Vérifier que la clé est correctement définie
import os
os.environ["TARDIS_API_KEY"] = "ts_live_xxxxxxxxxxxx"
✅ SOLUTION 2 : Vérifier le format de l'en-tête
headers = {
"Authorization": f"Bearer {TARDIS_API_KEY}" # Format correct
}
✅ SOLUTION 3 : Vérifier que la clé est active
Allez sur https://tardis.dev -> Settings -> API Keys -> vérifier le statut
Erreur 429 : Rate Limit dépassé
# ❌ ERREUR : Response 429 {"error": "Too Many Requests"}
Cause : Trop de requêtes en peu de temps
✅ SOLUTION : Implémenter un backoff exponentiel
import time
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
def create_session_with_retry():
"""Crée une session avec retry automatique"""
session = requests.Session()
retry_strategy = Retry(
total=5,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["HEAD", "GET", "OPTIONS"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
session.mount("http://", adapter)
return session
Utilisation
session = create_session_with_retry()
La session gérera automatiquement les rate limits
Erreur 400 : Paramètres de date invalides
# ❌ ERREUR : Response 400 {"error": "Invalid date range"}
Cause : Dates malformées ou période trop longue
✅ SOLUTION 1 : Vérifier le format des timestamps
L'API attend des timestamps Unix en secondes (pas millisecondes)
from_ts = int(datetime(2024, 1, 1, 0, 0, 0).timestamp()) # ✅ 1704067200
to_ts = int(datetime(2024, 1, 2, 0, 0, 0).timestamp()) # ✅ 1704153600
❌ ERREUR COURANTE : timestamps en millisecondes
bad_ts = 1704067200000 # ❌ Multiplié par 1000
✅ SOLUTION 2 : Limiter la période par requête
Maximum recommandé : 1 jour de données tick-by-tick par requête
MAX_PERIOD_SECONDS = 86400 # 24 heures
def fetch_with_period_limit(start_date, end_date):
"""Découpe les requêtes si nécessaire"""
delta = end_date - start_date
if delta.total_seconds() > MAX_PERIOD_SECONDS:
mid_date = start_date + timedelta(seconds=MAX_PERIOD_SECONDS)
# Récupérer en deux fois
fetch_tardis_data(start_date, mid_date)
fetch_tardis_data(mid_date, end_date)
else:
fetch_tardis_data(start_date, end_date)
Erreur 404 : Symbole ou exchange non supporté
# ❌ ERREUR : Response 404 ou données vides
Cause : Le symbole n'existe pas ou n'est pas dans l'historique
✅ SOLUTION : Vérifier les symboles disponibles
def list_available_symbols(exchange="binance"):
"""Récupère la liste des symboles disponibles"""
response = requests.get(
f"https://api.tardis.dev/v1/{exchange}/symbols",
headers={"Authorization": f"Bearer {TARDIS_API_KEY}"}
)
if response.status_code == 200:
return response.json()
return []
Vérifier avant de requêter
symbols = list_available_symbols()
print("BTCUSDT" in [s["symbol"] for s in symbols]) # Devrait être True
⚠️ Note : Tous les symboles ne sont pas disponibles
Vérifier la couverture sur https://docs.tardis.dev/historical
Bonnes pratiques et recommandations
- Utilisez le cache : Les mêmes données coûtent des credits API. Cachez localement.
- Découpez les périodes : Requêtes <24h pour éviter les timeouts
- Surveillez votre quota : Le monitoring est disponible dans le dashboard
- Testez avec le Free Trial : 7 jours suffisent pour valider votre use case
Récapitulatif
Dans ce tutoriel, vous avez appris à :
- Configurer votre environnement Python
- Obtenir une clé API Tardis.dev
- Récupérer des orderbooks historiques Binance avec pagination
- Analyser la profondeur du carnet d'ordres
- Gérer les erreurs courantes (401, 429, 400)
- Optimiser avec du caching local
Pour vos besoins en IA générative (analyse de données, génération de code de trading, documentation), pensez à HolySheep AI pour des économies de 85% sur les mêmes modèles occidentaux avec paiement en yuan via WeChat ou Alipay.
💡 Prochaine étape : Combiner les données d'orderbook avec des modèles de machine learning pour prédire les mouvements de prix ou détecter les manipulations de marché.
👉 Inscrivez-vous sur HolySheep AI — crédits offerts