La reconstruction précise d'un order book de niveau 2 est essentielle pour tester des stratégies de trading algorithmique. Dans cet article, nous explorons comment utiliser Tardis.dev pour accéder aux données historiques de Binance et reconstruire un carnet d'ordres complet.
Comprendre les données du carnet d'ordres Binance
Binance propose plusieurs types de données pour son carnet d'ordres :
- Depth Snapshot : image complète à un instant T (limité à 5000 niveaux)
- Depth Update : mises à jour incrémentales (delta)
- Trade Stream : transactions exécutées en temps réel
Configuration initiale avec l'API Tardis.dev
// Installation du client Tardis.market
npm install @tardis-dev/market-connector
// Configuration pour les données Binance spot
const config = {
exchange: 'binance',
symbol: 'BTCUSDT',
startDate: new Date('2024-06-01'),
endDate: new Date('2024-06-02'),
dataTypes: ['book_snapshot', 'book_diff', 'trade']
};
console.log('Configuration chargée:', config);
Reconstruction de l'Order Book L2
class OrderBookBuilder {
constructor(symbol) {
this.symbol = symbol;
this.bids = new Map(); // price -> quantity
this.asks = new Map();
this.lastUpdateId = 0;
}
// Applique un snapshot complet
applySnapshot(snapshot) {
this.bids.clear();
this.asks.clear();
for (const [price, qty] of snapshot.bids) {
this.bids.set(parseFloat(price), parseFloat(qty));
}
for (const [price, qty] of snapshot.asks) {
this.asks.set(parseFloat(price), parseFloat(qty));
}
this.lastUpdateId = snapshot.updateId;
return this.getLevel2();
}
// Applique un diff (mise à jour incrémentale)
applyDiff(diff) {
// Vérification de la séquence
if (diff.updateId <= this.lastUpdateId) {
return null; // Diff ignoré (hors séquence)
}
for (const [price, qty] of diff.b) {
const p = parseFloat(price);
const q = parseFloat(qty);
if (q === 0) {
this.bids.delete(p);
} else {
this.bids.set(p, q);
}
}
for (const [price, qty] of diff.a) {
const p = parseFloat(price);
const q = parseFloat(qty);
if (q === 0) {
this.asks.delete(p);
} else {
this.asks.set(p, q);
}
}
this.lastUpdateId = diff.updateId;
return this.getLevel2();
}
// Retourne les N meilleurs niveaux
getLevel2(depth = 25) {
const sortedBids = [...this.bids.entries()]
.sort((a, b) => b[0] - a[0])
.slice(0, depth);
const sortedAsks = [...this.asks.entries()]
.sort((a, b) => a[0] - b[0])
.slice(0, depth);
return {
timestamp: Date.now(),
symbol: this.symbol,
bids: sortedBids,
asks: sortedAsks,
spread: sortedAsks[0] ? sortedAsks[0][0] - sortedBids[0][0] : 0,
midPrice: sortedBids[0] && sortedAsks[0]
? (sortedBids[0][0] + sortedAsks[0][0]) / 2
: null
};
}
}
// Utilisation
const ob = new OrderBookBuilder('BTCUSDT');
console.log('OrderBook initialisé');
Intégration avec le flux de données Tardis
import { createHistoricalDataset } from '@tardis-dev/market-connector';
async function replayOrderBook() {
const ob = new OrderBookBuilder('BTCUSDT');
const trades = [];
const dataset = await createHistoricalDataset({
exchange: 'binance',
symbols: ['BTCUSDT'],
startDate: new Date('2024-06-01T00:00:00Z'),
endDate: new Date('2024-06-01T01:00:00Z'),
dataType: ['book_snapshot', 'book_diff', 'trade'],
onBookSnapshot: (snapshot) => {
const level2 = ob.applySnapshot(snapshot);
console.log(Snapshot reçu: ${snapshot.updateId});
},
onBookDiff: (diff) => {
const level2 = ob.applyDiff(diff);
if (level2) {
// Stocker pour backtesting
trades.push({
time: diff.timestamp,
...level2
});
}
},
onTrade: (trade) => {
// Capturer les transactions
trades.push({
time: trade.timestamp,
price: parseFloat(trade.price),
volume: parseFloat(trade.quantity),
side: trade.side
});
}
});
await dataset.fill();
return trades;
}
// Exécution
replayOrderBook()
.then(data => console.log(Données collectées: ${data.length} entrées))
.catch(err => console.error('Erreur:', err));
Stratégie de backtesting simple
class MarketMaker {
constructor(spreadPercent = 0.001) {
this.spreadPercent = spreadPercent;
this.position = 0;
this.pnl = 0;
this.trades = [];
}
evaluate(marketData) {
if (!marketData.midPrice) return;
const { midPrice, bids, asks, time } = marketData;
// Prix limites pour notre market making
const bidPrice = midPrice * (1 - this.spreadPercent);
const askPrice = midPrice * (1 + this.spreadPercent);
// Vérifier si notre ordre est exécuté
// Simulation simplifiée
for (const [price, qty] of asks) {
if (price <= askPrice && qty > 0) {
// Ordre d'achat exécuté
this.position += qty;
this.pnl -= price * qty;
this.recordTrade(time, 'buy', price, qty);
}
}
for (const [price, qty] of bids) {
if (price >= bidPrice && qty > 0) {
// Ordre de vente exécuté
this.position -= qty;
this.pnl += price * qty;
this.recordTrade(time, 'sell', price, qty);
}
}
}
recordTrade(time, side, price, qty) {
this.trades.push({ time, side, price, qty, position: this.position });
}
getStats() {
const buyVolume = this.trades
.filter(t => t.side === 'buy')
.reduce((sum, t) => sum + t.qty * t.price, 0);
const sellVolume = this.trades
.filter(t => t.side === 'sell')
.reduce((sum, t) => sum + t.qty * t.price, 0);
return {
totalPnl: this.pnl,
netPosition: this.position,
buyVolume,
sellVolume,
tradeCount: this.trades.length,
avgSpread: this.spreadPercent * 100
};
}
}
Optimisation des performances
Pour gérer de grands volumes de données, plusieurs techniques sont recommandées :
- Traitement par lots : grouper les mises à jour par intervalle de temps
- Structure de données efficace : utiliser SortedMap pour les recherches
- Indexation temporelle : permettre l'accès rapide à un timestamp donné
- Compression : stocker les deltas plutôt que les snapshots complets
Considérations pour les frais et la latence
Lorsque vous travaillez avec des données historiques pour le backtesting, gardez à l'esprit :
- Les frais de transaction Binance spot varient de 0.02% à 0.1% selon le volume
- La latence de reconstruction dépend de la granularité choisie
- Le slippage doit être simulé selon la profondeur du carnet
Pour qui / pour qui ce n'est pas fait
| Idéal pour | Moins adapté pour |
|---|---|
| Stratégies market making | Trading haute fréquence (HFT) pur |
| Analyse de liquidité | Données tick-by-tick en temps réel |
| Backtesting de stratégies等候 | Exécution automatisée ( nécessite un autre layer) |
| Recherche académique | Production sans supervision humaine |
Tarification et ROI
| Plan Tardis.dev | Prix approximatif | Cas d'usage |
|---|---|---|
| Free | 0$ (limité) | Tests et prototypes |
| Start | ~99$/mois | Développement单人策略 |
| Pro | ~499$/mois | Équipes et production |
Conclusion
La reconstruction du carnet d'ordres L2 avec Tardis.dev offre une base solide pour développer et tester des stratégies de trading algorithmique. La clé est de bien gérer la séquentialité des données et de simuler fidèlement les conditions réelles de marché.
N'hésitez pas à explorer la documentation officielle de Tardis.dev pour des fonctionnalités avancées comme la reconstruction multi-symbole et l'optimisation de la mémoire.
Cet article a été publié sur HolySheep AI Blog. Pour accéder à des ressources supplémentaires sur les APIs de données financières, consultez notre section guides techniques.
```