Type/to search
8
Follow
1364
Followers
Estrategia manual de cobertura de futuros y spot para monedas digitales
Discussions
Created 2021-09-08 14:47:33  Updated 2023-09-20 10:28:44
 3
 2916

img

Estrategia manual de cobertura de futuros y spot para monedas digitales

Dado que la frecuencia de cobertura de la estrategia de cobertura de futuros al contado no es particularmente alta, en realidad se puede operar manualmente. Sin embargo, resulta incómodo cambiar de una página de intercambio a otra, observar los precios y calcular las diferencias de precio manualmente. Además, a veces es posible que desees ver más variedades, por lo que no es necesario tener varios monitores para visualizar las condiciones del mercado. De esta manera, ¿se puede utilizar una estrategia semiautomática para satisfacer el requisito de operación manual? Es mejor tener variedad de variedades, ¡oh! Sí, sería mejor si pudieras abrir y cerrar posiciones con un solo clic. ¡Vaya! Sí, también debe haber una visualización de la posición...

Si tienes una necesidad, ¡actúa inmediatamente!

Diseñar una estrategia manual de cobertura de futuros y spot de moneda digital

Es un poco prolijo, con menos de 600 líneas de código.

function createManager(fuEx, spEx, symbolPairs, cmdHedgeAmount, fuMarginLevel, fuMarginReservedRatio) { var self = {} self.fuEx = fuEx self.spEx = spEx self.symbolPairs = symbolPairs self.pairs = [] self.fuExTickers = null self.spExTickers = null self.tickerUpdateTS = 0 self.fuMarginLevel = fuMarginLevel self.fuMarginReservedRatio = fuMarginReservedRatio self.cmdHedgeAmount = cmdHedgeAmount self.preUpdateAccTS = 0 self.accAndPosUpdateCount = 0 self.profit = [] self.allPairs = [] self.PLUS = 0 self.MINUS = 1 self.COVER_PLUS = 2 self.COVER_MINUS = 3 self.arrTradeTypeDesc = ["正套", "反套", "平正套", "平反套"] self.updateTickers = function() { self.fuEx.goGetTickers() self.spEx.goGetTickers() var fuExTickers = self.fuEx.getTickers() var spExTickers = self.spEx.getTickers() if (!fuExTickers || !spExTickers) { return null } self.fuExTickers = fuExTickers self.spExTickers = spExTickers self.tickerUpdateTS = new Date().getTime() return true } self.hedge = function(index, fuSymbol, spSymbol, tradeType, amount) { var fe = self.fuEx var se = self.spEx var pair = self.pairs[index] var timeStamp = new Date().getTime() var fuDirection = null var spDirection = null var fuPrice = null var spPrice = null if (tradeType == self.PLUS) { fuDirection = fe.OPEN_SHORT spDirection = se.OPEN_LONG fuPrice = pair.fuTicker.bid1 spPrice = pair.spTicker.ask1 } else if (tradeType == self.MINUS) { fuDirection = fe.OPEN_LONG spDirection = se.OPEN_SHORT fuPrice = pair.fuTicker.ask1 spPrice = pair.spTicker.bid1 } else if (tradeType == self.COVER_PLUS) { fuDirection = fe.COVER_SHORT spDirection = se.COVER_LONG fuPrice = pair.fuTicker.ask1 spPrice = pair.spTicker.bid1 } else if (tradeType == self.COVER_MINUS) { fuDirection = fe.COVER_LONG spDirection = se.COVER_SHORT fuPrice = pair.fuTicker.bid1 spPrice = pair.spTicker.ask1 } else { throw "unknow tradeType!" } fe.goGetAcc(fuSymbol, timeStamp) se.goGetAcc(spSymbol, timeStamp) var nowFuAcc = fe.getAcc(fuSymbol, timeStamp) var nowSpAcc = se.getAcc(spSymbol, timeStamp) if (!nowFuAcc || !nowSpAcc) { Log(fuSymbol, spSymbol, ",获取账户数据失败") return } pair.nowFuAcc = nowFuAcc pair.nowSpAcc = nowSpAcc var nowFuPos = fe.getFuPos(fuSymbol, timeStamp) var nowSpPos = se.getSpPos(spSymbol, spPrice, pair.initSpAcc, pair.nowSpAcc) if (!nowFuPos || !nowSpPos) { Log(fuSymbol, spSymbol, ",获取持仓数据失败") return } pair.nowFuPos = nowFuPos pair.nowSpPos = nowSpPos var fuAmount = amount var spAmount = amount if (tradeType == self.PLUS || tradeType == self.MINUS) { if (nowFuAcc.Balance < (pair.initFuAcc.Balance + pair.initFuAcc.FrozenBalance) * self.fuMarginReservedRatio + (fuAmount * fuPrice / self.fuMarginLevel)) { Log(pair.fuSymbol, "保证金不足!", "本次计划使用", (fuAmount * fuPrice / self.fuMarginLevel), "当前可用:", nowFuAcc.Balance, "计划预留:", (pair.initFuAcc.Balance + pair.initFuAcc.FrozenBalance) * self.fuMarginReservedRatio) return } if ((tradeType == self.PLUS && nowSpAcc.Balance < spAmount * spPrice)) { Log(pair.spSymbol, "资金不足!", "本次买入计划使用", spAmount * spPrice, "当前可用:", nowSpAcc.Balance) return } else if (tradeType == self.MINUS && nowSpAcc.Stocks < spAmount) { Log(pair.spSymbol, "资金不足!", "本次卖出计划使用", spAmount, "当前可用:", nowSpAcc.Stocks) return } } else { var fuLongPos = self.getLongPos(nowFuPos) var fuShortPos = self.getShortPos(nowFuPos) var spLongPos = self.getLongPos(nowSpPos) var spShortPos = self.getShortPos(nowSpPos) if ((tradeType == self.COVER_PLUS && !fuShortPos) || (tradeType == self.COVER_MINUS && !fuLongPos)) { Log(fuSymbol, spSymbol, ",期货没有对应持仓!") return } else if (tradeType == self.COVER_PLUS && Math.abs(fuShortPos.amount) < fuAmount) { fuAmount = Math.abs(fuShortPos.amount) } else if (tradeType == self.COVER_MINUS && Math.abs(fuLongPos.amount) < fuAmount) { fuAmount = Math.abs(fuLongPos.amount) } if ((tradeType == self.COVER_PLUS && !spLongPos) || (tradeType == self.COVER_MINUS && !spShortPos)) { Log(fuSymbol, spSymbol, ",现货没有对应持仓!") return } else if (tradeType == self.COVER_PLUS && Math.min(Math.abs(spLongPos.amount), nowSpAcc.Stocks) < spAmount) { spAmount = Math.min(Math.abs(spLongPos.amount), nowSpAcc.Stocks) } else if (tradeType == self.COVER_MINUS && Math.min(Math.abs(spShortPos.amount), nowSpAcc.Balance / spPrice) < spAmount) { spAmount = Math.min(Math.abs(spShortPos.amount), nowSpAcc.Balance / spPrice) } } fuAmount = fe.calcAmount(fuSymbol, fuDirection, fuPrice, fuAmount) spAmount = se.calcAmount(spSymbol, spDirection, spPrice, spAmount) if (!fuAmount || !spAmount) { Log(fuSymbol, spSymbol, "下单量计算错误:", fuAmount, spAmount) return } else { fuAmount = fe.calcAmount(fuSymbol, fuDirection, fuPrice, fuAmount[1]) spAmount = se.calcAmount(spSymbol, spDirection, spPrice, Math.min(fuAmount[1], spAmount[1])) if (!fuAmount || !spAmount) { Log(fuSymbol, spSymbol, "下单量计算错误:", fuAmount, spAmount) return } } Log("合约代码:", fuSymbol + "/" + spSymbol, "方向:", self.arrTradeTypeDesc[tradeType], "差价:", fuPrice - spPrice, "期货数量:", fuAmount, "现货数量:", spAmount, "@") fe.goGetTrade(fuSymbol, fuDirection, fuPrice, fuAmount[0]) se.goGetTrade(spSymbol, spDirection, spPrice, spAmount[0]) var feIdMsg = fe.getTrade() var seIdMsg = se.getTrade() return [feIdMsg, seIdMsg] } self.process = function() { var nowTS = new Date().getTime() if(!self.updateTickers()) { return } _.each(self.pairs, function(pair, index) { var fuTicker = null var spTicker = null _.each(self.fuExTickers, function(ticker) { if (ticker.originalSymbol == pair.fuSymbol) { fuTicker = ticker } }) _.each(self.spExTickers, function(ticker) { if (ticker.originalSymbol == pair.spSymbol) { spTicker = ticker } }) if (fuTicker && spTicker) { pair.canTrade = true } else { pair.canTrade = false } fuTicker = fuTicker ? fuTicker : {} spTicker = spTicker ? spTicker : {} pair.fuTicker = fuTicker pair.spTicker = spTicker pair.plusDiff = fuTicker.bid1 - spTicker.ask1 pair.minusDiff = fuTicker.ask1 - spTicker.bid1 if (pair.plusDiff && pair.minusDiff) { pair.plusDiff = _N(pair.plusDiff, Math.max(self.fuEx.judgePrecision(fuTicker.bid1), self.spEx.judgePrecision(spTicker.ask1))) pair.minusDiff = _N(pair.minusDiff, Math.max(self.fuEx.judgePrecision(fuTicker.ask1), self.spEx.judgePrecision(spTicker.bid1))) } if (nowTS - self.preUpdateAccTS > 1000 * 60 * 5) { self.fuEx.goGetAcc(pair.fuSymbol, nowTS) self.spEx.goGetAcc(pair.spSymbol, nowTS) var fuAcc = self.fuEx.getAcc(pair.fuSymbol, nowTS) var spAcc = self.spEx.getAcc(pair.spSymbol, nowTS) if (fuAcc) { pair.nowFuAcc = fuAcc } if (spAcc) { pair.nowSpAcc = spAcc } var nowFuPos = self.fuEx.getFuPos(pair.fuSymbol, nowTS) var nowSpPos = self.spEx.getSpPos(pair.spSymbol, (pair.spTicker.ask1 + pair.spTicker.bid1) / 2, pair.initSpAcc, pair.nowSpAcc) if (nowFuPos && nowSpPos) { pair.nowFuPos = nowFuPos pair.nowSpPos = nowSpPos self.keepBalance(pair) } else { Log(pair.fuSymbol, pair.spSymbol, "组合仓位更新失败,nowFuPos:", nowFuPos, " nowSpPos:", nowSpPos) } self.accAndPosUpdateCount++ } }) if (nowTS - self.preUpdateAccTS > 1000 * 60 * 5) { self.preUpdateAccTS = nowTS self.profit = self.calcProfit() LogProfit(self.profit[0], "期货:", self.profit[1], "现货:", self.profit[2], "&") // 打印总收益曲线,使用&字符不打印收益日志 } var cmd = GetCommand() if(cmd) { Log("交互命令:", cmd) var arr = cmd.split(":") if(arr[0] == "plus") { var pair = self.pairs[parseFloat(arr[1])] self.hedge(parseFloat(arr[1]), pair.fuSymbol, pair.spSymbol, self.PLUS, self.cmdHedgeAmount) } else if (arr[0] == "cover_plus") { var pair = self.pairs[parseFloat(arr[1])] self.hedge(parseFloat(arr[1]), pair.fuSymbol, pair.spSymbol, self.COVER_PLUS, self.cmdHedgeAmount) } } LogStatus("当前时间:", _D(), " 数据更新时间:", _D(self.tickerUpdateTS), "持仓账户更新计数:", self.accAndPosUpdateCount, "\n", "盈亏:", self.profit[0], " 期货盈亏:", self.profit[1], " 现货盈亏:", self.profit[2], "\n`" + JSON.stringify(self.returnTbl()) + "`", "\n`" + JSON.stringify(self.returnPosTbl()) + "`") } self.keepBalance = function (pair) { var nowFuPos = pair.nowFuPos var nowSpPos = pair.nowSpPos var fuLongPos = self.getLongPos(nowFuPos) var fuShortPos = self.getShortPos(nowFuPos) var spLongPos = self.getLongPos(nowSpPos) var spShortPos = self.getShortPos(nowSpPos) if (fuLongPos || spShortPos) { Log("不支持反套") } if (fuShortPos || spLongPos) { var fuHoldAmount = fuShortPos ? fuShortPos.amount : 0 var spHoldAmount = spLongPos ? spLongPos.amount : 0 var sum = fuHoldAmount + spHoldAmount if (sum > 0) { var spAmount = self.spEx.calcAmount(pair.spSymbol, self.spEx.COVER_LONG, pair.spTicker.bid1, Math.abs(sum), true) if (spAmount) { Log(pair.fuSymbol, pair.spSymbol, "现货头寸多出", Math.abs(sum), "fuShortPos:", fuShortPos, "spLongPos:", spLongPos) self.spEx.goGetTrade(pair.spSymbol, self.spEx.COVER_LONG, pair.spTicker.bid1, spAmount[0]) var seIdMsg = self.spEx.getTrade() } } else if (sum < 0) { var fuAmount = self.fuEx.calcAmount(pair.fuSymbol, self.fuEx.COVER_SHORT, pair.fuTicker.ask1, Math.abs(sum), true) if (fuAmount) { Log(pair.fuSymbol, pair.spSymbol, "期货头寸多出", Math.abs(sum), "fuShortPos:", fuShortPos, "spLongPos:", spLongPos) self.fuEx.goGetTrade(pair.fuSymbol, self.fuEx.COVER_SHORT, pair.fuTicker.ask1, fuAmount[0]) var feIdMsg = self.fuEx.getTrade() } } } } self.getLongPos = function (positions) { return self.getPosByDirection(positions, PD_LONG) } self.getShortPos = function (positions) { return self.getPosByDirection(positions, PD_SHORT) } self.getPosByDirection = function (positions, direction) { var ret = null if (positions.length > 2) { Log("持仓错误,检测到三个持仓:", JSON.stringify(positions)) return ret } _.each(positions, function(pos) { if ((direction == PD_LONG && pos.amount > 0) || (direction == PD_SHORT && pos.amount < 0)) { ret = pos } }) return ret } self.calcProfit = function() { var arrInitFuAcc = [] var arrNowFuAcc = [] _.each(self.pairs, function(pair) { arrInitFuAcc.push(pair.initFuAcc) arrNowFuAcc.push(pair.nowFuAcc) }) var fuProfit = self.fuEx.calcProfit(arrInitFuAcc, arrNowFuAcc) var spProfit = 0 var deltaBalance = 0 _.each(self.pairs, function(pair) { var nowSpAcc = pair.nowSpAcc var initSpAcc = pair.initSpAcc var stocksDiff = nowSpAcc.Stocks + nowSpAcc.FrozenStocks - (initSpAcc.Stocks + initSpAcc.FrozenStocks) var price = stocksDiff > 0 ? pair.spTicker.bid1 : pair.spTicker.ask1 spProfit += stocksDiff * price deltaBalance = nowSpAcc.Balance + nowSpAcc.FrozenBalance - (initSpAcc.Balance + initSpAcc.FrozenBalance) }) spProfit += deltaBalance return [fuProfit + spProfit, fuProfit, spProfit] } self.returnPosTbl = function() { var posTbl = { type : "table", title : "positions", cols : ["索引", "期货", "期货杠杆", "数量", "现货", "数量"], rows : [] } _.each(self.pairs, function(pair, index) { var nowFuPos = pair.nowFuPos var nowSpPos = pair.nowSpPos for (var i = 0 ; i < nowFuPos.length ; i++) { if (nowSpPos.length > 0) { posTbl.rows.push([index, nowFuPos[i].symbol, nowFuPos[i].marginLevel, nowFuPos[i].amount, nowSpPos[0].symbol, nowSpPos[0].amount]) } else { posTbl.rows.push([index, nowFuPos[i].symbol, nowFuPos[i].marginLevel, nowFuPos[i].amount, "--", "--"]) } } }) return posTbl } self.returnTbl = function() { var fuExName = "[" + self.fuEx.getExName() + "]" var spExName = "[" + self.spEx.getExName() + "]" var combiTickersTbl = { type : "table", title : "combiTickersTbl", cols : ["期货", "代码" + fuExName, "卖一", "买一", "现货", "代码" + spExName, "卖一", "买一", "正对冲差价", "反对冲差价", "正对冲", "正对冲平仓"], rows : [] } _.each(self.pairs, function(pair, index) { var spSymbolInfo = self.spEx.getSymbolInfo(pair.spTicker.originalSymbol) combiTickersTbl.rows.push([ pair.fuTicker.symbol, pair.fuTicker.originalSymbol, pair.fuTicker.ask1, pair.fuTicker.bid1, pair.spTicker.symbol, pair.spTicker.originalSymbol, pair.spTicker.ask1, pair.spTicker.bid1, pair.plusDiff, pair.minusDiff, {'type':'button', 'cmd': 'plus:' + String(index), 'name': '正套'}, {'type':'button', 'cmd': 'cover_plus:' + String(index), 'name': '平正套'} ]) }) var accsTbl = { type : "table", title : "accs", cols : ["代码" + fuExName, "初币", "初冻币", "初钱", "初冻钱", "币", "冻币", "钱", "冻钱", "代码" + spExName, "初币", "初冻币", "初钱", "初冻钱", "币", "冻币", "钱", "冻钱"], rows : [] } _.each(self.pairs, function(pair) { var arr = [pair.fuTicker.originalSymbol, pair.initFuAcc.Stocks, pair.initFuAcc.FrozenStocks, pair.initFuAcc.Balance, pair.initFuAcc.FrozenBalance, pair.nowFuAcc.Stocks, pair.nowFuAcc.FrozenStocks, pair.nowFuAcc.Balance, pair.nowFuAcc.FrozenBalance, pair.spTicker.originalSymbol, pair.initSpAcc.Stocks, pair.initSpAcc.FrozenStocks, pair.initSpAcc.Balance, pair.initSpAcc.FrozenBalance, pair.nowSpAcc.Stocks, pair.nowSpAcc.FrozenStocks, pair.nowSpAcc.Balance, pair.nowSpAcc.FrozenBalance] for (var i = 0 ; i < arr.length ; i++) { if (typeof(arr[i]) == "number") { arr[i] = _N(arr[i], 6) } } accsTbl.rows.push(arr) }) var symbolInfoTbl = { type : "table", title : "symbolInfos", cols : ["合约代码" + fuExName, "量精度", "价格精度", "乘数", "最小下单量", "现货代码" + spExName, "量精度", "价格精度", "乘数", "最小下单量"], rows : [] } _.each(self.pairs, function(pair) { var fuSymbolInfo = self.fuEx.getSymbolInfo(pair.fuTicker.originalSymbol) var spSymbolInfo = self.spEx.getSymbolInfo(pair.spTicker.originalSymbol) symbolInfoTbl.rows.push([fuSymbolInfo.symbol, fuSymbolInfo.amountPrecision, fuSymbolInfo.pricePrecision, fuSymbolInfo.multiplier, fuSymbolInfo.min, spSymbolInfo.symbol, spSymbolInfo.amountPrecision, spSymbolInfo.pricePrecision, spSymbolInfo.multiplier, spSymbolInfo.min]) }) var allPairs = [] _.each(self.fuExTickers, function(fuTicker) { _.each(self.spExTickers, function(spTicker) { if (fuTicker.symbol == spTicker.symbol) { allPairs.push({symbol: fuTicker.symbol, fuSymbol: fuTicker.originalSymbol, spSymbol: spTicker.originalSymbol, plus: fuTicker.bid1 - spTicker.ask1}) } }) }) _.each(allPairs, function(pair) { var findPair = null _.each(self.allPairs, function(selfPair) { if (pair.fuSymbol == selfPair.fuSymbol && pair.spSymbol == selfPair.spSymbol) { findPair = selfPair } }) if (findPair) { findPair.minPlus = pair.plus < findPair.minPlus ? pair.plus : findPair.minPlus findPair.maxPlus = pair.plus > findPair.maxPlus ? pair.plus : findPair.maxPlus pair.minPlus = findPair.minPlus pair.maxPlus = findPair.maxPlus } else { self.allPairs.push({symbol: pair.symbol, fuSymbol: pair.fuSymbol, spSymbol: pair.spSymbol, plus: pair.plus, minPlus: pair.plus, maxPlus: pair.plus}) pair.minPlus = pair.plus pair.maxPlus = pair.plus } }) return [combiTickersTbl, accsTbl, symbolInfoTbl] } self.onexit = function() { _G("pairs", self.pairs) _G("allPairs", self.allPairs) Log("执行扫尾处理,数据保存", "#FF0000") } self.init = function() { var fuExName = self.fuEx.getExName() var spExName = self.spEx.getExName() var gFuExName = _G("fuExName") var gSpExName = _G("spExName") if ((gFuExName && gFuExName != fuExName) || (gSpExName && gSpExName != spExName)) { throw "交易所对象发生变化,需要重置数据" } if (!gFuExName) { _G("fuExName", fuExName) } if (!gSpExName) { _G("spExName", spExName) } self.allPairs = _G("allPairs") if (!self.allPairs) { self.allPairs = [] } var arrPair = _G("pairs") if (!arrPair) { arrPair = [] } var arrStrPair = self.symbolPairs.split(",") var timeStamp = new Date().getTime() _.each(arrStrPair, function(strPair) { var arrSymbol = strPair.split("|") var recoveryPair = null _.each(arrPair, function(pair) { if (pair.fuSymbol == arrSymbol[0] && pair.spSymbol == arrSymbol[1]) { recoveryPair = pair } }) if (!recoveryPair) { var pair = { fuSymbol : arrSymbol[0], spSymbol : arrSymbol[1], fuTicker : {}, spTicker : {}, plusDiff : null, minusDiff : null, canTrade : false, initFuAcc : null, initSpAcc : null, nowFuAcc : null, nowSpAcc : null, nowFuPos : null, nowSpPos : null, fuMarginLevel : null } self.pairs.push(pair) Log("初始化:", pair) } else { self.pairs.push(recoveryPair) Log("恢复:", recoveryPair) } self.fuEx.pushSubscribeSymbol(arrSymbol[0]) self.spEx.pushSubscribeSymbol(arrSymbol[1]) if (!self.pairs[self.pairs.length - 1].initFuAcc) { self.fuEx.goGetAcc(arrSymbol[0], timeStamp) var nowFuAcc = self.fuEx.getAcc(arrSymbol[0], timeStamp) self.pairs[self.pairs.length - 1].initFuAcc = nowFuAcc self.pairs[self.pairs.length - 1].nowFuAcc = nowFuAcc } if (!self.pairs[self.pairs.length - 1].initSpAcc) { self.spEx.goGetAcc(arrSymbol[1], timeStamp) var nowSpAcc = self.spEx.getAcc(arrSymbol[1], timeStamp) self.pairs[self.pairs.length - 1].initSpAcc = nowSpAcc self.pairs[self.pairs.length - 1].nowSpAcc = nowSpAcc } Sleep(300) }) Log("self.pairs:", self.pairs) _.each(self.pairs, function(pair) { var fuSymbolInfo = self.fuEx.getSymbolInfo(pair.fuSymbol) if (!fuSymbolInfo) { throw pair.fuSymbol + ",品种信息获取失败!" } else { Log(pair.fuSymbol, fuSymbolInfo) } var spSymbolInfo = self.spEx.getSymbolInfo(pair.spSymbol) if (!spSymbolInfo) { throw pair.spSymbol + ",品种信息获取失败!" } else { Log(pair.spSymbol, spSymbolInfo) } }) _.each(self.pairs, function(pair) { pair.fuMarginLevel = self.fuMarginLevel var ret = self.fuEx.setMarginLevel(pair.fuSymbol, self.fuMarginLevel) Log(pair.fuSymbol, "杠杆设置:", ret) if (!ret) { throw "初始设置杠杆失败!" } }) } self.init() return self } var manager = null function main() { if(isReset) { _G(null) LogReset(1) LogProfitReset() LogVacuum() Log("重置所有数据", "#FF0000") } if (isOKEX_V5_Simulate) { for (var i = 0 ; i < exchanges.length ; i++) { if (exchanges[i].GetName() == "Futures_OKCoin" || exchanges[i].GetName() == "OKEX") { var ret = exchanges[i].IO("simulate", true) Log(exchanges[i].GetName(), "切换模拟盘") } } } var fuConfigureFunc = null var spConfigureFunc = null if (exchanges.length != 2) { throw "需要添加两个交易所对象!" } else { var fuName = exchanges[0].GetName() if (fuName == "Futures_OKCoin" && isOkexV5) { fuName += "_V5" Log("使用OKEX V5接口") } var spName = exchanges[1].GetName() fuConfigureFunc = $.getConfigureFunc()[fuName] spConfigureFunc = $.getConfigureFunc()[spName] if (!fuConfigureFunc || !spConfigureFunc) { throw (fuConfigureFunc ? "" : fuName) + " " + (spConfigureFunc ? "" : spName) + " not support!" } } var fuEx = $.createBaseEx(exchanges[0], fuConfigureFunc) var spEx = $.createBaseEx(exchanges[1], spConfigureFunc) manager = createManager(fuEx, spEx, symbolPairs, cmdHedgeAmount, fuMarginLevel, fuMarginReservedRatio) while(true) { manager.process() Sleep(interval) } } function onerror() { if (manager) { manager.onexit() } } function onexit() { if (manager) { manager.onexit() } }

Dado que las estrategias de múltiples variedades son más adecuadas para diseñar utilizando IO, el código utiliza unaMultiSymbolCtrlLibUna biblioteca de clases de plantilla (encapsulación, llamando a la interfaz de intercambio a través de IO). Por lo tanto, la estrategia no se puede probar retrospectivamente, pero sí se puede probar en una negociación simulada (aunque la negociación real se haya estado ejecutando durante 2 meses, todavía es necesario utilizar una negociación simulada durante la etapa de prueba y familiarización).

parámetro

Antes de comenzar la prueba, hablemos primero del diseño de parámetros.

img

No hay muchos parámetros de estrategia, los más importantes son:

  • Tabla de control de cobertura

    LTC-USDT-211231|LTC_USDT,BTC-USDT-211231|BTC_USDT

    Aquí debe establecer la estrategia para monitorear las combinaciones. Por ejemplo, la configuración anterior es para monitorear el contrato Litecoin (LTC-USDT-211231) del mercado de futuros y el Litecoin (LTC_USDT) del mercado al contado. Una combinación de contratos de futuros y pares de negociación al contado|Los símbolos se separan para formar un grupo. Utilizar en diferentes combinaciones,Símbolos separados. ¡Tenga en cuenta que todos los símbolos aquí corresponden al estado del método de entrada en inglés!
    Entonces, puede que me pregunte cómo encontrar el código de contrato. Estos códigos de contrato y pares de operaciones al contado están todos definidos por la bolsa. No está definido en la plataforma FMZ.
    Por ejemploLTC-USDT-211231Este contrato es actualmente un contrato subtrimestral, denominadonext_quarterEl sistema de interfaz de OKEX se llamaLTC-USDT-211231. Demostración de WexAppLitecoin/USDTEl par comercial se escribe comoLTC_USDT. Entonces, la forma de completar la información aquí depende del nombre definido en el intercambio.

  • Importe de cobertura de los controles interactivos
    Haga clic en el botón de control de la barra de estado para cubrir la cantidad. La unidad es el número de monedas y la estrategia la convertirá automáticamente en el número de contratos para realizar un pedido.

    img

El resto son funciones como configurar un disco simulado, reiniciar datos, utilizar la interfaz OKEX V5 (porque también es compatible con V3), etc., que no son particularmente importantes.

prueba

El primer objeto de intercambio agrega el intercambio de futuros y el segundo agrega el objeto de intercambio al contado.

Las bolsas de futuros utilizan la interfaz V5 de OKEX para simular el comercio, y las bolsas al contado utilizan wexApp para simular el comercio.

Hice clic en el botón de cobertura positiva de la combinación BTC y abrí una posición.

img

img

img

Luego hice clic en cerrar la posición.

img

img

¡Pérdida! ! ! Parece que cuando el margen de beneficio es pequeño, el cierre de la posición no puede cubrir la tarifa de manejo. Es necesario calcular la tarifa de manejo, el deslizamiento aproximado y luego planificar razonablemente el margen de cierre antes de cerrar la posición.

Código fuente de la estrategia: https://www.fmz.com/strategy/314352

Los que estén interesados ​​pueden utilizarlo y modificarlo.

Related Recommendations
Comment
All comments (3)

    570行出错,是不是少了哪个模板?

    4 years ago

    模版没有公开,但是复制这个完整的策略是直接可以引用到这个模版的。

    4 years ago

    aicoin有一个这个功能,用过

    4 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)