DEV Community

wang shadow
wang shadow

Posted on

A Practical Guide to Historical Market Replay in the Browser

Backtesting is useful, but it can feel abstract when you only read a final performance number. A historical market replay makes the process more concrete: choose a point in the past, hide the future, and make decisions one step at a time with virtual money.

This article explains the main product and engineering choices behind a browser-based market replay tool.

1. Start with a strict information boundary

The most important rule is that the interface must not reveal future candles, prices, or indicators. At time t, the user should see only data that would have been available at time t. This means the replay engine needs a cursor and a data window rather than a chart that simply renders the entire dataset.

A useful state model contains:

  • the selected instrument and timeframe;
  • the current historical cursor;
  • the visible candle range;
  • cash, positions, and unrealized profit or loss;
  • the next action available to the user.

Keeping these values explicit makes it easier to test that the future is actually hidden.

2. Separate the replay engine from the chart

The chart should render state, not decide what happens next. A small replay engine can expose operations such as stepForward(), buy(), sell(), and reset(). Each operation produces a new immutable state or a well-defined state transition.

This separation has two benefits. First, the same engine can power keyboard controls, buttons, and automated tests. Second, the accounting logic can be checked without depending on canvas rendering or browser events.

3. Make virtual-money accounting deterministic

Every simulated order should record its timestamp, side, quantity, execution price, and fees. The portfolio value can then be recomputed from the trade ledger instead of being incremented by scattered UI callbacks.

For a simple long-only simulator:

cash_after = cash_before - quantity * execution_price - fee

When the position is closed, realized profit should be calculated from the recorded entry price and exit price. Even a small fee model is better than silently assuming frictionless trading, because it keeps the exercise closer to the decisions a user would face in practice.

4. Treat indicators as views over visible data

Indicators should be calculated from the candles available at the current cursor. If an indicator is calculated from the complete historical series and then displayed during replay, it can accidentally leak future information through its values.

A safer design passes the visible slice into the indicator function. It also helps to show the indicator period in the interface so users understand the assumptions behind the signal.

5. Use the browser for accessibility and iteration

A browser-based implementation makes the experiment easy to start. It can provide keyboard shortcuts, responsive charts, and a shareable URL without requiring a local installation. The trade-off is that large datasets and rendering work need attention: load only the required range, keep the UI state small, and avoid rebuilding every chart element on every step.

For a practical example, ChartMini provides a free browser-based environment for replaying historical stock, forex, and crypto markets with virtual money. Its core idea is useful even if you are building your own implementation: make the timeline visible, keep the rules explicit, and let the user practice decisions without financial risk.

6. Test the uncomfortable edge cases

The most valuable tests are often the boring ones:

  • buying with insufficient cash;
  • selling more than the current position;
  • stepping past the final candle;
  • resetting after several trades;
  • changing timeframe while a position is open;
  • handling missing or irregular market data.

A deterministic fixture with a handful of candles is enough to verify the accounting rules. Then browser-level tests can check that the visible chart, balance, and trade history agree with the engine state.

Conclusion

Historical replay works best when it is treated as a controlled simulation rather than a chart animation. Hide future information, keep the accounting ledger explicit, calculate indicators only from visible data, and test the engine independently from the UI. These principles produce a more transparent learning tool and make the resulting code easier to extend.

Top comments (0)