En el artículo anterior, presentamos el arbitraje de cambio cruzado. En este artículo, echaremos un vistazo profundo a cómo aplicar el efecto Lead-Lag a la negociación de alta frecuencia, que requiere capturar pequeñas diferencias de precios en un tiempo muy corto y obtener ganancias rápidamente. El efecto Lead-Lag proporciona a los operadores información predictiva para ayudarlos a juzgar la tendencia a corto plazo de los precios y lograr el arbitraje entre diferentes intercambios.
Lo siguiente es:una simplificación del código públicoEl principio de código de esta estrategia original es muy simple y una vez fue muy rentable.
El llamado
La estrategia obtiene datos del libro de pedidos de diferentes intercambios casi de manera sincrónica, como el precio de oferta, el precio de compra, el volumen de pedidos pendientes, etc. Luego se compara el precio medio (es decir, el promedio del precio de compra y el precio de venta) de diferentes intercambios para inferir la dinámica del mercado.
La estrategia se centra principalmente en los cambios de precios de tres bolsas externas (okex, binance, huobipro):
Aquí, cada tendencia X está determinada por la diferencia entre el
La estrategia solo compra o vende después de que se confirma la tendencia, y cancela la orden anterior antes de colocar cada orden (es decir, evitando órdenes pendientes accidentales que conducen a la acumulación de riesgo). Al mismo tiempo, el script también establece módulos como apalancamiento, operación por lotes y monitoreo del control de riesgos, lo que significa que se utilizan múltiples cuentas y múltiples pares de divisas simultáneamente en la negociación en vivo, expandiendo así la frecuencia de negociación de la estrategia y la eficiencia de utilización del capital.
Además, esta estrategia es una estrategia de alta frecuencia. No necesita prestar atención a la ganancia o pérdida de cada orden, ni necesita detener la pérdida. Puede continuar siempre que haya una probabilidad de obtener ganancias.
// 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}`);
}
}
}
Los mercados se vuelven eficientes
Cuando cada vez más estrategias cuantitativas o de alta frecuencia están involucradas y encuentran la misma relación Lead-Lag, una gran cantidad de fondos eliminará la diferencia de precio rápidamente.
Restricciones de cambio o cambios de tarifas
A medida que la estructura de tarifas de diferentes intercambios cambia, una vez que los costos de tarifas exceden las ganancias de arbitraje, la rentabilidad de las estrategias de negociación de alta frecuencia se reducirá en gran medida.
Disminución y deslizamiento de la liquidez
Cuando el volumen del mercado es insuficiente, las estrategias de alta frecuencia a menudo se encuentran con deslizamientos más severos; o las órdenes grandes impulsarán los precios rápidamente, haciendo que el inicialmente esperado
Cambios en la volatilidad del mercado
Algunas estrategias funcionan muy bien bajo "alta volatilidad" o "período específico".Cuando el mercado es plano o la volatilidad disminuye y el apalancamiento se reduce, la estrategia pierde su entorno adecuado e incluso puede incurrir en pérdidas frecuentes.
El punto clave de la estrategia de negociación de alta frecuencia radica en la captura de precios de múltiples intercambios y el juicio de la síntesis de tendencias. Una vez que se realizó un método de negociación de entrada y salida de alta frecuencia y rápida basado en el principio de Lead-Lag: observar qué intercambio se mueve primero, y luego conducir a otros intercambios a seguir, capturando así diferencias de precios instantáneas o tendencias a corto plazo. Sin embargo, como dijo el autor, los cambios en el entorno del mercado, la homogeneidad de la estrategia, las tarifas de manejo y los límites de frecuencia han hecho que esta estrategia que se basa en el primer movimiento y luego mueve la diferencia de precio se vuelva poco a poco menos útil, e incluso pierda rentabilidad. Para aquellos que quieren explorar este tipo de estrategia de Lead-Lag nuevamente, es necesario optimizar el módulo de negociación en combinación con las últimas reglas de gestión de tarifas del mercado (liquidez, manejo de algoritmos, ajuste de velocidad), prestando atención a la competencia en un entorno de mercado en constante cambio.