Construire des stratégies multiculturelles en utilisant des interfaces de marché regroupées sur les échanges de crypto-monnaie

Auteur:Le petit rêve, Créé: 2021-03-17 18:38:47, Mis à jour: 2023-09-26 20:58:11

img

Construire des stratégies multiculturelles en utilisant des interfaces de marché regroupées sur les échanges de crypto-monnaie

Plateforme de négociation quantitative FMZStratégie de contournementIl est fréquent de voir des stratégies multiculturelles, tout en détectant des dizaines de marchés ou même un marché entier. Comment faire?

En lisant les deux échanges, Bitcoin et Token, et en consultant les documents API de l'échange, vous trouverez qu'ils ont tous une interface de marché agrégée:

L'interface utilisateur

  • Le projet de loi sur le Bitcoin:https://fapi.binance.com/fapi/v1/ticker/bookTickerL'interface renvoie les données

    [
        {
            "symbol": "BTCUSDT", // 交易对
            "bidPrice": "4.00000000", //最优买单价
            "bidQty": "431.00000000", //挂单量
            "askPrice": "4.00000200", //最优卖单价
            "askQty": "9.00000000", //挂单量
            "time": 1589437530011   // 撮合引擎时间
        }
        ...
    ]
    
  • Le projet de loi a été adopté par le Parlement.https://api.huobi.pro/market/tickersL'interface renvoie les données

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

    Cependant, ce n'est pas le cas, la structure que les interfaces de jetons retournent est la suivante:

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

    Il faut être prudent lorsque l'on traite les données renvoyées par l'interface.

Construire un cadre stratégique

Comment envelopper ces deux interfaces dans une stratégie et comment traiter les données? Je suis un peu dégoûté de ce que vous avez fait.

Tout d'abord, écrivez une fonction de construction pour construire des objets de contrôle.

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

Fonction d'API utilisée par FMZHttpQueryLes fonctions émettent des requêtes, accèdent à l'interface de l'échange.HttpQueryIl est nécessaire d'utiliser un traitement exceptionnel.try...catchTraiter les exceptions telles que les échecs de retour d'interface. Certains de vos camarades ici vont peut-être se demander: "Comment traiter les données qui sont retournées par les différentes structures d'interfaces de l'échange de bitcoins? C'est vrai, non seulement la structure des données renvoyées par l'interface de l'échange est différente, mais même le nom des champs de données renvoyés est différent. Une même signification peut avoir un nom différent. Par exemple, l'interface que nous avons énumérée ci-dessus.bidPriceLe bitcoin est appelé le bitcoin.bid

Nous utilisons ici les solutions de la fonction de rappel pour séparer ces parties de traitement spécial. Une fois que l'objet a été initialement utilisé, il se présente comme suit: (Le code suivant omet les fonctions de construction)createManagerJe vous en prie. Les contrats suivants sont surveillés avec des contrats à terme:["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]Les banques monétisées surveillent les transactions de ces pièces:["btcusdt", "ethusdt", "eosusdt", "etcusdt", "ltcusdt", "xrpusdt"]Par exemple:

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

Les tests sont en cours: Le premier objet de l'échange ajoute des contrats à terme en euros, le second objet de l'échange ajoute des tokens en espèces.img

img

On peut voir ici comment les opérations telles que la récupération des données de l'interface sont traitées de manière spécialisée par les différents échanges en utilisant des fonctions de récupération.

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

Une acquisition de marché est définie, puis une acquisition d'actifs de compte peut être définie, car les stratégies multiculturelles, les données des actifs de compte doivent également être multiples.

Dans la fonction de constructioncreateManagerAjouter des méthodes pour obtenir des actifs

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

De même, les noms des champs varient en raison du format de retour de l'interface d'échange, ce qui nécessite également un traitement spécialisé de la fonction de retour.

En utilisant le jeton comme exemple, le jeton comme exemple, le jeton comme exemple, on peut écrire la fonction de rappel comme ceci:

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

