Menggunakan Antara muka Pasaran Pengumpulan Platform Cryptocurrency untuk Membina Strategi Multi-Simbol

Penulis:Ninabadass, Dicipta: 2022-04-24 17:34:03, Dikemas kini:

Menggunakan Antara muka Pasaran Pengumpulan Platform Cryptocurrency untuk Membina Strategi Multi-Simbol

Dalam bahagian [Live] (https://www.fmz.com/liveDi dalam platform perdagangan kuant FMZ, strategi multi-simbol sering dilihat, yang dapat mengesan keadaan pasaran berpuluh-puluh simbol atau bahkan keseluruhan platform pada masa yang sama. Bagaimana ia dilakukan? Dan bagaimana ia harus direka? Artikel ini membawa anda untuk membincangkan bagaimana menggunakan antara muka pasaran agregat platform untuk membina strategi multi-simbol.

Ambil Binance dan Huobi sebagai contoh; jika anda memeriksa dokumentasi API mereka, anda akan mendapati terdapat antara muka yang dikumpulkan:

Antara muka pasaran

  • Kontrak Binance:https://fapi.binance.com/fapi/v1/ticker/bookTickerData yang dikembalikan antara muka:

    [
        {
            "symbol": "BTCUSDT", // trading pair
            "bidPrice": "4.00000000", //optimum bid price 
            "bidQty": "431.00000000", //bid quantity 
            "askPrice": "4.00000200", //optimum ask price 
            "askQty": "9.00000000", //ask quantity 
            "time": 1589437530011   // matching engine time 
        }
        ...
    ]
    
  • Huobi spot:https://api.huobi.pro/market/tickersData yang dikembalikan antara muka:

    [  
        {  
            "open":0.044297,      // open price 
            "close":0.042178,     // close price 
            "low":0.040110,       // the lowest price 
            "high":0.045255,      // the highest price 
            "amount":12880.8510,  
            "count":12838,
            "vol":563.0388715740,
            "symbol":"ethbtc",
            "bid":0.007545,
            "bidSize":0.008,
            "ask":0.008088,
            "askSize":0.009
        }, 
        ...
    ]
    

    Walau bagaimanapun, hasilnya sebenarnya tidak seperti itu, dan struktur sebenar yang dikembalikan oleh antara muka Huobi adalah:

    {
        "status": "ok",
        "ts": 1616032188422,
        "data": [{
      	  "symbol": "hbcbtc",
      	  "open": 0.00024813,
      	  "high": 0.00024927,
      	  "low": 0.00022871,
      	  "close": 0.00023495,
      	  "amount": 2124.32,
      	  "vol": 0.517656218,
      	  "count": 1715,
      	  "bid": 0.00023427,
      	  "bidSize": 2.3,
      	  "ask": 0.00023665,
      	  "askSize": 2.93
        }, ...]
    }
    

    Perhatian harus diberikan semasa memproses data yang dikembalikan oleh antara muka.

Membina Struktur Program Strategi

Bagaimana untuk merangkumi dua antara muka dalam strategi, dan bagaimana untuk memproses data? Mari kita lihat.

Pertama, menulis pembina, untuk membina objek kawalan

// parameter e is used to import the exchange object; parameter subscribeList is the trading pair list to be processed, such as ["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]
function createManager(e, subscribeList) {           
    var self = {}
    self.supportList = ["Futures_Binance", "Huobi"]  // the supported platform's 

    // object attribute 
    self.e = e
    self.name = e.GetName()
    self.type = self.name.includes("Futures_") ? "Futures" : "Spot"
    self.label = e.GetLabel()
    self.quoteCurrency = ""  
    self.subscribeList = subscribeList   // subscribeList : [strSymbol1, strSymbol2, ...]
    self.tickers = []                    // all market data obtained by the interfaces; define the data format as: {bid1: 123, ask1: 123, symbol: "xxx"}}
    self.subscribeTickers = []           // the market data needed; define the data format as: {bid1: 123, ask1: 123, symbol: "xxx"}}
    self.accData = null                  // used to record the account asset data 

    // initialization function 
    self.init = function() { 
    	// judge whether a platform is supported 
        if (!_.contains(self.supportList, self.name)) {        	
        	throw "not support"
        }
    }

    // judge the data precision 
    self.judgePrecision = function (p) {
        var arr = p.toString().split(".")
        if (arr.length != 2) {
            if (arr.length == 1) {
                return 0
            }
            throw "judgePrecision error, p:" + String(p)
        }
        
        return arr[1].length
    }

    // update assets 
    self.updateAcc = function(callBackFuncGetAcc) {
        var ret = callBackFuncGetAcc(self)
        if (!ret) {
        	return false 
        }
        self.accData = ret 
        return true 
    }

    // update market data 
    self.updateTicker = function(url, callBackFuncGetArr, callBackFuncGetTicker) {
    	var tickers = []
    	var subscribeTickers = []
    	var ret = self.httpQuery(url)
    	if (!ret) {
    		return false 
    	}
    	try {
            _.each(callBackFuncGetArr(ret), function(ele) {
            	var ticker = callBackFuncGetTicker(ele)
            	tickers.push(ticker)
            	for (var i = 0 ; i < self.subscribeList.length ; i++) {
            		if (self.subscribeList[i] == ele.symbol) {
            			subscribeTickers.push(ticker)
            		}
            	}
            })
        } catch(err) {
        	Log("error:", err)
        	return false 
        }

        self.tickers = tickers
        self.subscribeTickers = subscribeTickers
        return true 
    }

    self.httpQuery = function(url) {
    	var ret = null
        try {
            var retHttpQuery = HttpQuery(url)
            ret = JSON.parse(retHttpQuery)
        } catch (err) {
            // Log("error:", err)
            ret = null
        }
        return ret 
    }

    self.returnTickersTbl = function() {
        var tickersTbl = {
        	type : "table", 
        	title : "tickers",
        	cols : ["symbol", "ask1", "bid1"], 
        	rows : []
        }
        _.each(self.subscribeTickers, function(ticker) {        
        	tickersTbl.rows.push([ticker.symbol, ticker.ask1, ticker.bid1])
        })
        return tickersTbl
    }

    // initialization 
    self.init()
	return self 
}

Gunakan fungsi FMZ APIHttpQueryuntuk menghantar permintaan untuk mengakses antara muka platform.HttpQuery, anda perlu menggunakan pemprosesan pengecualiantry...catchuntuk mengendalikan pengecualian seperti kegagalan pengembalian antara muka. Beberapa pelajar di sini mungkin bertanya: Struktur data yang dikembalikan oleh antara muka platform agak berbeza, jadi bagaimana untuk menangani ia? Sebenarnya, bukan sahaja struktur data yang dikembalikan oleh antara muka platform berbeza, tetapi juga nama medan data yang dikembalikan juga berbeza. Makna yang sama boleh dinamakan dengan cara yang berbeza. Sebagai contoh, antara muka yang kami senaraikan di atas. Ungkapan yang sama bermaksud harga beli1, yang dipanggil:bidPricedalam Binance, tetapibiddi Huobi.

Kami menggunakan fungsi callback di sini dan memisahkan bahagian-bahagian yang memerlukan pemprosesan khusus secara bebas. Jadi selepas objek di atas dimulakan, ia menjadi seperti ini dalam penggunaan tertentu: (Kod berikut terlepas pembinacreateManager) kontrak yang dipantau oleh Binance Futures:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]Pasangan dagangan spot yang dipantau oleh Huobi Spot:["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"]

