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 문서를 확인해 보세요. 둘 다 통합된 시장 정보 인터페이스를 가지고 있다는 것을 알 수 있습니다.

마켓 인터페이스

  • 바이낸스 선물:
    https://fapi.binance.com/fapi/v1/ticker/bookTicker
    인터페이스 반환 데이터

    [ { "symbol": "BTCUSDT", // 交易对 "bidPrice": "4.00000000", //最优买单价 "bidQty": "431.00000000", //挂单量 "askPrice": "4.00000200", //最优卖单价 "askQty": "9.00000000", //挂单量 "time": 1589437530011 // 撮合引擎时间 } ... ]
  • 후오비 현재 통화 코인:
    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 }, ...] }

    인터페이스에서 반환된 데이터를 처리할 때는 주의하세요.

정책 프로그램 프레임워크 구축

이 두 인터페이스를 전략에 캡슐화하는 방법과 데이터를 처리하는 방법은 무엇입니까?
함께 살펴보도록 하겠습니다.

먼저, 제어 객체를 구성하는 생성자를 작성해 보겠습니다.

// 参数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 Futures를 추가하고 두 번째 거래소 객체는 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자산을 가져오는 방법 추가

// 更新资产 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)