2
Suivre
439
Abonnés

Exploration pratique des stratégies d'arbitrage au comptant : les pièges du idéal à la réalité

Créé le: 2025-11-28 14:22:49, Mis à jour le: 2025-12-16 11:31:06
comments   0
hits   345

Exploration pratique des stratégies d’arbitrage au comptant : les pièges du idéal à la réalité

Préface

Récemment, un ami m’a demandé de créer une stratégie d’arbitrage, une fonctionnalité qui faisait défaut sur la plateforme Inventor. Je pensais que ce serait simple, mais il m’a fallu environ un mois pour à peine faire fonctionner la logique de base. Avec le recul, je me rends compte que les difficultés rencontrées entre l’idée initiale et sa mise en œuvre étaient bien plus nombreuses que je ne l’avais imaginé.

Cet article documente les problèmes pratiques rencontrés et les solutions développées lors de l’élaboration de cette stratégie d’arbitrage.À des fins d’apprentissage et de référence uniquement ; il n’a aucune valeur d’investissement pratique.

La logique fondamentale de la stratégie

Il existe un écart de prix entre le contrat de livraison et le prix au comptant, qui fluctue généralement autour d’une certaine moyenne. Lorsque cet écart devient trop important, des opportunités d’arbitrage existent théoriquement.

L’idée de départ était simple :

  • Surveillez l’écart de prix entre les contrats au comptant et les contrats à livraison.
  • Ouvrez une position lorsque la différence de prix dépasse deux fois l’écart type.
  • Réalisez des profits en clôturant vos positions lorsque l’écart de prix revient à sa valeur initiale.

Ça a l’air génial, n’est-ce pas ? Mais en pratique, vous constaterez qu’il existe d’innombrables détails à gérer pour la simple étape d’« ouverture d’une position ».

Premier écueil : la stabilité des écarts de prix

Au départ, nous utilisions l’écart de prix comme indicateur direct, mais nous avons constaté que parfois cet écart continuait de s’accroître sans jamais revenir à son niveau initial. Par la suite, nous avons réalisé…Tous les écarts de prix ne sont pas stables.

À l’approche de la date de livraison, le comportement de l’écart peut évoluer. C’est pourquoi le test ADF a été ajouté afin de déterminer si la série de l’écart est stationnaire.

function adfTest(series, maxLag=null){
  const n = series.length;
  if(n<10) throw new Error('series too short');
  if(maxLag===null) maxLag = Math.floor(12*Math.pow(n/100, 1/4));
  
  // ... ADF检验的核心计算逻辑
  
  const res = ols(rows, Ys);
  const tstat = tStat(res.beta, res.cov, 1);
  return { tStat: tstat, pValue: pval, usedLag: p };
}

Au départ, nous avions ajouté de nombreux tests, notamment le test du rapport de variance, le test de demi-vie et le test de Kolmogorov-Smirnov, mais nous avons constaté qu’un trop grand nombre de tests réduisait considérablement le nombre de positions potentielles à ouvrir. Finalement, nous avons simplifié notre approche en ne conservant que le test ADF et en fixant le seuil de signification à 0,1.

Plus important encore, un élément supplémentaire a été ajouté.Compteur de défaillances continu

if (!adfPass) {
  stationarityFailCount[deliverySymbol] = (stationarityFailCount[deliverySymbol] || 0) + 1;
} else {
  stationarityFailCount[deliverySymbol] = 0;
}

let consecutiveFails = stationarityFailCount[deliverySymbol];
let canTrade = consecutiveFails < CONFIG.consecutiveFailThreshold;

Les transactions sont interdites si le test échoue trois fois de suite. Cela permet d’éviter l’ouverture de positions à l’aveugle lorsque le marché présente une anomalie.

Le deuxième écueil : la confusion qui entoure les statistiques de profits et pertes en temps réel

Calculer les profits et les pertes d’un compte à terme est simple : il suffit de regarder les variations du cours de l’USDT. Mais les comptes au comptant sont différents ; ils contiennent à la fois de l’USDT et des cryptomonnaies. Comment calculer ces pertes ?