function main() {
    var manager1 = createManager(exchanges[0], ["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"])
    var manager2 = createManager(exchanges[1], ["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"])   

    while (true) {
    	// update market data 
    	var ticker1GetSucc = manager1.updateTicker("https://fapi.binance.com/fapi/v1/ticker/bookTicker", 
    		function(data) {return data}, 
    		function (ele) {return {bid1: ele.bidPrice, ask1: ele.askPrice, symbol: ele.symbol}})
    	var ticker2GetSucc = manager2.updateTicker("https://api.huobi.pro/market/tickers", 
    		function(data) {return data.data}, 
    		function(ele) {return {bid1: ele.bid, ask1: ele.ask, symbol: ele.symbol}})
        if (!ticker1GetSucc || !ticker2GetSucc) {
        	Sleep(1000)
        	continue
        }
        
        var tbl1 = {
        	type : "table", 
        	title : "futures market data",
        	cols : ["futures contract", "futures buy1", "futures sell1"], 
        	rows : []
        }
        _.each(manager1.subscribeTickers, function(ticker) {
        	tbl1.rows.push([ticker.symbol, ticker.bid1, ticker.ask1])
        })
        var tbl2 = {
        	type : "table", 
        	title : "spot market data",
        	cols : ["spot contract", "spot buy1", "spot sell1"], 
        	rows : []
        }
        _.each(manager2.subscribeTickers, function(ticker) {
        	tbl2.rows.push([ticker.symbol, ticker.bid1, ticker.ask1])
        })
        LogStatus(_D(), "\n`" + JSON.stringify(tbl1) + "`", "\n`" + JSON.stringify(tbl2) + "`")
        Sleep(10000)
    }
}

