
Nos últimos artigos, discutimos o acesso aos DEXs tradicionais, e este artigo se concentrará no uso real e conduzirá testes reais de implantação de estratégias. A plataforma FMZ adicionou recentemente suporte para as exchanges descentralizadas WOOFi e EdgeX. Neste artigo, praticaremos algumas estratégias simples de ensino nessas duas bolsas.
Conecte sua carteira no WOOFi e, na página API KEY, você poderá visualizar as informações da chave de API, copiá-las, colá-las e configurá-las no FMZ.
Use o host mais recente da FMZ, que já oferece suporte a WOOFi DEX e EdgeX DEX, após o download e a implantação. Configure o objeto de troca na página: https://www.fmz.com/m/platforms/add e configure o AccountId, AccessKey e SecretKey do WOOFi.
Neste teste, usamos umProtótipo básico de estratégia de criação de mercado, combinado com o indicador de volatilidade do mercado (ATR), o intervalo entre ordens pendentes é calculado dinamicamente, e a identificação inteligente de posições e a lógica de colocação de ordens com prioridade no fechamento de posições são realizadas. A estratégia atualiza o livro de ordens em cada rodada, readquire as informações de profundidade e posição e coloca ordens de acordo com o intervalo de preço e a quantidade de ordens definidos. Todo o processo abrange:
Por meio dessa estratégia, podemos observar a eficiência real da transação, o atraso do pedido e a experiência de correspondência no WOOFi, estabelecendo a base para o design subsequente de estratégias mais complexas.
Usamos o ambiente de teste e a rede de teste do WOOFi: Arbitrum Sepolia.
exchange.SetBase(”https://testnet-api.orderly.org”)
Há uma torneira na rede de testes WOOFi que permite que você obtenha USDC facilmente para testes.
Código de estratégia:
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)
}
}
Prática de estratégia no WOOFi



As informações de API para configurar o EdgeX no FMZ são basicamente as mesmas do WOOFi, mas diferentes exchanges exigem informações de API diferentes. No EdgeX, você só precisa configurar AccountId e SecretKey. Elas também podem ser visualizadas na página de gerenciamento da API da conta depois de usar a carteira para se conectar ao front-end do EdgeX.
A estratégia que vamos implementar no EdgeX é baseada emBandas de Bollinger multicamadasA lógica de negociação quantitativa de abertura reversa + fechamento intermediário pode realizar arbitragem de volatilidade de curto prazo.
A estratégia é muito simples, a ideia central é:
Você pode não acreditar, mas escrever uma estratégia completa no FMZ leva apenas 50 linhas de código. O desenvolvimento atual de grandes modelos de IA reduziu muito o limite para o design de estratégias. As ideias de estratégia que testamos podem ser facilmente produzidas por IA, e a qualidade da escrita é suficiente. A única coisa é que a correção manual é necessária, mas isso reduziu muito o limite para que pessoas comuns usem a tecnologia de negociação quantitativa.
Código de estratégia:
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)
}
}
Vamos fazer primeiro um backtest de longo prazo:


Teste de implantação do EdgeX

As estratégias acima são apenas para fins de ensino e pesquisa. Tenha cuidado ao aplicá-los. Obrigado pela leitura.