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.
The mining screenshot of the strategy in the article.
Welcome friends who have good mining strategy ideas to share!
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:
Alright! The strategy needs a name, and let’s call it "Guess Which is Bigger (dYdX version).
The backtest is just for reference! It is mainly to check whether there are any bugs in the strategy; backtest with Binance Futures.
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.
This strategy is only for learning and reference. Don’t!! Don’t use it in a real bot ! !