Parses a CSV of OHLCV bars into the canonical dataset shape (unvalidated —
schema validation happens downstream, and plausibility is the rules
engine's job, not the parser's).
Two deliberate decisions (2026-07-31 audit):
Ragged rows: papaparse reports TooFewFields/TooManyFields in
result.errors. A few ragged rows are tolerated — the affected fields
simply land missing/undefined and schema validation flags those bars —
but when MORE than 10% of rows have a field-count mismatch the file is
structurally broken (wrong delimiter, shifted columns) and we throw an
IngestError naming the first offending rows instead of ingesting garbage.
Timestamps pass through normalizeTimestamp: compact YYYYMMDD dates and
plausible epoch seconds become ISO calendar dates; anything else is kept
raw. A missing timestamp stays ABSENT (never the literal string
'undefined') so schema validation fails with a clear required-field
message pointing at the real gap.
Parses a CSV of OHLCV bars into the canonical dataset shape (unvalidated — schema validation happens downstream, and plausibility is the rules engine's job, not the parser's).
Two deliberate decisions (2026-07-31 audit):
result.errors. A few ragged rows are tolerated — the affected fields simply land missing/undefined and schema validation flags those bars — but when MORE than 10% of rows have a field-count mismatch the file is structurally broken (wrong delimiter, shifted columns) and we throw an IngestError naming the first offending rows instead of ingesting garbage.normalizeTimestamp: compact YYYYMMDD dates and plausible epoch seconds become ISO calendar dates; anything else is kept raw. A missing timestamp stays ABSENT (never the literal string 'undefined') so schema validation fails with a clear required-field message pointing at the real gap.