Voici un détail qui passe facilement inaperçu :Le coût de stockage des marchandises au comptant variera en fonction des échanges.Par exemple, si vous achetez une cryptomonnaie pour 100 USDT, la vendez pour 90 USDT, puis la rachetez pour 85 USDT, votre prix de revient n’est plus de 100 USDT. Utiliser uniquement le prix figé au moment de l’ouverture de la position pour calculer la valeur de la cryptomonnaie ne reflétera pas la situation réelle de profit et de perte.

L’approche correcte estExtraire le prix de transaction moyen réel de l’objet commande.

let openSpotPrice = (openSpotOrder && openSpotOrder.AvgPrice) ? 
  openSpotOrder.AvgPrice : record.openSpotPrice;
let closeSpotPrice = closeSpotOrder.AvgPrice || currentPair.spotPrice;

Ensuite, le taux de rendement est calculé sur la base du prix de transaction réel :

// 正套:买现货+卖期货
if (record.direction === 'positive') {
  spotReturnRate = (closeSpotPrice - openSpotPrice) / openSpotPrice;
  deliveryReturnRate = (openDeliveryPrice - closeDeliveryPrice) / openDeliveryPrice;
} else {
  // 反套:卖现货+买期货
  spotReturnRate = (openSpotPrice - closeSpotPrice) / openSpotPrice;
  deliveryReturnRate = (closeDeliveryPrice - openDeliveryPrice) / openDeliveryPrice;
}

let totalReturnRate = spotReturnRate + deliveryReturnRate;
let requiredUSD = openSpotPrice * record.spotAmount;
let actualTotalPnl = totalReturnRate * requiredUSD;

Notez ici la logique de calcul des profits et pertes :

  • Ensemble régulierÀ cette époque, le marché au comptant était acheteur et le marché à terme était vendeur, donc le profit/la perte pour le marché au comptant = (prix de clôture - prix d’ouverture) / prix d’ouverture, et le profit/la perte pour le marché à terme = (prix d’ouverture - prix de clôture) / prix d’ouverture.
  • inverseÀ cette époque, le trading au comptant impliquait des ventes à découvert tandis que le trading de contrats à terme impliquait des ventes à l’achat, dans des directions opposées.

Enfin, le profit ou la perte réel(le) de chaque transaction est additionné(e) pour obtenir le profit ou la perte total(e) :

accumulatedProfit += actualTotalPnl;
_G('accumulatedProfit', accumulatedProfit);

Le troisième piège majeur : le piège à liquidités

Voilà le vrai problème. Pourquoi, après 10 ans d’activité, la plateforme Inventor Quantitative propose-t-elle si peu de stratégies d’arbitrage pour les contrats à terme ? La réponse est simple :Liquidités insuffisantes sur le marché des contrats de livraison

Question 1 : Transaction à une seule jambe

L’arbitrage n’est pas un conte de fées où l’on ouvre des positions simultanément. La réalité est la suivante :

  • L’ordre au comptant a été exécuté, mais l’ordre à terme est toujours en attente.
  • Ou bien l’ordre à terme a été exécuté, mais l’ordre au comptant a été annulé.

Il s’agit d’un exemple classique de « risque unilatéral ». Une jambe est investie, tandis que l’autre reste à l’extérieur. Dès lors, toute fluctuation de prix n’est plus un arbitrage, mais une position déséquilibrée.

La solution consiste à adhérermécanisme de retour en arrière

if (!deliveryOrder) {
  Log('❌ 期货卖单失败,回滚现货');
  exchanges[0].CreateOrder(pair.spotSymbol, 'sell', -1, spotAmount);
  addCooldown(pair.deliverySymbol, pair.coin, '期货卖单失败,已回滚现货');
  return false;
}

Si une étape échoue, passez immédiatement un ordre au marché pour clôturer l’étape déjà exécutée, réduisant ainsi l’exposition au risque de cette étape.

