Les ressources ont été chargées... Je charge...

Partage logique de la stratégie d'arbitrage sur les échanges multiples

Auteur:L'inventeur de la quantification - un petit rêve, Créé: 2022-07-12 17:20:06, mis à jour: 2023-09-25 19:47:14

img

Principes de stratégie

Pour des raisons de liquidité, lorsqu'il y a une grande quantité de fracas et de tirage sur le marché, il y aura inévitablement de grandes fluctuations de prix, et une différence de prix instantanée se formera entre les bourses, et la stratégie consiste à capturer ces moments dans lesquels des transactions rapides sont exécutées pour compléter le processus d'achat bas et de vente élevé. Certains clients m'ont demandé pourquoi je devais obtenir autant d'échanges. C'est inévitable. Ce que nous gagnons est la différence de prix instantanée entre les échanges. Plus il y a d'échanges, plus il y a d'opportunités pour la différence de prix formée après le croisement.

La logique de base de la stratégie
  1. Pour obtenir simultanément des informations sur les marchés de plusieurs bourses, elles doivent être obtenues simultanément afin de réduire le retard du marché obtenu.Plug-in simultané multi-échange
  2. Combinez les ordres de vente et d'achat de tous les ordres d'échange pour obtenir une information combinée sur les ordres, où RealPrice est le prix après déduction des frais de traitement,
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. Calculer le meilleur écart d'arbitrage à partir de l'information combinée du marché. Puisque nous prenons l'ordre, c'est-à-dire acheter à partir du prix le plus bas demander et vendre à partir du prix le plus élevé offrir, tant que bid.RealPrice > ask.RealPrice, il y a de la place pour le profit
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. À ce stade, nous avons obtenu les informations sur le spread d'arbitrage sur le marché, il y a donc plusieurs points de jugement sur la façon de choisir si l'exécution d'un commerce et combien de commerce:
  • Actifs résiduels courants
  • La taille de l'écart (si l'écart est trop faible, seul le montant de la devise sera équilibré, et si l'écart est suffisamment grand, le nombre de transactions sera maximisé)
  • Nombre d'ordres en attente
    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. Après avoir calculé le nombre d'ordres à passer, la transaction peut être exécutée.
            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. Il ne reste plus qu'à calculer les rendements, gérer les stop-loss sur les ordres ratés, etc.
Les bénéfices réels de la stratégie

img img img

Affichage actuel du bot réel, logique de base reste inchangée, optimisé pour prendre en charge plusieurs devises

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

Enfin, bienvenue à rejoindre la communication sur les échanges quantitatifs de Laoqiu:https://t.me/laoqiu_arbitrage


Relationnée

Plus de