وسائل لوڈ ہو رہے ہیں... لوڈنگ...

کریپٹوکرنسی دستی فیوچر اور اسپاٹ ہیج حکمت عملی

مصنف:نینا باداس, تخلیق: 2022-04-12 15:12:36, تازہ کاری: 2022-04-12 15:44:18

کریپٹوکرنسی دستی فیوچر اور اسپاٹ ہیج حکمت عملی

اس حقیقت کے پیش نظر کہ موجودہ ہیجنگ حکمت عملی کی ہیجنگ فریکوئنسی خاص طور پر زیادہ نہیں ہے ، یہ دراصل دستی طور پر کام کیا جاسکتا ہے۔ تاہم ، اگر آپ اسے دستی طور پر کرتے ہیں تو ، مختلف پلیٹ فارمز کے صفحات کو سوئچ کریں ، قیمتوں کا مشاہدہ کریں ، اور قیمتوں کے پھیلاؤ کا حساب لگائیں ، جو بہت تکلیف دہ ہے۔ بعض اوقات ، آپ زیادہ علامتیں دیکھنا چاہتے ہیں ، اور مارکیٹ کی قیمتوں کو ظاہر کرنے کے لئے کئی ڈسپلے ترتیب دینے کی ضرورت نہیں ہے۔ کیا نیم خودکار حکمت عملی کے ساتھ دستی آپریشن کی اس ضرورت کو حاصل کرنا ممکن ہے؟ اور زیادہ علامتیں رکھنا بہتر ہے؟ اوہ! ہاں۔ پوزیشنوں کو ایک کلک سے کھولنا اور بند کرنا بہتر ہے۔ اوہ ، ٹھیک ہے۔ پوزیشن ڈسپلے بھی ہے...

اگر ضرورت ہو تو اب کریں!

ایک کریپٹوکرنسی دستی فیوچر اور اسپاٹ ہیج حکمت عملی ڈیزائن کریں

