avatar of 发明者量化-小小梦 发明者量化-小小梦
フォロー ダイレクトメッセージ
4
フォロー
1271
フォロワー

デジタル通貨スポットヘッジ戦略設計(2)

作成日:: 2021-07-30 16:36:48, 更新日:: 2023-09-20 10:36:43
comments   5
hits   2474

デジタル通貨スポットヘッジ戦略設計(2)

デジタル通貨スポットヘッジ戦略設計(2)

前回の記事では、シンプルなヘッジ戦略を実装しました。次は、この戦略をアップグレードする方法を学びます。 戦略の変更は大きなものではありませんが、変更の詳細には注意が必要です。コード内の一部の部分の定義は以前から変更されており、理解する必要があります。

この戦略をアップグレードする必要性

  • スポット取引オブジェクトのレバレッジモードを切り替える この変更は実際の取引にのみ関係します。一部のスポット取引所にはスポット レバレッジ インターフェイスがあり、これも FMZ にカプセル化されています。 FMZ 上で直接カプセル化され、スポット レバレッジをサポートする交換オブジェクトの場合、モードを直接切り替えることができます。
  • スプレッドチャート表示を追加 スプレッドチャート表示を追加します。描画のみのためA交易所->B交易所B交易所->A交易所スプレッドをトリガーする水平線を描きます。直接使用する画线类库利点はシンプルで使いやすいことです。ここではFMZの使い方も学びます模版类库関数。
  • 一方的なヘッジ機能 特定のヘッジ取引において、2 つの取引所間の価格差を完全に元に戻すことは難しいため、この変更は非常に重要です。ほとんどの場合、ある取引所の価格は、他の取引所の価格よりも一貫して高くなります。この時点で、私たちの資産がすべてヘッジされている場合(つまり、コインはすべて低価格の取引所にあり、お金はすべて高価格の取引所にあります)。ヘッジは行き詰まり、価格変動に頼って利益を上げることはもはや不可能になった。このとき、少し損失を出してコインをヘッジし(高価格の取引所に再びコインを存在させ)、価格差が再び大きくなったときに利益をヘッジし続けるような戦略が必要です。
  • ヘッジスプレッドラインなどのパラメータをインタラクティブに変更する 戦略にインタラクティブ機能を追加すると、スプレッドトリガーラインをリアルタイムで変更できます。
  • ステータスバーの情報を整理し、表形式で表示する 表示するデータを整理して、観察しやすくします。

次に、これらのデザインを1つずつ実装してみましょう。

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

Binanceのスポット取引を例にとると、コードを使用してスポットレバレッジモードに切り替えますexchanges[i].IO、パラメータを渡すtrade_normalレバレッジポジションに切り替えて、パスインするtrade_super_marginレバレッジフルポジションに切り替えます。バックテストはサポートされていません。これは実際の取引でのみ使用されます。

存在するmain関数の先頭に次の準備フェーズを追加します。

    // 切换杠杆模式
    for (var i = 0 ; i < exchanges.length ; i++) {   // 遍历检测所有添加的交易所对象
        if (exchanges[i].GetName() == "Binance" && marginType != 0) {   // 如果当前i索引代表的交易所对象是币安现货,并且策略界面参数marginType选择的不是「普通币币」选项,执行切换
            if (marginType == 1) {
                Log(exchanges[i].GetName(), "设置为杠杆逐仓")
                exchanges[i].IO("trade_normal")
            } else if (marginType == 2) {
                Log(exchanges[i].GetName(), "设置为杠杆全仓")
                exchanges[i].IO("trade_super_margin")
            }
        }
    }

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

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

パッケージ化された描画テンプレートを使用するのは非常に簡単です。私たちが使用するテンプレートの名前は画线类库。 FMZプラットフォーム戦略広場で直接検索して取得できます。

デジタル通貨スポットヘッジ戦略設計(2)

または、リンク https://www.fmz.com/strategy/27293 を直接クリックして、このテンプレートのコピー ページに移動します。

デジタル通貨スポットヘッジ戦略設計(2)

このテンプレート ライブラリを独自の戦略ライブラリにコピーするには、ボタンをクリックします。

デジタル通貨スポットヘッジ戦略設計(2)

次に、ポリシー編集ページのテンプレート列で必要なテンプレートライブラリを確認できます。チェックボックスをオンにしてポリシーを保存すると、このポリシーはこのテンプレートを参照するようになります。ここでは、テンプレート ライブラリの使用について簡単に説明します。この戦略ではこのテンプレートがすでに参照されているため、操作を繰り返す必要はありません。この戦略を戦略スクエアにコピーすると、戦略編集ページのテンプレートの列に表示されます。画线类库すでに引用されています。

主に使い方を学びます画线类库グラフを描画する関数。

デジタル通貨スポットヘッジ戦略設計(2)

