Использование криптовалютных бирж для консолидации рыночных интерфейсов для построения разнообразной стратегии

Автор:Маленькие мечты, Создано: 2021-03-17 18:38:47, Обновлено: 2023-09-26 20:58:11

img

Использование криптовалютных бирж для консолидации рыночных интерфейсов для построения разнообразной стратегии

ФМЗ - квантовая торговая платформаСтратегический обзорКак это делается? И как это должно быть спроектировано? В этой статье мы расскажем вам о том, как использовать обменный интерфейс для создания многообразной стратегии.

Например, если перечислить две биржи: Binance и Token, и взглянуть на API-документы, то можно увидеть, что они имеют интегрированный рыночный интерфейс:

Интерфейсы

  • Соглашение Биньян:https://fapi.binance.com/fapi/v1/ticker/bookTickerИнтерфейс возвращает данные

    [
        {
            "symbol": "BTCUSDT", // 交易对
            "bidPrice": "4.00000000", //最优买单价
            "bidQty": "431.00000000", //挂单量
            "askPrice": "4.00000200", //最优卖单价
            "askQty": "9.00000000", //挂单量
            "time": 1589437530011   // 撮合引擎时间
        }
        ...
    ]
    
  • Например:https://api.huobi.pro/market/tickersИнтерфейс возвращает данные

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

    Однако на самом деле это не так, токены возвращают структуру:

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

    При обработке данных, возвращаемых интерфейсом, необходимо соблюдать меры предосторожности.

Строительство стратегической процедурной структуры

Как обернуть эти два интерфейса в стратегию и как обрабатывать данные? Посмотрите медленно вместе.

Начнем с написания конструкторской функции, которая используется для конструкции контрольных объектов.

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

Функции API с FMZHttpQueryФункция отправляет запросы, получает доступ к интерфейсу биржи.HttpQueryПри необходимости использовать исключительные действияtry...catchОбрабатывает исключения, такие как неудача возвращения интерфейса. Некоторые ученики могут спросить: "Что делать с данными, которые возвращаются через разные интерфейсы бирж?" Действительно, не только структура данных, возвращаемых интерфейсом биржи, отличается, но и названия возвращаемых областей данных различаются. Одно и то же может означать другое наименование.bidPriceВ тоне называетсяbid

Мы используем рельсы обратных функций, чтобы выделить эти части специального обработки. После того, как этот объект будет инициализирован, он будет выглядеть так: (Следующий код не включает конструкторскую функцию)createManager(См. Например, в Китае, в Китае, в Китае, в Китае, в Китае, в Китае, в Китае, в Китае.["BTCUSDT", "ETHUSDT", "EOSUSDT", "LTCUSDT", "ETCUSDT", "XRPUSDT"]Например, в Китае существуют две системы, которые контролируют транзакции в монетах:["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) {
    	// 更新行情数据
    	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)
    }
}

Запустить тест: Первый объект обмена добавляет фьючерсы на копейки, второй объект обмена добавляет токены.img

img

Как видно, здесь выполняются операции, такие как извлечение данных, возвращаемых интерфейсом, для специализированной обработки различных бирж с использованием функций обратной связи.

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

Разработано приобретение рынка, затем можно разработать приобретение аккаунта, так как многообразие стратегии, данные аккаунта также должны быть многочисленными.

В конструкции функцииcreateManagerДобавить способы получения активов

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

Кроме того, из-за формата, в котором интерфейс обмена возвращается, названия полей различаются, и здесь также требуется использовать спецификацию функции обратного вызова.

В качестве примера можно записать обратную функцию в виде:

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

Осуществление стратегической структуры, которая обеспечивает доступ к рынкам и функциям активов

Процесс:img

Активы:img

После получения данных о рынке, можно обрабатывать данные, чтобы рассчитать разницу между различными сортами и отслеживать разницу в рассрочке между несколькими парами сделок. В результате можно разработать многообразную стратегию хеджирования.

В соответствии с этим дизайном, можно расширить другие биржи, чтобы заинтересованные студенты могли попробовать.


Связанные

Больше

Я люблю Джимми.Как это связано с callBackFuncGetAcc? Я чувствую, что это набор функций в функциях, где вы узнаете эти знания?

Я люблю Джимми.Вопрос: Как вывести цены Bid1 и Ask1 на обе сделки одновременно при выставлении разницы?

ЗлтмОтлично.

Маленькие мечтыФункция обратного вызова Baidu.

Маленькие мечтыЭто два цикла, которые пересекают друг друга.

Маленькие мечтыЯ рассказал вам о разнице между настоящими и фьючерсными активами, а не об этом в статье. У нас есть данные, как их рассчитать, вы уменьшите или уменьшите?

Я люблю Джимми.Если вы хотите получить разницу между ценой покупки BTCUSDT и ценой продажи BTCUSDT: сначала пройдите через матрицу менеджера рынка фьючерсов 1.subscribeTickers, выясните матрицу продажи BTCUSDT 1.subscribeTickers[i].ask1.

Я люблю Джимми.Я имею в виду разницу между фьючерсом и наличными, а не разницу между фьючерсом или наличными покупками и продажами; проблема в том, что нельзя одновременно получить цену покупки и продажи на одном и том же фьючерсе. function GetBAspot ((syboml, tickerspot, BA) { for (var i = 0; i < tickerspot.length; i++) { if ((tickerspot[i].syboml!==syboml) {) Продолжайте }else if ((tickerspot[i].syboml===syboml) { var bidspot=tickerspot[i].bid1 var askspot=tickerspot[i].ask1 {y:bi} {y:bi} if ((BA==="bid") return bidspot (ответы на предложения) if ((BA==="ask") return askspot Если вы хотите получить ответ на запрос {y:bi} function 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"))))) }) {y:bi}

Маленькие мечтыЭто конкретное описание работает, покупают и продают одно и то же, разница в цене не уменьшается.

Я люблю Джимми.Почему в статье не опубликован исходный код изображения, на котором была получена разница в сроках?

Маленькие мечтыЯ не понимаю, что вы имеете в виду.

Я люблю Джимми.Я вижу, но нет единого определения того же пары транзакций.

Маленькие мечтыЕсли вы посмотрите на код, то увидите, что в нем есть данные о покупке и продаже.