یہاں لکھا ہوا کوڈ تھوڑا سا تھکا دینے والا ہے، 600 لائنوں تک نہیں پہنچتا۔

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 = ["positive arbitrage", "reverse arbitrage", "close positive arbitrage", "close reverse arbitrage"]

    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, ", fail to obtain the account data")
            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, ",fail to obtain the position data")
            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, "Inadequate margin!", "This time, plan to use", (fuAmount * fuPrice / self.fuMarginLevel), "Currently available:", nowFuAcc.Balance, 
                    "Plan to reserve:", (pair.initFuAcc.Balance + pair.initFuAcc.FrozenBalance) * self.fuMarginReservedRatio)
                return 
            }
            if ((tradeType == self.PLUS && nowSpAcc.Balance < spAmount * spPrice)) {  
                Log(pair.spSymbol, "Inadequate assets!", "This time, buy and plan to use", spAmount * spPrice, "Currently available:", nowSpAcc.Balance)
                return 
            } else if (tradeType == self.MINUS && nowSpAcc.Stocks < spAmount) {       
                Log(pair.spSymbol, "Inadequate assets!", "This time, sell and plan to use", spAmount, "Currently available:", 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, ", no corresponding position of futures!")
                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, ", no corresponding position of spot!")
                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, "Order amount calculation error:", 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, "Order amount calculation error:", fuAmount, spAmount)
                return 
            }
        }
        Log("Contract code:", fuSymbol + "/" + spSymbol, "Direction:", self.arrTradeTypeDesc[tradeType], "Spread:", fuPrice - spPrice, "Futures amount:", fuAmount, "Spot amount:", 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, "Fail to update combined position, nowFuPos:", nowFuPos, " nowSpPos:", nowSpPos)
                }
                self.accAndPosUpdateCount++    
            }
        })

        if (nowTS - self.preUpdateAccTS > 1000 * 60 * 5) {       
            self.preUpdateAccTS = nowTS
            self.profit = self.calcProfit()
            LogProfit(self.profit[0], "Futures:", self.profit[1], "Spot:", self.profit[2], "&")    // print the total equity curve, and use charater "&" to not print the equity log 
        }

        var cmd = GetCommand()
        if(cmd) {
            Log("Interactive command:", 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("Current date:", _D(), "  Data update date:", _D(self.tickerUpdateTS), "Update count of postion account:", self.accAndPosUpdateCount, "\n", "Profit and loss:", self.profit[0], "    Futures profit and loss:", self.profit[1],
            "    Spot profit and loss:", 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("Do not support reverse arbitrage") 
        }
        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, "spot long position", 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, "futures long position", 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("Position error, and three positions are detected:", 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 : ["Index", "Futures", "Futures Leverage", "Amount", "Spot", "Amount"], 
            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 : ["Futures", "Code" + fuExName, "Sell 1", "Buy 1", "Spot", "Code" + spExName, "Sell 1", "Buy 1", "Positive Hedge Spread", "Reverse Hedge Spread", "Positive Hedge", "Positive Hedge to close Positions"], 
            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': 'Positive Arbitrage'},
                {'type':'button', 'cmd': 'cover_plus:' + String(index), 'name': 'Close POsitive Arbitrage'}
            ])
        })

        var accsTbl = {
            type : "table", 
            title : "accs",
            cols : ["Code" + fuExName, "Initial Symbol", "Initial Frozen Symbol", "Initial Assets", "Initial Frozen Assets", "Symbol", "Frozen Symbol", "Assets", "Frozen Assets",
                "Code" + spExName, "Initial Symbol", "Initial Frozen Symbol", "Initial Assets", "Initial Frozen Assets", "Symbol", "Frozen Symbol", "Assets", "Forzen Assets"], 
            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 : ["Contract Code" + fuExName, "Amount Precision", "Price Precision", "Multiplier", "Minimum Order Amount", "Spot Code" + spExName, "Amount Precision", "Price Precision", "Multiplier", "Minimum Order Amount"], 
            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("Execute clean-up processing, and save the data", "#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 "The exchenge object is changed, so reset the data"
        }
        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("Initialize:", pair)
            } else {
                self.pairs.push(recoveryPair)
                Log("Recover:", 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 + ", fail to obtain the symbol information!"
            } else {
                Log(pair.fuSymbol, fuSymbolInfo)
            }
            var spSymbolInfo = self.spEx.getSymbolInfo(pair.spSymbol)
            if (!spSymbolInfo) {
                throw pair.spSymbol + ", fail to obtain the symbol information!"
            } 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, "Leverage Setting:", ret)
            if (!ret) {
                throw "Leverage initial setting failed!"
            }
        })
    }

    self.init()
    return self
}

var manager = null 
function main() {
    if(isReset) {        
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("Reset all data", "#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(), "Switch to simulated bot")
            }
        }
    }

    var fuConfigureFunc = null 
    var spConfigureFunc = null 
    if (exchanges.length != 2) {
        throw "Two exchange objects need to be added!"
    } else {
        var fuName = exchanges[0].GetName()
        if (fuName == "Futures_OKCoin" && isOkexV5) {
            fuName += "_V5"
            Log("Use OKEX V5 interface")
        }
        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()
    }
}

چونکہ کثیر علامت کی حکمت عملی آئی او ڈیزائن کے لئے زیادہ موزوں ہے، ایک ٹیمپلیٹ لائبریری کا نامMultiSymbolCtrlLibکوڈ میں استعمال کیا جاتا ہے (انکیپسولڈ اور تبادلہ انٹرفیس کو IO کے ذریعے کال کرنا) ۔ لہذا ، اس حکمت عملی کو بیک ٹسٹ نہیں کیا جاسکتا ، لیکن اس کا تجربہ سیمولیٹڈ بوٹ کے ساتھ کیا جاسکتا ہے (حالانکہ یہ 2 ماہ سے حقیقی بوٹ میں چل رہا ہے ، ٹیسٹ اور واقفیت کے مرحلے میں ، آپ اسے بہتر طور پر سیمولیٹڈ بوٹ میں چلائیں گے۔)

پیرامیٹر

ٹیسٹ سے پہلے، چلو پیرامیٹر ڈیزائن کے بارے میں بات کرتے ہیں.

img

حکمت عملی کے پیرامیٹرز بہت زیادہ نہیں ہیں، اور اہم ہیں:

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

