In response to the needs of many users, FMZ platform recently has supported the decentralized platform dYdX. Friends with strategies can mine on dYdX happily. Just a long time ago, I wanted to write a random trading strategy. It doesn't matter if I make profit or not. The purpose is to practice my technique and teach the strategy design by the way. So next, let's design a random platform strategy together. Don't worry about the performance of the strategy, and just learn the strategy design.
First Share the Mining
The mining screenshot of the strategy in the article.
/upload/asset/171ae7f5f6eeb7a3a977.png
Welcome friends who have good mining strategy ideas to share!
Random Trading Strategy Design
Let's have a brainstorm! We plan to design a strategy to place orders randomly without looking at indicators or prices. Ordering is nothing more than doing long and short, which is betting on probability. Then we use random numbers from 1 to 100 to determine whether doing long or doing short.
Condition of doing long: random numbers from 1 to 50.
Condition of doing short: random numbers from 51 to 100.
Doing long and short both need 50 numbers. Next, let's think about how to close positions. Since it is a bet, there must be a winning or losing standard. Then, let's set a fixed stopProfit and stopLoss as the standard of winning or losing. Take stopProfit as win, and stopLoss as lose. As for the appropriateness of stopProfit and stopLoss, it actually affects the profit and loss ratio, and the winning rate as well! (Is it effective to design a strategy in this way? Can it be guaranteed to be a positive mathematical expectation? Anyway, let’s do it first! Because it’s for learning and research!)
Trading is not cost-free, and there are factors such as slippoint and fees that are enough to pull our random trading winning rate to the side of less than 50%. Thinking of that, how to continue the design from here?
It is better to design scaling in by multiple to increase positions. Since it is a bet, the probability of successively losing 10 or 8 times should not be very large. So I want to design placing a small order amount in the first trade, as small as it can be. Then if I lose the bet, increase the order amount and continue to place random orders.
OK. The strategy is fine as simple as this.
Source code of the design:
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) } }
Strategy parameters:
/upload/asset/2694e8bcc528d437cc0cb.png
Alright! The strategy needs a name, and let's call it "Guess Which is Bigger (dYdX version).
Backtest
The backtest is just for reference!
It is mainly to check whether there are any bugs in the strategy; backtest with Binance Futures.
/upload/asset/268e64a6694b7c16a3da4.png
/upload/asset/166183dd960364f31622.png
/upload/asset/178bd94c3daf625671f6.png
/upload/asset/16696fe5bc71fdbf1d3e.png
The backtest is over, no bugs. But I feel like the backtest system was matched… let's run it in a real bot for observation.
Run in a Bot
/upload/asset/16a557dfccb3c7f68792.png
/upload/asset/163e177a6455396c096b.png
/upload/asset/167a21e95674da97ca9d.png
This strategy is only for learning and reference Don't!! Don't use it in a real bot ! !