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

デジタル通貨の現金ヘッジ戦略の設計 (1)

作者: リン・ハーン発明者 量化 - 微かな夢, 作成日:2021-07-19 17:38:24, 更新日:2023-09-20 10:35:16

img

デジタル通貨の現金ヘッジ戦略の設計 (1)

戦略設計の初心者にとって,ヘッジ戦略は非常に良い練習戦略です. この記事では,シンプルで実用的なデジタル通貨の現金ヘッジ戦略を実装し,初心者にいくつかの設計経験を学ぶことを望みます.

戦略のニーズに応じて,いくつかの関数,戦略のインターフェースのパラメータを設計します.

まず,この策略がデジタル通貨現金ヘッジ戦略であることを明確にするために,我々は最も簡単なヘッジを設計し,二つの現金取引所の間で高い価格で取引所のみを売却し,低価格で取引所のみを購入し,差額を稼ぎます. 高価格の取引所はすべてコインであるときに (高価格のコインがすべて売られているため),低価格の取引所はすべてコインであるときに (低価格のコインがすべて購入されているため),ヘッジはできません.

ハージング時に下注する価格,数量,取引所には精度制限があり,最小下注量制限もある.最小下注量制限以外の戦略は,ヘッジング時に最大下注量も考慮し,下注量が大きすぎると十分な注文量も持たない.また,2つの取引所が異なる通貨を計算した場合の為替レートの変換方法も考慮する必要がある.

戦略は,いくつかのパラメータを設計する必要があります.

  • 負債の引き下げについてhedgeDiffPriceこの値を超えると,ヘッジ操作を誘発します.
  • 最低の負債:minHedgeAmount負債の負債は,負債の負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として.
  • 最大ヘッジメント:maxHedgeAmount負債の負債は,負債の負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として,負債として.
  • A 価格精度:pricePrecisionAA取引所からの注文価格の精度 (小数値)
  • A 単位の精度:amountPrecisionAA取引所下位単位の精度 (小数位) 〔a〕
  • B価格の精度:pricePrecisionB取引所Bの注文価格の精度 (小数値)
  • B 単位の精度:amountPrecisionBB取引所下位単位の精度 (小数位)
  • A 取引所の為替:rateA,最初の追加された取引所のオブジェクトの為替換算は,デフォルトで1は変換されません.
  • 取引所Bの為替:rateB,第2の追加された取引所のオブジェクトの為替換,デフォルト1は変換されません.

ヘッジ戦略は,両口座のコインの数を常に不変に保つ必要がある (すなわち,いかなる方向のポジションも保持せず,中立である) のため,戦略には,常にバランスを検知するバランス論理が必要である.バランスを検知する際には,両取引所の資産データを入手することから逃れる.我々はそれを使用するために関数を書く必要がある.

  • アップデートAccs
    function updateAccs(arrEx) {
        var ret = []
        for (var i = 0 ; i < arrEx.length ; i++) {
            var acc = arrEx[i].GetAccount()
            if (!acc) {
                return null
            }
            ret.push(acc)
        }
        return ret 
    }
    

オーダーが完成していない場合,オーダーを一時的に取り消す必要があります. この操作はバランスモジュールやヘッジロジックの両方で処理する必要があります. そのため,オーダーを完全に取り消す関数を設計する必要があります.

  • キャンセル すべて
    function cancelAll() {
        _.each(exchanges, function(ex) {
            while (true) {
                var orders = _C(ex.GetOrders)
                if (orders.length == 0) {
                    break
                }
                for (var i = 0 ; i < orders.length ; i++) {
                    ex.CancelOrder(orders[i].Id, orders[i])
                    Sleep(500)
                }
            }
        })
    }
    

平衡コイン数では,ある深度データの中で,あるコイン数に累積する価格を探さなければなりません.

  • getDepthPrice について
    function getDepthPrice(depth, side, amount) {
        var arr = depth[side]
        var sum = 0
        var price = null
        for (var i = 0 ; i < arr.length ; i++) {
            var ele = arr[i]
            sum += ele.Amount
            if (sum >= amount) {
                price = ele.Price
                break
            }
        }
        return price
    }
    

