avatar of 发明者量化-小小梦 发明者量化-小小梦
fokus pada mesej peribadi
4
fokus pada
1271
Pengikut

Gunakan antara muka pasaran agregat pertukaran mata wang digital untuk membina strategi berbilang produk

Dicipta dalam: 2021-03-17 18:38:47, dikemas kini pada: 2024-12-05 22:00:42
comments   13
hits   2466

Gunakan antara muka pasaran agregat pertukaran mata wang digital untuk membina strategi berbilang produk

Gunakan antara muka pasaran agregat pertukaran mata wang digital untuk membina strategi berbilang produk

Platform Dagangan Kuantitatif FMZBahagian Pemerhatian StrategiAdalah perkara biasa untuk melihat beberapa strategi berbilang produk yang memantau keadaan pasaran berpuluh-puluh atau bahkan keseluruhan pasaran bursa secara serentak. Bagaimana ini dilakukan? Dan bagaimana ia harus direka? Artikel ini akan meneroka cara menggunakan antara muka pasaran agregat pertukaran untuk membina strategi berbilang produk.

Ambil Binance dan Huobi sebagai contoh, dan semak dokumen API mereka Kami mendapati bahawa kedua-duanya mempunyai antara muka maklumat pasaran agregat.

Antara muka pasaran

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

Walau bagaimanapun, ini tidak berlaku. Struktur yang sebenarnya dikembalikan oleh antara muka Huobi ialah:

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

Berhati-hati apabila memproses data yang dikembalikan oleh antara muka.

Membina rangka kerja program dasar

Bagaimana untuk merangkum kedua-dua antara muka ini dalam strategi dan bagaimana untuk memproses data? Mari kita lihat bersama-sama.

Mari kita mula-mula menulis pembina untuk membina objek kawalan.

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

Menggunakan fungsi API FMZHttpQueryFungsi menghantar permintaan untuk mengakses antara muka pertukaran. gunaHttpQueryPengendalian pengecualian diperlukantry...catchMengendalikan pengecualian seperti kegagalan pemulangan antara muka. Sesetengah pelajar mungkin bertanya: “Struktur data yang dikembalikan oleh antara muka pertukaran adalah berbeza. Bagaimanakah kita harus menanganinya? Sudah pasti tidak mungkin untuk menggunakan kaedah pemprosesan yang sama.” Sesungguhnya, bukan sahaja struktur data yang dikembalikan oleh antara muka pertukaran berbeza, malah penamaan medan data yang dikembalikan adalah berbeza. Makna yang sama mungkin dinamakan berbeza. Sebagai contoh, antara muka yang kami senaraikan di atas. Ungkapan yang sama bermaksud harga belian, yang dipanggil:bidPrice, yang dipanggilbid

Kami menggunakan fungsi panggil balik di sini untuk memisahkan bahagian pemprosesan khas ini. Jadi selepas objek di atas dimulakan, ia menjadi seperti ini apabila digunakan: (Kod berikut menghilangkan pembinacreateManager) Pantau kontrak ini dengan Binance Futures:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"] Huobi Spot memantau pasangan dagangan syiling kepada syiling ini:["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"]Contohnya.

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)
    }
}

Jalankan ujian: Objek pertukaran pertama menambah niaga hadapan Binance, dan objek pertukaran kedua menambah tempat Huobi Gunakan antara muka pasaran agregat pertukaran mata wang digital untuk membina strategi berbilang produk

Gunakan antara muka pasaran agregat pertukaran mata wang digital untuk membina strategi berbilang produk

Dapat dilihat di sini, operasi seperti cara mendapatkan data yang dikembalikan oleh antara muka diproses khusus untuk pertukaran yang berbeza menggunakan fungsi panggil balik.

    	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}})

Selepas merumuskan pemerolehan maklumat pasaran, kami seterusnya boleh merumuskan pemerolehan aset akaun Oleh kerana strategi berbilang produk, data aset akaun juga mesti berbilang. Nasib baik, antara muka aset akaun pertukaran biasanya mengembalikan semua data aset.

Dalam pembinacreateManagerTambahkan kaedah untuk mendapatkan aset

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

Selain itu, disebabkan oleh format dan nama medan yang berbeza yang dikembalikan oleh antara muka pertukaran, fungsi panggil balik juga diperlukan untuk pemprosesan khas.

Mengambil Huobi spot dan niaga hadapan Binance sebagai contoh, fungsi panggil balik boleh ditulis 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 
    }

Jalankan rangka kerja strategi dengan fungsi mendapatkan maklumat pasaran dan aset

Petikan: Gunakan antara muka pasaran agregat pertukaran mata wang digital untuk membina strategi berbilang produk

aset: Gunakan antara muka pasaran agregat pertukaran mata wang digital untuk membina strategi berbilang produk

Dapat dilihat bahawa selepas memperoleh data pasaran, data boleh diproses untuk mengira perbezaan harga setiap varieti dan memantau perbezaan harga spot-futures beberapa pasangan dagangan. Kemudian, strategi lindung nilai hadapan dan spot berbilang pelbagai boleh direka bentuk.

Mengikut kaedah reka bentuk ini, pertukaran lain juga boleh diperluaskan Pelajar yang berminat boleh mencubanya.