Question 2 : Les ordres au marché peuvent également être rejetés.

Plus absurde encore, il arrive que des ordres au marché échouent. Cela peut être dû aux contrôles des risques de la bourse ou à une profondeur de marché insuffisante ; en bref, l’ordre ne sera tout simplement pas exécuté.

Alors je l’ai fait.Double mécanisme d’ordre au marché et d’ordre à cours limité

function createOrderWithFallback(exchange, symbol, direction, amount, limitPrice, orderType, maxRetry = 3) {
  let useMarketOrder = (limitPrice === -1);
  
  // 先尝试限价单
  if (!useMarketOrder) {
    orderId = exchange.CreateOrder(symbol, direction, limitPrice, amount);
    if (!orderId) {
      Log(`❌ 限价单提交失败,改用市价单`);
      useMarketOrder = true;
    }
  }
  
  // 限价单失败则用市价单
  if (useMarketOrder && !orderId) {
    orderId = exchange.CreateOrder(symbol, direction, -1, marketAmount);
  }
  
  // ... 检查订单状态,失败则重试
}

Le système peut réessayer jusqu’à 3 fois, chaque tentative utilisant un ordre de marché comme filet de sécurité.

Question 3 : Le piège du montant dans les ordres d’achat au comptant

Ce piège est particulièrement bien dissimulé et exige une vigilance accrue. La quantité pour un ordre sur le marché à terme est de…Nombre de piècesCependant, la quantité commandée lors d’un ordre d’achat au marché au comptant est…Montant en USDT

Ici, une logique de conversion a été spécifiquement ajoutée :

function getActualAmount(useMarket) {
  if (isSpotBuy && useMarket) {
    // 现货市价买单:需要用USDT金额
    let currentPrice = getDepthMidPrice(exchange, symbol);
    let usdtAmount = amount * currentPrice;
    Log(`  💡 现货买单转换: ${amount.toFixed(6)} 币 → ${usdtAmount.toFixed(4)} USDT`);
    return usdtAmount;
  }
  return amount;
}

Le montant de cryptomonnaie utilisé dans un ordre à cours limité est automatiquement converti en USDT pour un ordre au marché.

Le quatrième piège : l’illusion des opportunités d’arbitrage

Un autre problème frustrant survient lorsqu’un signal d’arbitrage est détecté et que vous êtes prêt à ouvrir une position, mais que l’opportunité a déjà disparu au moment où vous passez l’ordre.

Les prix fluctuent en temps réel et les conditions de marché peuvent avoir évolué entre la détection du signal et l’exécution effective d’une position. Les écarts de prix peuvent s’être resserrés et les opportunités d’arbitrage peuvent avoir disparu. Si vous ouvrez imprudemment une position à ce stade, vous gaspillez simplement vos commissions.

Il a donc été ajouté.Mécanisme de confirmation secondaire

// 开仓前重新获取实时价格并验证套利机会
Log('🔄 重新获取实时Depth盘口价格并验证套利机会...');

let realtimeSpotPrice = getDepthMidPrice(exchanges[0], pair.spotSymbol, true);
let realtimeDeliveryPrice = getDepthMidPrice(exchanges[1], pair.deliverySymbol, true);

let realtimeSpread = realtimeDeliveryPrice - realtimeSpotPrice;
let realtimeSpreadRate = realtimeSpread / realtimeSpotPrice;

// 重新计算实时Z-Score
let realtimeZScore = (realtimeSpreadRate - mu) / (sigma || 1e-6);

// 验证:实时Z-Score是否仍然满足开仓条件
if (absRealtimeZ < CONFIG.zScoreEntry) {
  Log('❌ 套利机会已消失!');
  Log('  取消开仓,避免亏损');
  return false;
}

Avant de passer un ordre, vérifiez à nouveau le prix en temps réel, recalculez le score Z et n’exécutez l’ordre que si vous êtes sûr que l’opportunité existe toujours.

Le cinquième écueil : les problèmes hérités liés aux positions à terme.

