Skip to main content
A CSV file with OHLCV candles can be used as an additional data source in an indicator, the same way an additional instrument is used with Context.calc_on(): a @sec_context callback runs over the external candles, and its results are merged into the chart timescale.

CSV columns

The file must have a header row with these columns (any order, header names are case-insensitive, unknown extra columns are ignored):
candles.csv
Timestamps must be strictly increasing. Accepted time formats, cell value rules and file size limits are described in CSV format and limits. Note that candle timestamps cannot have a sub-second part.

Declaring the source

External candle close
Two parts do the work here. The @sec_context callback runs over the external candles exactly as it would over a secondary instrument, and source=sources.Csv(...) tells the platform where those candles come from. The source argument is mutually exclusive with exchange and ticker — an external source has no exchange or ticker of its own. Like any Context.calc_on() call, the source must be declared in __init__.

The time frame is required

For a candle CSV the time_frame argument of Context.calc_on() is required. The time frame is a property of your file — the platform does not guess it from the data:
  • time_frame declares the cadence of the rows. If rows arrive more frequently than the declared time frame, the file is rejected with the external_timeframe_mismatch error. The reverse mismatch — rows sparser than the declared time frame — is not detected.
  • Tick time frames are not supported for external sources.
  • Omitting time_frame is a compilation error.

How external candles align with the chart

An external candle CSV behaves like a secondary instrument on its own time frame. On each chart bar, the merged series returns the value of the latest external candle that has closed by the close of that bar:
5-minute CSV on a 1-minute chart
  • The candle that opens at 00:05 closes at 00:10, so its value 20 first appears on the chart bar that also closes at 00:10 — the 00:09 bar. On a daily CSV and a 1-hour chart this means Monday’s candle first appears on the bar covering Monday’s final hour.
  • The last candle (close 30) has not closed within the loaded history, so history bars never see it. When the chart switches to realtime, that candle is the freshest data available and the series starts returning 30.
  • Chart bars that come before the first loaded candle read that candle’s values instead of being empty.
  • These rules assume the CSV time frame is equal to or larger than the chart’s. With a finer CSV, each chart bar shows the last external candle that opened at or before the bar’s open.
With lookahead=True a candle is visible already from the chart bar where it opens:
Same file with lookahead=True
lookahead=True always requires an explicit time_frame.
lookahead=True lets a bar see values that were not yet final at that moment in time. In a backtest this shows up as results that are too good to repeat live (lookahead bias).

Where external candles differ from market instruments

  • Timestamps are interpreted as UTC and the external instrument runs on a 24/7 session — there are no trading-session gaps or exchange timezone.
  • There are no realtime updates: the series is history-only.
For file requirements, size limits and the full list of error codes, see CSV format and limits.