اس حقیقت کے پیش نظر کہ موجودہ ہیجنگ حکمت عملی کی ہیجنگ فریکوئنسی خاص طور پر زیادہ نہیں ہے ، یہ دراصل دستی طور پر کام کیا جاسکتا ہے۔ تاہم ، اگر آپ اسے دستی طور پر کرتے ہیں تو ، مختلف پلیٹ فارمز کے صفحات کو سوئچ کریں ، قیمتوں کا مشاہدہ کریں ، اور قیمتوں کے پھیلاؤ کا حساب لگائیں ، جو بہت تکلیف دہ ہے۔ بعض اوقات ، آپ زیادہ علامتیں دیکھنا چاہتے ہیں ، اور مارکیٹ کی قیمتوں کو ظاہر کرنے کے لئے کئی ڈسپلے ترتیب دینے کی ضرورت نہیں ہے۔ کیا نیم خودکار حکمت عملی کے ساتھ دستی آپریشن کی اس ضرورت کو حاصل کرنا ممکن ہے؟ اور زیادہ علامتیں رکھنا بہتر ہے؟ اوہ! ہاں۔ پوزیشنوں کو ایک کلک سے کھولنا اور بند کرنا بہتر ہے۔ اوہ ، ٹھیک ہے۔ پوزیشن ڈسپلے بھی ہے...
اگر ضرورت ہو تو اب کریں!
یہاں لکھا ہوا کوڈ تھوڑا سا تھکا دینے والا ہے، 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 ماہ سے حقیقی بوٹ میں چل رہا ہے ، ٹیسٹ اور واقفیت کے مرحلے میں ، آپ اسے بہتر طور پر سیمولیٹڈ بوٹ میں چلائیں گے۔)
ٹیسٹ سے پہلے، چلو پیرامیٹر ڈیزائن کے بارے میں بات کرتے ہیں.
حکمت عملی کے پیرامیٹرز بہت زیادہ نہیں ہیں، اور اہم ہیں:
LTC-USDT-211231|LTC_USDT,BTC-USDT-211231|BTC_USDT
یہاں ان مجموعوں کی نگرانی کے لئے حکمت عملی مرتب کرنا ہے۔ مثال کے طور پر ، مندرجہ بالا ترتیب فیوچر پلیٹ فارم کے لائیٹکوئن معاہدے (LTC-USDT-211231) اور اسپاٹ پلیٹ فارم کے لائیٹکوئن (LTC_USDT) کی نگرانی کرنا ہے۔ ایک مشترکہ فیوچر معاہدہ اور اسپاٹ ٹریڈنگ جوڑی کو تقسیم کیا جاتا ہے|
ایک مجموعہ بنانے کے لئے علامت. مختلف مجموعے کی طرف سے تقسیم کر رہے ہیں,
علامت. نوٹ کریں کہ یہاں علامات تمام انگریزی ان پٹ طریقہ کار کی حالت میں ہیں!
پھر آپ مجھ سے پوچھ سکتے ہیں کہ معاہدے کا کوڈ کیسے تلاش کیا جائے۔ یہ معاہدہ کوڈ اور اسپاٹ ٹریڈنگ کے جوڑے سب پلیٹ فارم کے ذریعہ بیان کیے گئے ہیں ، ایف ایم زیڈ پلیٹ فارم پر بیان نہیں کیے گئے ہیں۔
مثال کے طور پر، معاہدہLTC-USDT-211231
فی الحال اگلے سہ ماہی کے معاہدے، کہا جاتا ہےnext_quarter
FMZ پر، اور OKEX انٹرفیس کے نظام کو بلایا جاتا ہےLTC-USDT-211231
کے لئےLTC/USDTٹریڈنگ جوڑی، WexApp تخروپن بوٹ کے طور پر لکھا جاتا ہےLTC_USDT
تو یہاں بھرنے کا طریقہ مخصوص پلیٹ فارم میں بیان کردہ نام پر منحصر ہے.
انٹرایکٹو کنٹرولز کی ہیجنگ رقم اسٹیٹس بار میں کنٹرول بٹن پر کلک کریں ، یعنی ہیجنگ کی رقم۔ یونٹ کرنسی کی رقم ہے ، جسے آرڈر دینے کے لئے حکمت عملی کے ذریعہ خود بخود معاہدے کی رقم میں تبدیل کردیا جائے گا۔
دیگر افعال میں مشابہ بوٹ کو ترتیب دینا ، ڈیٹا کو ری سیٹ کرنا ، اوکیکس وی 5 انٹرفیس کا استعمال کرنا (کیونکہ یہ وی 3 کے ساتھ بھی مطابقت رکھتا ہے) اور دیگر افعال ہیں ، جو خاص طور پر اہم نہیں ہیں۔
پہلا شامل کردہ تبادلہ اعتراض فیوچر شامل کرنے والے پلیٹ فارم کا انتخاب کرتا ہے ، اور دوسرا اسپاٹ ایکسچینج اعتراض کا انتخاب کرتا ہے۔
فیوچر پلیٹ فارمز OKEX V5 انٹرفیس سمیلیٹڈ بوٹ کا استعمال کرتے ہیں ، اور اسپاٹ پلیٹ فارمز wexApp سمیلیٹڈ بوٹ کا استعمال کرتے ہیں۔
میں نے بی ٹی سی کے مجموعے کے مثبت ثالثی کے بٹن پر کلک کیا اور پوزیشن کھول دی۔
اس کے بعد، پوزیشن بند کرنے کے لئے مثبت ثالثی پر کلک کریں.
نقصان!! ایسا لگتا ہے کہ جب منافع کا پھیلاؤ چھوٹا ہوتا ہے تو ، پوزیشن بند کرنا فیس کو پورا نہیں کرسکتا ہے۔ فیس اور تخمینہ لگانے کا حساب لگانا ضروری ہے ، اور پھر پوزیشن کو بند کرنے کے لئے پھیلاؤ کو معقول حد تک منصوبہ بندی کرنا ، اور پھر پوزیشن کو بند کرنا۔
حکمت عملی کا ماخذ کوڈ:https://www.fmz.com/strategy/314352
جو بھی دلچسپی رکھتا ہے وہ اسے استعمال اور ترمیم کر سکتا ہے۔