Type/to search
7
Follow
359
Followers
複数の取引所におけるスポット価格差裁定戦略のロジックの共有
Original
Created 2022-06-27 21:26:27  Updated 2024-12-02 21:35:44
 4
 10034

img

戦略原則

流動性の問題から、市場で大量の売りや引きがあった場合、必然的に大きな価格変動が発生し、取引所間で瞬間的な価格差が生じます。戦略としては、これらの瞬間を捉えて高速取引を実行し、安く買って高く売るプロセスを完了します。
一部のクライアントは、なぜこんなに多くの取引所を持っているのかと私に尋ねました。これは避けられないことです。私たちが利益を得るのは、取引所間の瞬間的な価格差です。取引所の数が増えれば増えるほど、クロスオーバー後の価格差の機会が増えます。

戦略コアロジック
  1. 複数の取引所の相場情報を同時取得します。相場情報取得の遅延を減らすためには同時取得が必要です。同時取得については、私が共有したツールプラグインを参考にしてください。マルチエクスチェンジ同時プラグイン
  2. すべての取引所の売り値と買い値を結合して、総合見積情報を取得します。ここで、RealPrice は手数料を差し引いた価格です。
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. 組み合わせた市場情報から最も収益性の高い裁定スプレッドを計算します。我々は注文を受け付けており、つまり最低の売り値から買い、最高入札価格から売っているので、bid.RealPrice > ask.RealPriceである限り、利益の余地がある。
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], }); } //按最优价差排序 ret.sort((a, b) => { return (b.Bid.RealPrice - b.Ask.RealPrice) - (a.Bid.RealPrice - a.Ask.RealPrice); }); return ret; }
  1. 市場の裁定スプレッド情報を入手したので、取引を実行するかどうか、またどれだけの量を取引するかをどのように決定すればよいでしょうか。考慮すべき重要なポイントをいくつか挙げます。
  • 現在の残存資産
  • スプレッドの大きさ(スプレッドが小さすぎると通貨量のバランスのみが保たれ、スプレッドが十分に大きいと取引数が最大化されます)
  • 保留中の注文数
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("启动交易所平衡!"); } } } 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("启动货币迁移:", exchanges[bidOrder.Index].GetName(), "-->", exchanges[askOrder.Index].GetName()); } } } }
  1. 注文数量が計算されると、取引を実行できます。この戦略では、注文を受けると同時に注文を出すためにスリッページを直接追加する方法を使用します。
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. 残っているのは、利益を計算したり、失敗した注文のストップロスを処理したりするロジックです。
この戦略の実際の利点

img
img
img

現在のリアルタイム表示、コアロジックは変更されず、複数の通貨をサポートするように最適化されています

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

最後に、Laoqiu Quantitative Exchange への参加を歓迎します: https://t.me/laoqiu_arbitrage

Related Recommendations
Comment
All comments (4)

    大佬,minTakerAmount参数是怎么设置的

    2 years ago

    就怕小交易所跑路啊。

    3 years ago

    4 years ago

    秋哥威武。

    4 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)