Estrategia de arbitraje de diferencias al contado de múltiples bolsas Compartición lógica

El autor:Un sueño pequeño., Creado: 2022-07-12 17:20:06, Actualizado: 2023-09-25 19:47:14

img

Principios de la estrategia

Debido a razones de liquidez, cuando hay una gran cantidad de aplastamiento y tirón en el mercado, inevitablemente habrá grandes fluctuaciones de precios, y se formará una diferencia de precio instantánea entre los intercambios, y la estrategia es capturar estos momentos en los que se ejecutan operaciones rápidas para completar el proceso de comprar bajo y vender alto. Algunos clientes me preguntaron por qué tengo que obtener tantos intercambios. Esto es inevitable. Lo que ganamos es la diferencia de precio instantánea entre los intercambios. Cuanto más intercambios, más oportunidades para la diferencia de precio se forman después del cruce.

La lógica central de la estrategia
  1. Para obtener información de mercado de múltiples bolsas simultáneamente, debe obtenerse simultáneamente para reducir el retraso del mercado obtenido.Plug-in simultáneo de intercambio múltiple
  2. Combinar el pedido y la oferta de todas las órdenes de intercambio para obtener una información de pedido combinada, donde RealPrice es el precio después de deducir la tarifa de manejo,
function createOrders(depths, askOrders, bidOrders) {
    let asksIndex = 0;
    let bidIndex = 0;
    for (let i = 0; i < depths.length; i++) {
        let exchangeTariff = getExchangeTariff(i);
        let asks = depths[i].Asks;
        let bids = depths[i].Bids;
        for (let j = 0; j < Math.min(asks.length, bids.length, 20); j++) {
            if (asks[j].Amount >= minTakerAmount) {
                askOrders[asksIndex] = {
                    "Price": asks[j].Price,
                    "Amount": asks[j].Amount,
                    "Fee": asks[j].Price * exchangeTariff,
                    "RealPrice": asks[j].Price * (1 + exchangeTariff),
                    "Index": i,
                };
                asksIndex++;
            }
            if (bids[j].Amount >= minTakerAmount) {
                bidOrders[bidIndex] = {
                    "Price": bids[j].Price,
                    "Amount": bids[j].Amount,
                    "Fee": bids[j].Price * exchangeTariff,
                    "RealPrice": bids[j].Price * (1 - exchangeTariff),
                    "Index": i,
                };
                bidIndex++;
            }
        }
    }
    askOrders.sort(function (a, b) {
        return a.RealPrice - b.RealPrice;
    });
    bidOrders.sort(function (a, b) {
        return b.RealPrice - a.RealPrice;
    });
}
  1. Calcular el mejor diferencial de arbitraje a partir de la información combinada del mercado. ya que estamos tomando la orden, es decir, comprar desde el precio más bajo pedir y vender desde el precio más alto de oferta, siempre y cuando el bid.RealPrice > ask.RealPrice, hay espacio para la ganancia
