在过去的几篇文章中,我们围绕主流 DEX 的接入做了探讨,而本篇将聚焦于实际使用方面,进行实际策略部署测试。FMZ平台近期又新增支持了WOOFi和EdgeX去中心化交易所,本篇我们就一起在这两个交易所上实践运行一些简单的教学策略。
在WOOFi上连接钱包,然后在API KEY页面,可以查看到API秘钥信息,复制粘贴出来配置到FMZ上即可。
使用FMZ最新的托管者,已经支持WOOFi DEX和EdgeX DEX,下载、部署完成后。在页面: https://www.fmz.com/m/platforms/add 配置交易所对象,配置WOOFi的AccountId、AccessKey、SecretKey。
在本次测试中,我们使用了一个基础做市策略原型,结合市场波动率指标(ATR)动态计算挂单间距,并实现了对持仓的智能识别和平仓优先的下单逻辑。策略每轮刷新订单簿,重新获取深度与持仓信息,并按设定的价格间隔和下单数量进行挂单。整个流程涵盖了:
通过该策略,我们可以观察在 WOOFi 的实际成交效率、订单延迟、撮合体验,为后续设计更复杂的策略打下了基础。
我们使用WOOFi的测试环境、测试网:Arbitrum Sepolia。
exchange.SetBase(”https://testnet-api.orderly.org”)
在WOOFi测试网上有水龙头,可以很方便的获取测试用USDC。
策略代码:
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)
}
}
WOOFi上的策略实践
在FMZ上配置EdgeX的API信息与WOOFi基本一致,不过不同的交易所对于需要的API信息并不同,在EdgeX上只需要配置AccountId和SecretKey。这些同样在使用钱包连接EdgeX的前端后,在账户API管理页面查看。
对于在EdgeX上我们要实践的策略是一个基于多层布林带的反向开仓+中轨平仓的量化交易逻辑,实现短线波动套利。
策略十分简单,核心思路为:
可能您都不会相信,在FMZ上编写一个完整的策略竟然只有50行代码。目前AI大模型的发展给策略设计大大降低了门槛,我们测试的策略思路可以很轻松的让AI产出,编写质量也足够用,唯一的是需要人工修正,但是已经大大降低了普通人使用量化交易技术的门槛。
策略代码:
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)
}
}
我们先长期回测一下看看:
部署上EdgeX测试
以上策略仅教学研究为主,请谨慎实盘。感谢您的阅读。