[
예를 들어 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
인터페이스 반환 실패와 같은 예외를 처리하기 위해
여기서 어떤 학생들은 질문할 수 있습니다: bidPrice
바이낸스에서, 하지만bid
Huobi에서.
우리는 여기서 콜백 기능을 사용해서 전문적인 처리가 필요한 부분들을 분리합니다.
그래서 위의 객체가 초기화되면, 특정 용도로는 이렇게 됩니다.
(다음 코드는 생성자를 생략합니다.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를 추가합니다.
보시다시피, 여기서 콜백 함수는 인터페이스에 의해 반환된 데이터를 얻는 것과 같은 다른 플랫폼의 작업에 대한 특수 처리 작업을 수행하기 위해 호출됩니다.
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
}
시장:
자산:
시장 데이터를 얻은 후 각 기호의 가격 스프레드를 계산하고 여러 거래 쌍의 선물-스팟 가격 스프레드를 모니터링 할 수 있습니다. 그리고 여러분은 다중 기호의 선물 헤지 전략을 설계할 수 있습니다.
이런 디자인 방식에 따라 다른 플랫폼도 이렇게 확장될 수 있고, 관심 있는 학생들이 시도할 수 있습니다.