Backtester
The backtester replays a bot strategy over real historical price candles and reports how it would have performed — equity curve, drawdown, Sharpe ratio, and a full trade list. Critically, it runs the exact same tick() code that powers demo and live bots. There is no separate "simulation" strategy that might behave differently; a backtested result is the same program you'll later run for real.
Why this matters. Many platforms backtest with idealized logic and then trade with different code. GoodAI doesn't. The fill rules and fee model used in a backtest are the same shared engine demo bots use, so results carry over instead of evaporating in production.
Running a backtest
A backtest is defined by a few inputs:
| Input | What it is |
|---|---|
| Venue | The exchange to pull historical candles from (e.g. Binance, Bybit, Kraken). Candle history is per-venue. |
| Pair / symbol | The market to test, in canonical form (e.g. BTC-USDT). |
| Strategy (kind) | grid, dca, btd, or combo. |
| Interval | Candle granularity: 1h or 1m. 1-minute gives finer fills over short windows; 1-hour covers long ranges efficiently. |
| Date range | Start and end of the window. The UI offers presets — 6M, 1Y, 3Y, 5Y — or you can set custom dates (subject to your plan's window limit, below). |
| Strategy parameters | The same parameters as the live bot (grid count / order size; DCA base + safety orders, price step, take-profit; BTD order qty, MA period, dip %, take-profit, max lots; etc.). The symbol is filled in for you. |
| Initial capital | Starting quote balance for the simulation (defaults to 10,000). |
Parameter sweeps. Instead of one backtest you can run a sweep — up to 12 variants of a strategy (e.g. several grid counts, or a range of take-profit percentages) submitted as one batch. The variants share a sweep ID so you can rank them side by side and find the best-performing configuration.
Grid range default. If you run a GRID backtest without pinning the lower/upper price, the backtester derives the range from the loaded candle window (just under the lowest low, just over the highest high). For trustworthy results on a live bot, set the range yourself.
How the queue works
Backtests don't run instantly in your browser — they're asynchronous jobs. When you submit one:
- The job is written as queued. (A sweep creates one queued job per variant.)
- A background worker picks it up, marks it running, and backfills the historical candles for your venue/pair/interval/range via the exchange's REST API, storing them so repeat runs are fast.
- The worker replays the strategy over those candles, computes the metrics, and marks the job completed with its result — or failed with a reason if something went wrong (for example, no candle history exists yet for that venue/pair/range, in which case it suggests a shorter range).
One job per user at a time. The worker processes a given user's backtests one at a time, so a big sweep won't let one account monopolize the system. You can watch your queue depth (queued vs running) while you wait.
Cancelling. A backtest can be cancelled while it's still queued. Once a job has started running it can't be cancelled — it finishes on its own.
No candle history? If a backtest fails with a "no candle history for this venue/pair/range" message, the data hasn't been backfilled that far yet. Try a more recent or shorter range, or a more liquid pair.
Plan limits on the backtest window
How far back you can backtest depends on your plan:
| Plan | Maximum backtest window |
|---|---|
| Free | 6 months |
| Starter | 3 years |
| Pro | 5 years |
A request for a range longer than your plan allows is limited to your plan's maximum. (The 14-day sign-up trial runs at Pro-level limits.)
Reading the results
A completed backtest gives you an equity curve, a metrics summary, and the full trade history.
Equity curve
The line of your account value (cash + the marked-to-market value of any open position) at the close of every candle. This is the headline: a steady climb is what you want; a jagged or sinking line tells you the strategy struggled in that period.
Key metrics
| Metric | What it tells you |
|---|---|
| Total return % | Final equity vs. starting capital over the whole window. |
| CAGR % | Compound annual growth rate — return normalized to a per-year figure, so windows of different lengths are comparable. |
| Max drawdown % | The deepest peak-to-trough drop in the equity curve. Your worst losing stretch — the pain you'd have had to sit through. |
| Max drawdown duration | How long (in candles) the longest peak-to-recovery stretch lasted. A small drawdown that takes forever to recover is still a problem. |
| Sharpe / annualized Sharpe | Return per unit of volatility. Higher is better; the annualized figure is the comparable one. Roughly, it asks "was the return worth the bumpiness?" |
| Sortino | Like Sharpe but only penalizes downside volatility — useful when you don't mind upside swings. |
| Win rate % | Share of closing (sell) trades that exited at a profit versus their cost basis. |
| Profit factor | Gross realized profit ÷ gross realized loss. Above 1 means winners outweighed losers. |
| Exposure % | Share of candles the bot was holding a position. Low exposure with good returns means capital sat idle a lot — relevant for opportunity cost. |
| Buy & hold return % | What simply holding the asset over the same window would have returned — your benchmark. Beating this is the bar a strategy has to clear. |
| Total fees | All trading fees paid across every fill (quote currency). |
Read returns against buy & hold. A bot that made 20% in a window where the asset itself rose 40% underperformed doing nothing. Always compare the strategy's return to the buy & hold benchmark on the same metrics card.
Trade history
Every fill the bot made — timestamp, side (buy/sell), price, and quantity — so you can see exactly when and how it traded, and sanity-check that the behavior matches what you intended.
What the simulation models (and doesn't)
- Fills: a resting limit order fills when the candle's high-low range crosses its price (filled at the limit price, as a maker); market orders fill at the candle close as takers, with slippage applied.
- Fees: every fill pays a fee on its notional (taker-style — the same model demo uses). Total fees are reported.
- Not modeled yet: partial fills and order-queue position. Treat results as a strong directional estimate, not a tick-perfect guarantee.
See also
- Bot strategies — what each strategy does and its parameters.
- Plans & pricing — backtest window limits per tier.