Type/to search
8
Follow
1364
Followers
デジタル通貨取引所の集約された市場インターフェースを使用して、マルチプロダクト戦略を構築する
Discussions
Created 2021-03-17 18:38:47  Updated 2024-12-05 22:00:42
 13
 2819

img

デジタル通貨取引所の集約された市場インターフェースを使用して、マルチプロダクト戦略を構築する

FMZ 定量取引プラットフォーム戦略ウォッチセクション数十の取引所、あるいは取引所全体の市場状況を同時に監視するマルチプロダクト戦略がよく見られます。これはどうやって行うのですか?そして、どのように設計すればよいのでしょうか?この記事では、取引所の集約市場インターフェースを使用してマルチプロダクト戦略を構築する方法について説明します。

Binance と Huobi を例に、API ドキュメントを確認してください。どちらも集約された市場情報インターフェースを備えていることがわかります。

マーケットインターフェース

  • Binance先物:
    https://fapi.binance.com/fapi/v1/ticker/bookTicker
    インターフェースの戻りデータ

    [ { "symbol": "BTCUSDT", // 交易对 "bidPrice": "4.00000000", //最优买单价 "bidQty": "431.00000000", //挂单量 "askPrice": "4.00000200", //最优卖单价 "askQty": "9.00000000", //挂单量 "time": 1589437530011 // 撮合引擎时间 } ... ]
  • Huobiの現在の通貨コイン:
    https://api.huobi.pro/market/tickers
    インターフェースの戻りデータ

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

    しかし、そうではありません。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 つのインターフェースを戦略にカプセル化し、データを処理するにはどうすればよいでしょうか。
一緒に見てみましょう。

まず、コントロール オブジェクトを構築するためのコンストラクターを記述します。

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

FMZ API関数の使用HttpQueryこの関数は、交換インターフェースにアクセスするための要求を送信します。使用HttpQuery例外処理が必要ですtry...catchインターフェースの戻りエラーなどの例外を処理します。
学生の中には、「交換インターフェースによって返されるデータ構造が異なります。どのように対処すればよいでしょうか。同じ処理方法を使用することは絶対に不可能です。」と質問する人もいます。
実際、交換インターフェースによって返されるデータ構造が異なるだけでなく、返されるデータ フィールドの名前も異なります。同じ意味であっても、異なる名前で呼ばれることがあります。たとえば、上記に挙げたインターフェース。同じ表現は購入価格を意味し、次のように呼ばれます。bidPrice、これはbid

ここでは、コールバック関数を使用して、これらの特別な処理部分を分離します。
したがって、上記のオブジェクトを初期化した後、使用すると次のようになります。
(次のコードではコンストラクタを省略していますcreateManager
Binance Futures でこれらの契約を監視します:["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) { // 更新行情数据 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) } }

テストを実行します。
最初の取引所オブジェクトはBinance先物を追加し、2番目の取引所オブジェクトはHuobiスポットを追加します。
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アセットを取得するメソッドを追加する

// 更新资产 self.updateAcc = function(callBackFuncGetAcc) { var ret = callBackFuncGetAcc(self) if (!ret) { return false } self.accData = ret return true }

また、交換インターフェースによって返される形式やフィールド名が異なるため、特別な処理にはコールバック関数も必要です。

Huobi スポットと Binance 先物を例にとると、コールバック関数は次のように記述できます。

// 获取账户资产的回调函数 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 }

市場情報や資産を取得する機能を備えた戦略フレームワークを実行します

引用:
img

資産:
img

市場データを取得した後、そのデータを処理して各品種の価格差を計算し、複数の取引ペアのスポットと先物の価格差を監視できることがわかります。
その後、多種多様な先物およびスポットヘッジ戦略を設計できます。

この設計方法によれば、他の交流も拡大することができます。興味のある学生は試してみることができます。

Related Recommendations
Comment
All comments (13)

    更新资产里面的callBackFuncGetAcc是个参数,还是个函数呀?另外获取资产账户的两个回调函数callBackFuncGetHuobiAcc和callBackFuncGetFutures_BinanceAcc与callBackFuncGetAcc什么关系?我感觉是函数里面套函数,这块的知识哪里学习?

    5 years ago

    百度回调函数。

    5 years ago

    请问期现差价时,如何同时提取一个交易对的现货Bid1与期货Ask1的价格?

    5 years ago

    你看代码里买一、卖一都有数据的。

    5 years ago

    我看到了,但是没有统一指定同一交易对

    5 years ago

    没明白你的意思。

    5 years ago

    文章中获取期现差价的图怎么没公布源码呀?

    5 years ago

    这个具体编写就行了,买一卖一都有了,差价不就是相互减一下。

    5 years ago

    我的思路你看对不对?假如要获取BTCUSDT现货买一价和BTCUSDT期货卖一价的差价:首先遍历期货行情数组manager1.subscribeTickers,找出BTCUSDT的卖一价manager1.subscribeTickers[i].ask1,问题是如何在期货遍历数组进行时如何提取现货BTCUSDT的bid1价格,难道再间套遍历下现货行情数组manager1.subscribeTickers?不知道老师您明白我的问题了吗?

    5 years ago

    就是两个循环套着,遍历。

    5 years ago

    我的意思是期货与现货的差价,不是期货或现货买一卖一的差价;碰到的问题是,不能同时获取同一交易对期货买一价和现货的卖一价。比如:如何获取BTCUSDT现货买一价和BTCUSDT期货卖一价的差价。我写了下,下面代码不知道问题出在哪里?
    function GetBAspot(syboml,tickerspot,BA){
    for (var i = 0; i < tickerspot.length; i++) {
    if(tickerspot[i].syboml!==syboml){
    continue
    }else
    if(tickerspot[i].syboml===syboml){
    var bidspot=tickerspot[i].bid1
    var askspot=tickerspot[i].ask1
    }
    }
    if(BA==="bid")return bidspot
    if(BA==="ask")return askspot
    }
    function main(){
    _.each(manager1.subscribeTickers, 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")])
    })
    }

    5 years ago

    我给你说的就是现货和期货的差价,文章上不是都截图了,期现差价。
    数据都有了,具体怎么算,你减一下不就有了么。

    5 years ago

    厉害

    5 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)