仮想通貨のスポットヘッジ戦略の設計 (2)

作者: リン・ハーンリディア, 作成日:2022-07-19 15:19:52, 更新日:2023-09-24 19:34:38

img

仮想通貨のスポットヘッジ戦略の設計 (2)

この戦略をアップグレードする方法について学びます. この戦略をアップグレードするには, 戦略の変更は大きくありませんが,変更の詳細には注意が必要です.コード内のいくつかの場所の定義は,以前のものから変更されています.理解する必要があります.

この戦略を向上させる必要性

  • スポット取引対象のレバレッジモードを切り替える この変更は実際のボットのみに関連している.一部のスポット取引所にはスポットレバレッジインターフェースがあり,それらはFMZにもカプセル化されている.FMZに直接パッケージ化され,スポットレバレッジをサポートしている交換オブジェクトでは,モードを直接切り替えることができます.
  • スプレッドチャート表示を追加する 横幅線を描いているだけです.A exchange -> B exchange, B exchange -> A exchange横線を引くと,その横線がスプレッドを引き起こします.line drawing class library直接に対処する,その利点は使用が簡単である,ここで我々はまた,どのように使用するtemplate class libraryFMZの機能
  • 片側ヘッジ機能 この変化はかなり重要であり,特定のヘッジ取引中に2つの取引所の間の価格差を完全に逆転させることは困難である.ほとんどの場合,ある取引所の価格が他の取引所の価格よりも一貫して高い.この時点で,当社の資産が完全にヘッジされている場合 (すなわち,コインはすべて低価格の取引所で,お金は高価格の取引所で).ヘッジは停滞しており,利益を得るためにスプレッドの変動に依存することはもはや不可能です.この時点で,コインをヘッジするために少しお金を失うように戦略を作成する必要があります (コインを再び高い価格で取引所で存在させてください),価格の差が再び大きくなったとき,我々はヘッジを続け,利益を得ることができます.
  • 交互的に,ヘッジ・スプレッドラインなどのパラメータを修正する. 戦略にインタラクティブな機能を追加して リアルタイムでスプレッドトリガーラインを修正します
  • 状態バー情報を整理し,表形式で表示する 簡単に表示するために表示する必要があるデータを整理します.

次に,これらのデザインを"つ"つ実行しましょう.

スポット交換オブジェクトのレバレッジモードを切り替える

コードを使用します. ローバーモードに切り替える. ローバーモードに切り替える.exchanges[i].IOパラメータを入力trade_normalポジションごとにレバレッジポジションに切り替え,入力trade_super_marginバックテストはサポートされません.これは実際のボットでのみ使用されます.

準備段階に追加するmain機能:

    // Switch leverage mode
    for (var i = 0 ; i < exchanges.length ; i++) {   // Traverse and detect all added exchange objects
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   //If the exchange object represented by the current i-index is Binance spot, and the parameter marginType of the strategy interface is not the option of "common currency", execute the switch operation
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "Set to leveraged position-by-position")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "Set to leveraged full position")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

この戦略は,Binanceスポットのコイン対コインレバレッジモードを切り替えるためのコードのみを追加します. したがって,戦略パラメータのスイッチ設定は,Binanceスポットにのみ有効です.

スプレッドチャート表示を追加

簡単に使用できます. テンプレート名はLine Drawing LibraryFMZプラットフォームの戦略スクエアで直接検索して取得できます.

img

直接リンクをクリックしてください:https://www.fmz.com/strategy/27293このテンプレートのコピーページにジャンプします.

img

このテンプレートクラスライブラリを自分の戦略ライブラリにコピーします.

img

テンプレートクラスライブラリをチェックする. テンプレートクラスライブラリをチェックした後に,このテンプレートクラスライブラリを参照する. このテンプレートクラスライブラリの使用の簡潔な説明です. このテンプレートには既にテンプレートを参照されているので,操作を繰り返す必要はありません. この戦略を戦略の正方形にコピーすると,Line Drawing Library戦略編集ページのテンプレートバーで参照されています.

機能の使い方について学びます.Line Drawing Libraryグラフを描きます

img

拡大を図る計画ですA->B拡大するB->A2つの曲線 (現在のAからB,BからAのスプレッド), 2つの水平線 (トリガースプレッドライン) を上図のように描く必要があります.

引き金を引く線を設計したいからですA->BそしてB->A前回の記事では デザインを使えません 前回の記事では

      var targetDiffPrice = hedgeDiffPrice
      if (diffAsPercentage) {
          targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
      }

引き金を引くのは"つだけtargetDiffPrice- わかった まずパラメータを変換します.

img

そしてコードを変更します:

        var targetDiffPriceA2B = hedgeDiffPriceA2B
        var targetDiffPriceB2A = hedgeDiffPriceB2A
        if (diffAsPercentage) {
            targetDiffPriceA2B = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageA2B
            targetDiffPriceB2A = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentageB2A
        }

異なるトリガーラインは,前のものから変更されています.targetDiffPrice2からtargetDiffPriceA2B, targetDiffPriceB2A- わかった 次のステップは,線図ライブラリの線図関数を使って このデータを図に描くことです.

        // drawing
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // The first parameter of this function is the value of the horizontal line in the Y-axis direction, and the second parameter is the display text
        $.PlotHLine(targetDiffPriceB2A, "B->A")

戦略が実行されているとき このようなグラフがあります

img

