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

동전 고리량 거래는 새로운 것 같네요 -- 동전 고리량화로 당신을 더 가깝게 만듭니다.

저자:발명가들의 수량화 - 작은 꿈, 2021-06-04 10:08:48, 2021-12-04 21:14:15에 업데이트되었습니다.

img

동전구량화 거래 새게 보여서 가 당신을 동전구량화 가까이 데려간다 ((6))

지난 기사에서 우리는 함께 간단한 격자 전략을 만들었고, 이 기사에서는 이 전략을 업그레이드하고 확장하여 다양한 직급 격자 전략으로 확장하여 실제 테스트를 실시했습니다. 목표는 "성경"을 찾는 것이 아니라 전략 설계에서 설계 전략에 대한 다양한 문제를 탐구하고 생각하며 해결하는 것입니다. 이 기사에서는 이 전략을 설계하는 동안 내가 경험 한 몇 가지 내용을 설명합니다. 이 내용은 약간 복잡하며 프로그래밍에 대한 기초가 필요합니다.

전략적 필요에 기반한 디자인 사고

이 글은 이전 글과 마찬가지로 여전히 발명자에 기초한 수치입니다.FMZ.COM이 글은 이 글의 제목입니다.

  • 다양한 종류 그리고 저는 이 네트워크 전략이 단지BTC_USDT그리고 할 수 있습니다.LTC_USDT/EOS_USDT/DOGE_USDT/ETC_USDT/ETH_USDT◎ 현금 거래 쌍, 달리기를 원하는 품종은 동시에 격자 거래를 한다.

    ~~ 여러 가지 종류의 충격적인 상황을 포착하는 것은 좋은 느낌입니다. 이 프로젝트의 목표는 개발자들에 대한 관심을 높이는 것입니다.

    • 1, 먼저 여러 종류의 시장을 확보하십시오. 이것은 해결해야 할 첫 번째 문제입니다. 거래소의 API 문서를 확인한 후 일반적인 거래소가 종합 시장을 제공하는 인터페이스를 발견했습니다. OK, 시장 인터페이스를 사용하여 데이터를 얻습니다.

    • 2, 두 번째 문제는 계정 자산이다. 여러 가지 전략이 있기 때문에 각 거래의 자산별 관리를 고려해야 한다. 그리고 모든 자산의 데이터를 한 번에 얻고 기록해야 한다. 왜 계정 자산 데이터를 얻어야 하는가? 또한 각 거래의 기록을 분리해야 하는가? 왜냐하면 당신은 주문할 때 사용할 수 있는 자산을 판단해야 하기 때문에, 아니면 그것을 다시 판단해야 하기 때문입니다. 또한 수익을 계산해야 합니다. 아니면 초기 계정 자산 데이터를 기록하고, 현재 계정 자산 데이터를 얻고, 초기 대비로 수익과 손실을 계산해야 합니까? 좋은 점은 거래소의 자산 계정 인터페이스가 일반적으로 모든 통화 자산 데이터를 반환하는 것입니다. 우리는 한 번만 검색하고 데이터를 처리 할 수 있습니다.

    • 3, 전략 매개 변수 설계. 다종류의 매개 변수 설계와 단종류의 매개 변수 설계는 큰 차이가 있다. 다종류의 매개 변수 거래 논리는 동일하지만 거래 시 매개 변수는 다를 수 있다. 예를 들어, 격자 전략, BTC_USDT 거래를 할 때 0.01 BTC를 매 거래에 기대할 수 있다. 그러나 DOGE_USDT를 할 때 이 매개 변수 (거래 0.01 동전) 이라면 분명히 적합하지 않다. 물론 당신은 또한 USDT 금액으로 처리할 수 있다. 아마 동료들도 이 문제에 대해 생각해보고 이렇게 말할지도 모릅니다. "나는 몇 개의 더 많은 매개 변수를 설정할 수 있고, 다른 거래 쌍의 매개 변수를 분리해서 제어할 수 있다". 하지만 여전히 수요를 충족시킬 수 있는 유연성이 없나요? 몇 개의 매개 변수를 설정하는 것이 좋습니다. 세 개의 매개 변수를 설정합니다. 만약 제가 네 가지 종류를 만들면 어떨까요? 따라서 다종양 전략의 파라그램을 설계할 때 이러한 차별화 파라그램의 필요성을 충분히 고려해야 합니다. 하나의 해결책은 파라그램을 일반 문자열 또는 JSON 문자열로 설계하는 것입니다. 예를 들어:

      ETHUSDT:100:0.002|LTCUSDT:20:0.1
      

      이 부분의 분포는 각 품종의 데이터입니다.ETHUSDT:100:0.002이 자금은 ETH_USDT 거래 쌍을 제어하는 자금입니다.LTCUSDT:20:0.1LTC_USDT 거래 쌍을 제어한다. 중간에 있는 "goose"는 분할 역할을 한다.ETHUSDT:100:0.002여기서 ETHUSDT는 당신이 할 거래가 무엇인지, 100은 격자 간격, 0.002는 각 격자 거래에 대한 ETH 동전의 수, 오: 별명은 이 데이터를 분할하는 것입니다. (물론, 이러한 매개 변수 규칙은 전략 설계자가 만든 것입니다. 당신은 당신의 필요에 따라 디자인하는 것을 할 수 있습니다.) 이 문자열들은 당신이 해야 할 모든 종류의 매개 변수 정보를 포함하고 있으며, 이 문자열들을 정책에서 분석하고, 정책에 특정 변수를 부여하고, 각 종류의 거래 논리를 제어하기 위해 사용된다.

      function main() {
          var net = []  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据
          var params = "ETHUSDT:100:0.002|LTCUSDT:20:0.1"
          var arrPair = params.split("|")
          _.each(arrPair, function(pair) {
              var arr = pair.split(":")
              var symbol = arr[0]              // 交易对名称
              var diff = parseFloat(arr[1])    // 网格间距
              var amount = parseFloat(arr[2])  // 网格下单量
              net.push({symbol : symbol, diff : diff, amount : amount})
          })
          Log("网格参数数据:", net)
      }
      

      img

      JSON 문자열을 직접 사용할 수도 있습니다. 더 간단합니다.

      function main() {        
          var params = '[{"symbol":"ETHUSDT","diff":100,"amount":0.002},{"symbol":"LTCUSDT","diff":20,"amount":0.1}]'
          var net = JSON.parse(params)  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据        
          _.each(net, function(pair) {
              Log("交易对:", pair.symbol, pair)
          })
      }
      

      img

    • 4. 데이터 영구화 실전에서 사용할 수 있는 전략과 교육 전략의 차이는 크다. 이전 교육 전략은 단지 초기 테스트 전략의 논리, 디자인, 실전에서 고려해야 할 문제는 더 많습니다. 실전에서, 실전에서, 실전에서 열거나 중지할 수 있습니다. 이 경우, 실전에서 실행되는 모든 데이터가 손실됩니다. 그렇다면 실전에서 종료된 후, 재부팅이 이전 상태로 계속 될 수 있도록하는 방법은 무엇입니까? 이 경우, 리얼 디스크가 실행되는 동안 중요한 데이터를 영구적으로 저장하여 재부팅할 때 데이터를 읽고 계속 실행할 필요가 있습니다. 개발자의 양적 거래 플랫폼에서 사용할 수 있습니다._G()함수, 또는 데이터베이스 동작 함수DBExec()FMZ API 문서를 참조하십시오.

      예를 들어, 우리는 머리 함수를 설계했습니다._G()그레이드 데이터를 저장하는 함수.

      var net = null 
      function main() {  // 策略主函数
          // 首先读取储存的net
          net = _G("net")
          
          // ...
      }
      
      function onExit() {
          _G("net", net)
          Log("执行扫尾处理,保存数据", "#FF0000")
      }
      
      function onexit() {    // 平台系统定义的退出扫尾函数,在点击实盘停止时触发执行
          onExit()
      }
      
      function onerror() {   // 平台系统定义的异常退出函数,在程序发生异常时触发执行
          onExit()
      }
      
    • 5., 주문량 정확성, 주문 가격 정확성, 최소 주문량, 최소 주문 금액 등의 제한

      리테스트 시스템에서는 다음 단위량, 다음 단위 정확성 등에 대한 엄격한 제한이 없습니다. 그러나 실제 시간에는 각 거래소에서 신고 시 가격, 다음 단위량에 대한 엄격한 기준이있을 수 있으며 각 거래 쌍의 이러한 제한은 동일하지 않습니다. 그래서 종종 새로운 리테스트 시스템 테스트 OK이 있습니다.

      다종사적인 경우, 이 요구는 더 복잡하다. 단종 정책에서는 정확성 등을 지정하는 정보를 위한 매개 변수를 설계할 수 있지만, 다종사적인 정책을 설계할 때, 분명히 이 정보가 매개 변수에 기록되어 있어 매개 변수가 매우 희미하게 보일 것이다.

      이 때 거래소 API 문서를 살펴보고 거래소 문서를 통해 관련 정보에 대한 거래 인터페이스가 있는지 살펴볼 필요가 있습니다. 이러한 인터페이스가 있다면, 정책에서 자동 액세스 인터페이스 취득 정확도와 같은 정보를 설계하여 거래에 참여하는 거래 쌍 정보에 구성 할 수 있습니다.

    • 6. 다른 거래소에 적응 왜 이 질문을 마지막에 두는 걸까요? 위와 같은 문제 해결방법들이 마지막 문제를 야기하기 때문에, 우리의 전략적 계획은 종합 시장 인터페이스를 사용하며, 거래의 정확성에 대한 데이터의 적응을 위해 거래소를 방문하고, 각 거래 쌍을 개별적으로 처리하는 계정 정보에 액세스하는 등이 거래소에 따라 큰 차이를 가져올 수 있기 때문입니다. 인터페이스 호출에 차이가 있고, 메커니즘에 차이가 있다. 현장 거래소에 있어서는 이 격자 전략이 선물 버전으로 확장될 경우 차이는 조금 더 작다. 각 거래소 메커니즘에 대한 차이는 더 크다. 한 가지 해결 방법은 FMZ 템플릿 클래스 라이브러리를 설계하는 것이다. 이러한 차별화를 구현하는 것은 클래스 라이브러리에 기재된 디자인이다. 자체 전략과 거래소의 접합을 축소하는 것이다. 이렇게 하는 단점은 템플릿 클래스 라이브러리를 작성해야 한다는 것이고, 이 템플릿은 각 거래소에 대한 차이를 구체적으로 구현해야 한다는 것이다.

