Als Reaktion auf die Nachfrage vieler Benutzer hat die FMZ-Plattform kürzlich auf dYdX zugegriffen, eine dezentrale Börse. Jemand, der Strategien hat, kann den Prozess des Erwerbs der digitalen Währung dYdX genießen. Ich wollte vor langer Zeit nur eine stochastische Handelsstrategie schreiben, es spielt keine Rolle, ob sie Gewinne erzielt. Als nächstes kommen wir zusammen, um eine stochastische Austauschstrategie zu entwerfen, egal ob die Strategie gut funktioniert oder nicht, wir lernen nur das Strategiedesign.
Lassen Sie uns einen Brainstorming haben! Es ist geplant, eine Strategie zu entwerfen, um Befehle zufällig mit zufälligen Indikatoren und Preisen zu platzieren. Befehle zu platzieren ist nichts anderes als lang oder kurz zu gehen, nur auf die Wahrscheinlichkeit zu wetten. Dann werden wir die zufällige Zahl 1 ~ 100 verwenden, um zu bestimmen, ob man lang oder kurz geht.
Bedingung für den Long-Term: zufällige Zahl 1 bis 50. Bedingung für den Shorting: zufällige Zahl 51~100.
So sind sowohl Long als auch Short 50 Zahlen. Als nächstes sollten wir darüber nachdenken, wie man die Position schließt, da es sich um eine Wette handelt, dann muss es ein Kriterium für Gewinn oder Verlust geben. Wir setzen ein Kriterium für festes Stop-Profit und Verlust in der Transaktion fest. Stop-Profit für den Gewinn, Stop-Loss für den Verlust. Was die Menge des Stop-Profits und Verlustes angeht, so ist es eigentlich der Einfluss der Gewinn-Verlust-Ratio, oh ja! Es beeinflusst auch die Gewinnrate! (Ist dieses Strategie-Design effektiv? Kann es als positive mathematische Erwartungen garantiert werden? Machen Sie es zuerst! (Nachher ist es nur zum Lernen, Forschung!)
Der Handel ist nicht kostenlos, es gibt genug Slippage, Gebühren usw., um unsere stochastische Handelsgewinnrate auf die Seite von weniger als 50% zu ziehen. Wie entwerfen wir es also kontinuierlich? Wie wäre es mit dem Entwurf eines Multiplikators, um die Position zu erhöhen? Da es sich um eine Wette handelt, sollte die Wahrscheinlichkeit, dass ich 8 ~ 10 Mal in einer Reihe von zufälligen Trades verliere, gering sein. Die erste Transaktion wurde entworfen, um eine kleine Anzahl von Aufträgen zu platzieren, so klein wie möglich. Wenn ich dann verliere, erhöhe ich die Anzahl der Aufträge und werde weiterhin zufällig Aufträge platzieren.
Okay, die Strategie ist einfach.
Quellcode entworfen:
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("reset all data", "#FF0000")
}
exchange.SetContractType(ct)
var initPos = _C(exchange.GetPosition)
if (initPos.length != 0) {
throw "Strategy starts with a position!"
}
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("set the pricePrecision", 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 "failed to obtain initial interest"
}
} else {
totalEq = recoverTotalEq
}
} else {
totalEq = _C(exchange.GetAccount).Balance
}
while (1) {
if (openPrice == 0) {
// Update account information and calculate profits
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("place", direction > 50 ? "buying order" : "selling order", ", price:", 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
}
// Test for closing the position
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
// drawing the line
$.PlotLine("bid", depth.Bids[0].Price)
$.PlotLine("ask", depth.Asks[0].Price)
// stop loss
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
}
// stop profit
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
}
// Test the pending orders
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 {
// cancel pending orders
cancelAll()
Sleep(2000)
pos = _C(exchange.GetPosition)
// update the position after cancellation, and check it again
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 {
// cancel the pending orders
// reset openPrice
cancelAll()
openPrice = 0
}
Sleep(1000)
}
}
Strategieparameter:
Oh ja! Die Strategie braucht einen Namen, nennen wir sie
Das Backtesting ist nur zur Referenz, >_
Der Backtest ist abgeschlossen, es gibt keinen Fehler.
Diese Strategie dient nur zum Lernen und zur Referenz, nicht im echten Bot!