FMZ Platform Perdagangan KuantitatifStrategi PengamatanDalam artikel ini, kita akan membahas tentang bagaimana membangun strategi multi-varietas dengan menggunakan antarmuka pasar agregat.
Setelah daftar kedua bursa tersebut dan melihat dokumen API bursa, kita menemukan bahwa keduanya memiliki antarmuka pasar agregat:
Di sini, Anda dapat melihat beberapa contoh.https://fapi.binance.com/fapi/v1/ticker/bookTickerAntarmuka mengembalikan data
[
{
"symbol": "BTCUSDT", // 交易对
"bidPrice": "4.00000000", //最优买单价
"bidQty": "431.00000000", //挂单量
"askPrice": "4.00000200", //最优卖单价
"askQty": "9.00000000", //挂单量
"time": 1589437530011 // 撮合引擎时间
}
...
]
Bitcoin adalah mata uang tunai:https://api.huobi.pro/market/tickersAntarmuka mengembalikan data
[
{
"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
},
...
]
Namun, tidak demikian, struktur yang sebenarnya dikembalikan oleh antarmuka token adalah:
{
"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
}, ...]
}
Perhatian diperlukan saat memproses data yang dikembalikan oleh antarmuka.
Bagaimana cara membungkus dua antarmuka ini dalam strategi dan bagaimana menangani data? Mari kita lihat secara perlahan-lahan.
Pertama, tulislah constructor yang digunakan untuk membangun objek kontrol.
// 参数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
}
Fungsi API menggunakan FMZHttpQuery
Fungsi mengirim permintaan, mengakses antarmuka pertukaran.HttpQuery
Menggunakan penanganan yang tidak wajartry...catch
Mengatasi keanehan seperti kegagalan kembali antarmuka.
Beberapa siswa yang melihat ini mungkin bertanya: bagaimana dengan struktur data yang dikembalikan oleh antarmuka bursa yang berbeda?
Memang demikian, tidak hanya struktur data yang dikembalikan oleh antarmuka pertukaran yang berbeda, bahkan nama bidang data yang dikembalikan juga berbeda. Sebuah arti yang sama mungkin memiliki nama yang berbeda. Misalnya antarmuka yang kami daftarkan di atas.bidPrice
Ini adalah sebuah token yang disebutbid
。
Kami menggunakan fungsi callback untuk menyelesaikan, memisahkan bagian dari proses khusus ini.
Setelah initialization objek di atas, penggunaan spesifiknya akan menjadi seperti ini:
(Kode di bawah ini menghilangkan fungsi pembangun)createManager
Tidak ada.
Di bawah ini adalah daftar kontrak yang dapat dipantau dengan Bitcoin futures:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]
Bitcoin Cash memantau transaksi koin ini:["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"]
Contoh:
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)
}
}
Percobaan berjalan: Objek bursa pertama menambahkan futures koin, dan objek bursa kedua menambahkan token tunai
Seperti yang dapat dilihat, di sini, operasi seperti mengambil data yang dikembalikan antarmuka digunakan untuk memproses spesialisasi bursa yang berbeda menggunakan fungsi panggilan kembali.
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}})
Setelah penentuan pasar, maka penentuan aset akun dapat dilakukan, karena strategi multi-varietas, data aset akun juga harus berjumlah banyak.
Fungsi konstruksicreateManager
Tambahkan metode untuk mendapatkan aset
// 更新资产
self.updateAcc = function(callBackFuncGetAcc) {
var ret = callBackFuncGetAcc(self)
if (!ret) {
return false
}
self.accData = ret
return true
}
Juga karena format yang dikembalikan oleh antarmuka pertukaran, penamaan bidang bervariasi, di sini juga memerlukan pemrosesan spesialisasi menggunakan fungsi panggilan kembali.
Dengan menggunakan token cash, bitcoin futures sebagai contoh, kita bisa menulis fungsi callback seperti ini:
// 获取账户资产的回调函数
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
}
Pernyataan:
Aset:
Setelah mendapatkan data pasar, data dapat diproses untuk menghitung perbedaan dari berbagai varietas dan memantau perbedaan masa depan dari beberapa pasangan transaksi. Dengan demikian, strategi hedging futures yang beragam dapat dirancang.
Dengan desain seperti ini, kita dapat memperluas ke bursa lain, dan siswa yang tertarik dapat mencoba sendiri.
Cintai JimmyApakah callBackFuncGetAcc yang ada di dalam aset adalah parameter atau fungsi? Ada dua fungsi callback lainnya untuk mendapatkan akun aset yaitu callBackFuncGetHuobiAcc dan callBackFuncGetFutures_BinanceAcc.
Cintai JimmyBagaimana cara mengambil harga Bid1 dan Ask1 dari pasangan perdagangan saat harga futures berbeda?
ZltimSangat bagus.
Penemu Kuantitas - Mimpi KecilFungsi panggilan balik Baudagram.
Penemu Kuantitas - Mimpi KecilDi sini kita bisa melihat dua lingkaran yang saling terhubung dan melintasi.
Penemu Kuantitas - Mimpi KecilSaya memberi tahu Anda tentang perbedaan harga saham dan futures, bukan semua gambar di artikel ini, harga futures. Jika Anda memiliki data, bagaimana cara menghitungnya, apakah Anda mengurangi atau tidak?
Cintai JimmyJika Anda ingin mendapatkan perbedaan antara harga beli BTCUSDT dan harga jual BTCUSDT, Anda harus terlebih dahulu menjelajahi Arsitektur Manajer 1.subscribeTickers, cari tahu Arsitektur Manajer 1.subscribeTickers[i].ask1.
Cintai JimmySaya maksudkan selisih futures vs. spot, bukan selisih futures atau spot buy/sell; masalah yang saya hadapi adalah, tidak mungkin untuk mendapatkan harga jual dan harga beli futures pada saat yang sama. fungsi GetBAspot ((syboml, tickerspot, BA) { for (var i = 0; i < tickerspot.length; i++) { if ((tickerspot[i].syboml!==syboml) {) lanjutkan }else if ((tickerspot[i].syboml===syboml) { var bidspot=tickerspot[i].bid1 var askspot=tickerspot[i].ask1 Aku tidak tahu. Aku tidak tahu. if ((BA==="bid") return bidspot if ((BA==="ask") return askspot Aku tidak tahu. fungsi main (() { _.each ((manager1.subscribe Tickers, function ((ticker)) { var symb=ticker.symbol var symb1=manager1.symFuturesToSpot (symb) tbl1.rows.push (([ticker.symbol, ticker.bid1, ticker.ask1, manager1.Getfundingrate ((symb), manager1.Getrealrate ((symb, 50), GetBAspot ((symb1, SpotTickers, "ask"))))) Aku tidak tahu. Aku tidak tahu.
Penemu Kuantitas - Mimpi Kecil"Sebenarnya, saya tidak bisa mengatakan apa-apa, saya hanya ingin mengatakan bahwa saya tidak tahu apa-apa", katanya.
Cintai JimmyMengapa tidak ada sumber dari gambar yang diperoleh dari artikel ini?
Penemu Kuantitas - Mimpi KecilSaya tidak mengerti apa yang Anda maksudkan.
Cintai JimmySaya lihat, tapi tidak ada satuan yang menentukan pasangan transaksi yang sama.
Penemu Kuantitas - Mimpi KecilJika Anda melihat kode, Anda akan melihat bahwa ada data untuk membeli dan menjual.