avatar of 发明者量化-小小梦 发明者量化-小小梦
Seguir Mensajes Privados
4
Seguir
1271
Seguidores

Diseño e implementación del sistema de monitoreo de diferencias de precios de cambio DEX-CEX basado en cuantificación FMZ

Creado el: 2025-02-21 10:40:52, Actualizado el: 2025-02-21 13:53:00
comments   0
hits   1232

Diseño e implementación del sistema de monitoreo de diferencias de precios de cambio DEX-CEX basado en cuantificación FMZ

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 lenguaje de programación utilizado es Javascript.
  • Utilice la interfaz REST encapsulada.
  • Selección DEX: hiperlíquido, vértice.
  • Selección de CEX: binance, bybit.
  • La solicitud de datos de la cartera de pedidos utiliza solicitudes simultáneas de múltiples subprocesos.
  • Los productos de prueba deben ser los productos principales compartidos por todos los intercambios tanto como sea posible: pares de negociación spot de ETH, BTC/contratos perpetuos
  • Intente simplificar el diseño y proporcionar una implementación básica utilizando código simple y fácil de entender.

Implementación de código

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:

Diseño e implementación del sistema de monitoreo de diferencias de precios de cambio DEX-CEX basado en cuantificación FMZ

Mercado al contado

Monitorizar un producto puntual:

  • BTC_USDC Bitcoin a USDC al contado

Diseño e implementación del sistema de monitoreo de diferencias de precios de cambio DEX-CEX basado en cuantificación FMZ

Mercado de contratos

Monitorizar dos variedades:

  • ETH_USDC.swap Contrato perpetuo de Ethereum
  • BTC_USDC.swap Contrato perpetuo de Bitcoin

Diseño e implementación del sistema de monitoreo de diferencias de precios de cambio DEX-CEX basado en cuantificación FMZ

END

Dirección de expansión:

  • Monitoreo de umbrales y encapsulamiento de la lógica de transacciones.
  • Calcule las tarifas y los costos y calcule el rango de diferencial de cobertura razonable.
  • Utilice la interfaz websocket para obtener datos del mercado.

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.