特定のヘッジの下記の操作を設計し,並行下記の操作として設計する必要があります.

  • ハッジ
    function hedge(buyEx, sellEx, price, amount) {
        var buyRoutine = buyEx.Go("Buy", price, amount)
        var sellRoutine = sellEx.Go("Sell", price, amount)
        Sleep(500)
        buyRoutine.wait()
        sellRoutine.wait()
    }
    

そして最後に,平衡関数の設計を完了します.

  • keep バランス
    function keepBalance(initAccs, nowAccs, depths) {
        var initSumStocks = 0
        var nowSumStocks = 0 
        _.each(initAccs, function(acc) {
            initSumStocks += acc.Stocks + acc.FrozenStocks
        })
        _.each(nowAccs, function(acc) {
            nowSumStocks += acc.Stocks + acc.FrozenStocks
        })
      
        var diff = nowSumStocks - initSumStocks
        // 计算币差
        if (Math.abs(diff) > minHedgeAmount && initAccs.length == nowAccs.length && nowAccs.length == depths.length) {
            var index = -1
            var available = []
            var side = diff > 0 ? "Bids" : "Asks"
            for (var i = 0 ; i < nowAccs.length ; i++) {
                var price = getDepthPrice(depths[i], side, Math.abs(diff))
                if (side == "Bids" && nowAccs[i].Stocks > Math.abs(diff)) {
                    available.push(i)
                } else if (price && nowAccs[i].Balance / price > Math.abs(diff)) {
                    available.push(i)
                }
            }
            for (var i = 0 ; i < available.length ; i++) {
                if (index == -1) {
                    index = available[i]
                } else {
                    var priceIndex = getDepthPrice(depths[index], side, Math.abs(diff))
                    var priceI = getDepthPrice(depths[available[i]], side, Math.abs(diff))
                    if (side == "Bids" && priceIndex && priceI && priceI > priceIndex) {
                        index = available[i]
                    } else if (priceIndex && priceI && priceI < priceIndex) {
                        index = available[i]
                    }
                }
            }
            if (index == -1) {
                Log("无法平衡")            
            } else {
                // 平衡下单
                var price = getDepthPrice(depths[index], side, Math.abs(diff))
                if (price) {
                    var tradeFunc = side == "Bids" ? exchanges[index].Sell : exchanges[index].Buy
                    tradeFunc(price, Math.abs(diff))
                } else {
                    Log("价格无效", price)
                }
            }        
            return false
        } else if (!(initAccs.length == nowAccs.length && nowAccs.length == depths.length)) {
            Log("错误:", "initAccs.length:", initAccs.length, "nowAccs.length:", nowAccs.length, "depths.length:", depths.length)
            return true 
        } else {
            return true 
        }
    }
    

戦略のニーズに応じてこれらの関数を設計し,以下は戦略のメイン関数です.

策略主関数設計