線を超越しないように,リアルタイム・スプレッド・カーブを描きます.リアルタイム・スプレッド・データのカーブを描くコードをバランスチェックに入れます.

        if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
            nowAccs = _C(updateAccs, exchanges)
            var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
            cancelAll()
            if (isBalance) {
                lastKeepBalanceTS = ts
                if (isTrade) {
                    var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                    var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                    LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
                    isTrade = false 
                }                
            }

            $.PlotLine("A2B", depthA.Bids[0].Price - depthB.Asks[0].Price)  // Draw real-time spread curves
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // The first parameter is the name of the curve, and the second parameter is the value of the curve at the current moment, that is, the value in the Y-axis direction at the current moment
        }

この方法では,描写コードは4行しかありません. 実行時にグラフが表示されるようにします.

片側ヘッジ機能

上記のように,スプレッドトリガーラインは2つに変更され,A->BそしてB->Aこの方法では,以前の注文価格アルゴリズムを使用することはできません.代わりにスリップ価格を市場価格に追加する方法を使用します.

        if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPriceA2B && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A -> B market conditions are met            
            var priceSell = depthA.Bids[0].Price - slidePrice
            var priceBuy = depthB.Asks[0].Price + slidePrice
            var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
            if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance * 0.8 / priceSell > minHedgeAmount) {
                amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance * 0.8 / priceSell, maxHedgeAmount)
                Log("trigger A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // Tips
                hedge(exB, exA, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        } else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPriceB2A && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) {   // B -> A market conditions are met
            var priceBuy = depthA.Asks[0].Price + slidePrice
            var priceSell = depthB.Bids[0].Price - slidePrice
            var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
            if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance * 0.8 / priceBuy > minHedgeAmount) {
                amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance * 0.8 / priceBuy, maxHedgeAmount)
                Log("trigger B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  //Tips
                hedge(exA, exB, priceBuy, priceSell, amount)
                cancelAll()
                lastKeepBalanceTS = 0
                isTrade = true 
            }            
        }

買取価格と販売価格が2つのデータに分けられているため,ヘッジ機能はhedge修正する必要もあります

function hedge(buyEx, sellEx, priceBuy, priceSell, amount) {
    var buyRoutine = buyEx.Go("Buy", priceBuy, amount)
    var sellRoutine = sellEx.Go("Sell", priceSell, amount)
    Sleep(500)
    buyRoutine.wait()
    sellRoutine.wait()
}

これらの変更に基づいて,いくつかの小さな調整もあります. ここでは繰り返しません.詳細についてはコードを見ることができます.

交互的に,ヘッジ・スプレッドラインなどのパラメータを修正する.

戦略にインタラクションを追加し,戦略がリアルタイムでスプレッドトリガーラインを修正できるようにします.これは,ここで教学デモとして実装されている半自動戦略の設計要件です. 戦略のインタラクションデザインも非常にシンプルです.まず,戦略編集ページの戦略にインタラクションコントロールを追加します.

img

制御入力ボックスに値を入力した後,入力ボックス右のボタンをクリックします. 指示がすぐに戦略に送られます.例えば:値を入力します.123入力ボックスで,クリックしますA2B指示がすぐに戦略に送られます.

A2B:123

戦略コードに インタラクティブな検出と処理コードを 設計する

        // interact
        var cmd = GetCommand()   // Every time the loop is executed here, it checks whether there is an interactive command, and returns to an empty string if not.
        if (cmd) {               // An interactive command was detected, such as A2B:123
            Log("command received:", cmd)
            var arr = cmd.split(":")   // Split out the interactive control name and the value in the input box, arr[0] is A2B, arr[1] is 123
            if (arr[0] == "A2B") {     // Determine whether the triggered interactive control is A2B
                Log("Modify the parameters of A2B, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // Modify the trigger spread line
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // Modify the trigger spread line
                }
            } else if (arr[0] == "B2A") {           // Triggered control detected is B2A     
                Log("Modify the parameters of B2A, ", diffAsPercentage ? "The parameter is the difference percentage" : "The parameter is the difference:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

状態バー情報を整理し,表形式で表示する

ステータスバーのデータ表示を より組織的で観察しやすくします

        var tbl = {
            "type" : "table", 
            "title" : "data", 
            "cols" : ["exchange", "coin", "freeze coin", "denominated currency", "freeze denominated currency", "trigger spread", "current spread"], 
            "rows" : [], 
        }
        tbl.rows.push(["A:" + exA.GetName(), nowAccs[0].Stocks, nowAccs[0].FrozenStocks, nowAccs[0].Balance, nowAccs[0].FrozenBalance, "A->B:" + targetDiffPriceA2B, "A->B:" + (depthA.Bids[0].Price - depthB.Asks[0].Price)])
        tbl.rows.push(["B:" + exB.GetName(), nowAccs[1].Stocks, nowAccs[1].FrozenStocks, nowAccs[1].Balance, nowAccs[1].FrozenBalance, "B->A:" + targetDiffPriceB2A, "B->A:" + (depthB.Bids[0].Price - depthA.Asks[0].Price)])

        LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")

img

バックテスト

バックテストはテスト戦略,初期検出機能のみであり,多くのバグはバックテスト段階で実際にテストすることができます.バックテスト結果にあまり注意を払う必要はありません.最終戦略は依然として実際の環境でテストする必要があります.

img

戦略のソースコード:https://www.fmz.com/strategy/302834


関連性

もっと