Dans l'article précédent, nous avons introduit l'arbitrage croisé. Dans cet article, nous allons examiner en profondeur comment appliquer l'effet Lead-Lag au trading à haute fréquence, ce qui nécessite de capturer de petites différences de prix en très peu de temps et de réaliser des bénéfices rapidement.
Ce qui suit:une simplification du code publicLe principe de code de cette stratégie originale est très simple et était autrefois très rentable.
Le soi-disant
La stratégie obtient des données de carnet de commandes de différentes bourses presque en même temps, telles que le prix d'offre, le prix de vente, le volume d'ordres en attente, etc. Ensuite, le prix moyen (c'est-à-dire la moyenne du prix d'offre et du prix de vente) de différentes bourses est comparé pour en déduire la dynamique du marché.
La stratégie est principalement axée sur les variations de prix de trois bourses externes (okex, binance, huobipro):
Ici, chaque tendance X est déterminée par la différence entre le prix actuel et le prix passé qui dépasse un certain seuil (niveau * augmentation de prix). Après addition des signaux de hausse/baisse des trois bourses, si la tendance globale est supérieure à 0, cela signifie que le marché est généralement en hausse et que la stratégie est d'acheter; si la tendance est inférieure à 0, cela signifie que le marché est généralement en baisse et que la stratégie est de vendre.
La stratégie n'achète ou vend qu'après la confirmation de la tendance et annule l'ordre précédent avant de placer chaque ordre (c'est-à-dire en évitant les ordres en attente accidentels qui entraînent une accumulation de risques).
En outre, cette stratégie est une stratégie à haute fréquence. Vous n'avez pas besoin de prêter attention au profit ou à la perte de chaque ordre, et vous n'avez pas besoin d'arrêter la perte. Vous pouvez continuer tant qu'il y a une probabilité de réaliser des profits.
// Hyperparameter settings
const SYMBOL = "BTC_USDT"; // Trading pair
const PRICE_INCREMENT = 0.1; // Price increment
const LEVEL = 10; // Sensitivity of trend judgment
const RATIO = 10; // Order price adjustment ratio
const INTERVAL = 200; // Time interval (milliseconds)
const S_AMOUNT = 0.02; // Default transaction volume
const MIN_AMOUNT = 0.005; // Minimum transaction volume
// Initial state
let buyOrders = [];
let sellOrders = [];
let previousPrices = [0, 0, 0]; // Store the previous price
let loop = 0;
// Get order book data
function fetchOrderBooks() {
let orderBooks = [];
let tasks = [];
// Start asynchronous order book acquisition tasks for all exchanges
for (let i = 0; i < exchanges.length; i++) {
// Assume that each exchange object can call the Go method
let task = exchanges[i].Go("GetDepth");
tasks.push({ index: i, task: task });
}
// Wait for all tasks to complete and collect results
for (let i = 0; i < tasks.length; i++) {
let { index, task } = tasks[i];
try {
// Waiting for an asynchronous task to return a result
let depth = task.wait(1000);
// Check if the returned data is valid
if (!depth || !depth.Bids || !depth.Asks) {
throw new Error("The returned order book data is invalid");
}
// Add valid order book data to the result array
orderBooks[index] = depth;
} catch (error) {
// Recording error logs
Log(`Failed to obtain the order book of exchange ${index}: ${error.message}`);
// Added default order book data to avoid crashes
orderBooks[index] = {
Bids: [[0, 0]],
Asks: [[0, 0]]
};
}
}
return orderBooks;
}
// Judge the trends
function calculateTrend(orderBooks) {
let trends = [];
for (let i = 0; i < orderBooks.length; i++) {
const midPrice = (orderBooks[i].Bids[0][0] + orderBooks[i].Asks[0][0]) / 2;
if (midPrice > previousPrices[i] + LEVEL * PRICE_INCREMENT) {
trends.push(1); // Upward trend
} else if (midPrice < previousPrices[i] - LEVEL * PRICE_INCREMENT) {
trends.push(-1); // Downward trend
} else {
trends.push(0); // No significant trend
}
previousPrices[i] = midPrice; // Update price record
}
return trends.reduce((a, b) => a + b, 0); // Return to overall trend
}
// Cancel all pending orders
function cancelOrders(orders) {
for (let orderId of orders) {
try {
exchanges[0].CancelOrder(orderId); // Use the main exchange by default
Log(`Cancel order: ${orderId}`);
} catch (error) {
Log(`Failed to cancel order: ${error.message}`);
}
}
}
// Create a buy order
function createBuyOrder(price, amount) {
try {
const orderId = exchanges[0].Buy(price, amount);
buyOrders.push(orderId);
Log(`Create a buy order: price ${price}, quantity ${amount}`);
} catch (error) {
Log(`Failed to create buy order: ${error.message}`);
}
}
// Create a sell order
function createSellOrder(price, amount) {
try {
const orderId = exchanges[0].Sell(price, amount);
sellOrders.push(orderId);
Log(`Create a sell order: price ${price}, quantity ${amount}`);
} catch (error) {
Log(`Failed to create sell order: ${error.message}`);
}
}
function main() {
while (true) {
try {
// Get order book data
const orderBooks = fetchOrderBooks();
// Calculate trends
const trend = calculateTrend(orderBooks);
Log(`Current trend: ${trend}`);
// Cancel pending order
cancelOrders(buyOrders);
cancelOrders(sellOrders);
buyOrders = [];
sellOrders = [];
// Order based on trends
if (trend > 0 && loop > 0) {
const price = _N(orderBooks[0].Bids[0][0] + RATIO * PRICE_INCREMENT, 2);
const amount = _N(Math.max(S_AMOUNT, MIN_AMOUNT), 4);
createBuyOrder(price, amount);
} else if (trend < 0 && loop > 0) {
const price = _N(orderBooks[0].Asks[0][0] - RATIO * PRICE_INCREMENT, 2);
const amount = _N(Math.max(S_AMOUNT, MIN_AMOUNT), 4);
createSellOrder(price, amount);
}
// Loop count and interval
loop++;
Sleep(INTERVAL);
} catch (error) {
Log(`Main logic error: ${error.message}`);
}
}
}
Les marchés deviennent plus efficaces
Lorsque de plus en plus de stratégies quantitatives ou à haute fréquence sont impliquées et trouvent la même relation Lead-Lag, une grande quantité de fonds éliminera rapidement la différence de prix.
Restrictions de change ou changements de frais
À mesure que la structure des frais des différents échanges change, une fois que les coûts des frais dépassent les bénéfices de l'arbitrage, la rentabilité des stratégies de négociation à haute fréquence sera considérablement réduite.
Dégradation et dérapage de la liquidité
Lorsque le volume du marché est insuffisant, les stratégies à haute fréquence rencontrent souvent un glissement plus grave; ou de gros ordres poussent rapidement les prix à la hausse, ce qui entraîne l'effet de leurs propres ordres sur le "acheter bas et vendre haut" initialement attendu, ce qui entraîne une baisse des rendements.
Variations de la volatilité du marché
Certaines stratégies fonctionnent très bien dans des conditions de "haute volatilité" ou de "période spécifique".
Le point clé de la stratégie de négociation à haute fréquence réside dans la capture des prix de plusieurs bourses et le jugement de la synthèse de tendance. Il a réalisé une fois une méthode de négociation d'entrée et de sortie à très haute fréquence et rapide basée sur le principe de Lead-Lag: observer les prix des bourses qui se déplacent en premier, puis pousser les prix des autres bourses à suivre, capturant ainsi les différences de prix instantanées ou les tendances à court terme. Cependant, comme l'a dit l'auteur, les changements dans l'environnement du marché, l'homogénéité de la stratégie, les frais de manutention et les limites de fréquence ont rendu cette stratégie qui repose sur le premier mouvement puis le déplacement de la différence de prix progressivement moins utile, et même perdre de la rentabilité. Pour ceux qui veulent explorer à nouveau ce type de stratégie de Lead-Lag, il est nécessaire d'optimiser le module de négociation en combinaison avec les dernières règles de gestion des frais du marché (liquidité, algorithme de gestion, correspond