Menggunakan Platform Cryptocurrency Aggregated Market Interface untuk Membangun Strategi Multi-Simbol

Penulis:Ninabadass, Dibuat: 2022-04-24 17:34:03, Diperbarui:

Menggunakan Platform Cryptocurrency Aggregated Market Interface untuk Membangun Strategi Multi-Simbol

Di bagian [Live] (https://www.fmz.com/liveDalam hal ini, Anda dapat melihat strategi multi-simbol yang dapat mendeteksi kondisi pasar dari lusinan simbol atau bahkan seluruh platform pada saat yang sama. Bagaimana hal itu dilakukan? Dan bagaimana harus dirancang? Artikel ini membawa Anda untuk membahas bagaimana menggunakan antarmuka pasar agregat platform untuk membangun strategi multi-simbol.

Ambil Binance dan Huobi sebagai contoh; jika Anda memeriksa dokumentasi API mereka, Anda akan menemukan ada antarmuka agregat:

Antarmuka Pasar

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

    [
        {
            "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 antarmuka:

    [  
        {  
            "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
        }, 
        ...
    ]
    

    Namun, hasilnya sebenarnya tidak seperti itu, dan struktur yang sebenarnya dikembalikan oleh antarmuka 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 saat memproses data yang dikembalikan oleh antarmuka.

Membangun Struktur Program Strategi

Bagaimana untuk merangkum dua antarmuka dalam strategi, dan bagaimana untuk memproses data? Mari kita lihat.

Pertama, menulis constructor, untuk membangun kontrol objek

// 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 mengirim permintaan untuk mengakses antarmuka platform.HttpQuery, Anda perlu menggunakan exception processingtry...catchuntuk menangani pengecualian seperti kegagalan interface return. Beberapa siswa di sini mungkin bertanya: Struktur data yang dikembalikan oleh antarmuka platform sangat berbeda, jadi bagaimana mengatasinya? Memang, tidak hanya struktur data yang dikembalikan oleh antarmuka platform yang berbeda, tetapi juga nama-nama bidang data yang dikembalikan juga berbeda. Makna yang sama dapat dinamai secara berbeda. Misalnya antarmuka yang kami cantumkan di atas.bidPricedi Binance, tapibiddi Huobi.

Kami menggunakan fungsi callback di sini dan memisahkan bagian-bagian yang membutuhkan pemrosesan khusus secara independen. Jadi setelah objek di atas diinitialisasi, itu menjadi seperti ini dalam penggunaan spesifik: (Kode berikut menghilangkan konstruktorcreateManager) kontrak yang dipantau oleh Binance Futures:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]Pasangan perdagangan 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)
    }
}

Tes operasi: Tambahkan Binance Futures sebagai objek pertukaran pertama, dan tambahkan Huobi Spot sebagai objek pertukaran kedua.
img

img

Seperti yang Anda lihat, di sini fungsi callback dipanggil untuk melakukan pemrosesan khusus pada operasi di platform yang berbeda, seperti cara mendapatkan data yang dikembalikan oleh antarmuka.

    	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 mendesain metode untuk mendapatkan data pasar, kita dapat membuat metode untuk mendapatkan data pasar. Karena ini adalah strategi multi-simbol, data aset akun juga banyak. Untungnya, antarmuka aset akun platform umumnya mengembalikan data aset penuh.

Tambahkan metode untuk mendapatkan aset dalam konstruktorcreateManager:

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

Demikian pula, untuk format yang dikembalikan oleh antarmuka platform yang berbeda dan nama bidang yang berbeda, di sini kita perlu menggunakan fungsi callback untuk melakukan pemrosesan khusus.

Ambil Huobi Spot dan Binance Futures sebagai contoh, dan fungsi callback dapat 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 
    }

Mengoperasikan Struktur Strategi dengan Fungsi Mendapatkan Data Pasar dan Aset

Pasar:img

Aktif:img

Hal ini dapat dilihat bahwa setelah memperoleh data pasar, Anda dapat memproses data untuk menghitung spread harga dari setiap simbol, dan memantau spread harga spot futures dari beberapa pasangan perdagangan. Dan kemudian Anda dapat merancang strategi hedging berjangka multi-simbol.

Menurut cara desain ini, platform lain juga dapat diperluas seperti ini, dan siswa yang tertarik dapat mencobanya.


Lebih banyak