資源の読み込みに... 荷物...

クリプト通貨のスポットヘッジ戦略 (2)

作者: リン・ハーンニナバダス, 作成日:2022-04-14 16:17:46, 更新日:2022-04-15 14:16:23

クリプト通貨のスポットヘッジ戦略 (2)

簡単なヘッジ戦略を実装し 戦略のアップグレード方法を学びます 戦略には多くの変更はありませんが,変更の詳細には注意が必要です.コードのいくつかの場所の定義は,前回と比較して変更されています.

戦略の向上に関する要件

  • スポット交換オブジェクトの境界モードを切り替える この変更はボットにのみ関連している.一部のスポットプラットフォームにはスポットマージンインターフェースがあり,FMZにもカプセル化されている.FMZに直接カプセル化され,スポットマージンをサポートする交換オブジェクトでは,モードを直接切り替えることができます.
  • スプレッドチャート表示を追加する グラフの横幅曲線をプロットします. グラフの横幅曲線は,A->BそしてB->A横軸のスプレッドトリガーラインと同様に,我々は直接使用することができますchart plot libraryFMZの機能を使用する方法も学びます.template library together.
  • 単面ヘッジの機能 この変更は,特定のヘッジ取引中に2つのプラットフォーム間の価格差を完全に逆転させることは困難であるため,比較的大きい.ほとんどの場合,あるプラットフォームの価格は他のプラットフォームの価格よりも一貫して高い.この時点で,当社の資産が完全にヘッジされている場合 (つまり,すべての通貨シンボルが低い価格のプラットフォームにあり,資産はすべて高い価格のプラットフォームにあります).ヘッジは停滞しており,利益を得るためには,拡散の変動に依存することはもはや不可能です.この時点で,あなたは僅かな資産を失うだけで,通貨シンボルをヘッジし,戻す戦略を作成する必要があります (通貨シンボルを再び高い価格のプラットフォームに戻らせてください).価格のスペードが再び大きくなったとき,あなたはヘッジを続け,利益を得ることができます.
  • ヘッジ・スプレッドラインのようなパラメータをインタラクティブに変更します
    戦略にインタラクティブな機能を追加して,リアルタイムでスプレッドトリガーラインを修正します.
  • 状態バー情報を管理し,表形式で表示する 便利な観察のために,表示する必要があるデータを整理し管理する.

次は デザインのアイデアを一つずつ 実現しましょう

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

コードを使用します. このコードは,このコードを入力します.exchanges[i].IOパラメータをインポートtrade_normal単一の利益率に移行し,輸入trade_super_marginバックテストではサポートされません. それはボットでのみ使用できます.

準備の過程で,main機能,追加:

    // switch the margin mode 
    for (var i = 0 ; i < exchanges.length ; i++) {   // traverse and detect all exchange objects added
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   // if the exchange object represented by the current index i is Binance Spot, and the parameter marginType on the strategy interface is not selected as the "common spot" option, execute the switch
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "set to isolated margin")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "set to cross margin")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

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

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

模板の名前は,ここでは,この模板の名前ですchart plot LibraryFMZの広場で直接検索できます.

img

直接リンクをクリックすることもできますhttps://www.fmz.com/strategy/27293テンプレートのコピーページに跳ね込む.

img

簡単に自分の戦略ライブラリにテンプレートをコピーできます.

img

次に,戦略編集ページでは,テンプレート列で使用するテンプレートライブラリを確認できます. チェックした後,戦略を保存し,戦略はこのテンプレートライブラリを使用します. これはテンプレートライブラリの使用の簡潔な説明だけです. 戦略がすでにこのテンプレートを参照しているため,操作を繰り返す必要はありません. 戦略コードをスクエアにコピーすると,chart plot Library戦略編集ページのテンプレートバーで参照されています.

基本的には,コンピュータの機能をchart plot 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- わかった グラフの図面図書室のグラフプロット機能を使用して グラフ上のデータを描くことができます

        // plot
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // the first parameter of the 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

次に,リアルタイム・スプレッド・カーブを描いてください.過剰に描かれないようにするために,リアルタイム・スプレッド・カーブを描いたコードを バランス検出に入れます. s

        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)  // plot real-time spread curves
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // the first parameter is the curve name, and the second parameter is the curve value 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 condition satisfied             
            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("triggerA->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // prompt message
                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 condition satisfied 
            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("triggerB->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  // prompt message
                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

A2B と B2A と呼ばれる2つのコントロールが追加されました. コントロール入力ボックスに値を入力した後,入力ボックス右側のボタンをクリックします. 命令はすぐに戦略に送られます.例えば: enter the value123入力ボックスで,クリックしますA2B命令がすぐに戦略に送られます

A2B:123

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

        // interaction 
        var cmd = GetCommand()   // every time when the loop is operated here, it will detect whether an interactive command is sent; if no, return null string 
        if (cmd) {               // interactive command detected, such as A2B:123
            Log("received command:", cmd)
            var arr = cmd.split(":")   // split out the interactive control name and the value in the input box; arr[0] means A2B, and arr[1] means 123
            if (arr[0] == "A2B") {     // judge whether the triggered interactive control is A2B
                Log("modify parameterA2B,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // modify the spread trigger line 
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // modify the spread trigger line 
                }
            } else if (arr[0] == "B2A") {           // detected the triggered control is B2A 
                Log("modify parameterB2A,", diffAsPercentage ? "parameter of spread ratio:" : "parameter of spread:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

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

ステータスバーのデータ表示を より規制され 観察しやすくします

        var tbl = {
            "type" : "table", 
            "title" : "data", 
            "cols" : ["platform", "Currency", "frozenCurrrency", "quoteCurrency", "frozenQuoteCurrency", "triggerSpread", "currentSpread"], 
            "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

img

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


もっと