Nutzen Sie die aggregierte Marktoberfläche der Kryptowährungsplattform, um eine Multi-Symbol-Strategie zu erstellen

Schriftsteller:- Ich bin ein Idiot., Erstellt: 2022-04-24 17:34:03, Aktualisiert:

Nutzen Sie die aggregierte Marktoberfläche der Kryptowährungsplattform, um eine Multi-Symbol-Strategie zu erstellen

In der Rubrik [Live] (https://www.fmz.com/liveIn diesem Artikel wird Ihnen gezeigt, wie Sie die Plattform-aggregierte Marktoberfläche verwenden, um eine Multi-Symbol-Strategie zu erstellen.

Nehmen Sie Binance und Huobi zum Beispiel; wenn Sie sich ihre API-Dokumentation ansehen, werden Sie feststellen, dass es aggregierte Schnittstellen gibt:

Marktschnittstelle

  • Binance-Vertrag:https://fapi.binance.com/fapi/v1/ticker/bookTickerDie von der Schnittstelle zurückgegebenen Daten:

    [
        {
            "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/tickersDie von der Schnittstelle zurückgegebenen Daten:

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

    Das Ergebnis ist jedoch eigentlich nicht so, und die tatsächliche Struktur, die von der Huobi-Schnittstelle zurückgegeben wird, ist:

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

    Bei der Verarbeitung der von der Schnittstelle zurückgegebenen Daten ist Vorsicht geboten.

Konstruktion von Strategieprogrammen

Wie sollen die beiden Schnittstellen in die Strategie einfließen und wie sollen die Daten verarbeitet werden? Lasst uns mal sehen.

Zuerst schreiben Sie einen Konstruktor, um Kontrollobjekte zu konstruieren

// 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 
}

Funktion FMZ API verwendenHttpQuerySie können auch eine Anfrage zum Zugriff auf die Plattformoberfläche senden.HttpQuery, müssen Sie die Ausnahmeverarbeitung verwendentry...catchUm mit Ausnahmen wie z. B. Interface-Return-Fehlern umzugehen. Einige Studenten hier mögen fragen: Die Datenstrukturen, die von den Plattformschnittstellen zurückgegeben werden, sind sehr unterschiedlich, also wie geht man damit um?Es muss nicht möglich sein, die gleiche Verarbeitungsmethode zu verwenden In der Tat unterscheiden sich nicht nur die von der Plattformoberfläche zurückgegebenen Datenstrukturen, sondern auch die Namen der zurückgegebenen Datenfelder. Die gleiche Bedeutung kann unterschiedlich benannt werden. Zum Beispiel die oben aufgeführten Schnittstellen. Der gleiche Ausdruck bedeutet Buy1 Preis, der als:bidPricein Binance, aberbidin Huobi.

Wir verwenden die Rückruffunktion hier und trennen diese Teile, die eine spezielle Bearbeitung benötigen, unabhängig voneinander. Nachdem also das obige Objekt initialisiert wurde, wird es in der spezifischen Verwendung so: (Der folgende Code entzieht den KonstruktorcreateManager) von Binance Futures überwachte Verträge:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]von Huobi Spot überwachte Spot-Trading-Paare:["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)
    }
}

Betriebsprüfung: Binance Futures als erstes Austauschobjekt und Huobi Spot als zweites Austauschobjekt.
img

img

Wie Sie sehen können, wird hier die Callback-Funktion aufgerufen, um spezialisierte Verarbeitung von Operationen auf verschiedenen Plattformen durchzuführen, wie zum Beispiel, wie die von der Schnittstelle zurückgegebenen Daten erhalten werden.

    	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}})

Nach der Gestaltung der Methode zur Erfassung der Marktdaten können wir eine Methode zur Erfassung der Marktdaten erstellen. Da es sich um eine Multi-Symbol-Strategie handelt, sind die Kontovermögensdaten auch mehrfach.

Hinzufügen der Methode zur Erlangung von Vermögenswerten im KonstruktorcreateManager:

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

Ähnlich, für die von verschiedenen Plattform-Schnittstellen zurückgegebenen Formate und die Feldnamen sind unterschiedlich, hier müssen wir die Callback-Funktion verwenden, um eine spezielle Verarbeitung durchzuführen.

Nehmen wir Huobi Spot und Binance Futures als Beispiele, und die Rückruffunktion kann so geschrieben werden:

    // 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 
    }

Funktionieren der Strategiestruktur mit der Funktion der Erfassung von Marktdaten und Vermögenswerten

Markt:img

Vermögenswerteimg

Es kann gesehen werden, dass Sie nach Erhalt der Marktdaten die Daten verarbeiten können, um den Preisspread jedes Symbols zu berechnen und den Futures-Spot-Preisspread mehrerer Handelspare zu überwachen. Und dann können Sie eine Multi-Symbol-Futures-Hedging-Strategie entwerfen.

Nach dieser Art des Entwurfs können auch andere Plattformen so erweitert werden, und die interessierten Studenten können es ausprobieren.


Mehr