Type/to search
8
Follow
1364
Followers
Разработка и реализация мониторинга разницы цен на биржах DEX-CEX на основе количественной оценки FMZ
Discussions
Created 2025-02-21 10:40:52  Updated 2025-02-21 13:53:00
 0
 1716

img

Несколько бирж DEX, включая dydx_v4, hyperliquid, vertex и aevo, были инкапсулированы и подключены к FMZ. Поскольку конкуренция за ценовой арбитраж на централизованных биржах становится все более жесткой, многие количественные трейдеры обратили свое внимание на децентрализованные биржи. В этой статье мы обсудим разработку и реализацию мониторинга разницы цен между DEX и CEX.

Первым шагом стратегии хедж-арбитража является расчет разницы цен целевого портфеля, а также наблюдение и анализ наличия каких-либо торговых возможностей. Поэтому разработка и реализация стратегии мониторинга разницы в ценах является первой базовой задачей. Наши требования к проектированию:

  • Используемый язык программирования — Javascript.
  • Используйте инкапсулированный REST-интерфейс.
  • Выбор DEX: гипержидкость, вершина.
  • Выбор CEX: binance, bybit.
  • Запрос данных книги заказов использует многопоточные параллельные запросы.
  • Тестовые продукты должны быть основными продуктами, которые по возможности используются всеми биржами: спотовые торговые пары ETH, BTC/бессрочные контракты.
  • Постарайтесь упростить конструкцию и обеспечить базовую реализацию, используя простой и понятный код.

Реализация кода

Код состоит менее чем из 200 строк, и его предназначение — только вычислять разницу в цене определенного продукта в реальном времени на разных биржах. При первоначальном запуске стратегии все объекты обмена, настроенные для стратегии, будут классифицированы в группу DEX и группу CEX. Каждый опрос выполняется через многопоточную функцию Thread, инкапсулированную платформой FMZ, и одновременно запрашивает интерфейс REST: интерфейс книги заказов.GetDepth, запишите запрошенный список заказов на покупку и данные списка заказов на продажу требуемых сортов. Затем группа DEX и группа CEX объединяются в разностную комбинацию (комбинация DEX-CEX, т.е. арбитражная пара) и рассчитывается разница в цене.

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

На разных биржах один и тот же базовый актив может называться по-разному, поэтому название продукта необходимо скорректировать:
Программу необходимо настроить в соответствии с правилами наименования символов различных бирж. Например, торговые пары контрактов Vertex имеют следующие названия:XXX_USD, который на самом деле является бессрочным контрактом на основе USDC. Название ETH в ячейке Vertex — WETH.

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

Запрос данных
Прежде чем будут получены все данные о глубине, программа будет ждать и продолжать проверять, есть ли биржи, данные которых не были обновлены. Если данные не получены, программа будет спать 100 миллисекунд.
Запрошенные данные книги заказов записываются в объект, созданный threading.Dict() (используется для взаимодействия с параллельными потоками), и данные сбрасываются в конце каждого опроса.

Подвести итог
Реализация этой стратегии показывает, как отслеживать разницу цен на нескольких биржах в режиме реального времени и рассчитывать возможные арбитражные возможности. Благодаря разумной коррекции символов, глубокому сбору данных, точному контролю и многопоточной работе система может эффективно отслеживать разницу цен в реальном времени. Для тех, кто изучает стратегию, понимание идей реализации этого кода может помочь им освоить, как использовать API для получения данных о транзакциях, как обрабатывать данные с нескольких бирж, как рассчитывать и выводить спреды транзакций и как применять эти технологии в реальных транзакциях.

