avatar of 发明者量化-小小梦 发明者量化-小小梦
konzentrieren Sie sich auf Private Nachricht
4
konzentrieren Sie sich auf
1271
Anhänger

Nutzen Sie die aggregierte Marktschnittstelle digitaler Währungsbörsen, um Strategien für mehrere Produkte zu entwickeln

Erstellt in: 2021-03-17 18:38:47, aktualisiert am: 2024-12-05 22:00:42
comments   13
hits   2466

Nutzen Sie die aggregierte Marktschnittstelle digitaler Währungsbörsen, um Strategien für mehrere Produkte zu entwickeln

Nutzen Sie die aggregierte Marktschnittstelle digitaler Währungsbörsen, um Strategien für mehrere Produkte zu entwickeln

FMZ Quantitative HandelsplattformAbschnitt „Strategieüberwachung“Es kommt häufig vor, dass Multiproduktstrategien gleichzeitig die Marktbedingungen von Dutzenden oder sogar des gesamten Marktes einer Börse überwachen. Wie wird das gemacht? Und wie soll es gestaltet sein? In diesem Artikel erfahren Sie, wie Sie mithilfe der börsenaggregierten Marktschnittstelle eine Strategie für mehrere Produkte entwickeln.

Nehmen wir Binance und Huobi als Beispiele und überprüfen wir deren API-Dokumente. Wir stellen fest, dass beide über Schnittstellen für aggregierte Marktinformationen verfügen:

Marktschnittstelle

  [
      {
          "symbol": "BTCUSDT", // 交易对
          "bidPrice": "4.00000000", //最优买单价
          "bidQty": "431.00000000", //挂单量
          "askPrice": "4.00000200", //最优卖单价
          "askQty": "9.00000000", //挂单量
          "time": 1589437530011   // 撮合引擎时间
      }
      ...
  ]
  [  
      {  
          "open":0.044297,      // 开盘价
          "close":0.042178,     // 收盘价
          "low":0.040110,       // 最低价
          "high":0.045255,      // 最高价
          "amount":12880.8510,  
          "count":12838,
          "vol":563.0388715740,
          "symbol":"ethbtc",
          "bid":0.007545,
          "bidSize":0.008,
          "ask":0.008088,
          "askSize":0.009
      }, 
      ...
  ]

Dies ist jedoch nicht der Fall. Die von der Huobi-Schnittstelle tatsächlich zurückgegebene Struktur lautet:

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

Gehen Sie bei der Verarbeitung der von der Schnittstelle zurückgegebenen Daten vorsichtig vor.

Aufbau eines Rahmens für politische Programme

Wie lassen sich diese beiden Schnittstellen in der Strategie kapseln und wie lassen sich die Daten verarbeiten? Schauen wir es uns gemeinsam an.

Schreiben wir zunächst einen Konstruktor zum Erstellen des Steuerobjekts.

// 参数e用于传入exchange交易所对象,参数subscribeList是需要处理的交易对列表,例如["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]
function createManager(e, subscribeList) {           
    var self = {}
    self.supportList = ["Futures_Binance", "Huobi"]  // 支持的交易所的

    // 对象属性
    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 = []                    // 接口获取的所有行情数据,定义数据格式:{bid1: 123, ask1: 123, symbol: "xxx"}}
    self.subscribeTickers = []           // 需要的行情数据,定义数据格式:{bid1: 123, ask1: 123, symbol: "xxx"}}
    self.accData = null                  // 用于记录账户资产数据

    // 初始化函数
    self.init = function() { 
    	// 判断是否支持该交易所
        if (!_.contains(self.supportList, self.name)) {        	
        	throw "not support"
        }
    }

    // 判断数据精度
    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
    }

    // 更新资产
    self.updateAcc = function(callBackFuncGetAcc) {
        var ret = callBackFuncGetAcc(self)
        if (!ret) {
        	return false 
        }
        self.accData = ret 
        return true 
    }

    // 更新行情数据
    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("错误:", 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("错误:", 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
    }

    // 初始化
    self.init()
	return self 
}

Verwenden der FMZ API-FunktionenHttpQueryDie Funktion sendet eine Anfrage für den Zugriff auf die Exchange-Schnittstelle. verwendenHttpQueryAusnahmebehandlung ist erforderlichtry...catchBehandeln Sie Ausnahmen wie etwa Fehler bei der Schnittstellenrückgabe. Einige Studierende fragen sich vielleicht: „Die von den Austauschschnittstellen zurückgegebenen Datenstrukturen sind unterschiedlich. Wie sollen wir damit umgehen? Es ist definitiv nicht möglich, dieselbe Verarbeitungsmethode zu verwenden.“ Tatsächlich ist nicht nur die von der Austauschschnittstelle zurückgegebene Datenstruktur unterschiedlich, sondern sogar die Benennung der zurückgegebenen Datenfelder ist unterschiedlich. Dieselbe Bedeutung kann unterschiedlich benannt werden. Beispielsweise die Schnittstellen, die wir oben aufgelistet haben. Derselbe Ausdruck gilt auch für den Kaufpreis, der wie folgt lautet:bidPrice, das heißtbid

