Column Resolvers
Parquet-shape-portable helpers: volume_series, delta_series, vwap_series, df_col_or.
Why these helpers exist
Different parquets ship different columns. The resolvers let one indicator/strategy work on every shape.
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, the VWAP series) with an explicit fallback chain. Use them in calculate() instead of writing if/elif chains.
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.
volume_series
volume_series(df) -> np.ndarray
Per-bar volume with a fallback chain.
Priority:
volumecolumn (any OHLC parquet)bid_vol+ask_vol(TBBO-aggregated bars)tickCount(QC-converted parquets)- zeros (nothing available)
NaN entries are coerced to 0. Returns numpy array of length len(df).
Returns
numpy.ndarray of float64
Example
from quant_charts import indicator, plot, volume_series, PlotType
@indicator(name="Volume", overlay=False, required_columns=["close"])
class Volume:
def calculate(self, df):
vol = volume_series(df)
plot(vol, "Volume", color="#7AA2F7", plot_type=PlotType.HISTOGRAM)
delta_series
delta_series(df) -> np.ndarray
Per-bar signed delta with a fallback chain.
Priority:
deltacolumn (most OHLC parquets)ask_vol-bid_vol(TBBO-aggregated bars)sign(close - open)(any OHLC parquet)- zeros (nothing available)
NaN entries are coerced to 0. Pair with cvd(...) for cumulative volume delta.
Returns
numpy.ndarray of float64
Example
from quant_charts import delta_series, cvd, plot
delta_arr = delta_series(df)
cvd_arr = cvd(delta_arr)
plot(cvd_arr, "CVD", color="#7AA2F7")
vwap_series
vwap_series(df) -> np.ndarray
Per-bar VWAP from precomputed column or session-cumulative typical price.
Priority:
vwapcolumn (precomputed)- session-cumulative
typical_price * volume_series(df) / cumsum(volume_series(df))wheretypical_price = (high + low + close) / 3
Falls through volume_series(df) so it works regardless of whether volume, bid_vol+ask_vol, or tickCount is present. NaN denominators are handled internally.
Returns
numpy.ndarray of float64
Example
from quant_charts import vwap_series, vwap_band, ta, high, low, close
vwap = vwap_series(df)
atr = ta.atr(high, low, close, 14)
upper, lower = vwap_band(vwap, atr, mult=1.5)
df_col_or
df_col_or(df, *names, default=None) -> np.ndarray | default
First named column that exists, as a numpy array, or default if none exist.
Useful for opting into one of several alternative columns the data might or might not ship. Non-strict: returns default (None by default) when no name matches, so call sites can branch on is None.
Parameters
df(DataFrame, defaultrequired): pandas DataFrame*names(str, defaultrequired (1+)): candidate column names in priority orderdefault(Any, defaultNone): returned when no name matches
Returns
numpy.ndarray of float64, or default
Example
from quant_charts import df_col_or
import numpy as np
# pick the first available size column, fall back to zeros
size = df_col_or(df, "trade_size", "tickCount", default=np.zeros(len(df)))
# returns None when neither column exists; branch on it
vwap = df_col_or(df, "vwap")
if vwap is not None:
plot(vwap, "VWAP", color="#E0AF68")
raw_ticks
raw_ticksraw_ticks.df / raw_ticks[col] / raw_ticks.col_name
Full raw parquet DataFrame for the current trading day. Use when bar-level data is not enough.
Module-level accessor populated when the strategy or indicator is run with a raw TBBO parquet attached. Three access patterns:
raw_ticks.df-> the full pandas DataFrame for the day. None when no raw parquet is attached.raw_ticks["col"]-> pandas Series for one column. KeyError when raw_ticks is unavailable.raw_ticks.col_name-> numpy array for one column (attribute syntax). AttributeError when the column is missing.
Len check via len(raw_ticks); truthiness check via bool(raw_ticks). Use for analyses that need every tick (not the aggregated bar): print-by-print volume, signed trade direction, microstructure imbalance, large-trade filtering.
Example
from quant_charts import indicator, raw_ticks, log
@indicator(name="Big Prints", overlay=True, required_columns=["close"])
class BigPrints:
def calculate(self, df):
if not raw_ticks:
log("no raw parquet attached; skipping")
return
ticks = raw_ticks.df
big = ticks[ticks["volume"] > ticks["volume"].quantile(0.99)]
log(f"{len(big)} big prints in the session")
Notes
- Available only when the parent run was launched with a raw parquet path. Backtests and analyzer runs on aggregated OHLC files do not populate it.
- Returns numpy arrays via attribute access, pandas Series via item access. Pick whichever matches your downstream code.