리소스 로딩... 로딩...

디지털 화폐 현금 헤지킹 전략 설계 (1)

저자:발명가들의 수량화 - 작은 꿈, 2021-07-19 17:38:24, 업데이트: 2023-09-20 10:35:16

img

디지털 화폐 현금 헤지킹 전략 설계 (1)

전략 설계 초보자에게는 헤지 전략은 매우 좋은 연습 전략이다. 이 글은 간단한 하지만 실제적인 디지털 화폐 현금 헤지 전략을 구현하여 초보자가 디자인 경험을 배울 수 있기를 희망한다.

전략 요구에 따라 함수, 전략 인터페이스 파라미터들을 디자인합니다.

먼저, 우리가 계획하고 있는 전략은 디지털 화폐 현금 헤지핑 전략입니다. 우리는 가장 간단한 헤지핑을 설계했습니다. 두 현금 거래소 사이에서 높은 가격에 거래소를 판매하고 낮은 가격에 거래소를 구매하여 차이를 얻습니다. 높은 가격에 거래소가 모두 코인이 될 때 (높은 가격으로 거래소가 모두 판매되기 때문에), 낮은 가격에 거래소가 모두 코인이 될 때 (낮은 가격으로 거래소가 모두 코인이 될 때) 헤지핑이 불가능합니다.

헤지핑을 할 때 주문할 때 가격, 수, 거래소는 정밀 한계, 그리고 최소 주문량 한계도 있다. 최소 제한 외 전략은 헤지핑을 할 때 한 번에 헤지핑을 할 때 최대 주문량을 고려하기도 한다. 너무 큰 주문량도 있을 수 없다. 또한 두 거래소에서 계산된 화폐가 다르면 환율 전환을 어떻게 할 것인지 고려해야 한다. 헤지핑의 처리 수수료, 단점 먹는 것은 슬라이드 거래 비용이며, 차이는 있을 때만 헤지핑이 가능하기 때문에 헤지핑의 차이는 트리거 파워를 가지고 있으며, 차이는 적으면 손실이 된다.

이러한 고려를 바탕으로 전략은 몇 가지 매개 변수를 설계해야 합니다.

  • 헤드프라이즈:hedgeDiffPrice이 값을 초과할 때 헤지핑 동작을 트리거합니다.
  • 가장 작은 헤드오버:minHedgeAmount이 자금의 최소액은
  • 최대 헤지닝:maxHedgeAmount, 한 번에 헤드리지되는 최대 단위 금액 (동전 수) ᅳ
  • A 가격 정확성:pricePrecisionAA 거래소의 주문 가격 정확도 (소수자 수)
  • A 다음 단위 정확도:amountPrecisionAA 거래소의 단위 정확도 (小位数) ᅳ
  • B 가격 정확성:pricePrecisionBB 거래소에서 주문 가격의 정확도 (소수자 수)
  • B 아래 단위 정확도:amountPrecisionBB 거래소의 단위 정확도 (小位数)
  • A 거래소 환율:rateA, 첫 번째 추가된 거래소 객체의 환율 변환, 기본적으로 1이 변환되지 않습니다.
  • B 거래소 환율:rateB, 두 번째 추가된 거래소 객체의 환율 변환, 기본 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()
    }
    

마지막으로, 우리는 균형 함수의 디자인을 완료했습니다. 균형 함수는 약간 더 복잡합니다.

  • 유지합니다
    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)
    

    만약 환율 변수가rateArateB1로 설정되어 있습니다.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이 두 개의 동시 객체가 생성될 때,GetDepth()또한 인터페이스도 즉시 발생했고, 두 개의 심층 데이터 요청이 거래소에 전달되었습니다. 그 다음에는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◎ 이 매개 변수에 기반한 두 개의 다른 표시 또는 숨겨진 매개 변수는 다음과 같습니다: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 거래소 계정 자산 데이터를 표시합니다.

서로 다른 화폐에 대한 거래 쌍 처리

그리고 이 변수에서 우리는 변수 값의 변수를 설계했습니다.main이 함수의 초기 동작의 일부로 우리는 환율 변환을 설계했습니다.SetRate환율 변환 함수는 먼저 실행되어야 합니다. 이 함수는 두 가지 측면에 영향을 미칩니다.

  • 모든 시장 데이터, 주문 데이터, 보관 데이터의 가격 교환.
  • 계좌 자산의 화폐를 교환합니다. 예를 들어, 현재 거래가BTC_USDT그리고 그 가격 단위는USDT이 자금은 은행에 등록되어 있습니다.USDT▲ 만약 제가 CNY로 환산하고 싶다면,exchange.SetRate(6.8)그 다음에는exchange이 거래소 객체 아래의 모든 함수에서 얻은 데이터는 CNY로 교환됩니다. 왜 동전을 지불하는지에 대한SetRate함수 입력현재 화폐와 목표 화폐의 환율

전 전략:다른 통화에 대한 현금 헤지킹 전략 (교육)


관련

더 많은

우크라이나의 검사 신정말 멋지네요