템플릿 클래스 라이브러리를 디자인합니다.

위의 분석을 바탕으로, 전략과 거래소 메커니즘, 인터페이스 사이의 접합을 줄이기 위해 템플릿 클래스 라이브러리를 설계합니다.

이 템플릿 클래스 라이브러리를 다음과 같이 디자인할 수 있습니다.

function createBaseEx(e, funcConfigure) {
    var self = {}
    self.e = e 
    
    self.funcConfigure = funcConfigure
    self.name = e.GetName()
    self.type = self.name.includes("Futures_") ? "Futures" : "Spot"
    self.label = e.GetLabel()
    
    // 需要实现的接口
    self.interfaceGetTickers = null   // 创建异步获取聚合行情数据线程的函数
    self.interfaceGetAcc = null       // 创建异步获取账户数据线程的函数
    self.interfaceGetPos = null       // 获取持仓
    self.interfaceTrade = null        // 创建并发下单
    self.waitTickers = null           // 等待并发行情数据 
    self.waitAcc = null               // 等待账户并发数据
    self.waitTrade = null             // 等待下单并发数据
    self.calcAmount = null            // 根据交易对精度等数据计算下单量
    self.init = null                  // 初始化工作,获取精度等数据
    
    // 执行配置函数,给对象配置
    funcConfigure(self)

    // 检测configList约定的接口是否都实现
    _.each(configList, function(funcName) {
        if (!self[funcName]) {
            throw "接口" + funcName + "未实现"
        }
    })
    
    return self
}

