
Beberapa bursa DEX, termasuk dydx_v4, hyperliquid, vertex, dan aevo, telah dienkapsulasi dan dihubungkan pada FMZ. Karena persaingan untuk arbitrase harga di bursa terpusat menjadi semakin ketat, banyak pedagang kuantitatif telah mengalihkan perhatian mereka ke bursa terdesentralisasi. Dalam artikel ini, kita akan membahas desain dan implementasi pemantauan perbedaan harga antara DEX dan CEX.
Langkah pertama dari strategi arbitrase lindung nilai adalah menghitung perbedaan harga portofolio target dan mengamati serta menganalisis apakah ada peluang perdagangan. Oleh karena itu, merancang dan menerapkan strategi pemantauan perbedaan harga merupakan tugas dasar pertama. Persyaratan desain kami adalah:
Kodenya kurang dari 200 baris, dan fungsi yang dirancang hanya untuk menghitung perbedaan harga waktu nyata suatu produk tertentu di bursa yang berbeda. Saat strategi pertama kali dijalankan, semua objek pertukaran yang dikonfigurasi untuk strategi tersebut akan diklasifikasikan ke dalam grup DEX dan grup CEX. Setiap jajak pendapat dilakukan melalui fungsi multi-utas Thread yang dienkapsulasi oleh platform FMZ, dan secara bersamaan meminta antarmuka REST: antarmuka buku pesananGetDepth, mencatat data daftar pesanan beli yang diminta dan data daftar pesanan jual dari berbagai jenis yang dibutuhkan. Kemudian, grup DEX dan grup CEX digabungkan menjadi kombinasi perbedaan (kombinasi DEX-CEX, yaitu pasangan arbitrase), dan perbedaan harga dihitung.
Penentuan jenis pertukaran: Selama inisialisasi, objek pertukaran yang ditambahkan akan dinilai untuk menentukan apakah itu spot atau futures.
Bursa yang berbeda mungkin memiliki nama yang berbeda untuk aset dasar tertentu, sehingga nama produk perlu disesuaikan:
Program perlu disesuaikan dengan aturan penamaan simbol di berbagai bursa. Misalnya, pasangan perdagangan kontrak Vertex diberi nama sebagai berikut:XXX_USD, yang sebenarnya merupakan kontrak abadi berdasarkan USDC. Nama ETH di spot Vertex adalah WETH.
Dapatkan presisi: Selama inisialisasi, seluruh informasi pasar diperoleh. Berdasarkan simbol tertentu yang diminta, presisi yang sesuai dapat ditanyakan untuk operasi pemrosesan presisi data berikutnya.
Permintaan Data Sebelum semua data kedalaman diperoleh, program akan menunggu dan terus memeriksa apakah ada pertukaran yang datanya belum diperbarui. Jika data belum diperoleh, program akan tidur selama 100 milidetik. Data buku pesanan yang diminta dicatat dalam objek yang dibuat oleh threading.Dict() (digunakan untuk interaksi dengan thread bersamaan), dan data tersebut diatur ulang di akhir setiap jajak pendapat.
Meringkaskan Implementasi strategi ini menunjukkan cara memantau perbedaan harga di berbagai bursa secara real time dan menghitung kemungkinan peluang arbitrase. Melalui koreksi simbol yang wajar, penangkapan data yang mendalam, kontrol presisi dan operasi multi-utas, sistem dapat secara efisien memantau perbedaan harga waktu nyata. Bagi pembelajar strategi, memahami ide implementasi kode ini dapat membantu mereka menguasai cara menggunakan API untuk memperoleh data transaksi, cara memproses data dari berbagai bursa, cara menghitung dan mengeluarkan spread transaksi, serta cara menerapkan teknologi ini dalam transaksi sebenarnya.
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)
}
}
Desain parameter:

Memantau produk spot:

Pantau dua varietas:

Arah ekspansi:
Platform FMZ akan terus meningkatkan dukungan teknisnya untuk bursa terdesentralisasi (DEX) dan keuangan terdesentralisasi (DeFi), dan terus mengulangi dan memperbarui fungsi dan produk.
Terima kasih telah membaca.