
Trong một vài bài viết trước, chúng tôi đã thảo luận về quyền truy cập vào các DEX chính thống và bài viết này sẽ tập trung vào cách sử dụng thực tế và tiến hành các thử nghiệm triển khai chiến lược thực tế. Nền tảng FMZ gần đây đã bổ sung hỗ trợ cho các sàn giao dịch phi tập trung WOOFi và EdgeX. Trong bài viết này, chúng ta sẽ thực hành chạy một số chiến lược giảng dạy đơn giản trên hai sàn giao dịch này.
Kết nối ví của bạn trên WOOFi, sau đó trên trang API KEY, bạn có thể xem thông tin khóa API, sao chép, dán và định cấu hình trên FMZ.
Sử dụng máy chủ mới nhất của FMZ, hiện đã hỗ trợ WOOFi DEX và EdgeX DEX, sau khi tải xuống và triển khai. Cấu hình đối tượng trao đổi trên trang: https://www.fmz.com/m/platforms/add và cấu hình AccountId, AccessKey và SecretKey của WOOFi.
Trong thử nghiệm này, chúng tôi đã sử dụng mộtNguyên mẫu chiến lược tạo lập thị trường cơ bản, kết hợp với chỉ báo biến động thị trường (ATR), khoảng thời gian giữa các lệnh chờ được tính toán động và nhận dạng thông minh các vị thế cùng logic đặt lệnh với ưu tiên đóng các vị thế được thực hiện. Chiến lược này làm mới sổ lệnh ở mỗi vòng, lấy lại thông tin về độ sâu và vị thế, rồi đặt lệnh theo khoảng giá đã đặt và số lượng lệnh. Toàn bộ quá trình bao gồm:
Thông qua chiến lược này, chúng ta có thể quan sát hiệu quả giao dịch thực tế, độ trễ đơn hàng và trải nghiệm khớp lệnh trên WOOFi, đặt nền tảng cho việc thiết kế các chiến lược phức tạp hơn sau này.
Chúng tôi sử dụng môi trường thử nghiệm và mạng thử nghiệm của WOOFi: Arbitrum Sepolia.
exchange.SetBase(”https://testnet-api.orderly.org”)
Có một vòi trên mạng thử nghiệm WOOFi cho phép bạn dễ dàng lấy USDC để thử nghiệm.
Mã chiến lược:
function createOrders(e, symbol, side, ordersNum, beginPrice, firstAmount, spacing, pos) {
if (side == "buy" || side == "closesell") {
if (spacing > 0) {
throw "spacing error"
}
} else if (side == "sell" || side == "closebuy") {
if (spacing < 0) {
throw "spacing error"
}
} else {
throw "side error"
}
var holdAmount = 0
if (pos) {
holdAmount = pos.Amount
}
var amount = firstAmount
for (var i = 0 ; i < ordersNum ; i++) {
var id = null
amount = amount * 2
var price = beginPrice + i * spacing
if (price <= 0 || amount <= 0) {
Log("continue loop:", price, amount, "#FF0000")
continue
}
if (holdAmount - amount >= 0) {
id = e.CreateOrder(symbol, side == "buy" ? "closesell" : "closebuy", price, holdAmount)
holdAmount = 0
} else {
id = e.CreateOrder(symbol, side, price, amount)
}
Sleep(100)
}
}
function cancelAll(e, symbol) {
while (true) {
var orders = _C(e.GetOrders, symbol)
var sideOrders = []
for (var o of orders) {
sideOrders.push(o)
}
if (sideOrders.length == 0) {
break
}
for (var o of sideOrders) {
e.CancelOrder(o.Id, o)
}
Sleep(500)
}
}
function main() {
LogReset(1)
LogProfitReset()
exchange.SetBase("https://testnet-api.orderly.org")
// 参数
var symbol = "ETH_USDC.swap"
var ordersNum = 5
var orderAmount = 0.01
var priceSpace = 0
// 初始化
exchange.SetPrecision(2, 3)
var msg = []
var buyOrdersNum = ordersNum
var sellOrdersNum = ordersNum
while (true) {
cancelAll(exchange, symbol)
var r = _C(exchange.GetRecords, symbol, 60 * 5)
var art = TA.ATR(r, 20)
priceSpace = art[art.length - 1]
var pos = _C(exchange.GetPositions, symbol)
// depth
var depth = _C(exchange.GetDepth, symbol)
if (depth.Bids.length == 0 || depth.Asks.length == 0) {
msg.push("invalid depth")
} else {
var bid1Price = depth.Bids[0].Price
var ask1Price = depth.Asks[0].Price
var longPos = null
var shortPos = null
for (var p of pos) {
if (p.Type == PD_LONG) {
longPos = p
} else if (p.Type == PD_SHORT) {
shortPos = p
}
}
// long
createOrders(exchange, symbol, "buy", buyOrdersNum, bid1Price, orderAmount, -priceSpace, shortPos)
// short
createOrders(exchange, symbol, "sell", sellOrdersNum, ask1Price, orderAmount, priceSpace, longPos)
}
var acc = _C(exchange.GetAccount)
var orders = _C(exchange.GetOrders, symbol)
LogProfit(acc.Equity, "&")
var posTbl = {"type": "table", "title": "pos", "cols": ["Symbol", "Type", "Price", "Amount"], "rows": []}
for (var p of pos) {
posTbl["rows"].push([p.Symbol, p.Type == PD_LONG ? "多" : "空", p.Price, p.Amount])
}
var ordersTbl = {"type": "table", "title": "orders", "cols": ["Symbol", "Type", "Price", "Amount"], "rows": []}
for (var o of orders) {
ordersTbl["rows"].push([o.Symbol, o.Type == ORDER_TYPE_BUY ? "买" : "卖", o.Price, o.Amount])
}
LogStatus(_D(), "priceSpace:", priceSpace, "\n`" + JSON.stringify([posTbl, ordersTbl]) + "`")
Sleep(1000 * 60)
LogReset(1000)
}
}
Thực hành chiến lược trên WOOFi



Thông tin API để cấu hình EdgeX trên FMZ về cơ bản giống với thông tin dành cho WOOFi, nhưng các sàn giao dịch khác nhau yêu cầu thông tin API khác nhau. Trên EdgeX, bạn chỉ cần cấu hình AccountId và SecretKey. Những thông tin này cũng có thể được xem trên trang quản lý API tài khoản sau khi sử dụng ví để kết nối với giao diện EdgeX.
Chiến lược chúng tôi sẽ triển khai trên EdgeX dựa trênDải Bollinger nhiều lớpLogic giao dịch định lượng mở cửa ngược + đóng cửa giữa chừng có thể nhận ra sự chênh lệch biến động ngắn hạn.
Chiến lược này rất đơn giản, ý tưởng cốt lõi là:
Bạn có thể không tin, nhưng việc viết một chiến lược hoàn chỉnh trên FMZ chỉ cần 50 dòng mã. Sự phát triển hiện tại của các mô hình AI lớn đã hạ thấp đáng kể ngưỡng thiết kế chiến lược. Các ý tưởng chiến lược mà chúng tôi thử nghiệm có thể dễ dàng được đưa ra bởi AI và chất lượng bài viết cũng đủ tốt. Vấn đề duy nhất là cần phải hiệu chỉnh thủ công, nhưng nó đã hạ thấp đáng kể ngưỡng sử dụng công nghệ giao dịch định lượng để những người bình thường có thể thực hiện.
Mã chiến lược:
function main() {
var symbol = "ETH_USDT.swap"
var arrUp = []
var arrDown = []
let c = KLineChart({
overlay: true
})
while (true) {
var bolls = []
var r = _C(exchange.GetRecords, symbol)
for (var i = 0; i < 3; i++) {
var boll = TA.BOLL(r, 20, i + 1)
bolls.push(boll)
var up = boll[0][boll[0].length - 1]
var mid = boll[1][boll[1].length - 1]
var down = boll[2][boll[2].length - 1]
var close = r[r.length - 1].Close
if (close > up && i >= arrUp.length) {
exchange.CreateOrder(symbol, "sell", -1, 0.01 * (i + 1))
arrUp.push({"symbol": symbol, "amount": 0.01 * (i + 1)})
} else if (close < down && i >= arrDown.length) {
exchange.CreateOrder(symbol, "buy", -1, 0.01 * (i + 1))
arrDown.push({"symbol": symbol, "amount": 0.01 * (i + 1)})
} else if ((arrUp.length > 0 && close < mid) || (arrDown.length > 0 && close > mid)) {
var pos = exchange.GetPositions(symbol)
for (var p of pos) {
if (p.Type == PD_LONG) {
exchange.CreateOrder(symbol, "closebuy", -1, p.Amount)
} else if (p.Type == PD_SHORT) {
exchange.CreateOrder(symbol, "closesell", -1, p.Amount)
}
}
arrUp = []
arrDown = []
}
}
r.forEach(function(bar, index) {
c.begin(bar)
for (var i in bolls) {
var b = bolls[i]
c.plot(b[0][index], 'up_' + (i + 1))
c.plot(b[1][index], 'mid_' + (i + 1))
c.plot(b[2][index], 'down_' + (i + 1))
}
c.close()
})
LogStatus(_D(), "\n", arrUp, "\n", arrDown)
Sleep(500)
}
}
Trước tiên, chúng ta hãy thực hiện một thử nghiệm ngược dài hạn:


Triển khai thử nghiệm EdgeX

Các chiến lược trên chỉ dành cho mục đích giảng dạy và nghiên cứu. Hãy cẩn thận khi áp dụng chúng. Cảm ơn các bạn đã đọc.