Strategy Backtester

Backtester

Build • Test • Improve

Choose a strategy, add your candles and run. Your script and data stay in your browser.

1. Strategy, complete

A strategy or an indicator, Pine v4 to v6. Converted instantly in your browser.

Use one or the other. Whichever is selected above is what runs.

strategy.pine21 lines

Recognised strategy: EMA cross with ATR stop and target, 5 inputs

Script inputs

Read from the script. Change a value and run again.

2. Instrument, not complete yet

Optional. Fills in the lot size, tick size, price precision and the currency shown in the results. Any market works, since the candles are yours.

Set your own quantity per lot and tick size in the fields below.

3. Candle data, not complete yet

Excel or CSV with timestamp, open, high, low, close. Volume is optional. Processed in your browser.

4. Test setup, not complete yet

Timeframe, position size and the rules each run follows.

Timeframe

Your data is resampled to this. You cannot go below its own timeframe.

Size and range

PnL is points × quantity. Lot sizes change over time, so adjust the quantity if yours differs.

Total quantity

1

Ready when you are

The script is converted into strategy code in your browser, then replayed bar by bar on your candles. Results appear here in the same layout as your backtest.py report.

  • Pine script

    Paste it or upload a .pine file. “Use sample” loads an EMA crossover to try.

  • Candle data

    Upload the Excel file. The data’s own timeframe is detected.

  • Timeframe

    Pick the timeframe to test on, then press Run backtest.

JavaScript generated from your Pine script. It is what runs on your candles, bar by bar.

"use strict";
const R = rt;
let i = 0, S = null;
const INIT = 100000;
let $fastLen = NaN;
let $slowLen = NaN;
let $atrLen = NaN;
let $atrMult = NaN;
let $rr = NaN;
const _s1 = new R.Ema();
let $fast = NaN;
const _s2 = new R.Ema();
let $slow = NaN;
const _s3 = new R.Atr();
let $atr = NaN;
const _s4 = new R.Cross();
const _s5 = new R.Cross();
return {
  onBar(idx, s) {
    i = idx; S = s;
    $fastLen = R.inNum(inputs, "fastLen", 9, true);
    $slowLen = R.inNum(inputs, "slowLen", 21, true);
    $atrLen = R.inNum(inputs, "atrLen", 14, true);
    $atrMult = R.inNum(inputs, "atrMult", 1.5);
    $rr = R.inNum(inputs, "rr", 2);
    $fast = _s1.n(d.close[i], $fastLen);
    $slow = _s2.n(d.close[i], $slowLen);
    $atr = _s3.n(d, i, $atrLen);
    if (_s4.n($fast, $slow, 1)) {
      R.strat.entry(S, "Long", "long", undefined, undefined, undefined);
      R.strat.exit(S, "Long exit", "Long", { profit: undefined, limit: (d.close[i] + (($atr * $atrMult) * $rr)), loss: undefined, stop: (d.close[i] - ($atr * $atrMult)), trailPrice: undefined, trailPoints: undefined, trailOffset: undefined }, undefined);
    }
    if (_s5.n($fast, $slow, -1)) {
      R.strat.entry(S, "Short", "short", undefined, undefined, undefined);
      R.strat.exit(S, "Short exit", "Short", { profit: undefined, limit: (d.close[i] - (($atr * $atrMult) * $rr)), loss: undefined, stop: (d.close[i] + ($atr * $atrMult)), trailPrice: undefined, trailPoints: undefined, trailOffset: undefined }, undefined);
    }
  }
};

Ready to run?

Press Run backtest once the checklist is complete. Your results will show here.

  • Instant resultsNo installation needed
  • Your candlesAny market, any vendor
  • Custom inputsFull control
  • In-browserYour data stays private