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를 사용하는 방법도 배울 것입니다.模版类库기능.
  • 일방향 헤지 함수 이러한 변화는 특정 헤지 거래에서 두 거래소 간의 가격 차이를 완전히 되돌리는 것이 어렵기 때문에 매우 중요한 의미를 갖습니다. 대부분의 경우 한 거래소의 가격은 다른 거래소의 가격보다 꾸준히 높습니다. 이때, 우리의 자산은 모두 헤지되어 있습니다(즉, 모든 코인은 가격이 낮은 거래소에 있고, 모든 돈은 가격이 높은 거래소에 있습니다). 헤지거래는 중단되었고 더 이상 가격 변동에 의존해 수익을 낼 수 없게 되었습니다. 이때 전략은 코인을 헤지하기 위해 약간의 돈을 잃을 수 있는 방식이어야 합니다(코인이 높은 가격으로 거래소에 다시 존재하도록 함). 그런 다음 가격이 상승하면 헤지를 계속하고 수익을 낼 수 있습니다. 차이가 다시 커진다.
  • 헤지 스프레드 라인과 같은 매개변수를 대화형으로 수정합니다. 전략에 대화형 기능을 추가하면 스프레드 트리거 라인을 실시간으로 수정할 수 있습니다.
  • 상태표시줄 정보를 정리하여 표 형태로 표시 쉽게 관찰할 수 있도록 표시할 데이터를 구성합니다.

다음으로, 이러한 디자인을 하나씩 구현해 보겠습니다.

스팟거래 객체의 레버리지 모드를 전환합니다.

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

여기의 전략은 바이낸스 현물의 코인 대 코인 레버리지 모드를 전환하기 위한 코드만 추가하므로, 전략 매개변수에 설정된 스위치는 바이낸스 현물에만 유효합니다.

스프레드 차트 표시 추가

패키지된 도면 템플릿을 사용하는 것은 매우 간단합니다. 우리가 사용하는 템플릿의 이름은 다음과 같습니다.画线类库. FMZ 플랫폼 전략 광장에서 직접 검색하여 얻을 수 있습니다.

디지털화폐 스팟헤징 전략설계(2)

혹은 https://www.fmz.com/strategy/27293 링크를 직접 클릭하여 이 템플릿의 복사 페이지로 이동하세요.

디지털화폐 스팟헤징 전략설계(2)

버튼을 클릭하면 이 템플릿 라이브러리를 귀하의 전략 라이브러리로 복사할 수 있습니다.

디지털화폐 스팟헤징 전략설계(2)

그런 다음 정책 편집 페이지에서 템플릿 열에 필요한 템플릿 라이브러리를 확인할 수 있습니다. 확인란을 선택하고 정책을 저장하면 이 정책은 이 템플릿을 참조합니다. 여기서는 템플릿 라이브러리의 사용법을 간략하게 설명합니다. 이 전략은 이미 이 템플릿을 참조했으므로 작업을 반복할 필요가 없습니다. 이 전략을 Strategy Square에 복사한 후에는 전략 편집 페이지의 템플릿 열에서 해당 전략을 볼 수 있습니다.画线类库이미 인용됨.

우리는 주로 사용하는 방법을 배웁니다画线类库그래프를 그리는 함수.

디지털화폐 스팟헤징 전략설계(2)

우리는 계획하고 있습니다A->B가격차이는,B->A가격차이와 가격차이 트리거라인이 그려집니다. 위 그림과 같이 두 개의 곡선(A에서 B로의 현재 가격 차이, B에서 A로의 현재 가격 차이)과 두 개의 수평선(트리거 가격 차이 선)을 그려야 합니다.

우리는 일방적인 헤지를 설계해야 하기 때문에,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。 여기서 코드를 수정해야 합니다. 먼저 매개변수를 수정해야 합니다.

디지털화폐 스팟헤징 전략설계(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줄의 그리기 코드만으로 전략이 실행될 때 차트를 표시할 수 있습니다.

일방향 헤지 함수

위에서 언급했듯이, 가격 차이 트리거 라인이 두 개로 변형되어 제어됩니다.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 
            }            
        }

매수가격과 매도가격이 두 개의 데이터로 분리되어 있으므로 헤지기능은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)

두 개의 컨트롤이 추가되었습니다. 하나는 A2B이고 다른 하나는 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