戦略は,FMZで,mainこの関数は,この関数で実行されます.main初期化する部分には,いくつかの手順があります.

  • 取引所のオブジェクト名 戦略の多くの操作が取引所のオブジェクトに使用されるため,例えば市場を取得,注文を下ろすなど. だから,長い名前を使うのは面倒です. 小さなコツは,簡単な名前を使用することです.

    var exA = exchanges[0]
    var exB = exchanges[1]
    

    後にコードを書くのは快適です.

  • 通貨レート,精度に関する設計

      // 精度,汇率设置
      if (rateA != 1) {
          // 设置汇率A
          exA.SetRate(rateA)
          Log("交易所A设置汇率:", rateA, "#FF0000")
      }
      if (rateB != 1) {
          // 设置汇率B
          exB.SetRate(rateB)
          Log("交易所B设置汇率:", rateB, "#FF0000")
      }
      exA.SetPrecision(pricePrecisionA, amountPrecisionA)
      exB.SetPrecision(pricePrecisionB, amountPrecisionB)
    

    変数値がrateArateB設定が1である場合は,rateA != 1あるいはrateB != 1通貨の変換を設定しない.

  • すべてのデータをリセットします.

    img

    時には,ポリシー開始時にすべてのログ,空白記録のデータを削除する必要がある場合もあります. ポリシーインターフェースのパラメータをデザインできます.isReset策略で初期化された部分の設計を再設定するコード,例えば:

      if (isReset) {   // 当isReset为真时重置数据
          _G(null)
          LogReset(1)
          LogProfitReset()
          LogVacuum()
          Log("重置所有数据", "#FF0000")
      }
    
  • 初期アカウントデータを復元,現在のアカウントデータを更新 バランスを判断するために,戦略は,最初の口座資産の状況と現在の状況との対比を継続的に記録し,その状況と現在の状況との対比を記録する必要があります.nowAccsこの変数は,現在のアカウントのデータを記録するものです.updateAccs取引所の口座情報を入手する.initAccs取引所Aと取引所Bのコイン数,定価コイン数などのデータ) を記録する.initAccsまず使用する_G()機能復元 ((_G 機能は永続的にデータを記録し,記録されたデータを復元することができます.APIのドキュメントを参照してください:リンク検索ができない場合は,現在のアカウント情報で割り当てて使用してください._G函数記録.

    このコードは,

      var nowAccs = _C(updateAccs, exchanges)
      var initAccs = _G("initAccs")
      if (!initAccs) {
          initAccs = nowAccs
          _G("initAccs", initAccs)
      }
    

取引論理,主関数の主回路

主回路内のコードは,戦略論理の各回合で実行されるプロセスであり,繰り返し実行されるプロセスが主回路を形成する.

  • 市場データを入手し,市場データの有効性を判断する

          var ts = new Date().getTime()
          var depthARoutine = exA.Go("GetDepth")
          var depthBRoutine = exB.Go("GetDepth")
          var depthA = depthARoutine.wait()
          var depthB = depthBRoutine.wait()
          if (!depthA || !depthB || depthA.Asks.length == 0 || depthA.Bids.length == 0 || depthB.Asks.length == 0 || depthB.Bids.length == 0) {
              Sleep(500)
              continue 
          }
    

    この FMZ プラットフォームを使って行われている並行関数ですexchange.Go呼び出しを作成しましたGetDepth()インタフェースの同期オブジェクトdepthARoutinedepthBRoutine│ この2つの対称オブジェクトが作成されたとき,呼び出しGetDepth()インタフェースもすぐに発生し,この時点で2つの深度データ取得の要求が取引所に送信された. 呼び出しますdepthARoutinedepthBRoutine対象についてwait()深いデータを得る方法.
    深度データを取得した後に,深度データの有効性を検証する.データ異常の場合,実行を誘発する.continue文は主回路を再実行します.

  • 使用する价差值参数か差价比例パラメータは?

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

    FMZのパラメータは,あるパラメータに基づいて作れます.表示する可能性は隠れているこの式は,この式を,この式で定義します.价格差ありがとうございました.差价比例

    img

    戦略インターフェースのパラメータにパラメータを追加しましたdiffAsPercentage◎このパラメータに基づいて表示または隠す他の2つのパラメータは,以下のように設定されます:hedgeDiffPrice@!diffAsPercentageどこにいるのかdiffAsPercentageこのパラメータを表示するには,hedgeDiffPercentage@diffAsPercentageどこにいるのかdiffAsPercentageこのパラメータを表示するには, デザインを重ねて 選んでみましたdiffAsPercentageパラメータは,差値比率でヘッジを誘発する条件である.diffAsPercentage価格差がヘッジとして引き起こす条件である.

  • ハードゲージを誘発する条件を判断する

          if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPrice && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A -> B 盘口条件满足            
              var price = (depthA.Bids[0].Price + depthB.Asks[0].Price) / 2
              var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
              if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance / price > minHedgeAmount) {
                  amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance / price, maxHedgeAmount)
                  Log("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, price, amount, nowAccs[1].Balance / price, nowAccs[0].Stocks)  // 提示信息
                  hedge(exB, exA, price, amount)
                  cancelAll()
                  lastKeepBalanceTS = 0
                  isTrade = true 
              }            
          } else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPrice && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) {   // B -> A 盘口条件满足
              var price = (depthB.Bids[0].Price + depthA.Asks[0].Price) / 2
              var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
              if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance / price > minHedgeAmount) {
                  amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance / price, maxHedgeAmount)
                  Log("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, price, amount, nowAccs[0].Balance / price, nowAccs[1].Stocks)  // 提示信息
                  hedge(exA, exB, price, amount)
                  cancelAll()
                  lastKeepBalanceTS = 0
                  isTrade = true 
              }            
          }
    

    金融危機は,金融危機の初期段階から始まっています. 1、最初にヘッジ差を満たし,開口の差が設定された差のパラメータを満たす場合にのみヘッジすることができます. 2,取引可能なヘッジは,パラメータに設定された最小ヘッジを満たす必要がある.異なる取引所によって制限される最小単位の量が異なるため,両者の最小を取ることである. 3. 取引所での資産を売り,取引所での資産を買い,取引所での資産を売り,取引所での資産を買い. これらの条件が満たされた場合,ヘッジ関数を実行すると,ヘッジオフ命令が実行されます. 主関数の前に変数を事前に宣言します.isTradeこの変数は,ヘッジが発生したかどうかを示すために使用されます.trueそして,グローバル変数をリセットします.lastKeepBalanceTS0 (lastKeepBalanceTSは,最近のバランス操作のタイムラベルをマークするために使用され,0に設定すると,バランス操作は即座に起動します),そしてすべての挂列を削除します.

  • バランス操作

          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 
                  }                
              }            
          }
    

    負債の負債は,負債の負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債の負債として,負債の負債として,lastKeepBalanceTS0にリセットすると,バランス操作は即座に起動します.バランスが成功した後,収益を計算します.

  • ステータスバー情報

          LogStatus(_D(), "A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, " B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, " targetDiffPrice:", targetDiffPrice, "\n", 
              "当前A,Stocks:", nowAccs[0].Stocks, "FrozenStocks:", nowAccs[0].FrozenStocks, "Balance:", nowAccs[0].Balance, "FrozenBalance", nowAccs[0].FrozenBalance, "\n", 
              "当前B,Stocks:", nowAccs[1].Stocks, "FrozenStocks:", nowAccs[1].FrozenStocks, "Balance:", nowAccs[1].Balance, "FrozenBalance", nowAccs[1].FrozenBalance, "\n", 
              "初始A,Stocks:", initAccs[0].Stocks, "FrozenStocks:", initAccs[0].FrozenStocks, "Balance:", initAccs[0].Balance, "FrozenBalance", initAccs[0].FrozenBalance, "\n", 
              "初始B,Stocks:", initAccs[1].Stocks, "FrozenStocks:", initAccs[1].FrozenStocks, "Balance:", initAccs[1].Balance, "FrozenBalance", initAccs[1].FrozenBalance)
    

    ステータスバーは特に複雑な設計ではない.現在の時間を表示し,A取引所からB取引所への差とB取引所からA取引所への差を示します.現在のヘッジ目標差を示します.A取引所の口座資産データを表示し,B取引所の口座資産データを表示します.

異なる通貨の取引対の処理

戦略の初期には,この2つのパラメータを組み合わせました.mainこの関数の初期操作の部分では, 換算を設計しました.SetRate換算関数は最初に実行する必要があります. この関数は2つの側面に影響します.

  • すべての市場データ,注文データ,収納データにおける価格交換.
  • 口座の資産の通貨の換算. 例えば,現在の取引対はBTC_USDT価格単位はUSDT銀行口座の資産には,USDT代入したい場合は,コードに設定します.exchange.SetRate(6.8)簡単にexchangeこの取引所のオブジェクトの下にあるすべての関数の取得データは,CNYに換算されます. 通貨の価格がSetRate函数伝送現在の通貨対目標通貨の為替

海外のメディアは,異なる通貨の現金ヘッジ戦略 (教材)


関連性

もっと

松鼠の野放人 _ ウクライナの聖剣素晴らしい