Il arrive parfois, lors du redémarrage d’une stratégie ou de la clôture d’une position, que des positions résiduelles subsistent sur le compte à terme. Si ces positions ne sont pas traitées, les nouvelles positions risquent de se superposer aux anciennes, ce qui peut entraîner une augmentation incontrôlée de la taille du portefeuille.

Il a donc été ajouté.Liquidation forcée avant l’ouverture d’une positionLa logique :

// 检查期货现有仓位并平仓
let existingPosition = getPositionBySymbol(pair.deliverySymbol);

if (existingPosition && Math.abs(existingPosition.Amount) > 0) {
  Log('⚠️ 检测到该合约的现有仓位,执行平仓操作...');
  
  let closeDirection = existingPosition.Type === PD_LONG ? 'closebuy' : 'closesell';
  let closeAmount = Math.abs(existingPosition.Amount);
  
  let closeOrder = createOrderWithFallback(
    exchanges[1],
    pair.deliverySymbol,
    closeDirection,
    closeAmount,
    -1,
    '期货'
  );
  
  if (!closeOrder) {
    Log('❌ 平仓现有持仓失败,终止开仓');
    addCooldown(pair.deliverySymbol, pair.coin, '平仓现有持仓失败');
    return false;
  }
}

Avant d’ouvrir une position, vérifiez-la d’abord. S’il reste des positions ouvertes, clôturez-les afin de garantir un compte propre.

Le sixième écueil majeur : le piège du décalage des données Ticker

Voici l’intégralité du processus de développement stratégiqueLes plus dissimulés et les plus mortelsUn des problèmes.

Une fois la stratégie mise en œuvre, un phénomène étrange a été observé :

  • Un signal d’arbitrage a été détecté, il est temps d’ouvrir une position.
  • Le prix optimal d’un ordre à cours limité est calculé en additionnant et en soustrayant la différence de prix du prix du ticket.
  • En conséquence, la commande est restée en suspens, dans l’attente d’être exécutée.
  • Après une longue attente sans qu’aucune transaction ne soit effectuée, la commande a été annulée.

Essayez plutôt les ordres au marché ? Le résultat a été encore pire :

  • L’ordre au marché a été exécuté avec succès.
  • Cependant, le prix de la transaction était complètement différent de l’écart d’arbitrage attendu.
  • L’opportunité d’arbitrage envisagée s’est avérée non rentable une fois la transaction finalisée.

Que s’est-il passé exactement ? Après avoir comparé à plusieurs reprises les données de transactions en temps réel de la bourse, le problème a finalement été découvert :

Courant vs Profondeur : La différence fondamentale entre les données

Les données boursières reflètent le prix de transaction réel le plus récent.Cela semble convenir, mais pour les marchés à faible liquidité comme les contrats de livraison, des problèmes surgissent :

时间轴:
10:00:00 - 有人以50000成交了1张合约 → Ticker价格更新为50000
10:00:05 - 盘口挂单:买49800 / 卖50200(但没有成交)
10:00:10 - 盘口挂单:买49850 / 卖50150(但没有成交)
...
10:05:00 - Ticker价格仍然是50000(因为5分钟内没有新的成交)

Avez-vous remarqué le problème ?Le cours de 50 000 points de l’action appartenait déjà au passé il y a 5 minutes.Cependant, le prix actuel du marché (prix du carnet d’ordres) pourrait être de 4985050150.

Si vous utilisez le prix Ticker de 50 000 pour calculer les opportunités d’arbitrage et passer des ordres à cours limité, alors :

  1. Erreur de jugementLes signaux d’arbitrage sont calculés sur la base de prix obsolètes.
  2. La commande a échouéLe prix de l’ordre à cours limité est trop éloigné du prix réel du marché, ce qui rend la transaction impossible.
  3. Perte de marchéUn ordre au marché a été utilisé pour forcer une transaction, mais le prix réel était complètement différent de celui prévu.

Pourquoi les cotations des contrats de livraison sont-elles particulièrement peu fiables ?

