Data Access
Price series, OHLC columns, TBBO tick fields, composite prices, and time components.
close
Closing price for each bar as a pandas Series.
The most commonly used price input and the default for most indicator calculations. Supports all standard pandas operations.
On TBBO files (when read from Python), close is the per-bar last mid-price after the WASM aggregator builds bars at the active timeframe.
Returns
pandas Series of float64
Example
from quant_charts import close
sma_20 = close.rolling(20).mean()
ema_12 = close.ewm(span=12, adjust=False).mean()
daily_return = close.pct_change()
Output
>>> close.head()
0 100.578931
1 100.436809
2 102.385924
3 105.363522
4 104.579579
dtype: float64
open
Opening price for each bar as a pandas Series.
The opening price of each bar. Useful for gap analysis (comparing current open to previous close) and candlestick pattern detection.
Returns
pandas Series of float64
Example
from quant_charts import open, close
gap = open - close.shift(1)
high
Highest price reached during each bar.
Used for channel indicators, range calculations, true range, and resistance level detection.
Returns
pandas Series of float64
Example
from quant_charts import high, low
bar_range = high - low
highest_20 = high.rolling(20).max()
low
Lowest price reached during each bar.
Used alongside high for volatility measures, channel indicators, and support level detection.
Returns
pandas Series of float64
Example
from quant_charts import high, low
lowest_20 = low.rolling(20).min()
Column resolvers (volume_series / delta_series / vwap_series / df_col_or)
Helpers that resolve volume / delta / VWAP across different parquet shapes via priority chains.
Different parquets ship different columns. Native OHLC files often carry volume / delta / vwap; TBBO-aggregated bars carry bid_vol / ask_vol / tickCount; some older files only have tickCount. Hard-coding column names breaks portability across data files. The four helpers below resolve a single concept (the volume signal, the signed delta signal, etc.) with an explicit fallback chain so your indicator/strategy works on every parquet shape:
volume_series(df)->volume->bid_vol+ask_vol->tickCount-> zerosdelta_series(df)->delta->ask_vol-bid_vol->sign(close-open)-> zerosvwap_series(df)-> precomputedvwapcolumn -> session-cumulative typical price *volume_series(df)df_col_or(df, "name1", "name2", default=None)-> first column that exists, or the default
All resolvers return numpy arrays of length len(df) (or default for df_col_or). NaN entries are coerced to 0 inside volume_series and delta_series so cumulative sums stay finite.
Declare required_columns=[...] only for columns your math truly needs (typically high/low/close); leave optional columns out and read them via the resolvers so the validator does not reject parquets that lack the optional columns.
Returns
numpy.ndarray of float64
Example
from quant_charts import indicator, plot, volume_series, delta_series, vwap_series, cvd, df_col_or
@indicator(name="Order-Flow Light", overlay=False, required_columns=["close"])
class OrderFlowLight:
def calculate(self, df):
vol = volume_series(df) # works on any parquet shape
cvd_arr = cvd(delta_series(df))
vwap = vwap_series(df) # uses precomputed column or builds session VWAP
custom = df_col_or(df, "trade_size", "tickCount", default=vol)
plot(cvd_arr, "CVD", color="#7AA2F7")
volume
Trading volume for each bar.
Total traded volume within each bar. May be zero if volume data is unavailable. Used for VWAP, volume analysis, and liquidity filtering.
On TBBO data (Python execution path) this is the per-bar sum of trade volume aggregated by scripts/strategy_executor.py.
Returns
pandas Series of float64
Example
from quant_charts import close, volume
vwap = (close * volume).cumsum() / volume.cumsum()
Output
>>> volume.head()
0 18702.0
1 10384.0
2 10404.0
3 50943.0
4 57926.0
dtype: float64
delta
Per-bar signed volume delta (buyer minus seller).
Positive when buyers lift the offer, negative when sellers hit the bid. Pair with the cvd() helper for cumulative volume delta.
Returns
pandas Series of float64
Example
from quant_charts import delta, cvd
cumdelta = cvd(delta)
vwap
Session volume-weighted average price.
Available where the parquet provides it (or computed from volume + close otherwise). Pair with vwap_band(vwap, atr, mult) for mean-reversion envelopes.
Returns
pandas Series of float64
Example
from quant_charts import vwap, ta, high, low, close, vwap_band
atr = ta.atr(high, low, close, 14)
upper, lower = vwap_band(vwap, atr, mult=1.5)
bid_vol / ask_vol
Per-bar sum of bid_size / ask_size on TBBO bars.
Aggregated by scripts/strategy_executor.py from raw tick bid_size/ask_size. Pair with imbalance(bid_vol, ask_vol) for an order-book pressure ratio.
Note: the WASM chart aggregator only emits 6 fields per bar; bid_vol/ask_vol live on the strategy-execution DataFrame, not the chart bar.
Returns
pandas Series of float64
Example
from quant_charts import bid_vol, ask_vol, imbalance
imb = imbalance(bid_vol, ask_vol)
buy_pressure = imb > 0.6
bid_price / ask_price / mid_price
TBBO best bid/ask/mid prices per bar.
Available on TBBO files; fall back to close on OHLC-only sources so cross-mode code stays symmetric.
Returns
pandas Series of float64
Example
from quant_charts import bid_price, ask_price, mid_price
spread_pct = (ask_price - bid_price) / mid_price * 100
bid_size / ask_size
TBBO per-tick resting size at best bid / ask.
Tick-mode quantity. Fall back to bid_vol / ask_vol on OHLC-aggregated TBBO bars so imbalance(bid_size, ask_size) works at any execution timeframe.
Returns
pandas Series of float64
Example
from quant_charts import bid_size, ask_size, imbalance
imb = imbalance(bid_size, ask_size)
hl2
Median price: (high + low) / 2
Midpoint of high and low. Less noisy than close alone and often used as a smoothed input for oscillators and moving averages.
Returns
pandas Series of float64
Example
from quant_charts import hl2
smoothed = hl2.rolling(14).mean()
Notes
- Formula:
(high + low) / 2
hlc3
Typical price: (high + low + close) / 3
Incorporates close for more weight toward the final traded price. Commonly used in VWAP-like calculations.
Returns
pandas Series of float64
Example
from quant_charts import hlc3
typical = hlc3.rolling(20).mean()
Notes
- Formula:
(high + low + close) / 3
ohlc4
Average price: (open + high + low + close) / 4
The most balanced representation of each bar's price action, weighting all four components equally.
Returns
pandas Series of float64
Example
from quant_charts import ohlc4
balanced = ohlc4.ewm(span=20).mean()
Notes
- Formula:
(open + high + low + close) / 4
TBBO vs OHLC
Two source-data types. Python only runs on OHLC bars; tick-level TBBO uses Rust.
Quant Charts ingests two parquet shapes:
- OHLC files (e.g.
MNQ_OHLC.parquet): pre-aggregated bars with open/high/low/close/volume and optional delta/vwap. Python strategies and indicators run directly on these. - TBBO files (e.g.
TBBO_Converted.parquet): tick-level bid/ask/bid_size/ask_size/volume/delta. Python execution uses an in-memory aggregator (scripts/strategy_executor.py) to produce OHLC bars at the active timeframe before callingcalculate(self, df). Tick-level access (per-tick bid/ask/microprice) is only available in Rust.
If you need per-tick decisions (microprice, spread compression, large-trade detection at tick granularity), write a Rust .rs file and use the #[strategy] or #[indicator] macro.
Example
# Python (OHLC bar path):
@indicator("VWAP Bands", overlay=True, data_mode='ohlc')
class VwapBands:
def calculate(self, df):
plot(df['vwap'], "VWAP")
# Rust (TBBO tick path):
#[indicator(name = "Spread Heatmap", overlay = false)]
pub struct SpreadHeatmap { /* ... */ }
Notes
- Python
data_modeaccepts'ohlc'only. Tick mode for Python was removed. - TBBO files still render in the chart via the WASM aggregator (6 fields per bar).
- On TBBO data, Python strategies see
bid_vol/ask_volcolumns produced by the bar aggregator.
price
price(source?)
Get the active price series for the chart.
Returns the appropriate price Series for OHLC bars. Pass "open", "high", "low", "close", "hl2", "hlc3", or "ohlc4" to pick a specific source.
Parameters
source(str, default"close"): OHLC source name
Returns
pandas Series
Example
src = price() # close by default
mid = price("hl2") # explicit hl2
is_ohlc_mode
is_ohlc_mode()
Returns True if the chart is showing OHLC candles.
Returns
bool
Example
if is_ohlc_mode():
true_range = high - low
is_tick_mode
is_tick_mode()
Returns True if the chart is showing tick data (TBBO files in tick view).
Python strategies always receive aggregated bars, but indicators that render directly on a tick-mode chart can branch on this. For tick-level computation use a Rust indicator.
Returns
bool
Example
if is_tick_mode():
spread = price("ask") - price("bid")
is_native_ohlc
is_native_ohlc()
Returns True if the source is native OHLC (real intra-bar variation).
Distinguishes native OHLC files (real open/high/low/close) from tick-derived OHLC (O=H=L=C=mid_price). Use this to gate calculations that need true range.
Returns
bool
Example
if is_native_ohlc():
tr = high - low
else:
tr = price().rolling(2).apply(lambda x: abs(x[1] - x[0]))
get_source_data_type
get_source_data_type()
Returns "TBBO", "OHLC", or None.
Returns
Optional[str]
Example
kind = get_source_data_type()
if kind == "TBBO":
log("running on tick-derived bars")
on_tick
on_tick(func)
Decorator: wrapped function only runs in tick mode.
Returns the decorated function unchanged but short-circuits to None when the chart is in OHLC mode. Use to keep tick-only logic out of OHLC code paths without an explicit if.
Returns
callable
Example
from quant_charts import on_tick
@on_tick
def microprice_drift():
return (ask_price + bid_price) * 0.5
drift = microprice_drift() # None in OHLC mode
on_ohlc
on_ohlc(func)
Decorator: wrapped function only runs in OHLC mode.
Returns
callable
Example
@on_ohlc
def true_range():
return (high - low).rolling(14).mean()
either
either(tick_func, ohlc_func)
Run tick_func() in tick mode, ohlc_func() in OHLC mode.
Convenience for two-implementation indicators where the tick path differs structurally from the OHLC path.
Returns
Any
Example
from quant_charts import either
result = either(
lambda: (ask_price - bid_price).rolling(20).mean(),
lambda: (high - low).rolling(20).mean(),
)
hour
Hour of day (0-23) in US/Eastern time.
Lazy proxy that extracts the hour from each bar's timestamp. Works like a numpy array in comparisons.
Important: Futures sessions cross midnight. A "Monday" session starts Sunday 6pm ET.
Returns
TimeSeries (int)
Example
from quant_charts import hour, minute
rth = (hour >= 9) & (hour < 16)
asian = (hour >= 19) | (hour < 1)
market_open = (hour == 9) & (minute == 30)
minute
Minute of hour (0-59).
Lazy proxy that extracts the minute from each bar's timestamp. Converted to US/Eastern time.
Returns
TimeSeries (int)
Example
from quant_charts import hour, minute
first_half = minute < 30
market_open = (hour == 9) & (minute == 30)
second
Second of minute (0-59). Useful for tick-level timing.
Lazy proxy, converted to US/Eastern time.
Returns
TimeSeries (int)
Example
from quant_charts import second
on_the_minute = second == 0
day_of_week
Day of week (0=Monday, 6=Sunday).
US/Eastern time. Remember: futures Sunday session = day_of_week == 6.
Returns
TimeSeries (int)
Example
from quant_charts import day_of_week
is_monday = day_of_week == 0
is_friday = day_of_week == 4
weekday = day_of_week < 5