Ujian operasi: Tambah Binance Futures sebagai objek pertukaran pertama, dan tambah Huobi Spot sebagai objek pertukaran kedua.
img

img

Seperti yang anda lihat, di sini fungsi callback dipanggil untuk melakukan pemprosesan khusus pada operasi di platform yang berbeza, seperti bagaimana untuk mendapatkan data yang dikembalikan oleh antara muka.

    	var ticker1GetSucc = manager1.updateTicker("https://fapi.binance.com/fapi/v1/ticker/bookTicker", 
    		function(data) {return data}, 
    		function (ele) {return {bid1: ele.bidPrice, ask1: ele.askPrice, symbol: ele.symbol}})
    	var ticker2GetSucc = manager2.updateTicker("https://api.huobi.pro/market/tickers", 
    		function(data) {return data.data}, 
    		function(ele) {return {bid1: ele.bid, ask1: ele.ask, symbol: ele.symbol}})

Setelah merancang kaedah untuk mendapatkan data pasaran, kita boleh membuat kaedah untuk mendapatkan data pasaran. kerana ia adalah strategi multi-simbol, data aset akaun juga berganda.

Tambah kaedah mendapatkan aset dalam pembinacreateManager:

    // update assets
    self.updateAcc = function(callBackFuncGetAcc) {
        var ret = callBackFuncGetAcc(self)
        if (!ret) {
        	return false 
        }
        self.accData = ret 
        return true 
    }

Begitu juga, untuk format yang dikembalikan oleh antara muka platform yang berbeza dan nama medan berbeza, di sini kita perlu menggunakan fungsi callback untuk melakukan pemprosesan khusus.

Ambil Huobi Spot dan Binance Futures sebagai contoh, dan fungsi callback boleh ditulis seperti ini:

    // the callback function of obtaining the account assets 
    var callBackFuncGetHuobiAcc = function(self) {
        var account = self.e.GetAccount()
        var ret = []
        if (!account) {
        	return false 
        }
        // construct the array structure of assets 
        var list = account.Info.data.list
        _.each(self.subscribeList, function(symbol) {
            var coinName = symbol.split("usdt")[0]
            var acc = {symbol: symbol}
            for (var i = 0 ; i < list.length ; i++) {
            	if (coinName == list[i].currency) {
                    if (list[i].type == "trade") {
                        acc.Stocks = parseFloat(list[i].balance)
                    } else if (list[i].type == "frozen") {
                    	acc.FrozenStocks = parseFloat(list[i].balance)
                    }
                } else if (list[i].currency == "usdt") {
                	if (list[i].type == "trade") {
                		acc.Balance = parseFloat(list[i].balance)
                	} else if (list[i].type == "frozen") {
                		acc.FrozenBalance = parseFloat(list[i].balance)
                	}
                }
            }
            ret.push(acc)
        })
        return ret 
    }

    var callBackFuncGetFutures_BinanceAcc = function(self) {
    	self.e.SetCurrency("BTC_USDT")   // set to USDT-margined contract trading pair 
        self.e.SetContractType("swap")   // all are perpetual contracts
        var account = self.e.GetAccount() 
        var ret = []
        if (!account) {
        	return false 
        }
        var balance = account.Balance
        var frozenBalance = account.FrozenBalance
        // construct asset data structure 
        _.each(self.subscribeList, function(symbol) {
            var acc = {symbol: symbol}
            acc.Balance = balance
            acc.FrozenBalance = frozenBalance
            ret.push(acc)
        })
        return ret 
    }

Mengendalikan struktur strategi dengan fungsi mendapatkan data pasaran dan aset

Pasaran:img

Aset:img

Ia dapat dilihat bahawa selepas mendapatkan data pasaran, anda boleh memproses data untuk mengira harga spread setiap simbol, dan memantau harga spread spot berjangka beberapa pasangan dagangan. Dan kemudian anda boleh merancang strategi lindung nilai berjangka multi-simbol.

Menurut cara reka bentuk ini, platform lain juga boleh diperluaskan seperti ini, dan pelajar yang berminat boleh mencubanya.


Lebih lanjut