@dataclass, and each CSV column is
mapped to a field of that dataclass.
Declaring a schema
- Field types can be
float,int,bool,str, a nested@dataclass, orOptional[...]of a scalar type. Optionalmarks a field as nullable: an empty CSV cell reads asNone.Optionalis only allowed on scalar fields, not on nested dataclasses. Reading such a field gives anindie.Optionalvalue: test it withis Noneor unwrap it with.value()/.value_or().listfields are not supported here, even though@dataclassallows them elsewhere in Indie. Recursive dataclass references are not supported either.- Field names must be ASCII identifiers; the name
_is reserved. - A schema can have at most 64 scalar fields in total. Fields inside nested dataclasses count toward the limit; the field holding the nested dataclass itself does not.
intfields must fit into a 32-bit range; declare the field asfloatif you need larger values.
Matching CSV columns to fields
Columns are matched to fields by header name:- The match is exact and case-sensitive: field
signalreads the columnsignal, notSignal. - Fields of nested dataclasses use a dotted path: a field
betainside a nested dataclass stored in fieldriskreads the columnrisk.beta. - The time column is separate from the schema. Its default name is
time(case-insensitive) and can be changed with thetime_columnargument ofsources.Csv(). - Unknown extra columns are ignored; a missing schema column is an error.
risk with a field beta reads its column as risk.beta:
factors.csv
ModelOutput schema from above maps to a file like this:
signals.csv
confidence cell — valid because confidence is declared Optional[float].
Timestamps must be strictly increasing; accepted time formats are listed in
CSV format and limits.
Processing rows with a callback: @data_context
A @data_context[T] callback is the typed-data counterpart of @sec_context: it runs once per external row, and its
results are merged into the chart timescale of the calling context.
External model signal
@data_context callback the external rows are available as self.data — a series of your dataclass, where
self.data[0] is the current row. An external source carries no candles, so the candle members of the context
(self.open, self.high, self.low, self.close, self.volume and derived values) are not available and produce
a compile error. self.time, self.bar_index and the bar-state flags remain available.
Context.calc_on() with a @data_context callback requires the source argument and does not accept exchange or
ticker.
Reading rows without a callback: request_series
If you do not need per-row processing, request the typed series directly:
Risk-adjusted close
request_series[T] returns a Series[T] aligned to the calling context: on each bar, [0] is the latest external
row with a timestamp at or before that bar.
On chart bars before the first external row, reading a typed series with
[0] raises an error: No data at this bar yet. Use .get(offset, default) with a default row to read this series during warm-up. Pass a default row as in the example above:
.get(0, RiskFactor(1.0)) returns the default until the first row arrives. Float series merged from a
@data_context callback do not raise: on bars before the first row they read the first row’s result.Time frame: omitted or explicit
For typed data thetime_frame argument is optional.
If you omit it, the rows are treated as point-in-time events with no cadence. Each row becomes visible on the first
chart bar that opens at or after the row’s timestamp. When several rows fall inside one chart bar, series reads see
the latest of them, while a @data_context callback still runs once per row.
With an explicit time_frame=, the rows are treated as a regular series on that time frame, with the same
close-time alignment and lookahead behavior as
external candles. Rows
must not be more frequent than the declared time frame. lookahead=True always requires an explicit
time_frame.
One schema per source
Within one indicator, the same CSV source (the same URL andtime_column) must always be requested with the same
dataclass schema — requesting it with two different schemas is an error. Each distinct combination of source, time
frame and lookahead counts as one additional instrument toward the shared limit; identical requests are counted
once.
For file requirements, size limits and the full list of error codes, see
CSV format and limits.