Trong phần [
Hãy lấy Binance và Huobi làm ví dụ; nếu bạn kiểm tra tài liệu API của họ, bạn sẽ thấy có các giao diện tổng hợp:
Hợp đồng Binance:https://fapi.binance.com/fapi/v1/ticker/bookTickerDữ liệu được trả về giao diện:
[
{
"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/tickersDữ liệu được trả về giao diện:
[
{
"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
},
...
]
Tuy nhiên, kết quả thực sự không giống như vậy, và cấu trúc thực tế được trả về bởi giao diện Huobi là:
{
"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
}, ...]
}
Cần chú ý khi xử lý dữ liệu được trả về bởi giao diện.
Làm thế nào để gói gọn hai giao diện trong chiến lược, và làm thế nào để xử lý dữ liệu? Hãy xem xem.
Đầu tiên, viết một constructor, để xây dựng các đối tượng điều khiển
// 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
}
Sử dụng hàm FMZ APIHttpQuery
để gửi một yêu cầu truy cập giao diện nền tảng.HttpQuery
, bạn cần sử dụng xử lý ngoại lệtry...catch
để xử lý các ngoại lệ như lỗi trả về giao diện.
Một số sinh viên ở đây có thể hỏi: bidPrice
trong Binance, nhưngbid
ở Huobi.
Chúng tôi sử dụng chức năng gọi lại ở đây và tách những phần cần xử lý chuyên môn một cách độc lập.
Vì vậy, sau khi đối tượng trên được khởi tạo, nó trở thành như thế này trong việc sử dụng cụ thể:
(Mật mã sau bỏ qua các nhà xây dựngcreateManager
)
các hợp đồng được Binance Futures giám sát:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]
Các cặp giao dịch tại chỗ được theo dõi bởi 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)
}
}
Xét nghiệm hoạt động:
Thêm Binance Futures làm đối tượng trao đổi đầu tiên, và thêm Huobi Spot làm đối tượng trao đổi thứ hai.
Như bạn có thể thấy, ở đây hàm callback được gọi để thực hiện xử lý chuyên biệt trên các hoạt động trên các nền tảng khác nhau, như cách lấy dữ liệu được trả về bởi giao diện.
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}})
Sau khi thiết kế phương pháp thu thập dữ liệu thị trường, chúng ta có thể tạo ra một phương pháp thu thập dữ liệu thị trường. Vì nó là một chiến lược đa biểu tượng, dữ liệu tài sản tài khoản cũng là nhiều. May mắn thay, giao diện tài sản tài khoản nền tảng thường trả về dữ liệu tài sản đầy đủ.
Thêm phương pháp để có được tài sản trong constructorcreateManager
:
// update assets
self.updateAcc = function(callBackFuncGetAcc) {
var ret = callBackFuncGetAcc(self)
if (!ret) {
return false
}
self.accData = ret
return true
}
Tương tự như vậy, đối với các định dạng được trả về bởi các giao diện nền tảng khác nhau và tên trường khác nhau, ở đây chúng ta cần sử dụng hàm callback để thực hiện xử lý chuyên biệt.
Hãy lấy Huobi Spot và Binance Futures làm ví dụ, và hàm callback có thể được viết như thế này:
// 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
}
Thị trường:
Tài sản:
Có thể thấy rằng sau khi có được dữ liệu thị trường, bạn có thể xử lý dữ liệu để tính chênh lệch giá của mỗi biểu tượng, và theo dõi chênh lệch giá tương lai tại chỗ của nhiều cặp giao dịch. Và sau đó bạn có thể thiết kế một chiến lược bảo hiểm tương lai đa biểu tượng.
Theo cách thiết kế này, các nền tảng khác cũng có thể được mở rộng như thế này, và những sinh viên quan tâm có thể thử nó.