Skip to content

Learn trading

Backtesting honestly

Trading on margin can lose you more than you put in. Past results, including backtests, do not predict future results. Cloud9Trader provides tools and education, not financial advice. Read the full risk warning.

A backtest runs your algorithm against past prices and shows what it would have done. It is the cheapest way to find out that an idea does not work. It cannot show that an idea will work: the past is one path out of many, and markets change.

Treat a good backtest as permission to test further, not as a forecast.

  • Too little data. Ten trades prove nothing. Look for hundreds, across quiet and busy markets and more than one year.
  • Costs left out. Real trading has slippage (filling at a worse price than you saw), commission at some brokers, and financing on positions held overnight.
  • Look-ahead bias. A rule that uses information it could not have had at the time, such as a bar’s close before the bar has closed, looks brilliant and cannot be traded.
  • Survivorship bias. Testing only on markets that are still around today leaves out the ones that collapsed. This matters most for stocks and coins.
  • Overfitting. Tuning settings until the past looks perfect. See Overfitting and optimization.

The code that backtests your algorithm is the same code that runs it live. Only the broker behind it changes, from a real one to an emulated one fed with past prices.

  • Fills. A buy fills at the historical ask and a sell at the historical bid, instantly. The spread is whatever the data shows. There is no slippage, no commission and no financing, so live results will be somewhat worse.
  • Stops and targets. Checked on every price. If the price jumps past a stop, it fills at the jumped price, as it would live.
  • Margin. Each position uses margin at the instrument’s margin rate, and if available margin reaches zero every position is closed as a margin call.
  • Every tick or minute data. Every tick replays each recorded price change. Minute data replays each minute as four prices, open, high, low, close, always in that order. That is quicker, but it cannot know whether the high or the low came first, so a stop loss and a take profit inside the same minute can trigger in the wrong order. If your stops are close to the price, check the result on every tick.

A worked example: 200 trades, 80 winners averaging 30 dollars and 120 losers averaging 15 dollars.

  • Win rate: 80 ÷ 200 = 40%. On its own it says little.
  • Expectancy (average result per trade): (0.40 × 30) − (0.60 × 15) = 12 − 9 = 3 dollars. Positive, but small: costs of 3 dollars a trade would erase it.
  • Profit factor (gross gains ÷ gross losses): (80 × 30) ÷ (120 × 15) = 2,400 ÷ 1,800 = 1.33.
  • Maximum drawdown: the largest fall from a peak in equity to a later low. Ask whether you could sit through it with real money.

The backtest Dashboard shows Total Profit, Return, Maximum Drawdown, Position Count and Realized Pips, with daily and monthly Sharpe and Sortino ratios, which compare return with how bumpy it was. The Positions list exports to CSV if you want to compute win rate and expectancy yourself. In the list of an algorithm’s backtests, Return / Drawdown is the return divided by the maximum drawdown. It is not a profit factor (gross gains divided by gross losses).