私たちは計画していますA->B価格差、B->A価格差と価格差トリガーラインが描画されます。上の図に示すように、2 つの曲線 (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
      }

トリガースプレッドは1つだけtargetDiffPrice。 したがって、ここではコードを変更して、まずパラメータを変更する必要があります。

デジタル通貨スポットヘッジ戦略設計(2)

次にコードを変更します。

        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
        }

このように、価格差トリガーラインは前回から変更されますtargetDiffPrice一つが二つになったtargetDiffPriceA2BtargetDiffPriceB2A。 次に、線描画ライブラリの線描画機能を使用して、このデータをチャートに描画します。

        // 画图
        $.PlotHLine(targetDiffPriceA2B, "A->B")  // 该函数第一个参数是水平线在Y轴方向上的值,第二个参数是显示文本
        $.PlotHLine(targetDiffPriceB2A, "B->A")

戦略が実行されると、このようなチャートが表示されます。

デジタル通貨スポットヘッジ戦略設計(2)

次に、過剰描画を避けるためにリアルタイムのスプレッド カーブを描画します。残高チェックにリアルタイムの価格差データの曲線を描画するコードを入れます。

        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)  // 画实时差价曲线
            $.PlotLine("B2A", depthB.Bids[0].Price - depthA.Asks[0].Price)  // 第一个参数是曲线名称,第二个参数是曲线当前时刻的值,即当前时刻Y轴方向上的值
        }

この方法では、わずか 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 盘口条件满足            
            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("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[1].Balance * 0.8 / priceSell, nowAccs[0].Stocks)  // 提示信息
                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 盘口条件满足
            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("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, priceBuy, priceSell, amount, nowAccs[0].Balance * 0.8 / priceBuy, nowAccs[1].Stocks)  // 提示信息
                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()
}

これらの変更に基づいていくつかの小さな調整も行われていますが、ここでは詳しく説明しません。詳細についてはコードを参照してください。

ヘッジスプレッドラインなどのパラメータをインタラクティブに変更する

戦略にインタラクティブ性を追加して、戦略がスプレッド トリガー ラインをリアルタイムで変更できるようにします。これは半自動戦略の設計要件であり、ここでは教育デモンストレーションとしても実装されています。 戦略のインタラクション設計も非常にシンプルです。まず、戦略編集ページで戦略にインタラクティブなコントロールを追加します。

デジタル通貨スポットヘッジ戦略設計(2)

2 つのコントロールが追加されます。1 つは A2B と呼ばれ、もう 1 つは B2A と呼ばれます。コントロール入力ボックスに値を入力した後、入力ボックスの右側にあるボタンをクリックします。指示はすぐに戦略に送信されます。例:入力ボックスに値を入力します123、 クリックA2Bこのボタンは、戦略に指示をすぐに送信します。

A2B:123

戦略コード内にインタラクション検出および処理コードを設計します。

        // 交互
        var cmd = GetCommand()   // 每次循环执行到这里时,都检测有没有交互指令过来,没有则返回空字符串
        if (cmd) {               // 检测到有交互指令,例如:A2B:123
            Log("接收到命令:", cmd)
            var arr = cmd.split(":")   // 拆分出交互控件名称和输入框中的值,arr[0]就是A2B,arr[1]就是123
            if (arr[0] == "A2B") {     // 判断触发的交互控件是不是A2B
                Log("修改A2B的参数,", diffAsPercentage ? "参数为差价百分比" : "参数为差价:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageB2A = parseFloat(arr[1])     // 修改触发差价线
                } else {
                    hedgeDiffPriceA2B = parseFloat(arr[1])          // 修改触发差价线
                }
            } else if (arr[0] == "B2A") {           // 检测到触发的控件是B2A     
                Log("修改B2A的参数,", diffAsPercentage ? "参数为差价百分比" : "参数为差价:", arr[1])
                if (diffAsPercentage) {
                    hedgeDiffPercentageA2B = parseFloat(arr[1])
                } else {
                    hedgeDiffPriceB2A = parseFloat(arr[1])
                }
            }
        }

ステータスバーの情報を整理し、表形式で表示する

ステータス バーのデータを整理して見やすくします。

        var tbl = {
            "type" : "table", 
            "title" : "数据", 
            "cols" : ["交易所", "币", "冻结币", "计价币", "冻结计价币", "触发差价", "当前差价"], 
            "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) + "`")

デジタル通貨スポットヘッジ戦略設計(2)

バックテスト

バックテストは戦略のテストと機能の予備的な検出に過ぎません。バックテストの段階では、実際に多くのバグをテストすることができます。バックテストの結果にあまり注意を払う必要はありません。最終的な戦略は、実際の環境でテストする必要があります。

デジタル通貨スポットヘッジ戦略設計(2)

デジタル通貨スポットヘッジ戦略設計(2)

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