In response to the demand of many users, the FMZ platform has accessed dYdX recently, a decentralized exchange. Someone who have strategies can enjoy the process of acquiring digital currency dYdX. I just wanted to write a stochastic trading strategy for a long time ago, it doesn't matter whether it make profits. So next we come together to design a stochastic exchange strategy, no matter the strategy performs good or not, we just learn the strategy design.
Let's look at the process of acquiring digital currency
The screenshot of acquiring digital currency strategy in this article:
Stochastic trading strategy design
Let's have a brainstorm! It is planned to design a strategy of placing orders randomly with random indicators and prices. Placing orders is nothing more than going long or going short, just betting on the probability. Then we will use the random number 1~100 to determine whether to go long or go short.
Condition for going long : random number 1~50.
Condition for going short : random number 51~100.
Thus both going long and going short are 50 numbers. Next, let's think about how to close the position, since it is a bet, then there must be a criteria for win or lose. We set a criteria for fixed stop profit and loss in the transaction. Stop profit for the winning, stop loss for the losing. As for the amount of stop profit and loss, it is actually the impact of the profit and loss ratio, oh yes! It also affect the win rate! (Is this strategy design effective? Can it be guaranteed as a positive mathematical expectations? Do it first! (After, it is just for learning, research!)
Trading is not cost-free, there is enough slippage, fees, etc. to pull our stochastic trading win rate towards the side of less than 50%. So how to design it continuely?
How about designing a multiplier to increase the position? Since it is a bet, then the probability of losing for 8~10 times in a row of random trades should be low. So the first transaction was designed to place a small amount of orders, as small as possible. Then if I lose, I will increase the amount of orders and continue to place orders randomly.
OK, the strategy is designed simply.
Source code designed:
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) } }
Strategy parameters:
Oh yes! The strategy needs a name, let's call it "guess the size (dYdX version)".
Backtest
Backtesting is for reference only, >_<!
The main purpose is to check whether there is any bug in the strategy, backtesting by Binance Futures.
The backtest has finished, there is no bug.
This strategy is used for learning and reference only, do not use it in the real bot!