OHLC & EOD
What OHLC is
OHLCVC — Open, High, Low, Close, Volume, Count — is a summary of trading activity over a fixed time interval, computed from the underlying SIP trade stream:
- Open — price of the first qualifying trade in the interval.
- High / Low — max / min price among qualifying trades in the interval.
- Close — price of the last qualifying trade in the interval.
- Volume — sum of incremental sizes from qualifying trades.
- Count — number of qualifying trades.
Not every trade reported on the SIP feed qualifies. The SIP defines a condition for each trade indicating whether it can contribute to the consolidated last price, high, low, or volume. ThetaData honors those conditions — for example, late reports and Form T (pre/post-market) trades are deliberately excluded from regular-session high/low, even though the trade itself is real.
How ThetaData computes OHLC
For each interval, ThetaData:
- Drops cancelled trades (condition codes 40–44) and trades with
priceType=0orsize=0. - Applies SIP filtering — a trade contributes to High/Low/Open/Close only if its trade condition allows it to update those fields. See Trade Conditions for the full table.
- Applies a price-deviation sanity check — a trade whose price is more than ±5% from the most recent verified legitimate trade is excluded from H/L/Open/Close. This is a defense against upstream feed corruption (phantom prints with otherwise-normal metadata). The check carries state chronologically across bars, so a rejected trade cannot bootstrap the next. The check is bypassed for low-priced assets (reference price at or below $5), where >5% moves are routine on legitimate ticks (e.g. an option premium going from $0.10 to $0.11).
- Computes O/H/L/C from the qualifying trades; computes Volume and Count from the subset of incremental-volume trades (volume aggregation is intentionally separate so a phantom rejected from H/L still appears in the volume total and in the raw trade endpoint).
This matches the SIP-published OHLC behavior used by most market participants, plus a small amount of upstream-feed-error mitigation.
Extended-hours OHLC
Pre-market (04:00–09:30 ET) and post-market (16:00–20:00 ET) OHLC bars are inherently less reliable than regular-session bars. The SIP feed does not always provide enough metadata to distinguish a legitimate extended-hours print from upstream feed corruption: a phantom trade with an off-market price can carry the exact same trade condition, exchange, and condition flags as the legitimate trades around it. In those cases no condition-based filter can target it.
The ±5% sanity check catches the obviously wrong cases. Subtler off-by-a-few-percent corruption can still appear in extended-hours OHLC, because tightening the threshold further would also reject legitimate fast moves on low-liquidity symbols (where a single wide-spread print can deviate several percent from the prior trade).
If your use case requires extended-hours OHLC stricter than this, consume the raw trade endpoint and apply whatever filtering fits your needs.
EOD
There is no nationally consolidated EOD feed for stocks, indices, or options:
- The equity SIPs (UTP and CTA) each publish EOD reports at ~17:00 ET on a per-feed basis. ThetaData will be exposing these directly, plus a merged report, in the near future.
- The options SIP (OPRA) publishes EOD reports on a per-participant-exchange basis. Coverage is unreliable — some exchanges don't publish when they should — making a nationally consolidated EOD report impractical to construct.
To work around this, ThetaData generates a normalized EOD report at 17:15 ET every trading day for stocks, indices, and options. The behavior is identical across asset classes, which simplifies cross-asset analysis.
Edge cases
- Zero-valued bars. If a less-liquid contract (e.g. a deeply OTM/ITM option) shows zero OHLC for an interval, it means there were no qualifying trades during that interval — not a data error.
- Missing EOD for illiquid options. Same cause: no qualifying trades during the day.
- Sparse extended-hours bars. Many symbols have little or no extended-hours activity. Sparse or zero bars in pre/post-market are expected on these names.
Build your own OHLC
If ThetaData's behavior doesn't fit your use case — different filtering rules, custom outlier handling, alternative bar boundaries — use the raw trade endpoints:
/v3/stock/history/trade/v3/option/history/trade/v3/index/history/trade
Each row carries the trade's condition so you can replicate or modify ThetaData's logic on the client side and apply any additional filter (e.g. NBBO cross-check, custom outlier thresholds, per-symbol rules).