Sử dụng giao diện thị trường tổng hợp nền tảng tiền điện tử để xây dựng chiến lược đa biểu tượng

Tác giả:Ninabadass, Tạo: 2022-04-24 17:34:03, Cập nhật:

Sử dụng giao diện thị trường tổng hợp nền tảng tiền điện tử để xây dựng chiến lược đa biểu tượng

Trong phần [Live] (https://www.fmz.com/liveTrong bài viết này, chúng ta sẽ thảo luận về cách sử dụng giao diện thị trường tổng hợp nền tảng để xây dựng một chiến lược đa biểu tượng.

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:

Giao diện thị trường

  • 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.

Xây dựng cấu trúc chương trình chiến lược

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: Cấu trúc dữ liệu được trả về bởi các giao diện nền tảng khá khác nhau, vậy làm thế nào để giải quyết nó? Trong thực tế, không chỉ các cấu trúc dữ liệu được trả về bởi giao diện nền tảng là khác nhau, mà cả tên của các trường dữ liệu được trả về cũng khác nhau.bidPricetrong 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.
img

img

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 
    }

Hoạt động cấu trúc chiến lược với chức năng thu thập dữ liệu thị trường và tài sản

Thị trường:img

Tài sản:img

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ó.


Thêm nữa