디지털 화폐 선물 클래스 마틴 전략 설계

저자:작은 꿈, 2021-07-02 14:35:34, 업데이트: 2023-09-21 21:09:56

img

디지털 화폐 선물 클래스 마틴 전략 설계

최근 FMZ 공식 그룹에서 마틴 유형의 전략이 비교적 많이 논의되고 있으며 플랫폼에서 디지털 통화 계약에 대한 마틴 전략은 거의 없습니다. 그래서, 이 기회를 사용하여 간단한 디지털 통화 선물 마틴 전략을 설계했습니다. 마틴 유형의 전략이라고 말하는 이유는 잠재적인 위험이 실제로 적지 않기 때문에 마틴 전략이 완전히 마틴 전략에 따라 설계되지 않았기 때문입니다. 그러나 이러한 전략은 여전히 적지 않은 위험을 가지고 있으며 마틴 유형의 전략의 매개 변수 설정과 위험 지수가 관련되어 있으며 위험을 무시할 수 없습니다.

이 글은 주로 마틴형 전략의 디자인에서 학습을 설명하는데, 전략적 아이디어는 이미 분명하고, FMZ 사용자로서 우리는 전략적 디자인에 더 많은 관심을 가지고 있다.

공동의 권익에 대한 접근

디지털 화폐 선물 전략을 설계할 때, 이 자료는 종종 사용된다. 왜냐하면 수익을 계산하기 위해서, 특히 부동 수익을 계산하기 위해서. 왜냐하면 보유가 담보금을 차지하기 때문에, 기고도 차지한다. 이 때 FMZ 플랫폼의 API 인터페이스를 호출한다.exchange.GetAccount()사용가능한 자산과 종목된 자산의 동결이 취득된다. 실제로 대부분의 디지털 통화 선물 거래소는 FMZ에 통일 된 패키지가 없지만 전체 이익 데이터를 제공합니다.

그래서 우리는 다른 거래소에 따라 다른 기능을 설계하여 이 데이터를 얻었습니다.

// OKEX V5 获取总权益
function getTotalEquity_OKEX_V5() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
            totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

// 币安期货
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

코드에서totalEquity그리고 우리가 필요로 하는 전체 권익입니다. 그리고 우리는 다시 함수를 입력으로 호출해서 거래소의 이름에 따라 해당 함수를 호출합니다.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "不支持该交易所"
    }
}

몇 가지 보조 기능을 설계합니다.

기본 함수, 기본 논리를 설계하기 전에. 우리는 보조 함수를 설계하기 위해 준비해야 합니다.

  • 현재 모든 게시물을 삭제합니다

    function cancelAll() {
        while (1) {
            var orders = _C(exchange.GetOrders)
            if (orders.length == 0) {
                break
            }
            for (var i = 0 ; i < orders.length ; i++) {
                exchange.CancelOrder(orders[i].Id, orders[i])
                Sleep(500)
            }
            Sleep(500)
        }
    }
    

    이 함수는 FMZ 전략 광장에서 종종 전략 예제 코드를 보는 사람들에게 익숙하다고 생각합니다. 많은 전략이 비슷한 디자인을 사용했습니다.

  • 선물의 하위 주문 동작

    function trade(distance, price, amount) {
        var tradeFunc = null 
        if (distance == "buy") {
            tradeFunc = exchange.Buy
        } else if (distance == "sell") {
            tradeFunc = exchange.Sell
        } else if (distance == "closebuy") {
            tradeFunc = exchange.Sell
        } else {
            tradeFunc = exchange.Buy
        }
        exchange.SetDirection(distance)
        return tradeFunc(price, amount)
    }
    
    function openLong(price, amount) {
        return trade("buy", price, amount)
    }
    
    function openShort(price, amount) {
        return trade("sell", price, amount)
    }
    
    function coverLong(price, amount) {
        return trade("closebuy", price, amount)
    }
    
    function coverShort(price, amount) {
        return trade("closesell", price, amount)
    }
    

    선물 거래는 네 가지 방향이 있습니다: 오픈롱, 오픈쇼트, 커버롱, 커버쇼트. 그래서 우리는 네 가지 주문 기능을 설계했습니다. 만약 주문만 고려한다면 다음과 같은 몇 가지 요소가 필요합니다. 방향, 주문 가격, 주문량. 그래서 우리는 이 프로젝트의 제목을 디자인했습니다.trade이 함수들은方向(distance)下单价格(price)下单量(amount)이 모든 것은 명확한 시기의 동작입니다. 이 함수들의 호출은 결국 openLong, openShort, coverLong, coverShort 등의 함수들로 이루어진다.trade함수는 실제 기능을 수행합니다. 즉, 정해진 방향, 가격, 양에 따라 선물 거래소에 주문합니다.

