Construir estrategias multivariadas con interfaces de mercado agregadas de intercambios de moneda digital

El autor:Un sueño pequeño., Creado: 2021-03-17 18:38:47, Actualizado: 2023-09-26 20:58:11

img

Construir estrategias multivariadas con interfaces de mercado agregadas de intercambios de moneda digital

Plataforma de comercio cuantificado FMZLa estrategia de los plazosA menudo se encuentran estrategias de múltiples tipos, al mismo tiempo que se detectan decenas de mercados o incluso un mercado completo de intercambio. ¿Cómo se hace esto? ¿Y cómo se debe diseñar?

En la lista de los dos intercambios, Bitcoin y Token, los documentos API de los intercambios muestran que todos tienen interfaces de mercado agregadas:

Interfaz de trabajo

  • El acuerdo de Binance:https://fapi.binance.com/fapi/v1/ticker/bookTickerInterfaz de retorno de datos

    [
        {
            "symbol": "BTCUSDT", // 交易对
            "bidPrice": "4.00000000", //最优买单价
            "bidQty": "431.00000000", //挂单量
            "askPrice": "4.00000200", //最优卖单价
            "askQty": "9.00000000", //挂单量
            "time": 1589437530011   // 撮合引擎时间
        }
        ...
    ]
    
  • El dinero en efectivo de la moneda:https://api.huobi.pro/market/tickersInterfaz de retorno de datos

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

    Sin embargo, en realidad no es así, y la estructura de retorno real de la interfaz de los tokens es:

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

    Hay que tener cuidado al procesar los datos que devuelve la interfaz.

Construir un marco de procedimiento estratégico

¿Cómo se envuelven estas dos interfaces en la estrategia y cómo se manejan los datos? ¿Qué es lo que está sucediendo?

Primero, escriba una función constructora para construir objetos de control.

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

Funciones de API con FMZHttpQueryFunción para enviar solicitudes y acceder a la interfaz de intercambio.HttpQueryCuando se requiere un tratamiento excepcionaltry...catchTratar las excepciones, como el fallo de retorno de la interfaz. Algunos de los estudiantes que ven esto pueden preguntarse: ¿cómo se trata la estructura de los datos devueltos por las interfaces de los intercambios de tiburones? De hecho, no sólo la estructura de los datos que devuelven las interfaces de los intercambios es diferente, sino que incluso los nombres de los campos de datos devueltos son diferentes. Un mismo significado puede ser un nombre diferente. Por ejemplo, la interfaz que enumeramos anteriormente.bidPriceEn el token se llamabid

Aquí usamos la función de recuperación para resolver y separar estas partes de los tratamientos especiales. Cuando se inicializa el objeto anterior, el uso específico es el siguiente: (El siguiente código omite la función de construcción)createManager¿Qué es esto? Los futuros de Bitcoin monitorean los siguientes contratos:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]El dinero en efectivo vigila las transacciones de monedas:["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"]Por ejemplo.

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

La prueba está en marcha: El primer objeto de intercambio añade futuros de bitcoins, el segundo objeto de intercambio añade tokens en efectivoimg

img

Como se puede ver, aquí se realizan operaciones como extraer datos de la interfaz de retorno para realizar un procesamiento especializado de diferentes intercambios usando funciones de retorno.

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

Se establece una adquisición de mercado y luego se puede establecer una adquisición de activos de cuenta, ya que la estrategia de múltiples variedades, los datos de activos de la cuenta también deben ser múltiples.

En la función de construccióncreateManagerAñadir métodos para obtener activos

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

También, debido al formato en el que se devuelve la interfaz de intercambio, los nombres de los campos varían, lo que también requiere un procesamiento especializado con funciones de retorno.

En el caso de los futuros de divisas, las funciones de retorno se pueden escribir así:

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

Operar un marco estratégico que tenga acceso a las funciones de mercado y de activos

El caso:img

Los activos:img

Se puede ver que una vez que se obtienen los datos del mercado, se pueden procesar los datos para calcular las diferencias de las variedades y monitorear las diferencias de vencimiento de varios pares de transacciones. En este sentido, la estrategia de hedge de futuros de varias variedades puede ser diseñada.

De acuerdo con este diseño, también se puede ampliar a otras bolsas, y los estudiantes interesados pueden probar.


Relacionados

Más.

Quiero a Jimmy.¿Qué relación tiene callBackFuncGetAcc con callBackFuncGetAcc? ¿Me siento como un conjunto de funciones dentro de la función, dónde aprendí esto?

Quiero a Jimmy.¿Cómo se extrae el precio de Bid1 y Ask1 de un par de activos al mismo tiempo?

ZltimQué bueno.

Un sueño pequeño.La función de retorno de Baudita.

Un sueño pequeño.Los dos círculos se encuentran juntos, atravesados.

Un sueño pequeño.Lo que te digo es que la diferencia entre el precio de los activos y el precio de los futuros, que no es todo lo que se muestra en el artículo, es la diferencia de los futuros. Los datos están disponibles, ¿qué se puede hacer concretamente, si se reduce o no?

Quiero a Jimmy.¿Estás de acuerdo con mi opinión? Si quieres obtener la diferencia entre el precio de compra y el precio de venta de BTCUSDT en el mercado de futuros: primero explora el conjunto de mercados de futuros manager1.subscribeTickers, descubre el conjunto de mercados de futuros manager1.subscribeTickers[i].ask1, el problema es cómo extraer el precio de la oferta de BTCUSDT en el mercado de futuros durante el proceso de exploración, ¿puedes espiar el conjunto de mercados de futuros manager1.subscribeTickers?

Quiero a Jimmy.Me refiero a la diferencia entre el precio de compra y el precio de venta de los futuros, no a la diferencia entre el precio de compra y el precio de venta de los futuros; el problema es que no se puede obtener al mismo tiempo el precio de compra y el precio de venta de los futuros. Por ejemplo: ¿cómo obtener la diferencia entre el precio de compra y el precio de venta de los futuros BTC USDT? La función GetBAspot ((syboml, tickerspot, BA) para (var i = 0; i < tickerspot.length; i++) { Si es posible, el punto de inflexión es el punto de inflexión. ¿Qué es esto? ¿Qué es esto? Si el punto de inflexión es el punto de inflexión, el punto de inflexión es el punto de inflexión. var bidspot=tickerspot[i].bid1 y el punto de venta es el punto de venta. var askspot=tickerspot[i].ask1 y el siguiente es el siguiente: ¿Qué es eso? ¿Qué es eso? El punto de venta de regreso es el punto de venta. Si usted tiene una pregunta, usted puede responder. ¿Qué es eso? La función principal ((() { _.each ((manager1.subscribe Tickers, function ((ticker)) { El nombre de la página es el mismo que el nombre del usuario Var es el símbolo de la página. var symb1=manager1.symFuturesToSpot ((symb) es el nombre de un sistema de gestión de futuros. Tbl1.rows.push (([ticker.symbol, ticker.bid1, ticker.ask1, manager1.Getfundingrate ((symb), manager1.Getrealrate ((symb, 50), GetBAspot ((symb1, SpotTickers, "ask"))))) ¿Qué es eso? ¿Qué es eso?

Un sueño pequeño.En el caso de los países en vías de desarrollo, la diferencia de precios no se reduce.

Quiero a Jimmy.¿Por qué no se publicó el código fuente de la imagen de la diferencia de precio en el artículo?

Un sueño pequeño.No entiendo lo que quieres decir.

Quiero a Jimmy.Lo veo, pero no hay unidad que especifique el mismo par de transacciones.

Un sueño pequeño.Si buscas en el código, compras y vendes todos los datos.