ابتدائیوں کے لئے کریپٹوکرنسی مقداری تجارت - آپ کو کریپٹوکرنسی مقداری کے قریب لے جانا (8)

مصنف:لیدیہ, تخلیق: 2022-08-10 15:02:37, تازہ کاری: 2023-09-19 21:38:29

img

ابتدائیوں کے لئے کریپٹوکرنسی مقداری تجارت - آپ کو کریپٹوکرنسی مقداری کے قریب لے جانا (8)

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

سپوئلر الرٹ، حکمت عملی چل رہا ہے، اور میں تھوڑا سا پرجوش ہوں!

img

img

img

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

پچھلے مضمون میں کوڈ کی بنیاد پر حکمت عملی کے ڈیزائن میں واپس، حکمت عملی شامل کی جاتی ہے:

  • ڈیٹا مستقل مزاجی ڈیزائن (ڈیٹا کو بچانے اور دوبارہ شروع کرنے کے بعد ڈیٹا کو بحال کرنے کے لئے _G فنکشن کا استعمال کریں)
  • ہر نگرانی شدہ CFD جوڑی کے لئے گرڈ ڈیٹا کی ساخت شامل کی گئی (حفاظت کھولنے اور بند ہونے والی پوزیشنوں کو کنٹرول کرنے کے لئے استعمال کیا جاتا ہے)
  • کھلی اور بند پوزیشنوں کو ہیج کرنے کے لئے ایک سادہ ہیجنگ فنکشن لاگو کیا
  • متغیر منافع اور نقصان کا حساب کرنے کے لئے ایک کل ایکویٹی حصول فنکشن شامل کیا گیا
  • حالت بار ڈیٹا آؤٹ پٹ ڈسپلے شامل کر دیا گیا.

مندرجہ بالا اضافی افعال ہیں۔ ڈیزائن کو آسان بنانے کے ل the ، یہ حکمت عملی صرف مثبت ہیجنگ (مختصر طویل مدتی معاہدے ، طویل قریبی مدتی معاہدے) کے لئے ڈیزائن کی گئی ہے۔ فی الحال ، دائمی معاہدے (قریبی مدت) میں منفی فیس کی شرح ہے ، جو صرف دائمی معاہدے کے ل long طویل عرصے تک دیکھ سکتا ہے کہ آیا یہ شرح کے منافع کو بڑھا سکتا ہے۔

ایک وقت کے لئے حکمت عملی چلنے دو ~

تقریباً 3 دن تک ٹیسٹ کرنے کے بعد، پھیلاؤ میں اتار چڑھاؤ اب بھی ممکن ہے۔

img

img

img

یہاں ہم کچھ فنڈنگ کی شرحوں کے منافع دیکھ سکتے ہیں۔

img

ذیل میں حکمت عملی کا ماخذ کوڈ شیئر کریں:

var arrNearContractType = strNearContractType.split(",")
var arrFarContractType = strFarContractType.split(",")

var nets = null
var initTotalEquity = null 
var OPEN_PLUS = 1
var COVER_PLUS = 2


function createNet(begin, diff, initAvgPrice, diffUsagePercentage) {
    if (diffUsagePercentage) {
        diff = diff * initAvgPrice
    }
    var oneSideNums = 3
    var up = []
    var down = []
    for (var i = 0 ; i < oneSideNums ; i++) {
        var upObj = {
            sell : false, 
            price : begin + diff / 2 + i * diff
        }
        up.push(upObj)

        var j = (oneSideNums - 1) - i
        var downObj = {
            sell : false,
            price : begin - diff / 2 - j * diff
        }
        if (downObj.price <= 0) {  // Price cannot be less than or equal to 0 
            continue
        }
        down.push(downObj)
    }
    return down.concat(up)
}

function createCfg(symbol) {
    var cfg = {
        extension: {
            layout: 'single', 
            height: 300,
            col: 6
        },
        title: {
            text: symbol
        },
        xAxis: {
            type: 'datetime'
        },
        series: [{
            name: 'plus',
            data: []
        }]
    }
    return cfg
}

function formatSymbol(originalSymbol) {
    var arr = originalSymbol.split("-")
    return [arr[0] + "_" + arr[1], arr[0], arr[1]]
}