주 함수

전략적 아이디어는 간단하다. 현재 가격에 기반선 아래의 일정 거리에 판매를 붙여 놓거나 구매를 붙여 놓는다. 거래가 완료되면 남은 모든 주문을 취소하고, 보유 가격에 따라 일정 거리에 새로운 평형 주문을 붙여 놓으며, 업데이트 후의 현재 가격에 부가 주문을 붙여 놓지만, 추가된 주문을 두 배로 할 수 없다.

  • 초기 직업 주문 ID를 기록하기 위해 두 개의 글로벌 변수가 필요합니다.

    var buyOrderId = null
    var sellOrderId = null
    

    다음에는 OKEX_V5 모형 디스크를 사용하는 옵션이 정책 인터페이스 파라미터에 설계되어 있습니다. 그래서 코드에서 몇 가지 작업을 수행합니다:

    var exName = exchange.GetName()    
    // 切换OKEX V5模拟盘
    if (isSimulate && exName == "Futures_OKCoin") {
        exchange.IO("simulate", true)
    }
    

    또한 인터페이스 파라미터에는 모든 정보를 다시 설정할 수 있는 옵션이 설계되어 있기 때문에 코드에는 그에 따른 처리도 있습니다:

    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("重置所有数据", "#FF0000")
    }
    

    우리는 영원한 계약으로만 달렸기 때문에 여기서 죽은 것으로 기록되어 있습니다. 영원한 계약으로만 설정되어 있습니다.

    exchange.SetContractType("swap")
    

    그리고 우리는 주문 가격 정확성, 주문량 정확성 문제도 고려해야 합니다. 만약 정밀성이 제대로 설정되지 않으면, 전략 계산 과정에서 정밀성이 손실되고, 데이터의 소수 단위가 많으면 주문을 할 때 거래소 인터페이스에 의해 거부될 수 있습니다.

    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("设置精度", pricePrecision, amountPrecision)
    

    디자인적으로 간단한 데이터 복구 기능

    if (totalEq == -1 && !IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = getTotalEquity()
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "获取初始权益失败"
            }
        } else {
            totalEq = recoverTotalEq
        }
    }
    

    만약 당신이 정책 실행 시 초기 계정 총 권익을 지정하고 싶다면, 당신은 그 매개 변수를 설정할 수 있습니다totalEq이 매개 변수를 -1로 설정하면, 전략은 저장된 총권익 데이터를 읽게 된다. 저장되지 않은 총권익 데이터는, 현재 읽힌 총권익을 전략 실행 진행의 초기 총권익으로, 그 후 총권익이 증가하면 0이고, 총권익이 감소하면 손실이다.

  • 주요 논리 초기 작업이 완료된 후, 마침내 전략의 주요 논리 부분에 도달했습니다. 설명하기 위해, 나는 코드 설명서에 직접 설명서를 작성했습니다.

      while (1) {                                  // 策略主要逻辑设计为一个死循环
          var ticker = _C(exchange.GetTicker)      // 首先读取当前行情信息,主要用到最新成交价
          var pos = _C(exchange.GetPosition)       // 读取当前持仓数据
          if (pos.length > 1) {                    // 判断持仓数据,由于这个策略的逻辑,是不太可能同时出现多空持仓的,所以发现同时出现多空持仓就抛出错误
              Log(pos)
              throw "同时有多空持仓"                  // 抛出错误,让策略停止
          }
          // 根据状态而定
          if (pos.length == 0) {                    // 根据持仓状态做出不同操作,pos.length == 0是当没有持仓时
              // 未持仓了,统计一次收益
              if (!IsVirtual()) {
                  var currTotalEq = getTotalEquity()
                  if (currTotalEq) {
                      LogProfit(currTotalEq - totalEq, "当前总权益:", currTotalEq)
                  }
              }
    
              buyOrderId = openLong(ticker.Last - targetProfit, amount)       // 挂开多仓的买单
              sellOrderId = openShort(ticker.Last + targetProfit, amount)     // 挂开空仓的卖单
          } else if (pos[0].Type == PD_LONG) {   // 有多头持仓,挂单位置、数量有所不同
              var n = 1
              var price = ticker.Last
              buyOrderId = openLong(price - targetProfit * n, amount)
              sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
          } else if (pos[0].Type == PD_SHORT) {   // 有空头持仓,挂单位置、数量有所不同
              var n = 1
              var price = ticker.Last
              buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
              sellOrderId = openShort(price + targetProfit * n, amount)
          }
    
          if (!sellOrderId || !buyOrderId) {   // 如果有一边挂单失败就取消所有挂单,重来
              cancelAll()
              buyOrderId = null 
              sellOrderId = null
              continue
          } 
    
          while (1) {  // 挂单完成,开始监控订单
              var isFindBuyId = false 
              var isFindSellId = false
              var orders = _C(exchange.GetOrders)
              for (var i = 0 ; i < orders.length ; i++) {
                  if (buyOrderId == orders[i].Id) {
                      isFindBuyId = true 
                  }
                  if (sellOrderId == orders[i].Id) {
                      isFindSellId = true 
                  }               
              }
              if (!isFindSellId && !isFindBuyId) {    // 检测到买卖单都成交了
                  cancelAll()
                  break
              } else if (!isFindBuyId) {   // 检测到买单成交
                  Log("买单成交")
                  cancelAll()
                  break
              } else if (!isFindSellId) {  // 检测到卖单成交
                  Log("卖单成交")
                  cancelAll()
                  break
              }
              LogStatus(_D())
              Sleep(3000)
          }
          Sleep(500)
      }
    

