Data accessor reference
Three market and calendar accessors, bar, option, and time, return Signals. Four backtest-context accessors, book(), position(), leg(slug), and option.contract(...), return Tables you project a single column from with field access. Which accessor is legal depends on the evaluation context. This is the lookup companion to the data accessors tour: signatures, parameters, and returned columns live here; the conceptual teaching (spines, sampling, alignment) lives there.
Every option.* read is a 2D bilinear interpolation across the option surface, not a raw per-contract quote.
Accessor model
Every market accessor method returns a Signal: a {timestamp, value} series where value is Float64 and nullable and timestamp is tz-aware America/New_York. Each accessor evaluates on its own spine, the complete set of valid timestamps for that accessor. bar and time run on the equity spine; option runs on the equity-option spine. Both spines run 09:31 through the session close on NYSE trading days: 390 observations on a normal day, 210 on an early-close day. Missing minutes inside the spine are null, never dropped. Two Signals at different cadences combine on the union spine with backward as-of fill; see the execution model.
Every method accepts three optional keyword arguments:
samplingsampling(...)bucketing.bucketingbucketing(...)sampling.symbolThe symbol override accepts any launch ticker, enabling cross-symbol expressions like bar.close() / bar.close(symbol="QQQ"). All launch tickers carry bar.* and option.* coverage. See data coverage for the symbol list and per-symbol history depth.
option.* values are computed marks interpolated from the surface; bar.* returns the recorded bar; missing minutes inside the spine are null, never dropped.
bar.* (equity bars)
One-minute OHLCV for the underlying, on the equity spine. Each timestamp is the bar close; the bar window is [t − 1 min, t]. The 9:31 bar covers 9:30–9:31; the 16:00 bar covers 15:59–16:00 (13:00 on an early-close day).
bar.open()S used in the IV and greeks pipeline.bar.high()bar.low()bar.close()bar.volume()Parameters. symbol (override, case-insensitive), split_adjusted (bool, default true), dividend_adjusted (bool, default true), sampling, bucketing. No positional arguments.
// Daily closing price, sampled at each session close
bar.close(sampling=sampling(period="day", time="close"))bar.* prices are split- and dividend-adjusted by default. Every bar method takes split_adjusted and dividend_adjusted (bool, both default true); set either to false for raw, as-printed prices. See stock price adjustments.
Notes. vwap is intentionally not exposed; it is null on zero-volume bars. Use bar.close() as a price proxy. bar.* reads are split- and dividend-adjusted by default; setting the split_adjusted and dividend_adjusted switches (both default true) to false returns raw, as-printed prices.
option.* (option surface)
Implied volatility and the five greeks off the interpolated option surface, on the equity-option spine. Every method fetches a continuous surface value at the requested dte and either delta or moneyness.
option.iv(...)option.delta(...)option.gamma(...)option.theta(...)option.vega(...)option.rho(...)option.contract(...)ContractTable of the single real contract nearest the target (see below).Shared selection parameters (all option.* methods):
dtetype"call" | "put""call"delta0.5 (call) / -0.5 (put)moneyness.moneynessln(K/forward), centered on the implied forward; 0 is at-the-money-forward. Mutually exclusive with delta.symbolsamplingsampling(...)bucketing.bucketingbucketing(...)sampling.option.iv adds two parameters:
iv_type"bid" | "mid" | "ask""mid"use_ex_earn_ivfalsetrue, returns the earnings-adjusted IV. null only for symbols with no earnings calendar (SPY and broad-market ETFs); for contracts expiring before the next earnings date, or when the decomposition fails to converge, it returns the regular IV rather than null.// 30-DTE 16-delta put mid IV, sampled to daily close
option.iv(dte=30, type="put", delta=-0.16, sampling=sampling(period="day", time="close"))Every option.* value is a 2D bilinear interpolation across DTE and the chosen delta or moneyness dimension. When the surface is too sparse to interpolate, when no arbitrage-free IV can be recovered, or when a solve fails or falls outside plausibility bounds, the result is null, never extrapolated. See implied volatility and greeks.
option.contract(...) -> ContractTable
Selects, for each minute on the equity-option spine, the single real option contract whose dte plus exactly one of delta / moneyness / strike most closely matches the targets within thresholds. All arguments after dte are keyword-only.
option.contract(
dte, // required, first positional
type = "call",
delta = None,
moneyness = None,
strike = None,
dte_threshold = 5,
delta_threshold = 0.05,
moneyness_threshold = 0.05,
strike_threshold = 1.0,
size = 1,
) -> ContractTabledtetype"call" | "put""call"deltadelta / moneyness / strike is required.moneynessln(K/forward) (centered on the implied forward).strikedte_threshold5|dte_actual − dte| in days.delta_threshold0.05|delta_actual − delta|.moneyness_threshold0.05|moneyness_actual − moneyness|.strike_threshold1.0|strike_actual − strike|.size1scaled_* columns.Selection is by threshold-normalized weighted-sum distance to the targets. Ties break on ascending expiration, then strike, then right. If no contract satisfies all thresholds at a minute, every column is null for that minute.
Project a single column with field access: option.contract(dte=30, delta=0.30).mid. The 20 projectable columns:
strikedtedte_threshold).deltagammathetavegarhoivmid(bid + ask) / 2.bidaskunderlying_pricemoneynessln(K/forward) (centered on the implied forward) at this minute.multipliersizescaled_deltadelta × size.scaled_gammagamma × size.scaled_thetatheta × size.scaled_vegavega × size.scaled_rhorho × size.// 30-DTE 30-delta call: per-minute mid premium
option.contract(dte=30, delta=0.30).midIn a backtest, option.contract(...) is the contract selection slot; delta, moneyness, strike, and size may be cross-leg expressions, while dte and the thresholds must be constants.
leg(slug) -> LegTable
Addresses one held leg of the position under evaluation by its strategy slug, a non-empty string literal: leg("short_put"). Greeks and quotes come from the held contract's marks. The slug tracks the role, not the contract, so a window over leg("short_put").delta continues across a replace_leg roll. A declared-but-not-held slug yields an all-null row.
LegTable carries the 20 ContractTable columns above plus 13 entry-snapshot columns, captured at position open and preserved across rolls:
entry_strikestrike captured at entry.entry_dtedte captured at entry.entry_deltadelta captured at entry.entry_gammagamma captured at entry.entry_thetatheta captured at entry.entry_vegavega captured at entry.entry_rhorho captured at entry.entry_iviv captured at entry.entry_midmid captured at entry.entry_bidbid captured at entry.entry_askask captured at entry.entry_underlying_priceunderlying_price captured at entry.entry_moneynessmoneyness captured at entry.// Adjustment trigger: roll when the short put's delta breaches 0.40
leg("short_put").delta > 0.40The comparison returns a Float64 1.0/0.0 Signal. The entry_* columns exist only on a live held leg (in an adjustment trigger). In a contract-selection signal, leg(slug) resolves to the run-start candidate, which has no entry snapshot, so referencing an entry_* column there is a compile-time error. See signals inside a backtest.
position() -> PositionTable
Reads the per-minute state of the position under evaluation, aggregated across its legs. Available inside adjustment triggers only, where it evaluates once per open position per minute. Net greeks are sums of the legs' size-scaled greeks times lots; any contributing leg being null makes the aggregate null.
unrealized_pnlrealized_pnlinitial_marginmaintenance_marginmarket_valuenet_deltascaled_delta × lots.net_gammascaled_gamma × lots.net_thetascaled_theta × lots.net_vegascaled_vega × lots.net_rhoscaled_rho × lots.lotsleg_countdteentry_net_deltanet_delta from each leg's delta captured at entry.entry_net_gammanet_gamma from each leg's gamma captured at entry.entry_net_thetanet_theta from each leg's theta captured at entry.entry_net_veganet_vega from each leg's vega captured at entry.entry_net_rhonet_rho from each leg's rho captured at entry.// Adjustment trigger: 15-observation mean net delta runs long
rolling_mean(position().net_delta, 15) > 0.50rolling_mean(position().net_delta, 15) averages the last 15 observations. On the 1-minute spine that is 15 minutes. Sample or bucket to daily first if you want 15 trading days.
book() -> BookTable
Reads the per-minute whole-account state during a backtest. Available in entry signals, exit signals, and adjustment triggers. It evaluates once per minute for the whole run regardless of how many positions are open. Values are dollars except the two noted.
cashnlvinitial_marginmaintenance_marginexcess_liquiditymargin_utilization_pctnull when NLV is non-positive; can exceed 100 in margin distress.unrealized_pnlrealized_pnlposition_count// Entry or adjustment: fire when excess liquidity drops below a floor
book().excess_liquidity < 5000time.* (calendar signals)
Deterministic NYSE calendar functions on the equity spine. No data query. Because they depend only on the public NYSE schedule, forward-looking reads (past=False) are permitted here; this is distinct from the no-lookahead rule that governs market data.
Calendar attributes (no positional arguments; optional sampling, bucketing, symbol):
time.day_of_week()time.day_of_month()time.day_of_year()time.week_of_month()time.month()time.quarter()time.hour()time.minute()time.minute_of_day()time.is_week_end()time.is_month_end()Windowed functions:
time.trading_days(calendar_days, past)calendar_days calendar days. Constant within a session.time.trading_minutes(calendar_days, past)time.calendar_days(trading_days, past)trading_days trading days (the inverse of trading_days).time.session_fraction(past)past=True, default) or remaining, in [0, 1].past=False looks forward, past=True looks backward. session_fraction uses total_bars = 390 on a normal day, 210 on an early-close day.
// End-of-month flag for rebalancing logic
time.is_month_end()Note. time.quarter() returns the calendar quarter (1–4) as a value. It is unrelated to period="quarter" in a sampling or bucketing config.
Accessor availability by context
The market and calendar accessors (bar, option, time) are available everywhere. The backtest-state accessors are gated by the evaluation context:
book()position()leg(slug)entry_* columns present)entry_* columns)In contract selection, leg(slug) resolves to another leg's run-start candidate, which places one leg relative to another:
// Contract selection: long put 5 strikes below the short put
option.contract(dte=30, type="put", strike=leg("short_put").strike - 5)Referencing an entry_* column in contract selection is a compile-time error (the candidate has no entry snapshot). Using any accessor outside its context raises an availability error.
Sampling & bucketing configuration
Both config builders shape every accessor read. They are mutually exclusive on one call: sampling selects a point-in-time row, bucketing aggregates a window.
sampling(*, period, multiplier=1, offset, time, times, days, weeks, months)
periodminute, hour, day, week, month, quartermultiplier1period="quarter", multiplier=4 is annual).time"open", "close", "HH:MM"period="day". period="day" without time defaults to time="close"; this is the only remaining default cascade.timesdays, weeks, monthsoffsetbucketing(*, period, agg="last", multiplier=1, offset, partial=true)
periodminute, hour, day, week, month, quarteraggfirst, last, max, min, mean, sumlast.multiplier1partialtrueoffsetNote. Some listings of the bucketing signature omit quarter, but quarter is a valid bucketing period today, matching sampling.
What is not exposed
The engine computes the following upstream, but no accessor reads them today. Each is named so you do not reach for an accessor that does not exist. Do not invent a name for any of these.
- Vanna and all second-order greeks.
- The implied forward, carry, borrow, and the risk-free rate. The rate surfaces only inside
option.rho, never as its own series (see implied forward, carry and rates). - Dealer exposure, GEX and VEX (see dealer exposure: GEX and VEX).
- The dividend-escrowed spot, the informational dividend yield, and the ex-dividend date (see dividends).
- The earnings metrics: implied move, event vol, ambient vol, and the next earnings date (see earnings volatility and implied move).
- The IV quality and provenance flags (
iv_status,spread_pct,is_one_sided,is_parity_recovered,spot_staleness_minutes,iv_model,is_floored_t).
For the full availability status, see Platform status.