Um diese speziellen Verarbeitungsteile voneinander zu trennen, verwenden wir hier Callback-Funktionen. Nachdem das obige Objekt initialisiert wurde, sieht es bei Verwendung folgendermaßen aus: (Der folgende Code lässt den Konstruktor auscreateManager) Überwachen Sie diese Verträge mit Binance Futures:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"] Huobi Spot überwacht diese Coin-to-Coin-Handelspaare:["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"]Zum Beispiel.

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) {
    	// 更新行情数据
    	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 : "期货行情数据",
        	cols : ["期货合约", "期货买一", "期货卖一"], 
        	rows : []
        }
        _.each(manager1.subscribeTickers, function(ticker) {
        	tbl1.rows.push([ticker.symbol, ticker.bid1, ticker.ask1])
        })
        var tbl2 = {
        	type : "table", 
        	title : "现货行情数据",
        	cols : ["现货合约", "现货买一", "现货卖一"], 
        	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)
    }
}

Führen Sie die Tests aus: Das erste Börsenobjekt fügt Binance-Futures hinzu, und das zweite Börsenobjekt fügt Huobi-Spot hinzu Nutzen Sie die aggregierte Marktschnittstelle digitaler Währungsbörsen, um Strategien für mehrere Produkte zu entwickeln

Nutzen Sie die aggregierte Marktschnittstelle digitaler Währungsbörsen, um Strategien für mehrere Produkte zu entwickeln

Es ist ersichtlich, dass hier die Vorgänge, wie beispielsweise das Abrufen der von der Schnittstelle zurückgegebenen Daten, für unterschiedliche Börsen speziell mithilfe von Rückruffunktionen verarbeitet 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}})

Nachdem wir die Marktinformationserfassung formuliert haben, können wir als nächstes die Kontovermögenserfassung formulieren. Aufgrund der Mehrproduktstrategie müssen auch die Kontovermögensdaten vielfältig sein. Glücklicherweise gibt die Vermögensschnittstelle des Börsenkontos im Allgemeinen alle Vermögensdaten zurück.

Im KonstruktorcreateManagerFügen Sie eine Methode zum Abrufen von Assets hinzu

    // 更新资产
    self.updateAcc = function(callBackFuncGetAcc) {
        var ret = callBackFuncGetAcc(self)
        if (!ret) {
        	return false 
        }
        self.accData = ret 
        return true 
    }

Aufgrund der unterschiedlichen Formate und Feldnamen, die von der Exchange-Schnittstelle zurückgegeben werden, sind für spezielle Verarbeitungen auch Rückruffunktionen erforderlich.

Am Beispiel von Huobi Spot und Binance Futures kann die Rückruffunktion wie folgt geschrieben werden:

    // 获取账户资产的回调函数
    var callBackFuncGetHuobiAcc = function(self) {
        var account = self.e.GetAccount()
        var ret = []
        if (!account) {
        	return false 
        }
        // 构造资产的数组结构
        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")   // 设置为U本位合约的交易对
        self.e.SetContractType("swap")   // 合约都是永续合约
        var account = self.e.GetAccount() 
        var ret = []
        if (!account) {
        	return false 
        }
        var balance = account.Balance
        var frozenBalance = account.FrozenBalance
        // 构造资产数据结构
        _.each(self.subscribeList, function(symbol) {
            var acc = {symbol: symbol}
            acc.Balance = balance
            acc.FrozenBalance = frozenBalance
            ret.push(acc)
        })
        return ret 
    }

Führen Sie einen Strategierahmen mit der Funktion, Marktinformationen und Vermögenswerte zu erhalten.

Zitate: Nutzen Sie die aggregierte Marktschnittstelle digitaler Währungsbörsen, um Strategien für mehrere Produkte zu entwickeln

Vermögenswerte: Nutzen Sie die aggregierte Marktschnittstelle digitaler Währungsbörsen, um Strategien für mehrere Produkte zu entwickeln

Es ist ersichtlich, dass nach dem Erhalt der Marktdaten die Daten verarbeitet werden können, um die Preisdifferenz jeder Sorte zu berechnen und die Spot-Futures-Preisdifferenz mehrerer Handelspaare zu überwachen. Anschließend kann eine vielfältige Futures- und Spot-Hedging-Strategie entwickelt werden.

Nach dieser Gestaltungsmethode können auch andere Austausche ausgebaut werden. Interessierte Studierende können es ausprobieren.