Skip to content
Backtesting

Replay the bars you ship.

History and real time come back from one endpoint, so nothing about your test path is retrofitted.

The run

Run a rule on the bars.

Fills, realized and open — off one response, at whatever speed you read it.

Return

−0.28%

realized plus unrealized · 29 of 29 bars fed

Realized

−0.28%

1 closed trade

Unrealized

0.00%

flat, so nothing to mark

Position

Flat

in above 1.1560

29 daily bars for Euro, from 2026-08-26 to 2026-09-23. The drawn window runs from 1.1323 to 1.1863.

Actions 2

Breakout buys a close above the channel, sells a close below it

  • Sell2026-09-111.1598−0.28%
  • Buy2026-09-031.1630
GET /v1/prices/ohlcv?asset=EUR&interval=1d&from=2026-07-26T00:00:00.000Z&to=2026-09-24T00:00:00.000Z&limit=60

One response. The cursor is an index into it, not a second call.

Rule
breakout · 4-bucket channel · one unit · long only · filled at the close · no fees or slippage
No size
8 of 29
The build

Page the window, then replay.

BUILD · THE REPLAY
let from = windowStart
while (from < windowEnd) {
  const { data } = await ohlcv('EUR', { interval: '1d', from })
  if (data.length === 0) break
  for (const bar of data) strategy.onBar(bar)
  // to is exclusive, so the next page opens on the next bucket
  from = nextBucket(data[data.length - 1].timestamp)
}

One request per page, ordered by construction, and the same four prices the live screens draw.

  • A gap is an absence.

    A bucket nothing was published for is missing from the response, not carried forward and not zeroed.

  • Null is not zero.

    volume is null when no size was published — and on a coarse bucket rather than a partial sum of the minutes that did.

  • The universe stays yours.

    Survivorship, corporate actions and which instruments you were allowed to hold that day are your harness’s — this contract ends at the bar.