Data accessors (bar, option, time)
A standalone signal reads market data through three accessors: bar.* (1-minute OHLCV), option.* (interpolated IV and greeks, plus single-contract selection), and time.* (deterministic NYSE-calendar signals). Every accessor method returns a Signal on the same spine, so you can combine them in one expression.
Every method returns a Float64 Signal, nullable, timestamps tz-aware in America/New_York, on the 09:31-to-close spine. Every method takes an optional sampling= or bucketing= (mutually exclusive) and an optional per-call symbol= override. bar and option query market data; time computes calendar attributes with no data query. Member access is dot-plus-call: write bar.close(), never a bare close.
For a terse per-method lookup of signatures and defaults, see the data accessor reference. This page is the tour.
How accessors work
All three accessors return Signals on one spine: 09:31 to market close, NYSE trading days only, timestamps in America/New_York. Values are Float64 and nullable, so missing data is null rather than a dropped row. Because bar and option share the equity-option spine, a mixed expression like bar.close() / option.iv(30) aligns on the union spine.
Every method accepts two more optional arguments beyond its own:
sampling=orbucketing=, mutually exclusive on a single call.samplingselects a point-in-time value;bucketingaggregates a window. Both are covered in the execution model.symbol=, a per-call override of the context symbol (case-insensitive). It applies to that one call only and does not mutate the context, which is what makes a cross-symbol expression work:bar.close() / bar.close(symbol="QQQ").
Positional rule: dte is the only positional argument (on option.*). Once you pass any argument by name, every following argument must be named too.
The available symbols and their history are listed on the data coverage page. time.* works for any symbol because it reads the calendar, not a data table.
bar: equity bars
bar reads 1-minute OHLCV. Five methods, each returning a Float64 Signal:
bar.open(): the bar open. This is the spot price used in the IV and greeks pipeline.bar.high(): the highest traded price in the bar.bar.low(): the lowest traded price in the bar.bar.close(): the closing (last) price of the bar.bar.volume(): total share volume in the bar.
Each timestamp is the bar's close time, and the bar covers [t − 1min, t]. On a normal session 09:31 is the first bar and 16:00 is the last; on an early-close day the last bar is 13:00. bar methods take symbol=, sampling=, bucketing=, split_adjusted=, and dividend_adjusted= (no dte or type).
// Intraday high-low range on the 1-minute equity spine
bar.high() - bar.low()// Daily close, sampled at each session close
bar.close(sampling=sampling(period="day", time="close"))vwap is not exposed: it is null on zero-volume bars and adds ambiguity downstream. Use bar.close() as a price proxy when you need one.
Split and dividend adjustment
bar prices are split- and dividend-adjusted by default. Every bar.* method takes two boolean parameters, split_adjusted and dividend_adjusted, both defaulting true. Set either to false to read raw, as-printed prices.
For how the adjusted series is constructed, and the look-ahead trap it introduces, see stock price adjustments.
option: surface IV and greeks
option reads the volatility surface. Six methods, each returning a Float64 Signal on the equity-option spine:
option.delta(), option.gamma(), option.theta(), option.vega(), option.rho(), option.iv().
All six share the same contract-selection arguments:
dte:Int, required, the first positional argument. Non-negative calendar days to expiration.type:"call"or"put", default"call".- Exactly one of
delta(a number; default resolves to the 0.5-delta, roughly at-the-money, contract, or -0.5 for a put) ormoneyness(log-moneynessln(K/forward)centered on the implied forward, where0.0is at-the-money-forward).deltaandmoneynessare mutually exclusive. sampling=,bucketing=,symbol=, as above.
option.iv adds two arguments:
iv_type:"bid","mid", or"ask", default"mid".use_ex_earn_iv:Bool, defaultfalse. When true it returns the earnings-adjusted IV, which removes the variance attributable to a pending earnings event. It isnullonly for a symbol with no earnings calendar (SPY and other broad-market ETFs), and wherever the underlying regular IV is itselfnull. For a contract expiring before the next earnings date, or when the earnings-IV decomposition cannot be resolved, it returns the regular IV rather than goingnull.
// 30-DTE mid IV, sampled to daily
option.iv(30, sampling=sampling(period="day", time="close"))Because the earnings-adjusted value is null on a symbol with no earnings, fall back to standard IV where you need a value at every timestamp:
// 30-DTE ex-earnings mid IV, falling back to standard mid IV where absent
coalesce(option.iv(30, use_ex_earn_iv=true), option.iv(30))Option values are 2D-interpolated surface values
Every option.* read is a 2D-interpolated surface value, not a single listed contract's quote. The engine fetches four bracketing contracts (two DTE levels by two delta or moneyness levels), interpolates the delta or moneyness dimension at each DTE level, then interpolates across DTE. When the surface is sparse or the fit cannot be resolved, the result is null, never extrapolated.
When you need one real, tradable contract rather than a surface value, use option.contract(...).
option.contract(...): selecting one real contract
option.contract(...) returns a Table (a ContractTable), not a Signal. It selects, for each minute on the equity-option spine, the single real contract whose dte and one of delta / moneyness / strike best match your targets within thresholds. A minute with no in-threshold contract yields null columns.
Project one numeric column with field access, which gives you a Signal:
// Per-minute mid premium of the 30-DTE 30-delta call
option.contract(dte=30, delta=0.30).midThe full column surface, the matching thresholds, and cross-leg use are documented on signals inside a backtest. This page covers only the standalone shape.
time: deterministic calendar signals
time computes calendar attributes from the NYSE session schedule. No data query runs. Every method takes no positional arguments (except the windowed functions below), returns the attribute of each spine timestamp, and supports optional sampling, bucketing, and symbol.
time.day_of_week()time.day_of_month()time.day_of_year()time.week_of_month()time.month()time.quarter()period="quarter" sampling)time.hour()time.minute()time.minute_of_day()time.is_week_end()time.is_month_end()Four windowed functions take a window size and a keyword-only past= flag:
time.trading_days(calendar_days, *, past=false): NYSE trading days inside a calendar-day window.calendar_days=0returns1.0. Constant within a session (it depends on the date, not the intraday time).time.trading_minutes(calendar_days=0, *, past=false): trading minutes relative to the current bar, current bar always included. Withcalendar_days=0, past=falseit is the minutes remaining to close; withpast=trueit is the minutes elapsed from open.time.calendar_days(trading_days, *, past=false): the inverse oftrading_days. Returnsnullif the target trading day falls outside the available calendar.trading_days=0returns0.0.time.session_fraction(*, past=true): the fraction of the session elapsed by default, or remaining withpast=false. Range[0, 1], current bar included.
// Fraction of the session still remaining, on the 1-minute spine
time.session_fraction(past=false)Why time.* may look forward
past=false is permitted on the windowed time functions because they read the deterministic public NYSE calendar, not market prices. No-lookahead governs market data, and a public schedule is not market data, so a forward-looking calendar count does not violate it.
Both session_fraction and trading_minutes scale off the session's total bar count, total_bars: 390 on a normal day (09:31–16:00) and 210 on an early-close day (09:31–13:00).
What's computed but not readable
The methodology computes more upstream than the accessors expose today. Each quantity below is named, but no accessor returns it. Naming an accessor here would mean inventing one, so this list names the quantity and where it is documented, not an accessor.
option.rho, which is a greek, not a rate accessoruse_ex_earn_iv flag on option.ivIf you need one of these today, the value is not reachable from a signal.