Opérer un cadre stratégique avec des fonctions d'accès aux marchés et aux actifs

Les faits:img

Les actifs:img

Une fois que vous avez accès aux données du marché, vous pouvez traiter les données pour calculer les différences entre les variétés et surveiller les différences de vente sur plusieurs paires de transactions. Il est possible de concevoir une stratégie de couverture à terme multifonctionnelle.

Selon cette conception, d'autres bourses peuvent être élargies et les étudiants intéressés peuvent essayer.


Relationnée

Plus de

Je t'aime, Jimmy.Qu'est-ce que cela a à voir avec callBackFuncGetAcc? Je sens que c'est un ensemble de fonctions dans une fonction. Où est-ce que je peux apprendre cela?

Je t'aime, Jimmy.Comment extraire simultanément le prix Bid1 et le prix Ask1 d'une paire de produits sur le marché à la différence de prix?

ZltimC'était génial.

Le petit rêveLa fonction de rappel de Baudelaire.

Le petit rêveIl y a deux cycles qui se rejoignent et traversent.

Le petit rêveJe vous ai parlé de la différence entre les options et les contrats à terme, et l'article n'en est pas tout à fait le schéma, les contrats à terme. Il y a des données, mais comment les calculer?

Je t'aime, Jimmy.Si vous voulez obtenir la différence entre le prix d'achat et le prix de vente de BTCUSDT sur le marché des contrats à terme: passez d'abord par le gestionnaire de marché des contrats à terme 1.subscribeTickers, découvrez le gestionnaire de prix de vente de BTCUSDT 1.subscribeTickers[i].ask1, la question est de savoir comment extraire le prix de l'offre de BTCUSDT sur le marché des contrats à terme lors de l'analyse des contrats à terme, est-ce que vous espionnez le gestionnaire de marché des contrats à terme 1.subscribeTickers?

Je t'aime, Jimmy.J'entends par là la différence entre les prix des futures et les prix du spot, et non pas les prix des futures ou des options; le problème est que vous ne pouvez pas obtenir à la fois le prix d'achat et le prix de vente des futures sur la même transaction. Par exemple: comment obtenir la différence entre le prix d'achat et le prix de vente des futures BTC USDT. La fonction GetBAspot ((syboml, tickerspot, BA) { est une fonction qui permet d'obtenir des informations sur le point de départ d'un message. pour (var i = 0; i < tickerspot.length; i++) { Si vous avez un problème avec le point de commande, veuillez nous contacter. Poursuite Je ne sais pas. Si vous avez un problème avec le point de commande, veuillez nous contacter. var bidspot=tickerspot[i].bid1 Il est possible de modifier le point de vente Var est le point de départ de la requête. Je ne sais pas. Je ne sais pas. Si vous souhaitez modifier le point de vente, veuillez cliquer sur le bouton de commande. Si vous souhaitez modifier le fichier, veuillez modifier le fichier. Je ne sais pas. fonction main (() { _.each ((manager1.subscribe Tickers, function ((ticker)) { Je suis en train d'écrire un article sur ce sujet Var symb=ticker.symbol Vous pouvez ajouter votre symbole Var symb1=manager1.symFuturesToSpot (en anglais seulement) Il s'agit d'un système d'exploitation qui est utilisé par les utilisateurs pour gérer des données personnelles. Il est utilisé pour gérer des données personnelles. Je ne sais pas. Je ne sais pas.

Le petit rêveIl y a une différence de prix entre les deux, et la différence de prix n'est pas négligeable.

Je t'aime, Jimmy.Pourquoi n'a-t-on pas publié le code source de l'image de la différence de prix?

Le petit rêveJe ne comprends pas ce que vous voulez dire.

Je t'aime, Jimmy.Je vois, mais il n'y a pas de paire de transactions identiques.

Le petit rêveVous pouvez voir dans le code que les données de l'achat et de la vente sont toutes les mêmes.