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:

  1. volume column (any OHLC parquet)
  2. bid_vol + ask_vol (TBBO-aggregated bars)
  3. tickCount (QC-converted parquets)
  4. 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:

  1. delta column (most OHLC parquets)
  2. ask_vol - bid_vol (TBBO-aggregated bars)
  3. sign(close - open) (any OHLC parquet)
  4. 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:

  1. vwap column (precomputed)
  2. session-cumulative typical_price * volume_series(df) / cumsum(volume_series(df)) where typical_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, default required): pandas DataFrame
  • *names (str, default required (1+)): candidate column names in priority order
  • default (Any, default None): 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.