이 모든 논리와 디자인은 설명되어 있습니다.

재검토

이 모든 것이 5월 19일 행사를 경험하는 전략이다.

img

img

이 모든 것은 마틴과 같은 전략이 여전히 위험을 안고 있다는 것을 보여줍니다.

리얼 디스크는 OKEX V5 모의 레이싱을 즐길 수 있습니다.

img

그라운드:https://www.fmz.com/strategy/294957

이 전략은 주로 학습을 위해 사용되며, 금과 은은 조심스럽게 사용해야 합니다 ~!


관련

더 많은

리사20231이 문장은 한 가지 질문입니다. if (!isFindSellId &&!isFindBuyId) { // 매각된 주문을 확인합니다 만약 당신이 주문을 탐지할 때, 당신이 구매와 판매를 동시에 빠르게 처리한다면, 당신은 오류를 던질 수 있습니까?

네오1898또 다른 문제는 계약 모델이 전체 또는 단위로 어떻게 설정되는지입니다.

네오1898계약은 두 배로 정해져 있지 않은가? 두 배로 정해져 있지 않은가? 두 배로 정해져 있지 않은가?

가벼운 구름이 모든 것을 이해하게 된 건 정말 감사해요. 그리고는 수록문제 모니터링을 배웠습니다. 그리고는 양면 마틴을 썼습니다. 2일 동안 580줄을 썼습니다. [박수]

hk량/upload/asset/1a9ebf427c4e2cbf1c327.png 거짓 진실 교환?

꿈은 8자리입니다.만약

꿈은 8자리입니다.소유자 권익 합계

null그 피해를 막아야 할까요?

btcrobot마틴, 다시 계산해, 0으로

wqy이 식의 n은 항상 1과 같습니다.

이브달레이이 전략은 더 많은 공백을 두 번 열었나요? 아니면 한 번 열었나요?

작은 꿈오류를 던지지 않습니다. 여전히 모든 연결을 취소하고, 현재 순환을 건너뛰고, 연결 논리를 계속합니다. 거래가 즉시 완료되면 가격 차이 수익을 먹는 것과 같습니다.

작은 꿈일반적으로는 전체 저장소를 사용해야 합니다.

작은 꿈리버지는 자신의 위험 선호도에 따라 거래소에서 설정할 수 있습니다.

작은 꿈전체 666개!

작은 꿈이변이 isFindBuyId라고 불린다면, 그것은 적절하지 않습니다. 이변은 isNotFindBuyId라고 해야 합니다.

작은 꿈이 전략은 손해를 막기 위해 설계되지 않았습니다. 그래서, 이 곡선은 올라가는 방향으로 보입니다.

작은 꿈마틴의 귀환. 이 문서는 주로 교육 전략 설계에 관한 것입니다. 너무 많은 관심을 기울이지 않습니다.

작은 꿈그 N는 나중에 변경을 위해 사용되는데, 예를 들어 n 배의 거리를 더하는 것을 생각해보면, 일시적으로 1로 정할 수 있다.

작은 꿈이 글은 다른 글과 비교해서