가상화폐 플랫폼 집계 시장 인터페이스를 사용하여 다중 기호 전략을 구성합니다.

저자:니나바다스, 창작: 2022-04-24 17:34:03, 업데이트:

가상화폐 플랫폼 집계 시장 인터페이스를 사용하여 다중 기호 전략을 구성합니다.

[Live 섹션] (https://www.fmz.com/liveFMZ 퀀트 트레이딩 플랫폼의 경우, 다중 기호 전략이 종종 볼 수 있으며, 이는 수십 개의 기호 또는 심지어 전체 플랫폼의 시장 조건을 동시에 감지 할 수 있습니다. 어떻게 수행됩니까? 그리고 어떻게 설계되어야합니까? 이 기사는 다중 기호 전략을 구축하기 위해 플랫폼 집계 시장 인터페이스를 사용하는 방법을 논의합니다.

예를 들어 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 
        }
        ...
    ]
    
  • Huobi 스팟: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
        }, ...]
    }
    

    인터페이스에서 반환된 데이터를 처리할 때 주의가 필요합니다.

전략 프로그램 구조를 구축

어떻게 두 인터페이스를 전략에 포괄하고 데이터를 처리할 수 있을까요? 좀 봐보자

먼저, 컨트롤 객체를 구성하기 위해 구성자를 작성

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

작동 테스트: 첫 번째 거래소 객체로 바이낸스 퓨처스를 추가하고 두 번째 거래소 객체로 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 
    }

마찬가지로, 서로 다른 플랫폼 인터페이스에서 반환된 형식과 필드 이름이 다르기 때문에 여기서 우리는 특수 처리를 위해 콜백 함수를 사용해야합니다.

Huobi Spot와 Binance Futures를 예로 들자면 콜백 함수는 다음과 같이 쓸 수 있습니다.

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

시장 데이터를 얻은 후 각 기호의 가격 스프레드를 계산하고 여러 거래 쌍의 선물-스팟 가격 스프레드를 모니터링 할 수 있습니다. 그리고 여러분은 다중 기호의 선물 헤지 전략을 설계할 수 있습니다.

이런 디자인 방식에 따라 다른 플랫폼도 이렇게 확장될 수 있고, 관심 있는 학생들이 시도할 수 있습니다.


더 많은