javascript
let symbolList = [] function createEx(idx, exs) { let self = {} let cexEidList = ["Binance", "Bybit", "Futures_Binance", "Futures_Bybit"] let dexEidList = ["Vertex", "Hyperliquid", "Futures_Hyperliquid", "Futures_Vertex"] self.name = exs[idx].GetName() self.idx = idx self.e = exs[idx] self.depths = threading.Dict() self.markets = self.e.GetMarkets() if (!self.markets) { throw "GetMarkets error" } if (dexEidList.includes(self.name)) { self.type = "DEX" } else if (cexEidList.includes(self.name)) { self.type = "CEX" } else { throw "not support " + self.name } if (self.name.startsWith("Futures_")) { self.isFutures = true } else { self.isFutures = false } self.correctSymbol = function(symbol) { if (self.name == "Vertex") { let correctList = {"BTC_USDC": "WBTC_USDC", "ETH_USDC": "WETH_USDC"} if (typeof(correctList[symbol]) != "undefined") { return correctList[symbol] } } else if (self.name == "Hyperliquid") { let correctList = {"BTC_USDC": "UBTC_USDC"} if (typeof(correctList[symbol]) != "undefined") { return correctList[symbol] } } else if (self.name == "Futures_Hyperliquid") { return symbol.replace("_USDC", "_USD") } return symbol } self.reqDepth = function(symbol) { symbol = self.correctSymbol(symbol) threading.Thread(function(idx, symbol, threadingDict) { let depth = exchanges[idx].GetDepth(symbol) if (depth) { threadingDict.set(symbol, depth) } else { threadingDict.set(symbol, null) } }, self.idx, symbol, self.depths) } self.getPrecision = function(symbol) { symbol = self.correctSymbol(symbol) let marketInfo = self.markets[symbol] if (marketInfo) { return [marketInfo.PricePrecision, marketInfo.AmountPrecision] } else { return [8, 8] } } self.init = function() { self.depths = threading.Dict() } self.getDepth = function(symbol) { symbol = self.correctSymbol(symbol) return self.depths.get(symbol) } return self } function createManager(symbolList, exs) { let self = {} self.symbolList = symbolList self.exchanges = [] self.hedgePair = [] self.initHedgePair = function () { for (let i in exs) { let ex = createEx(i, exs) self.exchanges.push(ex) } let arrDEX = self.exchanges.filter(item => item.type == "DEX") let arrCEX = self.exchanges.filter(item => item.type == "CEX") for (let dex of arrDEX) { for (let cex of arrCEX) { self.hedgePair.push({"dex": dex, "cex": cex}) } } } self.calcHedgeData = function () { let beginTimestamp = new Date().getTime() for (let e of self.exchanges) { for (let symbol of self.symbolList) { e.reqDepth(symbol) } } while (true) { let isWait = false for (let e of self.exchanges) { for (let symbol of self.symbolList) { let depth = e.getDepth(symbol) if (depth == null || typeof(depth) == "undefined") { isWait = true } } } if (isWait) { Sleep(100) } else { break } } let tbls = [] for (let symbol of self.symbolList) { let tbl = {"type": "table", "title": symbol + "差价", "cols": ["pair", "bid-ask", "ask-bid", "dex ask", "dex bid", "cex ask", "cex bid"], "rows": []} for (let p of self.hedgePair) { let dex = p["dex"] let cex = p["cex"] let pricePrecision = Math.max(dex.getPrecision(symbol)[0], cex.getPrecision(symbol)[0]) let dexDepth = dex.getDepth(symbol) let cexDepth = cex.getDepth(symbol) if (dexDepth && cexDepth) { p["bid-ask"] = _N(dexDepth.Bids[0].Price - cexDepth.Asks[0].Price, pricePrecision) p["ask-bid"] = _N(dexDepth.Asks[0].Price - cexDepth.Bids[0].Price, pricePrecision) // 输出信息、观察测试 Log(dex.name, cex.name, symbol, "bid-ask:", p["bid-ask"], ", ask-bid", p["ask-bid"]) p[dex.name + "-ask"] = dexDepth.Asks[0].Price + "/" + dexDepth.Asks[0].Amount p[dex.name + "-bid"] = dexDepth.Bids[0].Price + "/" + dexDepth.Bids[0].Amount p[cex.name + "-ask"] = cexDepth.Asks[0].Price + "/" + cexDepth.Asks[0].Amount p[cex.name + "-bid"] = cexDepth.Bids[0].Price + "/" + cexDepth.Bids[0].Amount } else { p["bid-ask"] = "--" p["ask-bid"] = "--" p[dex.name + "-ask"] = "--" p[dex.name + "-bid"] = "--" p[cex.name + "-ask"] = "--" p[cex.name + "-bid"] = "--" } let pairName = dex.name + "-" + cex.name tbl["rows"].push([pairName, p["bid-ask"], p["ask-bid"], p[dex.name + "-ask"], p[dex.name + "-bid"], p[cex.name + "-ask"], p[cex.name + "-bid"]]) } tbls.push(tbl) } for (let e of self.exchanges) { e.init() } let endTimestamp = new Date().getTime() return [tbls, (endTimestamp - beginTimestamp) + "毫秒"] } self.initHedgePair() return self } function main() { LogReset(1) let loopCount = 0 symbolList = strSymbolList.split(",") let m = createManager(symbolList, exchanges) while (true) { let ret = m.calcHedgeData() loopCount++ LogStatus(_D(), "耗时:", ret[1], ", 轮询次数:", loopCount, "\n", "`" + JSON.stringify(ret[0]) + "`") Sleep(1000) } }

Параметры конструкции:

img

Спотовый рынок

Мониторинг спотового продукта:

  • BTC_USDC Биткоин к USDC спот

img

Контрактный рынок

Монитор двух разновидностей:

  • ETH_USDC.swap Бессрочный контракт Ethereum
  • BTC_USDC.swap Бессрочный контракт Bitcoin

img

END

Направление расширения:

  • Мониторинг пороговых значений и инкапсуляция логики транзакций.
  • Рассчитайте комиссии и издержки, а также рассчитайте разумный диапазон спреда хеджирования.
  • Используйте интерфейс веб-сокета для получения рыночных данных.

Платформа FMZ продолжит улучшать техническую поддержку децентрализованных бирж (DEX) и децентрализованных финансов (DeFi), а также постоянно совершенствовать и обновлять функции и продукты.

Спасибо за прочтение.

Comment
All comments (0)
No data
No data
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)