Strategi Hedging Mata Uang Digital

Penulis:Mimpi kecil, Dibuat: 2021-09-08 14:47:33, Diperbarui: 2023-09-20 10:28:44

img

Strategi Hedging Mata Uang Digital

Karena frekuensi strategi hedging saat ini tidak terlalu tinggi, sebenarnya dapat dioperasikan secara manual. Tetapi jika hanya dioperasikan secara manual, beralih ke berbagai halaman bursa, melihat harga, menghitung perbedaan sangat tidak nyaman, dan kadang-kadang Anda mungkin ingin melihat beberapa varietas lebih banyak, mendapatkan beberapa indikator yang menunjukkan tren juga tidak terlalu diperlukan.

Jika ada permintaan, segera lakukan!

Merancang strategi untuk melakukan hedging futures digital secara manual

"Saya tidak tahu apa yang harus saya lakukan", kata dia, "tapi saya tidak tahu apa yang harus dilakukan".

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

Karena strategi multi-varietas lebih cocok untuk digunakan dalam desain IO, kode ini menggunakan namaMultiSymbolCtrlLibSebuah database kelas template (dibungkus, melalui IO memanggil antarmuka pertukaran) ‒ jadi kebijakan tidak dapat ditelusuri kembali, tetapi dapat diuji dengan piringan analog (meskipun piringan nyata juga telah berjalan selama 2 bulan, pengujian, tahap akrab masih berjalan dengan piringan analog).

Parameter

Sebelum kita mencoba, mari kita bahas tentang desain parameter.

img

Beberapa parameter strategi yang tidak banyak, namun yang lebih penting adalah:

  • Tabel Kontrol Hedging

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

    Di sini adalah pengaturan strategi yang memantau kedua kombinasi tersebut, misalnya pengaturan di atas memantau kontrak Litecoin di bursa berjangka (LTC-USDT-211231) dan Litecoin di bursa over-the-counter (LTC_USDT).|Simbol terpisah untuk membentuk kombinasi; kombinasi yang berbeda digunakan,Simbol yang terpisah. Perhatikan bahwa simbol di sini adalah tombol status cara mengetik bahasa Inggris! Anda mungkin bertanya kepada saya bagaimana cara menemukan kode kontrak, kode kontrak yang digunakan untuk perdagangan langsung didefinisikan oleh bursa; tidak didefinisikan di platform FMZ. Misalnya:LTC-USDT-211231Kontrak ini saat ini adalah kontrak kuartal kedua, yang disebut di FMZ.next_quarterSistem antarmuka OKEX adalah apa yang disebutnya.LTC-USDT-211231◊ WexApp Analog Disk untukLitecoin/USDTPerdagangan adalah tentang menulis.LTC_USDTOleh karena itu, bagaimana cara mengisinya di sini, lihat nama yang didefinisikan di bursa tersebut.

  • Hedging dari Interactive Controller Klik tombol status, jumlah yang dijamin. Satuan adalah jumlah koin, dan kebijakan akan secara otomatis diubah menjadi jumlah surat kontrak.

    img

Yang lain adalah pengaturan cakram analog, reset data, menggunakan antarmuka OKEX V5 (karena juga kompatibel dengan V3) dan sebagainya.

Pengujian

Objek bursa pertama menambahkan bursa berjangka, dan objek bursa kedua menambahkan bursa langsung.

Bursa berjangka menggunakan OKEX V5 interface analog, dan bursa langsung menggunakan wexApp analog.

Jika Anda menekan tombol set yang sesuai dengan kombinasi BTC, Anda akan membuka perdagangan.

img

img

img

"Saya tidak tahu apa yang akan terjadi", katanya.

img

img

Ternyata ketika perbedaan keuntungan kecil, neraca tidak dapat menutupi biaya prosedur, perlu menghitung biaya prosedur, mungkin titik geser, dan kemudian merencanakan secara rasional perbedaan neraca, kemudian neraca.

Kode sumber strategi:https://www.fmz.com/strategy/314352

Jika Anda tertarik, Anda bisa menggunakannya, mengubahnya.


Berkaitan

Lebih banyak

Ludwig570 baris yang salah, apakah salah satu template yang hilang?

MengkuantifikasiAicoin memiliki fitur ini.

Mimpi kecilTemplate ini tidak tersedia untuk umum, tetapi untuk menyalin kebijakan lengkap ini dapat langsung dihubungkan ke template ini.