| name | history |
| description | Use whenever you reach for a `history()` request — a startup seed, a one-off lookback, or a recent past value like the previous daily close. For a rolling statistic recomputed every bar, prefer a streaming indicator (see indicators). |
History requests — seeds, lookbacks, and recent past values
Use history() for a one-off need: seeding a signal at startup, a single lookback, or reading a recent past value (like yesterday's close). If instead you need a rolling statistic recomputed on every bar or scheduled event — a moving average, momentum, rolling volatility — register a streaming indicator once and read it (see the indicators skill); don't call history() every time to recompute it (slow, and easy to get the as-of bar wrong).
Two return shapes: typed bars vs the DataFrame — pick by how you'll use it
history() returns different shapes depending on the overload; choosing the right one avoids a lot of DataFrame wrangling.
- Iterating bar-by-bar → use the TYPED overload
self.history[TradeBar](symbol, period, resolution) (or [QuoteBar]). It yields TradeBar objects you read directly — bar.end_time, bar.open, bar.high, bar.low, bar.close, bar.volume — with no reset_index, no MultiIndex, no .dt accessor. This is the right tool for building per-day/per-bar records or finding the bar at a specific time.
- Vectorized column math → use the DataFrame overload
self.history(symbol, period, resolution) and operate on columns, e.g. df["close"].pct_change().std().
- DataFrame gotcha: the index is a MultiIndex , and the level is the bar's time (every LEAN bar is timestamped at its end). For specifically, the first regular-hours minute bar is stamped 09:31 (the 09:30→09:31 bar), not 09:30 — so matching a target time to the bar's silently yields empty results. (Treating the symbol level as the time column is the other common slip.) The typed overload sidesteps all of this — just read .