function main() {	
    if (isSimulate) {
    	exchange.IO("simulate", true)  // Switch to simulation environment
    	Log("Only OKEX V5 API is supported, switch to OKEX V5 simulation bot:")
    } else {
    	exchange.IO("simulate", false)  // Switch to real bot
    	Log("Only OKEX V5 API is supported, switch to OKEX V5 simulation bot:")
    }    
    if (exchange.GetName() != "Futures_OKCoin") {
    	throw "Support OKEX futures"
    }

    // Initialization
    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("Reset all data", "#FF0000")
    }

    // Initialization marker
    var isFirst = true 

    // Profit print period
    var preProfitPrintTS = 0
    // Total equity
    var totalEquity = 0
    var posTbls = []   // Position table array

    // Declare arrCfg
    var arrCfg = []
    _.each(arrNearContractType, function(ct) {
        arrCfg.push(createCfg(formatSymbol(ct)[0]))
    })
    var objCharts = Chart(arrCfg)
    objCharts.reset()
    
    // Create object
    var exName = exchange.GetName() + "_V5"
    var nearConfigureFunc = $.getConfigureFunc()[exName]
    var farConfigureFunc = $.getConfigureFunc()[exName]
    var nearEx = $.createBaseEx(exchange, nearConfigureFunc)
    var farEx = $.createBaseEx(exchange, farConfigureFunc)

    // Pre-write the contract that require subscriptions
    _.each(arrNearContractType, function(ct) {
        nearEx.pushSubscribeSymbol(ct)
    })
    _.each(arrFarContractType, function(ct) {
        farEx.pushSubscribeSymbol(ct)
    })

    while (true) {
        var ts = new Date().getTime()
        // Obtain market data
        nearEx.goGetTickers()
        farEx.goGetTickers()
        var nearTickers = nearEx.getTickers()
        var farTickers = farEx.getTickers()  
        if (!farTickers || !nearTickers) {
            Sleep(2000)
            continue
        }

        var tbl = {
            type : "table",
            title : "Long term-near term spread",
            cols : ["Trading pair", "long term", "near term", "positive hedging", "negative hedging"],
            rows : []
        }        
        
        var subscribeFarTickers = []
        var subscribeNearTickers = []
        _.each(farTickers, function(farTicker) {
            _.each(arrFarContractType, function(symbol) {
                if (farTicker.originalSymbol == symbol) {
                    subscribeFarTickers.push(farTicker)
                }
            })
        })

        _.each(nearTickers, function(nearTicker) {
            _.each(arrNearContractType, function(symbol) {
                if (nearTicker.originalSymbol == symbol) {
                    subscribeNearTickers.push(nearTicker)
                }
            })
        })

        var pairs = []        
        _.each(subscribeFarTickers, function(farTicker) {
            _.each(subscribeNearTickers, function(nearTicker) {                
                if (farTicker.symbol == nearTicker.symbol) {
                    var pair = {symbol: nearTicker.symbol, nearTicker: nearTicker, farTicker: farTicker, plusDiff: farTicker.bid1 - nearTicker.ask1, minusDiff: farTicker.ask1 - nearTicker.bid1}
                    pairs.push(pair)
                    tbl.rows.push([pair.symbol, farTicker.originalSymbol, nearTicker.originalSymbol, pair.plusDiff, pair.minusDiff])
                    for (var i = 0 ; i < arrCfg.length ; i++) {
                        if (arrCfg[i].title.text == pair.symbol) {
                            objCharts.add([i, [ts, pair.plusDiff]])
                        }                        
                    }
                }
            })
        })

        // Initialization
        if (isFirst) {
            isFirst = false 
            var recoveryNets = _G("nets")
            var recoveryInitTotalEquity = _G("initTotalEquity")
            if (!recoveryNets) {
                // Check positions
                _.each(subscribeFarTickers, function(farTicker) {
                    var pos = farEx.getFuPos(farTicker.originalSymbol, ts)
                    if (pos.length != 0) {
                        Log(farTicker.originalSymbol, pos)
                        throw "Initialized with a position"
                    }
                })
                _.each(subscribeNearTickers, function(nearTicker) {
                    var pos = nearEx.getFuPos(nearTicker.originalSymbol, ts)
                    if (pos.length != 0) {
                        Log(nearTicker.originalSymbol, pos)
                        throw "Initialized with a position"
                    }
                })                
                // Construct nets
                nets = []
                _.each(pairs, function (pair) {
                    farEx.goGetAcc(pair.farTicker.originalSymbol, ts)
                    nearEx.goGetAcc(pair.nearTicker.originalSymbol, ts)
                    var obj = {
                        "symbol" : pair.symbol, 
                        "farSymbol" : pair.farTicker.originalSymbol,
                        "nearSymbol" : pair.nearTicker.originalSymbol,
                        "initPrice" : (pair.nearTicker.ask1 + pair.farTicker.bid1) / 2, 
                        "prePlus" : pair.farTicker.bid1 - pair.nearTicker.ask1,                        
                        "net" : createNet((pair.farTicker.bid1 - pair.nearTicker.ask1), diff, (pair.nearTicker.ask1 + pair.farTicker.bid1) / 2, true), 
                        "initFarAcc" : farEx.getAcc(pair.farTicker.originalSymbol, ts), 
                        "initNearAcc" : nearEx.getAcc(pair.nearTicker.originalSymbol, ts),
                        "farTicker" : pair.farTicker,
                        "nearTicker" : pair.nearTicker,
                        "farPos" : null, 
                        "nearPos" : null,
                    }
                    nets.push(obj)
                })
                var currTotalEquity = getTotalEquity()
                if (currTotalEquity) {
                	initTotalEquity = currTotalEquity
                } else {
                	throw "Initialization to obtain total equity failed!"
                }                
            } else {
                // Recovery
                nets = recoveryNets
                initTotalEquity = recoveryInitTotalEquity
            }
        }

        // Retrieve the grid and check if the trading is triggered
        _.each(nets, function(obj) {
            var currPlus = null
            _.each(pairs, function(pair) {
                if (pair.symbol == obj.symbol) {
                    currPlus = pair.plusDiff
                    obj.farTicker = pair.farTicker
                    obj.nearTicker = pair.nearTicker
                }
            })
            if (!currPlus) {
                Log("Not found", obj.symbol, " 's spread")
                return 
            }

            // Check grid, add dynamically
            while (currPlus >= obj.net[obj.net.length - 1].price) {
                obj.net.push({
                    sell : false,
                    price : obj.net[obj.net.length - 1].price + diff * obj.initPrice,
                })
            }
            while (currPlus <= obj.net[0].price) {
                var price = obj.net[0].price - diff * obj.initPrice
                if (price <= 0) {
                    break
                }
                obj.net.unshift({
                    sell : false,
                    price : price,
                })
            }
            
            // Search grid
            for (var i = 0 ; i < obj.net.length - 1 ; i++) {
                var p = obj.net[i]
                var upP = obj.net[i + 1]
                if (obj.prePlus <= p.price && currPlus > p.price && !p.sell) {
                    if (hedge(nearEx, farEx, obj.nearSymbol, obj.farSymbol, obj.nearTicker, obj.farTicker, hedgeAmount, OPEN_PLUS)) {   // Positive hedging opening position
                        p.sell = true 
                    }
                } else if (obj.prePlus >= p.price && currPlus < p.price && upP.sell) {
                    if (hedge(nearEx, farEx, obj.nearSymbol, obj.farSymbol, obj.nearTicker, obj.farTicker, hedgeAmount, COVER_PLUS)) {   // Positive hedging closing position
                        upP.sell = false 
                    }
                }
            }
            obj.prePlus = currPlus  // Record the current spread as a cache, and use it to judge whether it's above the SMA or below the SMA next time
            // Add other chart outputs
        })        

        if (ts - preProfitPrintTS > 1000 * 60 * 5) {   // Print every 5 minutes       
        	var currTotalEquity = getTotalEquity()
        	if (currTotalEquity) {
        		totalEquity = currTotalEquity
        		LogProfit(totalEquity - initTotalEquity, "&")   // Print dynamic equity profits
        	}

        	// Check positions
        	posTbls = []  // Reset, update
            _.each(nets, function(obj) {
                var currFarPos = farEx.getFuPos(obj.farSymbol)
                var currNearPos = nearEx.getFuPos(obj.nearSymbol)
                if (currFarPos && currNearPos) {
                	obj.farPos = currFarPos
                	obj.nearPos = currNearPos
                }
                var posTbl = {
                	"type" : "table", 
                	"title" : obj.symbol, 
                	"cols" : ["contract code", "amount", "price"], 
                	"rows" : [] 
                }
                _.each(obj.farPos, function(pos) {
                    posTbl.rows.push([pos.symbol, pos.amount, pos.price])
                })  
                _.each(obj.nearPos, function(pos) {
                	posTbl.rows.push([pos.symbol, pos.amount, pos.price])
                })
                posTbls.push(posTbl)
            })

            preProfitPrintTS = ts
        }

        // Show grid
        var netTbls = []
        _.each(nets, function(obj) {
            var netTbl = {
            	"type" : "table",
            	"title" : obj.symbol,
            	"cols" : ["grid"],
            	"rows" : []
            }
            _.each(obj.net, function(p) {
            	var color = ""
            	if (p.sell) {
            		color = "#00FF00"
            	}
            	netTbl.rows.push([JSON.stringify(p) + color])
            })
            netTbl.rows.reverse()
            netTbls.push(netTbl)
        })

        LogStatus(_D(), "total equity:", totalEquity, "initial total equity:", initTotalEquity, "floating profit and loss:", totalEquity - initTotalEquity, 
        	"\n`" + JSON.stringify(tbl) + "`" + "\n`" + JSON.stringify(netTbls) + "`" + "\n`" + JSON.stringify(posTbls) + "`")
        Sleep(interval)
    }
}