La liquidité des contrats de livraison est bien pire que celle des contrats au comptant :

  • Marché au comptantUn grand nombre de transactions sont effectuées chaque seconde, et le prix du Ticker est mis à jour quasiment en temps réel avec un décalage minime.
  • Contrat de livraisonUne transaction peut prendre plusieurs minutes, voire plus, car le prix affiché sur le Ticker accuse un retard important.

Pour les contrats à faible liquidité, l’écart entre le prix du marché et le prix réel du carnet d’ordres peut atteindre :

  • Valeurs normales : 0,1 % - 0,5 %
  • Période de fluctuation : 1 % à 3 % voire plus

Pour les stratégies d’arbitrage, cet écart est fatal. L’avantage escompté en termes de différence de prix n’est peut-être que de 0,5 %, mais le prix de transaction réel s’avère totalement différent.

Solution : remplacer Ticker par les données du disque Depth

Puisque Ticker n’est pas fiable, utilisons…Données de profondeur (profondeur du carnet d’ordres)

function getDepthMidPrice(exchange, symbol, logDetail = false) {
    let depth = exchange.GetDepth(symbol);
    if (!depth || !depth.Bids || depth.Bids.length === 0 || 
        !depth.Asks || depth.Asks.length === 0) {
        Log(`❌ 获取${symbol}盘口失败`);
        return null;
    }
    
    let bestBid = depth.Bids[0].Price;  // 最优买价
    let bestAsk = depth.Asks[0].Price;  // 最优卖价
    let midPrice = (bestBid + bestAsk) / 2;  // 中间价
    
    if (logDetail) {
        let spread = bestAsk - bestBid;
        let spreadRate = spread / midPrice * 100;
        Log(`📊 ${symbol} 盘口: Bid=${bestBid.toFixed(2)}, Ask=${bestAsk.toFixed(2)}, Mid=${midPrice.toFixed(2)}, Spread=${spread.toFixed(2)} (${spreadRate.toFixed(3)}%)`);
    }
    
    return midPrice;
}

Avantages des données de profondeur :

  • En temps réelReflète l’état actuel et réel du carnet de commandes, sans aucun décalage.
  • précisionVotre ordre sera mis en correspondance avec ces carnets d’ordres, et il s’agira du prix réel du marché.
  • opérabilitéLes ordres à cours limité calculés sur la base des prix du carnet d’ordres ont une probabilité plus élevée d’être exécutés.

Système de tarification double de la stratégie

Finalement adoptéSolution hybride de Ticker + Depth

1. Utilisez Ticker pour conserver les séquences de données historiques.

// 用Ticker更新历史价差序列(保持连续性)
let spotTicker = exchanges[0].GetTicker(pair.spotSymbol);
let deliveryTicker = exchanges[1].GetTicker(pair.deliverySymbol);

pair.spotPrice = spotTicker.Last;
pair.deliveryPrice = deliveryTicker.Last;
pair.spread = pair.deliveryPrice - pair.spotPrice;

// 历史序列用于ADF检验、Z-Score计算
priceHistory[pair.deliverySymbol].push({
    time: Date.now(),
    spreadRate: pair.spread / pair.spotPrice,
    spread: pair.spread,
    spotPrice: pair.spotPrice,
    deliveryPrice: pair.deliveryPrice
});

Pourquoi utilise-t-on encore Ticker pour les données historiques ? Parce que c’est nécessaire.continuité des donnéesSi les données historiques sont également représentées en utilisant la profondeur, les fluctuations des prix du carnet d’ordres entraîneront des discontinuités dans la séquence historique, affectant la précision de l’analyse statistique.

2. Utilisez la profondeur pour un jugement en temps réel et une vérification de l’ouverture de position.

// 开仓前用Depth重新验证套利机会
let realtimeSpotPrice = getDepthMidPrice(exchanges[0], pair.spotSymbol, true);
let realtimeDeliveryPrice = getDepthMidPrice(exchanges[1], pair.deliverySymbol, true);