$.createBaseEx = createBaseEx
$.getConfigureFunc = function(exName) {
    dicRegister = {
        "Futures_OKCoin" : funcConfigure_Futures_OKCoin,    // OK期货的实现
        "Huobi" : funcConfigure_Huobi,
        "Futures_Binance" : funcConfigure_Futures_Binance,
        "Binance" : funcConfigure_Binance,
        "WexApp" : funcConfigure_WexApp,                    // wexApp的实现
    }
    return dicRegister
}

템플릿에서 특정 거래소에 대한 작성 구현, 예를 들어 FMZ의 WexApp 모형으로:

function funcConfigure_WexApp(self) {
    var formatSymbol = function(originalSymbol) {
        // BTC_USDT
        var arr = originalSymbol.split("_")
        var baseCurrency = arr[0]
        var quoteCurrency = arr[1]
        return [originalSymbol, baseCurrency, quoteCurrency]
    }

    self.interfaceGetTickers = function interfaceGetTickers() {
        self.routineGetTicker = HttpQuery_Go("https://api.wex.app/api/v1/public/tickers")
    }

    self.waitTickers = function waitTickers() {
        var ret = []
        var arr = JSON.parse(self.routineGetTicker.wait()).data
        _.each(arr, function(ele) {
            ret.push({
                bid1: parseFloat(ele.buy), 
                bid1Vol: parseFloat(-1),
                ask1: parseFloat(ele.sell), 
                ask1Vol: parseFloat(-1),
                symbol: formatSymbol(ele.market)[0],
                type: "Spot", 
                originalSymbol: ele.market
            })
        })
        return ret 
    }

    self.interfaceGetAcc = function interfaceGetAcc(symbol, updateTS) {
        if (self.updateAccsTS != updateTS) {
            self.routineGetAcc = self.e.Go("GetAccount")
        }
    }

    self.waitAcc = function waitAcc(symbol, updateTS) {
        var arr = formatSymbol(symbol)
        var ret = null 
        if (self.updateAccsTS != updateTS) {
            ret = self.routineGetAcc.wait().Info
            self.bufferGetAccRet = ret 
        } else {
            ret = self.bufferGetAccRet
        }
        if (!ret) {
            return null 
        }        
        var acc = {symbol: symbol, Stocks: 0, FrozenStocks: 0, Balance: 0, FrozenBalance: 0, originalInfo: ret}
        _.each(ret.exchange, function(ele) {
            if (ele.currency == arr[1]) {
                // baseCurrency
                acc.Stocks = parseFloat(ele.free)
                acc.FrozenStocks = parseFloat(ele.frozen)
            } else if (ele.currency == arr[2]) {
                // quoteCurrency
                acc.Balance = parseFloat(ele.free)
                acc.FrozenBalance = parseFloat(ele.frozen)
            }
        })
        return acc
    }

    self.interfaceGetPos = function interfaceGetPos(symbol, price, initSpAcc, nowSpAcc) {
        var symbolInfo = self.getSymbolInfo(symbol)
        var sumInitStocks = initSpAcc.Stocks + initSpAcc.FrozenStocks
        var sumNowStocks = nowSpAcc.Stocks + nowSpAcc.FrozenStocks
        var diffStocks = _N(sumNowStocks - sumInitStocks, symbolInfo.amountPrecision)
        if (Math.abs(diffStocks) < symbolInfo.min / price) {
            return []
        }
        return [{symbol: symbol, amount: diffStocks, price: null, originalInfo: {}}]
    }

    self.interfaceTrade = function interfaceTrade(symbol, type, price, amount) {
        var tradeType = ""
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeType = "bid"
        } else {
            tradeType = "ask"
        }
        var params = {
            "market": symbol,
            "side": tradeType,
            "amount": String(amount),
            "price" : String(-1),
            "type" : "market"
        }
        self.routineTrade = self.e.Go("IO", "api", "POST", "/api/v1/private/order", self.encodeParams(params))
    }

    self.waitTrade = function waitTrade() {
        return self.routineTrade.wait()
    }

    self.calcAmount = function calcAmount(symbol, type, price, amount) {
        // 获取交易对信息
        var symbolInfo = self.getSymbolInfo(symbol)
        if (!symbol) {
            throw symbol + ",交易对信息查询不到"
        }
        var tradeAmount = null 
        var equalAmount = null  // 记录币数
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeAmount = _N(amount * price, parseFloat(symbolInfo.pricePrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min)
                return false 
            }
            equalAmount = tradeAmount / price
        } else {
            tradeAmount = _N(amount, parseFloat(symbolInfo.amountPrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min / price) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min / price)
                return false 
            }
            equalAmount = tradeAmount
        }
        return [tradeAmount, equalAmount]
    }

    self.init = function init() {   // 自动处理精度等条件的函数
        var ret = JSON.parse(HttpQuery("https://api.wex.app/api/v1/public/markets"))
        _.each(ret.data, function(symbolInfo) {
            self.symbolsInfo.push({
                symbol: symbolInfo.pair,
                amountPrecision: parseFloat(symbolInfo.basePrecision),
                pricePrecision: parseFloat(symbolInfo.quotePrecision),
                multiplier: 1,
                min: parseFloat(symbolInfo.minQty),
                originalInfo: symbolInfo
            })
        })        
    }
}

