クリプト通貨プラットフォームの総合市場インターフェースを使用して,マルチシンボル戦略を構築する

作者: リン・ハーンニナバダス作成日:2022-04-24 17:34:03 更新日:

クリプト通貨プラットフォームの総合市場インターフェースを使用して,マルチシンボル戦略を構築する

[ライブ] (https://www.fmz.com/liveFMZ Quant トレーディング プラットフォームでは,マルチシンボルの戦略がしばしば見られ,同時に数十のシンボル,または全体的なプラットフォームの市場状況を検出することができます. どのように実行されますか? どのように設計されるべきですか? この記事では,マルチシンボルの戦略を構築するためにプラットフォームの総市場インターフェースを使用する方法について議論します.

例えばBinanceとHuobiを例に挙げると,APIのドキュメントをチェックすると,

市場インターフェース

  • バイナンス契約:https://fapi.binance.com/fapi/v1/ticker/bookTickerインタフェースから返されるデータ:

    [
        {
            "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 
        }
        ...
    ]
    
  • ハウビースポット:https://api.huobi.pro/market/tickersインタフェースから返されるデータ:

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

    Huobi インターフェイスが返した実際の構造は以下の通りです.

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

    インターフェースで返されるデータを処理する際には注意が必要です.

戦略プログラム構造を構築する

どうやって2つのインターフェースを 戦略に組み込むのか? どうやってデータを処理するのか? 見てみよう

コントロールオブジェクトを構成するコンストラクタを書きます

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

FMZ API 関数を使用するHttpQueryプラットフォームインターフェースにアクセスする要求を送信します.HttpQuery,例外処理を使用する必要があります.try...catchインターフェースの返却失敗などの例外を処理する. プラットフォームインターフェースが返したデータ構造はかなり異なっています.それではどう対処しますか?同じ処理方法を使用することは不可能です. 実際,プラットフォームインターフェイスが返したデータ構造が異なるだけでなく,返したデータフィールドの名前も異なる.同じ意味が異なる名前になることもあります.例えば,上記のインターフェースです.同じ表現はbuy1価格を意味します.bidPriceバイナンスでもbidHuobiで

特殊処理を必要とする部品を 独立して分離します 特殊処理が必要な部品を 独立して分離します 特定の用途ではこんな感じになります. 特定の用途ではこんな感じになります. (次のコードはコンストラクタを省略しています.createManager) について バイナンス・フューチャーズによって監視されている契約:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]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)
    }
}

動作試験: 最初の交換オブジェクトとしてBinance Futuresを追加し,第2の交換オブジェクトとしてHuobi Spotを追加します.
img

img

インターフェースで返されたデータを取得する方法のように 異なるプラットフォームの操作の特殊処理を行うために呼び出されます.

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

市場データを入手する方法を設計した後,市場データを入手する方法を作成できます.マルチシンボル戦略であるため,アカウント資産データも複数です. 幸いにも,プラットフォームアカウント資産インターフェースは一般的に完全な資産データを返します.

コンストラクタで資産を取得する方法を追加するcreateManager:

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

同じように,異なるプラットフォームインターフェイスが返したフォーマットとフィールド名が異なる場合,ここでは特殊処理を行うためにコールバック関数を使用する必要があります.

コールバック関数はこう書ける:

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

市場データと資産の取得の機能を持つ戦略構造を運用する

市場:img

資産:img

各シンボルの価格のスプレッドを計算し,複数の取引ペアの先物価格のスプレッドを監視できます. 複数のシンボルのフューチャー・ヘッジ戦略を 設計できます

興味のある生徒が試すことができます. デザインの方法としては,


もっと