
Dans les derniers articles, nous avons discuté de l’accès aux DEX grand public, et cet article se concentrera sur l’utilisation réelle et effectuera des tests de déploiement de stratégie réels. La plateforme FMZ a récemment ajouté la prise en charge des échanges décentralisés WOOFi et EdgeX. Dans cet article, nous allons nous exercer à mettre en œuvre quelques stratégies d’enseignement simples sur ces deux échanges.
Connectez votre portefeuille sur WOOFi, puis sur la page API KEY, vous pouvez afficher les informations de la clé API, la copier et la coller et la configurer sur FMZ.
Utilisez le dernier hôte de FMZ, qui prend déjà en charge WOOFi DEX et EdgeX DEX, après le téléchargement et le déploiement. Configurez l’objet d’échange sur la page : https://www.fmz.com/m/platforms/add, et configurez AccountId, AccessKey et SecretKey de WOOFi.
Dans ce test, nous avons utilisé unPrototype de stratégie de base de création de marché, combiné à l’indicateur de volatilité du marché (ATR), l’intervalle entre les ordres en attente est calculé de manière dynamique, et l’identification intelligente des positions et la logique de passation des ordres avec priorité sur la clôture des positions sont réalisées. La stratégie actualise le carnet d’ordres à chaque tour, réacquiert les informations de profondeur et de position et place les ordres en fonction de l’intervalle de prix et de la quantité d’ordre définis. L’ensemble du processus couvre :
Grâce à cette stratégie, nous pouvons observer l’efficacité réelle des transactions, le délai de commande et l’expérience de correspondance sur WOOFi, jetant les bases de la conception ultérieure de stratégies plus complexes.
Nous utilisons l’environnement de test et le réseau de test de WOOFi : Arbitrum Sepolia.
exchange.SetBase(”https://testnet-api.orderly.org”)
Il existe un robinet sur le réseau de test WOOFi qui vous permet d’obtenir facilement des USDC pour les tests.
Code de stratégie :
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)
}
}
Pratique de stratégie sur WOOFi



Les informations API pour la configuration d’EdgeX sur FMZ sont fondamentalement les mêmes que celles de WOOFi, mais différents échanges nécessitent des informations API différentes. Sur EdgeX, vous devez uniquement configurer AccountId et SecretKey. Ceux-ci peuvent également être consultés sur la page de gestion de l’API du compte après avoir utilisé le portefeuille pour se connecter au front-end EdgeX.
La stratégie que nous allons mettre en œuvre sur EdgeX est basée surBandes de Bollinger multicouchesLa logique de trading quantitative d’ouverture inversée + clôture à mi-parcours peut réaliser un arbitrage de volatilité à court terme.
La stratégie est très simple, l’idée principale est :
Vous ne le croirez peut-être pas, mais écrire une stratégie complète sur FMZ ne prend que 50 lignes de code. Le développement actuel de grands modèles d’IA a considérablement abaissé le seuil de conception de stratégies. Les idées de stratégie que nous avons testées peuvent être facilement produites par l’IA, et la qualité de rédaction est suffisante. La seule chose est qu’une correction manuelle est nécessaire, mais cela a considérablement abaissé le seuil pour que les gens ordinaires utilisent la technologie de trading quantitatif.
Code de stratégie :
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)
}
}
Commençons par effectuer un backtest à long terme :


Déployer le test EdgeX

Les stratégies ci-dessus sont destinées uniquement à des fins d’enseignement et de recherche. Soyez prudent lorsque vous les appliquez. Merci de votre lecture.