En réponse aux besoins de nombreux utilisateurs, la plate-forme FMZ a récemment pris en charge la plate-forme décentralisée dYdX. Les amis ayant des stratégies peuvent extraire sur dYdX avec plaisir. Il y a très longtemps, je voulais écrire une stratégie de trading aléatoire. Peu importe que je fasse du profit ou non. Le but est de pratiquer ma technique et d'enseigner la conception de la stratégie en passant.
La capture d'écran de la stratégie minière dans l'article.
Bienvenue aux amis qui ont de bonnes idées de stratégie minière à partager!
Nous prévoyons de concevoir une stratégie pour placer des ordres au hasard sans regarder les indicateurs ou les prix. L'ordre n'est rien de plus que faire long et court, ce qui est parier sur la probabilité. Ensuite, nous utilisons des nombres aléatoires de 1 à 100 pour déterminer si faire long ou faire court.
Condition de faire long: nombres aléatoires de 1 à 50. Condition de faire court: nombres aléatoires de 51 à 100.
Les positions longues et courtes ont toutes deux besoin de 50 chiffres. Ensuite, réfléchissons à la façon de fermer les positions. Puisqu'il s'agit d'un pari, il doit y avoir un standard gagnant ou perdant. Ensuite, définissons un stopProfit et un stopLoss fixes comme norme de gain ou de perte. Prenons stopProfit comme gain et stopLoss comme perte. Quant à l'adéquation de stopProfit et stopLoss, cela affecte en fait le ratio profit-perte, ainsi que le taux de gain! (Est-il efficace de concevoir une stratégie de cette façon? Peut-on garantir qu'il s'agit d'une attente mathématique positive? Quoi qu'il en soit, faisons-le d'abord! Parce que c'est pour l'apprentissage et la recherche!)
Le trading n'est pas gratuit, et il y a des facteurs tels que le point de glissement et les frais qui sont suffisants pour tirer notre taux de gain de trading aléatoire à moins de 50%. Il est préférable de concevoir l'échelle par multiple pour augmenter les positions. Puisqu'il s'agit d'un pari, la probabilité de perdre successivement 10 ou 8 fois ne devrait pas être très grande. Je veux donc concevoir en plaçant un petit montant d'ordre dans le premier commerce, aussi petit que possible. Ensuite, si je perds le pari, augmentez le montant de l'ordre et continuez à placer des ordres aléatoires.
La stratégie est très simple.
Code source du dessin:
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 "Position detected when starting the strategy!"
}
exchange.SetPrecision(pricePrecision, amountPrecision)
Log("setPrecision", 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 "fail to obtain the initial equity"
}
} else {
totalEq = recoverTotalEq
}
} else {
totalEq = _C(exchange.GetAccount).Balance
}
while (1) {
if (openPrice == 0) {
// update account information, and calculate the profit
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 ? "buy order" : "sell 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
}
// detect close positions
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
// plot
$.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
}
// detect 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)
// after canceling, update positions, which needs to be detected 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 pending orders
// reset openPrice
cancelAll()
openPrice = 0
}
Sleep(1000)
}
}
Paramètres de stratégie:
La stratégie a besoin d'un nom, et appelons-la " Devinez lequel est le plus grand (version dYdX).
Le backtest est juste pour référence! Il s'agit principalement de vérifier s'il y a des bugs dans la stratégie; backtest avec Binance Futures.
Le backtest est terminé, pas de bugs, mais j'ai l'impression que le système de backtest a été assorti... allons le faire fonctionner dans un vrai bot pour l'observation.
Cette stratégie est uniquement à des fins d'apprentissage et de référence.Ne le fais pas.!! Ne le fais pas.Utilisez-le dans un vrai robot!