function getArbitrageOrders(askOrders, bidOrders) {
    let ret = [];
    for (let i = 0; i < askOrders.length; i++) {
        for (let j = 0; j < bidOrders.length; j++) {
            let bidOrder = bidOrders[j];
            let askOrder = askOrders[i];
            if (bidOrder.Index === askOrder.Index) {
                continue
            }
            let minMigrateDiffPrice = ((askOrder.Price + bidOrder.Price) / 2 * minMigrateDiffPricePercent / 100);
            if (bidOrder.RealPrice - askOrder.RealPrice > minMigrateDiffPrice) {
                ret.push({
                    "Ask": askOrder,
                    "Bid": bidOrder,
                })
            }
        }
    }
    if (ret.length === 0) {
        ret.push({
            "Ask": askOrders[0],
            "Bid": bidOrders[0],
        });
    }
    //Sort by best spread
    ret.sort((a, b) => {
        return (b.Bid.RealPrice - b.Ask.RealPrice) - (a.Bid.RealPrice - a.Ask.RealPrice);
    });
    return ret;
}
  1. En este punto, hemos obtenido la información sobre el diferencial de arbitraje en el mercado, por lo que hay varios puntos de juicio sobre cómo elegir si ejecutar una operación y cuánto comerciar:
  • Activos restantes corrientes
  • El tamaño del diferencial (si el diferencial es demasiado pequeño, solo se equilibrará la cantidad de moneda, y si el diferencial es lo suficientemente grande, se maximizará el número de operaciones)
  • Número de órdenes pendientes
    var askOrder = arbitrageOrder.Ask;
    var bidOrder = arbitrageOrder.Bid;
    var perAmountFee = arbitrageOrder.Ask.Fee + arbitrageOrder.Bid.Fee;
    var minRealDiffPrice = (askOrder.Price + bidOrder.Price) / 2 * minDiffPricePercent / 100;
    var minMigrateDiffPrice = ((askOrder.Price + bidOrder.Price) / 2 * minMigrateDiffPricePercent / 100);
    var curRealDiffPrice = arbitrageOrder.Bid.RealPrice - arbitrageOrder.Ask.RealPrice;
    var buyExchange = exchanges[arbitrageOrder.Ask.Index];
    var sellExchange = exchanges[arbitrageOrder.Bid.Index];
    var buySellAmount = 0;
    if (curRealDiffPrice > minRealDiffPrice) {
        buySellAmount = math.min(
            bidOrder.Amount,
            askOrder.Amount,
            maxTakerAmount,
            runningInfo.Accounts[bidOrder.Index].CurStocks,
            runningInfo.Accounts[askOrder.Index].CurBalance / askOrder.Price
        );
    } else if (bidOrder.Index !== askOrder.Index) {
        if (migrateCoinEx == -1) {
            if (curRealDiffPrice > minMigrateDiffPrice && runningInfo.Accounts[bidOrder.Index].CurStocks - runningInfo.Accounts[askOrder.Index].CurStocks > maxAmountDeviation) {
                buySellAmount = math.min(
                    bidOrder.Amount,
                    askOrder.Amount,
                    maxTakerAmount,
                    runningInfo.Accounts[bidOrder.Index].CurStocks,
                    runningInfo.Accounts[askOrder.Index].CurBalance / askOrder.Price,
                    runningInfo.Accounts[bidOrder.Index].CurStocks - ((runningInfo.Accounts[bidOrder.Index].CurStocks + runningInfo.Accounts[askOrder.Index].CurStocks) / 2)
                );
                if (buySellAmount >= minTakerAmount) {
                    Log("Start exchange balancing!");
                }
            }
        } else if (migrateCoinEx == askOrder.Index) {
            if (curRealDiffPrice > minMigrateDiffPrice && runningInfo.Accounts[bidOrder.Index].CurStocks > 0) {
                buySellAmount = math.min(
                    bidOrder.Amount,
                    askOrder.Amount,
                    maxTakerAmount,
                    runningInfo.Accounts[bidOrder.Index].CurStocks,
                    runningInfo.Accounts[askOrder.Index].CurBalance / askOrder.Price
                );
                if (buySellAmount >= minTakerAmount) {
                    Log("Initiate currency migration:", exchanges[bidOrder.Index].GetName(), "-->", exchanges[askOrder.Index].GetName());
                }
            }
        }
    }
  1. Después de calcular el número de órdenes a colocar, la transacción puede ser ejecutada.
            var buyWait = buyExchange.Go("Buy", _N(askOrder.Price * (1.01), pricePrecision), buySellAmount);
            var sellWait = sellExchange.Go("Sell", _N(bidOrder.Price * (0.99), pricePrecision), buySellAmount);
            var startWaitTime = new Date().getTime()
            Sleep(3000);
            var buyOrder = buyWait.wait()
            var sellOrder = sellWait.wait()
  1. Todo lo que queda es la lógica de calcular los rendimientos, manejar las pérdidas de parada en órdenes fallidas, y así sucesivamente.
Los beneficios reales de la estrategia

img img img

Display actual de bot real, lógica central permanece sin cambios, optimizado para soportar múltiples monedas

https://www.fmz.com/robot/464965

Por último, bienvenido a unirse a la comunicación de intercambio cuantitativo Laoqiu:https://t.me/laoqiu_arbitrage


Relacionados

Más.