// 基于Depth价格重新计算Z-Score
let realtimeSpread = realtimeDeliveryPrice - realtimeSpotPrice;
let realtimeSpreadRate = realtimeSpread / realtimeSpotPrice;
let realtimeZScore = (realtimeSpreadRate - mu) / (sigma || 1e-6);

// 二次验证:套利机会是否仍然存在
if (Math.abs(realtimeZScore) < CONFIG.zScoreEntry) {
    Log('❌ 套利机会已消失(基于Depth实时价格)');
    return false;
}

3. Calculez le prix de l’ordre limite en utilisant la profondeur.

// 基于Depth价格和平均价差计算限价单价格
let spreadDeviation = realtimeSpread - avgSpread;
let adjustmentRatio = Math.min(
    Math.abs(spreadDeviation) * CONFIG.limitOrderSpreadRatio,
    spreadStd * 0.5
);

if (direction === 'positive') {
    spotLimitPrice = realtimeSpotPrice + adjustmentRatio;
    deliveryLimitPrice = realtimeDeliveryPrice - adjustmentRatio;
} else {
    spotLimitPrice = realtimeSpotPrice - adjustmentRatio;
    deliveryLimitPrice = realtimeDeliveryPrice + adjustmentRatio;
}

Le prix de l’ordre à cours limité ainsi calculé est basé sur le carnet d’ordres réel, ce qui augmente considérablement la probabilité d’exécution.

4. Calculer les profits et les pertes en temps réel à l’aide de Depth.

function calculateUnrealizedPnL(record, currentPair) {
    // 优先用Depth价格计算实时盈亏
    let currentSpotPrice = getDepthMidPrice(exchanges[0], currentPair.spotSymbol);
    let currentDeliveryPrice = getDepthMidPrice(exchanges[1], currentPair.deliverySymbol);
    
    // Depth获取失败才回退到Ticker
    if (!currentSpotPrice || !currentDeliveryPrice) {
        currentSpotPrice = currentPair.spotPrice;
        currentDeliveryPrice = currentPair.deliveryPrice;
    }
    
    // 计算盈亏...
}

Comparaison des effets réels des combats

Problèmes liés à l’utilisation de Ticker :

检测到套利信号(基于Ticker)
→ 计算限价单价格
→ 下单等待
→ 长时间不成交(价格已经不对了)
→ 改用市价单
→ 成交价格和预期差很多
→ 套利失败或微利

Améliorations après utilisation de Depth :

检测到套利信号(基于Ticker历史)
→ 用Depth重新验证(机会仍在)
→ 基于Depth计算限价单价格
→ 下单,价格贴近盘口
→ 较快成交
→ 成交价格符合预期
→ 套利成功

Optimisation de la tarification des ordres à cours limité

Si nous utilisons des ordres à cours limité, comment fixer le prix ? Si nous le fixons de manière trop agressive, la transaction n’aboutira pas ; si nous le fixons de manière trop prudente, nous n’obtiendrons pas un bon prix.

En fonction du prix de la profondeur, l’approche est la suivante :Ajustement dynamique en fonction de l’écart entre l’écart de prix actuel et l’écart de prix moyen.

let spreadDeviation = realtimeSpread - avgSpread;
let adjustmentRatio = Math.min(
  Math.abs(spreadDeviation) * CONFIG.limitOrderSpreadRatio,
  spreadStd * 0.5
);

// 限制调整幅度在合理区间
let minAdjustment = realtimeSpotPrice * 0.0005;
let maxAdjustment = realtimeSpotPrice * 0.005;
adjustmentRatio = Math.max(minAdjustment, Math.min(maxAdjustment, adjustmentRatio));

S’il s’agit d’un ensemble complet (avec une grande différence de prix) :

  • Prix ​​d’achat au comptant = Point médian de la profondeur + marge d’ajustement
  • Prix ​​de vente à terme = Point médian de la profondeur - Plage d’ajustement

Cela permet de conclure des transactions avec un écart de prix favorable, tout en évitant de s’éloigner trop du carnet d’ordres et donc de manquer une transaction.

