Construir uma estratégia multi-diversidade usando a interfaz de mercado agregada de uma troca de moeda digital

Autora:Sonhos pequenos, Criado: 2021-03-17 18:38:47, Atualizado: 2023-09-26 20:58:11

img

Construir uma estratégia multi-diversidade usando a interfaz de mercado agregada de uma troca de moeda digital

Plataforma de troca quantitativa FMZA estratégia do panoramaÉ frequente encontrar estratégias de múltiplas variedades, ao mesmo tempo em que se detectam dezenas de mercados ou até mesmo um mercado inteiro. Como fazer isso?

Para listar as duas trocas de Bitcoin e Token, veja o documento da API da bolsa e veja que todas elas possuem uma interface de mercado agregado:

Interface de negócios

  • O acordo de Binance:https://fapi.binance.com/fapi/v1/ticker/bookTickerInterface de retorno de dados

    [
        {
            "symbol": "BTCUSDT", // 交易对
            "bidPrice": "4.00000000", //最优买单价
            "bidQty": "431.00000000", //挂单量
            "askPrice": "4.00000200", //最优卖单价
            "askQty": "9.00000000", //挂单量
            "time": 1589437530011   // 撮合引擎时间
        }
        ...
    ]
    
  • O Bitcoin é uma moeda em dinheiro:https://api.huobi.pro/market/tickersInterface de retorno de dados

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

    Mas, na realidade, não é assim, a estrutura que a interface do token retorna é:

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

    É necessário ter cuidado ao processar os dados retornados pela interface.

Construir um quadro de procedimentos estratégicos

Como envolver essas duas interfaces na estratégia e como processar os dados? A gente pode ver tudo juntos, devagar.

Primeiro, escreva uma função de construção para construir objetos de controle.

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

Funções de API com FMZHttpQueryFunções para enviar solicitações e acessar interfaces de exchanges.HttpQueryQuando é necessário o tratamento de exceçõestry...catchTratar de exceções, como falhas de retorno de interface. Alguns dos alunos que vêem aqui podem perguntar: "Como lidar com as diferentes estruturas de dados que as interfaces das bolsas de alumínio retornam? Na verdade, não só a estrutura de dados de interfaces de trocas é diferente, mas até mesmo os nomes dos campos de dados retornados são diferentes. Um mesmo significado pode ser um nome diferente. Por exemplo, a interface que listamos acima.bidPriceA moeda é chamadabid

Nós usamos soluções de chamadas para separar essas partes de tratamentos especiais. O objeto acima é initializado e, quando usado especificamente, fica assim: (O código abaixo omite a função de construção)createManagerNão. Os futuros em Bitcoin são monitorados por:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]O Bitcoin Cash monitora as transações de moedas para:["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"]Por exemplo:

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

A partir de agora, a empresa está em desenvolvimento. O primeiro objeto de troca adiciona futuros de moeda digital e o segundo objecto de troca adiciona dinheiro de tokens.img

img

Como se pode ver, aqui, operações como a extração de dados de retorno da interface são usadas para processar a especialização de diferentes exchanges usando funções 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}})

A aquisição de mercado é definida e a aquisição de ativos de conta pode ser definida em seguida, pois a estratégia multi-variedade é que os dados de ativos de conta também devem ser múltiplos.

Em funções de construçãocreateManagerAdicionar métodos para obter os ativos

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

Também, devido ao formato de retorno da interface do exchange, os nomes dos campos variam, o que também requer o tratamento especializado de funções de retorno.

Em um exemplo de moeda corrente, moeda de futuro, a função de retorno pode ser escrita assim:

    // 获取账户资产的回调函数
    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 um quadro estratégico com funções de acesso ao mercado, ativos

O que aconteceu:img

Ativos:img

A partir daí, o cliente pode visualizar a diferença entre as diferentes variedades, monitorando a diferença entre os diferentes pares de transações. A partir daí, pode-se criar uma estratégia de hedge de futuros de várias variedades.

De acordo com este design, outras casas de câmbio podem ser expandidas e os alunos interessados podem experimentá-las.


Relacionados

Mais.

Eu amo o Jimmy.O que a callBackFuncGetAcc tem a ver com o callBackFuncGetAcc? Eu sinto que é um conjunto de funções dentro de funções, onde aprender esse conhecimento?

Eu amo o Jimmy.Como extrair simultaneamente o preço do Bid1 e do Ask1 de um par de negociações em um prazo de diferença?

ZltimMuito bem.

Sonhos pequenosA função de chamada de volta do Baudoin.

Sonhos pequenosAfinal, o que eu quero dizer é que os dois ciclos se cruzam e atravessam.

Sonhos pequenosO que eu estou dizendo é a diferença entre o preço de venda e o preço de venda de futuros, não é tudo descrito no artigo, é a diferença de venda. A questão é: o que você está fazendo para diminuir ou não?

Eu amo o Jimmy.Se você quiser obter a diferença entre o preço de compra e o preço de venda do BTCUSDT no mercado de futuros: primeiro percorra o gerenciador de mercado de futuros 1.subscribeTickers, descubra o gerenciador de preço de venda do BTCUSDT 1.subscribeTickers[i].ask1, a questão é como extrair o preço de oferta do BTCUSDT no mercado de futuros quando o gerenciamento de mercado de futuros é feito, será que o gerenciador de mercado de futuros 1.subscribeTickers?

Eu amo o Jimmy.Eu quero dizer a diferença entre o preço de compra e o preço de venda de futuros, e não o preço de compra e venda de futuros ou de futuros; o problema é que não é possível obter o preço de compra e o preço de venda do mesmo negócio. função GetBAspot ((syboml, tickerspot, BA) { para (var i = 0; i < tickerspot.length; i++) { If (tickerspot [i].syboml!==syboml) { Continuar }else If (tickerspot [i].syboml ===syboml) { var bidspot=tickerspot[i].bid1 var askspot=tickerspot[i].ask1 Não. Não. If ((BA==="bid") return bidspot (em inglês) if ((BA==="ask") return askspot Não. função main() { _.each ((manager1.subscribe Tickers, 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"))))) Não. Não.

Sonhos pequenosA diferença de preços não é uma redução da diferença de preços.

Eu amo o Jimmy.Como é que o código de origem do artigo não foi divulgado?

Sonhos pequenosNão entendo o que você quer dizer.

Eu amo o Jimmy.Eu vi, mas não há uma unificação para especificar o mesmo par de transações.

Sonhos pequenosVocê vê que o código tem dados de compra e venda.