
Varios exchanges DEX, incluidos dydx_v4, hyperliquid, vertex y aevo, se han encapsulado y conectado en FMZ. A medida que la competencia por el arbitraje de precios en exchanges centralizados se vuelve cada vez más feroz, muchos traders cuantitativos han centrado su atención en exchanges descentralizados. En este artículo, analizaremos el diseño y la implementación del monitoreo de la diferencia de precios entre DEX y CEX.
El primer paso de la estrategia de arbitraje de cobertura es calcular la diferencia de precios de la cartera objetivo y observar y analizar si existen oportunidades comerciales. Por lo tanto, diseñar e implementar una estrategia de monitoreo de diferencias de precios es la primera tarea básica. Nuestros requisitos de diseño son:
El código tiene menos de 200 líneas y su función diseñada es únicamente calcular la diferencia de precio en tiempo real de un determinado producto en diferentes intercambios. Cuando se ejecuta la estrategia inicialmente, todos los objetos de intercambio configurados para la estrategia se clasificarán en el grupo DEX y el grupo CEX. Cada sondeo se realiza a través de la función multiproceso Thread encapsulada por la plataforma FMZ, y solicita simultáneamente la interfaz REST: la interfaz del libro de órdenes.GetDepth, registre la lista de órdenes de compra solicitadas y los datos de la lista de órdenes de venta de las variedades requeridas. Luego, el grupo DEX y el grupo CEX se combinan en una combinación de diferencia (combinación DEX-CEX, es decir, par de arbitraje) y se calcula la diferencia de precio.
Determinación del tipo de cambio: Durante la inicialización, se evaluará el objeto de intercambio agregado para determinar si es al contado o futuros.
Es posible que distintos intercambios tengan distintos nombres para un determinado activo subyacente, por lo que es necesario ajustar el nombre del producto:
El programa debe ajustarse de acuerdo con las reglas de denominación de los símbolos de los diferentes intercambios. Por ejemplo, los pares comerciales de los contratos Vertex se denominan de la siguiente manera:XXX_USD, que en realidad es un contrato perpetuo basado en USDC. El nombre de ETH en el spot de Vertex es WETH.
Obtenga precisión: Durante la inicialización se obtiene toda la información del mercado. Según el símbolo específico solicitado, se puede consultar la precisión correspondiente para las operaciones posteriores de procesamiento de precisión de datos.
Solicitud de datos Antes de obtener todos los datos de profundidad, el programa esperará y seguirá verificando si hay intercambios cuyos datos no se hayan actualizado. Si no se han obtenido los datos, el programa permanecerá en suspensión durante 100 milisegundos. Los datos del libro de órdenes solicitados se registran en un objeto creado por threading.Dict() (utilizado para la interacción con subprocesos simultáneos) y los datos se restablecen al final de cada sondeo.
Resumir Esta implementación de estrategia muestra cómo monitorear las diferencias de precios en múltiples intercambios en tiempo real y calcular posibles oportunidades de arbitraje. A través de una corrección de símbolos razonable, captura de datos profunda, control de precisión y operación multiproceso, el sistema puede monitorear eficientemente las diferencias de precios en tiempo real. Para los estudiantes de estrategia, comprender las ideas de implementación de este código puede ayudarlos a dominar cómo usar la API para obtener datos de transacciones, cómo procesar datos de múltiples intercambios, cómo calcular y generar diferenciales de transacciones y cómo aplicar estas tecnologías en transacciones reales.
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)
}
}
Diseño de parámetros:

Monitorizar un producto puntual:

Monitorizar dos variedades:

Dirección de expansión:
La plataforma FMZ continuará mejorando su soporte técnico para los intercambios descentralizados (DEX) y las finanzas descentralizadas (DeFi), e iterará y actualizará continuamente funciones y productos.
Gracias por leer.