Mécanisme de période de refroidissement

Toute tentative infructueuse d’ouverture de position indique un problème sur le marché, pouvant être dû à une liquidité insuffisante ou à une volatilité excessive. Dans ce cas, il convient de ne pas réessayer immédiatement, mais de garder son calme.

Par conséquent, une pénalité a été ajoutée à chaque paire de transactions ayant échoué.Temps de recharge de 10 minutes

function addCooldown(deliverySymbol, coin, reason) {
  pairCooldowns[deliverySymbol] = Date.now() + CONFIG.cooldownDuration;
  Log(`⏸️ ${deliverySymbol} 进入10分钟冷却期`);
  Log(`   原因: ${reason}`);
  _G('pairCooldowns', pairCooldowns);
}

Durant la période de refroidissement, aucune position ne sera ouverte pour cette paire de devises afin d’éviter les échecs répétés et les frais de transaction inutiles.

Lacunes actuelles et axes d’amélioration

Cette stratégie n’est encore qu’un travail en cours et de nombreux aspects peuvent être optimisés :

1. Problème de retard Actuellement, les prix sont récupérés par interrogation périodique, ce qui entraîne une latence importante. Le passage à WebSocket pour la mise à jour des prix en temps réel améliorerait considérablement la vitesse de réponse.

2. Optimisation du contrôle des risques La méthode actuelle de stop-loss est relativement simple et directe, et vous pouvez envisager :

  • Stop loss dynamique (ajusté en fonction de la volatilité)
  • Ordre stop-loss temporel (liquidation forcée en raison d’une durée de détention excessive)
  • Contrôle de retrait maximal

3. Gestion du dérapage La stratégie de tarification des ordres à cours limité peut être rendue plus intelligente, par exemple en s’ajustant dynamiquement en fonction de facteurs tels que la profondeur du carnet d’ordres et le volume récent des transactions.

4. Autres applications des données de profondeur Il permet d’analyser les déséquilibres du carnet d’ordres, de prédire les tendances des prix et d’améliorer le taux de réussite des arbitrages.

Résumer

Les stratégies d’arbitrage semblent attrayantes, mais en pratique, il est clair que d’innombrables pièges séparent l’idéal de la réalité.

  • Pièges des tests de stationnarité
  • Pièges des statistiques de profits et pertes
  • Le piège de l’insuffisance de liquidités
  • Les pièges des transactions à une seule jambe
  • Les pièges de l’échec des ordres au marché
  • Pièges liés au montant d’achat au comptant
  • Le piège des opportunités d’arbitrage qui disparaissent
  • Le gouffre des positions résiduelles
  • Le défaut le plus fatal réside dans le délai de réponse du mécanisme du téléscripteur.

En particulier, le problème du retard des données Ticker constitue un obstacle dans l’ensemble du processus de développement stratégique.C’est celle qu’on néglige le plus facilement, mais qui a le plus grand impact.Les pièges. Pour les marchés de contrats de livraison à faible liquidité :

Principe fondamental : utiliser le Ticker pour maintenir la continuité historique et la Depth pour saisir les opportunités en temps réel.

  • Ticker est adapté à l’analyse des données historiques (test ADF, calcul du score Z).
  • La profondeur est adaptée au jugement en temps réel et à l’exécution des transactions (vérification de l’ouverture des positions, tarification des ordres à cours limité, calcul des profits et des pertes).

Cet article relate les problèmes rencontrés et les solutions apportées au cours du processus d’exploration, et nous espérons qu’il pourra servir de référence à tous.Pour rappel, cet article a pour seul but d’informer et de susciter la discussion. Le code est encore en développement et ne doit pas être utilisé directement en situation de trading réel.

Si vous utilisez une stratégie similaire, n’hésitez pas à en discuter avec moi. Le marché est complexe, et c’est précisément cette complexité qui rend le trading quantitatif si difficile.

Code source de la stratégie : https://www.fmz.com/strategy/519280