그리고 이 템플릿을 전략으로 사용하는 것은 간단합니다.

function main() {
    var fuExName = exchange.GetName()
    var fuConfigureFunc = $.getConfigureFunc()[fuExName]
    var ex = $.createBaseEx(exchange, fuConfigureFunc)

    var arrTestSymbol = ["LTC_USDT", "ETH_USDT", "EOS_USDT"]
    var ts = new Date().getTime()
    
    // 测试获取行情
    ex.goGetTickers()
    var tickers = ex.getTickers()
    Log("tickers:", tickers)
    
    // 测试获取账户信息
    ex.goGetAcc(symbol, ts)
    
    _.each(arrTestSymbol, function(symbol) {        
        _.each(tickers, function(ticker) {
            if (symbol == ticker.originalSymbol) {
                // 打印行情数据
                Log(symbol, ticker)
            }
        })

        // 打印资产数据
        var acc = ex.getAcc(symbol, ts)
        Log("acc:", acc.symbol, acc)
    })
}

실제 전략

위의 템플릿을 기반으로 설계 작성 전략은 매우 간단하며 전체 전략은 약 300+ 줄로 디지털 통화 현금의 다품질 격자 전략을 구현합니다.

img

img

현재 수익을 내고 있습니다.T_T이 글은 한글로 번역되어 있습니다.

이 사이트는 WexApp를 이용하는 유저들의 관심사를 담고 있습니다.

购买地址: https://www.fmz.com/m/s/284507
注册码: 
adc7a2e0a2cfde542e3ace405d216731
f5db29d05f57266165ce92dc18fd0a30
1735dca92794943ddaf277828ee04c27
0281ea107935015491cda2b372a0997d
1d0d8ef1ea0ea1415eeee40404ed09cc

200U 이상, 그냥 뛰고, 큰 단면 행렬을 만납니다, 천천히 출혈. 현금 네트워크의 가장 큰 장점은: 이 잠들 수 있습니다! 5월 27일부터 현재까지 안정성이 흔들리지 않고 있으며, 선물망은 당분간 시도하지 않을 것입니다.


관련

더 많은

소모학 양성램프, 쿼티, 램프, 램프, 램프,

9개의 태양 위원장님!

궤도 생물감사합니다.

발명가들의 수량화 - 작은 꿈감사합니다!

발명가들의 수량화 - 작은 꿈감사합니다!