avatar of 发明者量化-小小梦 发明者量化-小小梦
집중하다 사신
4
집중하다
1271
수행원

FMZ 정량화 기반 DEX-CEX 거래소 가격 차이 모니터링 설계 및 구현

만든 날짜: 2025-02-21 10:40:52, 업데이트 날짜: 2025-02-21 13:53:00
comments   0
hits   1232

FMZ 정량화 기반 DEX-CEX 거래소 가격 차이 모니터링 설계 및 구현

dydx_v4, hyperliquid, vertex, aevo를 포함한 여러 DEX 거래소가 캡슐화되어 FMZ에 연결되었습니다. 중앙 집중형 거래소에서 가격 차익 거래 경쟁이 점점 더 치열해짐에 따라 많은 양적 거래자가 분산형 거래소로 관심을 돌렸습니다. 이 글에서는 DEX와 CEX 간의 가격 차이 모니터링 설계 및 구현에 대해 논의합니다.

헤지 차익거래 전략의 첫 번째 단계는 목표 포트폴리오의 가격 차이를 계산하고 거래 기회가 있는지 관찰하고 분석하는 것입니다. 따라서 가격 차이 모니터링 전략을 설계하고 구현하는 것이 첫 번째 기본 작업입니다. 당사의 설계 요구 사항은 다음과 같습니다.

  • 사용되는 프로그래밍 언어는 Javascript입니다.
  • 캡슐화된 REST 인터페이스를 사용합니다.
  • DEX 선택: 하이퍼리퀴드, 버텍스.
  • CEX 선택: 바이낸스, 바이비트.
  • 주문장 데이터를 요청하려면 다중 스레드 동시 요청을 사용합니다.
  • 테스트 제품은 가능한 모든 거래소에서 공유하는 주류 제품이어야 합니다: ETH, BTC 현물 거래 쌍/영구 계약
  • 간단하고 이해하기 쉬운 코드를 사용하여 디자인을 단순화하고 기본 구현을 제공해보세요.

코드 구현

코드는 200줄도 안 되며, 설계된 기능은 특정 상품의 다양한 거래소 간 실시간 가격 차이를 계산하는 것입니다. 전략이 처음 실행되면 해당 전략에 대해 구성된 모든 거래소 객체가 DEX 그룹과 CEX 그룹으로 분류됩니다. 각 폴은 FMZ 플랫폼에 의해 캡슐화된 멀티스레드 기능 스레드를 통해 수행되고 동시에 REST 인터페이스(주문장 인터페이스)를 요청합니다.GetDepth, 필요한 품종에 대한 요청된 매수 주문 목록과 판매 주문 목록 데이터를 기록합니다. 이후, DEX 그룹과 CEX 그룹을 차액 조합(DEX-CEX 조합, 즉, 아비트라지 페어)으로 합치고, 가격 차이를 계산합니다.

교환 유형 결정: 초기화하는 동안 추가된 거래소 객체가 현물인지 선물인지 판별됩니다.

각 거래소마다 특정 기초 자산에 대한 이름이 다를 수 있으므로 상품 이름을 조정해야 합니다. 이 프로그램은 다양한 거래소의 심볼 명명 규칙에 맞게 조정되어야 합니다. 예를 들어, Vertex 계약의 거래 쌍은 다음과 같이 명명됩니다.XXX_USD이는 실제로 USDC를 기반으로 하는 영구 계약입니다. Vertex의 위치에서 ETH의 이름은 WETH입니다.

정확도를 얻으세요: 초기화하는 동안 전체 시장 정보를 얻습니다. 요청된 특정 심볼에 따라 후속 데이터 정밀도 처리 작업을 위해 해당 정밀도를 쿼리할 수 있습니다.

데이터 요청 모든 심도 데이터를 얻기 전에 프로그램은 대기하며 데이터가 업데이트되지 않은 교환이 있는지 계속 확인합니다. 데이터를 얻지 못하면 프로그램은 100밀리초 동안 대기합니다. 요청된 주문장 데이터는 threading.Dict()에 의해 생성된 객체에 기록되고(동시 스레드와의 상호작용에 사용됨), 데이터는 각 폴이 끝날 때 재설정됩니다.

요약하다 이 전략 구현은 여러 거래소의 가격 차이를 실시간으로 모니터링하고 가능한 차익거래 기회를 계산하는 방법을 보여줍니다. 합리적인 기호 수정, 심층적인 데이터 수집, 정밀한 제어 및 다중 스레드 작업을 통해 시스템은 실시간 가격 차이를 효율적으로 모니터링할 수 있습니다. 전략 학습자의 경우 이 코드의 구현 아이디어를 이해하면 API를 사용하여 거래 데이터를 얻는 방법, 여러 거래소의 데이터를 처리하는 방법, 거래 스프레드를 계산하고 출력하는 방법, 이러한 기술을 실제 거래에 적용하는 방법을 익히는 데 도움이 될 수 있습니다.

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

매개변수 설계:

FMZ 정량화 기반 DEX-CEX 거래소 가격 차이 모니터링 설계 및 구현

현물 시장

스팟 제품 모니터링:

  • BTC_USDC 비트코인 ​​대 USDC 현물

FMZ 정량화 기반 DEX-CEX 거래소 가격 차이 모니터링 설계 및 구현

계약 시장

두 가지 종류를 모니터링합니다.

  • ETH_USDC.swap 이더리움 영구 계약
  • BTC_USDC.swap 비트코인 ​​영구 계약

FMZ 정량화 기반 DEX-CEX 거래소 가격 차이 모니터링 설계 및 구현

END

확장 방향:

  • 트랜잭션 로직의 임계값 모니터링 및 캡슐화.
  • 수수료와 비용을 계산하고, 합리적인 헤지 스프레드 범위를 계산하세요.
  • 웹소켓 인터페이스를 사용하여 시장 데이터를 얻으세요.

FMZ 플랫폼은 분산형 거래소(DEX)와 분산형 금융(DeFi)에 대한 기술 지원을 지속적으로 강화하고, 기능과 제품을 지속적으로 반복하고 업데이트할 것입니다.

읽어주셔서 감사합니다.