یہاں ان مجموعوں کی نگرانی کے لئے حکمت عملی مرتب کرنا ہے۔ مثال کے طور پر ، مندرجہ بالا ترتیب فیوچر پلیٹ فارم کے لائیٹکوئن معاہدے (LTC-USDT-211231) اور اسپاٹ پلیٹ فارم کے لائیٹکوئن (LTC_USDT) کی نگرانی کرنا ہے۔ ایک مشترکہ فیوچر معاہدہ اور اسپاٹ ٹریڈنگ جوڑی کو تقسیم کیا جاتا ہے|ایک مجموعہ بنانے کے لئے علامت. مختلف مجموعے کی طرف سے تقسیم کر رہے ہیں,علامت. نوٹ کریں کہ یہاں علامات تمام انگریزی ان پٹ طریقہ کار کی حالت میں ہیں! پھر آپ مجھ سے پوچھ سکتے ہیں کہ معاہدے کا کوڈ کیسے تلاش کیا جائے۔ یہ معاہدہ کوڈ اور اسپاٹ ٹریڈنگ کے جوڑے سب پلیٹ فارم کے ذریعہ بیان کیے گئے ہیں ، ایف ایم زیڈ پلیٹ فارم پر بیان نہیں کیے گئے ہیں۔ مثال کے طور پر، معاہدہLTC-USDT-211231فی الحال اگلے سہ ماہی کے معاہدے، کہا جاتا ہےnext_quarterFMZ پر، اور OKEX انٹرفیس کے نظام کو بلایا جاتا ہےLTC-USDT-211231کے لئےLTC/USDTٹریڈنگ جوڑی، WexApp تخروپن بوٹ کے طور پر لکھا جاتا ہےLTC_USDTتو یہاں بھرنے کا طریقہ مخصوص پلیٹ فارم میں بیان کردہ نام پر منحصر ہے.

  • انٹرایکٹو کنٹرولز کی ہیجنگ رقم اسٹیٹس بار میں کنٹرول بٹن پر کلک کریں ، یعنی ہیجنگ کی رقم۔ یونٹ کرنسی کی رقم ہے ، جسے آرڈر دینے کے لئے حکمت عملی کے ذریعہ خود بخود معاہدے کی رقم میں تبدیل کردیا جائے گا۔

    img

دیگر افعال میں مشابہ بوٹ کو ترتیب دینا ، ڈیٹا کو ری سیٹ کرنا ، اوکیکس وی 5 انٹرفیس کا استعمال کرنا (کیونکہ یہ وی 3 کے ساتھ بھی مطابقت رکھتا ہے) اور دیگر افعال ہیں ، جو خاص طور پر اہم نہیں ہیں۔

ٹیسٹ

پہلا شامل کردہ تبادلہ اعتراض فیوچر شامل کرنے والے پلیٹ فارم کا انتخاب کرتا ہے ، اور دوسرا اسپاٹ ایکسچینج اعتراض کا انتخاب کرتا ہے۔

فیوچر پلیٹ فارمز OKEX V5 انٹرفیس سمیلیٹڈ بوٹ کا استعمال کرتے ہیں ، اور اسپاٹ پلیٹ فارمز wexApp سمیلیٹڈ بوٹ کا استعمال کرتے ہیں۔

میں نے بی ٹی سی کے مجموعے کے مثبت ثالثی کے بٹن پر کلک کیا اور پوزیشن کھول دی۔

img

img

img

اس کے بعد، پوزیشن بند کرنے کے لئے مثبت ثالثی پر کلک کریں.

img

img

نقصان!! ایسا لگتا ہے کہ جب منافع کا پھیلاؤ چھوٹا ہوتا ہے تو ، پوزیشن بند کرنا فیس کو پورا نہیں کرسکتا ہے۔ فیس اور تخمینہ لگانے کا حساب لگانا ضروری ہے ، اور پھر پوزیشن کو بند کرنے کے لئے پھیلاؤ کو معقول حد تک منصوبہ بندی کرنا ، اور پھر پوزیشن کو بند کرنا۔

حکمت عملی کا ماخذ کوڈ:https://www.fmz.com/strategy/314352

جو بھی دلچسپی رکھتا ہے وہ اسے استعمال اور ترمیم کر سکتا ہے۔


مزید