
Als Reaktion auf zahlreiche Benutzeranforderungen unterstützte die FMZ-Plattform kürzlich die dezentrale Börse dYdX. Freunde mit Strategien können glücklich dYdX abbauen. Es war einfach so, dass ich schon vor langer Zeit eine zufällige Handelsstrategie schreiben wollte. Dabei war es egal, ob ich damit Geld verdiente oder verlor. Der Zweck bestand darin, Strategiedesign zu üben und gleichzeitig zu lehren. Lassen Sie uns also gemeinsam eine Strategie für den zufälligen Austausch entwickeln. Machen Sie sich keine Sorgen über die Leistung der Strategie. Lernen wir einfach etwas über Strategieentwicklung.
Screenshot des strategischen Bergbaus in diesem Artikel.

Freunde, die gute Ideen für Bergbaustrategien haben, können ebenfalls gerne eine Nachricht hinterlassen!
Lasst uns „wild denken“! Ich habe vor, eine Strategie zu entwickeln, die zufällig Aufträge erteilt, ohne Indikatoren oder Preise zu berücksichtigen. Aufträge sind nichts anderes als Long- oder Short-Positionen, und Sie müssen lediglich die Wahrscheinlichkeiten vorhersagen. Dann verwenden wir Zufallszahlen von 1 bis 100, um Long und Short zu bestimmen.
Lange Bedingungen: Zufallszahlen 1–50. Bedingungen für Leerverkäufe: Zufallszahlen 51–100.
Die Zahlen für Long- und Short-Positionen betragen 50. Als nächstes überlegen wir, wie wir die Position schließen. Da es sich um ein Glücksspiel handelt, muss es einen Standard für Gewinn und Verlust geben. Dann legen wir bei der Transaktion feste Take-Profit- und Stop-Loss-Werte als Maßstab für Gewinn oder Verlust fest. Wenn Sie den Gewinn stoppen, gewinnen Sie; wenn Sie den Verlust stoppen, verlieren Sie. Was die entsprechenden Take-Profit- und Stop-Loss-Einstellungen betrifft, so wirkt sich dies tatsächlich auf das Gewinn- und Verlustverhältnis aus, oh ja! Es wirkt sich auch auf die Gewinnrate aus! (Ist diese Designstrategie effektiv? Kann sie eine positive mathematische Erwartung garantieren? Lassen Sie es uns zuerst tun! Schließlich dient es zum Lernen und zur Forschung!)
Der Handel ist nicht kostenlos. Faktoren wie Slippage und Bearbeitungsgebühren reichen aus, um unsere Gewinnquote beim zufälligen Handel auf unter 50 % zu drücken. Wie sollte ich unter Berücksichtigung dieser Tatsache weiter entwerfen? Es ist besser, eine Erhöhung mehrerer Positionen zu planen. Da es sich um ein Glücksspiel handelt, sollte die Wahrscheinlichkeit, 8 von 10 zufälligen Transaktionen hintereinander zu verlieren, nicht sehr hoch sein. Deshalb möchte ich die erste Transaktion so gestalten, dass die Bestellgröße sehr klein ist, so klein wie möglich. Wenn Sie die Wette dann verlieren, erhöhen Sie die Bestellmenge und erteilen Sie weiterhin zufällige Bestellungen.
OK, so einfach ist die Strategiegestaltung.
Design-Quellcode:
var openPrice = 0
var ratio = 1
var totalEq = null
var nowEq = null
function cancelAll() {
while (1) {
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
break
}
for (var i = 0 ; i < orders.length ; i++) {
exchange.CancelOrder(orders[i].Id, orders[i])
Sleep(500)
}
Sleep(500)
}
}
function main() {
if (isReset) {
_G(null)
LogReset(1)
LogProfitReset()
LogVacuum()
Log("重置所有数据", "#FF0000")
}
exchange.SetContractType(ct)
var initPos = _C(exchange.GetPosition)
if (initPos.length != 0) {
throw "策略启动时有持仓!"
}
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("设置精度", pricePrecision, amountPrecision)
if (!IsVirtual()) {
var recoverTotalEq = _G("totalEq")
if (!recoverTotalEq) {
var currTotalEq = _C(exchange.GetAccount).Balance // equity
if (currTotalEq) {
totalEq = currTotalEq
_G("totalEq", currTotalEq)
} else {
throw "获取初始权益失败"
}
} else {
totalEq = recoverTotalEq
}
} else {
totalEq = _C(exchange.GetAccount).Balance
}
while (1) {
if (openPrice == 0) {
// 更新账户信息,计算收益
var nowAcc = _C(exchange.GetAccount)
nowEq = IsVirtual() ? nowAcc.Balance : nowAcc.Balance // equity
LogProfit(nowEq - totalEq, nowAcc)
var direction = Math.floor((Math.random()*100)+1) // 1~50 , 51~100
var depth = _C(exchange.GetDepth)
if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
Sleep(1000)
continue
}
if (direction > 50) {
// long
openPrice = depth.Bids[1].Price
exchange.SetDirection("buy")
exchange.Buy(Math.abs(openPrice) + slidePrice, amount * ratio)
} else {
// short
openPrice = -depth.Asks[1].Price
exchange.SetDirection("sell")
exchange.Sell(Math.abs(openPrice) - slidePrice, amount * ratio)
}
Log("下", direction > 50 ? "买单" : "卖单", ",价格:", Math.abs(openPrice))
continue
}
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
var pos = _C(exchange.GetPosition)
if (pos.length == 0) {
openPrice = 0
continue
}
// 平仓检测
while (1) {
var depth = _C(exchange.GetDepth)
if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
Sleep(1000)
continue
}
var stopLossPrice = openPrice > 0 ? Math.abs(openPrice) - stopLoss : Math.abs(openPrice) + stopLoss
var stopProfitPrice = openPrice > 0 ? Math.abs(openPrice) + stopProfit : Math.abs(openPrice) - stopProfit
var winOrLoss = 0 // 1 win , -1 loss
// 画线
$.PlotLine("bid", depth.Bids[0].Price)
$.PlotLine("ask", depth.Asks[0].Price)
// 止损
if (openPrice > 0 && depth.Bids[0].Price < stopLossPrice) {
exchange.SetDirection("closebuy")
exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)
winOrLoss = -1
} else if (openPrice < 0 && depth.Asks[0].Price > stopLossPrice) {
exchange.SetDirection("closesell")
exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
winOrLoss = -1
}
// 止盈
if (openPrice > 0 && depth.Bids[0].Price > stopProfitPrice) {
exchange.SetDirection("closebuy")
exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)
winOrLoss = 1
} else if (openPrice < 0 && depth.Asks[0].Price < stopProfitPrice) {
exchange.SetDirection("closesell")
exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
winOrLoss = 1
}
// 检测挂单
Sleep(2000)
var orders = _C(exchange.GetOrders)
if (orders.length == 0) {
pos = _C(exchange.GetPosition)
if (pos.length == 0) {
if (winOrLoss == -1) {
ratio++
} else if (winOrLoss == 1) {
ratio = 1
}
break
}
} else {
// 撤销挂单
cancelAll()
Sleep(2000)
pos = _C(exchange.GetPosition)
// 撤销后更新持仓,需要再次检查
if (pos.length == 0) {
if (winOrLoss == -1) {
ratio++
} else if (winOrLoss == 1) {
ratio = 1
}
break
}
}
var tbl = {
"type" : "table",
"title" : "info",
"cols" : ["totalEq", "nowEq", "openPrice", "bid1Price", "ask1Price", "ratio", "pos.length"],
"rows" : [],
}
tbl.rows.push([totalEq, nowEq, Math.abs(openPrice), depth.Bids[0].Price, depth.Asks[0].Price, ratio, pos.length])
tbl.rows.push(["pos", "type", "amount", "price", "--", "--", "--"])
for (var j = 0 ; j < pos.length ; j++) {
tbl.rows.push([j, pos[j].Type, pos[j].Amount, pos[j].Price, "--", "--", "--"])
}
LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
}
} else {
// 撤销挂单
// 重置openPrice
cancelAll()
openPrice = 0
}
Sleep(1000)
}
}
Strategieparameter:

Ach ja! Die Strategie braucht einen Namen, nennen wir sie „Rate die Größe (dYdX-Version)“.
Backtesting dient nur zu Referenzzwecken._<! Der Hauptzweck besteht darin, zu prüfen, ob die Strategie Fehler enthält, und ein Backtesting der Binance-Futures durchzuführen.




Backtesting ist abgeschlossen, keine Fehler. Aber ich habe das Gefühl, dass ich das Backtest-System möglicherweise überangepasst habe … T_T, lass es mich in Echtzeit ausprobieren.



Diese Strategie dient ausschließlich zu Lern- und Referenzzwecken.10 Millionen~10 MillionenVerwenden Sie es nicht im Ernst! !