function getTotalEquity() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
        	totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
        	Log("Failed to obtain the total equity of the account!")
        	return null
        }
    }
    return totalEquity
}

function hedge(nearEx, farEx, nearSymbol, farSymbol, nearTicker, farTicker, amount, tradeType) {
    var farDirection = null
    var nearDirection = null
    if (tradeType == OPEN_PLUS) {
        farDirection = farEx.OPEN_SHORT
        nearDirection = nearEx.OPEN_LONG
    } else {
        farDirection = farEx.COVER_SHORT
        nearDirection = nearEx.COVER_LONG
    }
    var nearSymbolInfo = nearEx.getSymbolInfo(nearSymbol) 
    var farSymbolInfo = farEx.getSymbolInfo(farSymbol)
    nearAmount = nearEx.calcAmount(nearSymbol, nearDirection, nearTicker.ask1, amount * nearSymbolInfo.multiplier)
    farAmount = farEx.calcAmount(farSymbol, farDirection, farTicker.bid1, amount * farSymbolInfo.multiplier)
    if (!nearAmount || !farAmount) {
        Log(nearSymbol, farSymbol, "Order amount calculation error:", nearAmount, farAmount)
        return 
    }
    nearEx.goGetTrade(nearSymbol, nearDirection, nearTicker.ask1, nearAmount[0])
    farEx.goGetTrade(farSymbol, farDirection, farTicker.bid1, farAmount[0])
    var nearIdMsg = nearEx.getTrade()
    var farIdMsg = farEx.getTrade()
    return [nearIdMsg, farIdMsg]
}

function onexit() {
	Log("Execute the tail function", "#FF0000")
    _G("nets", nets)
    _G("initTotalEquity", initTotalEquity)
    Log("save the data:", _G("nets"), _G("initTotalEquity"))
}

img

حکمت عملی کا عوامی خطابhttps://www.fmz.com/strategy/288559

حکمت عملی میں ایک ٹیمپلیٹ کلاس لائبریری استعمال کی گئی ہے جو میں نے خود لکھی ہے ، جو عوامی نہیں ہے کیونکہ یہ بہت اچھی نہیں ہے۔ مذکورہ بالا حکمت عملی کا ماخذ کوڈ اس ٹیمپلیٹ کو استعمال کیے بغیر تبدیل کیا جاسکتا ہے۔

اگر آپ دلچسپی رکھتے ہیں تو، آپ کو ٹیسٹ کرنے کے لئے ایک OKEX V5 تخروپن بوٹ استعمال کر سکتے ہیں. اوہ! اس طرح، اس حکمت عملی backtested نہیں کیا جا سکتا ~


متعلقہ

مزید