Quant Charts Indicator API Reference (Python)

Everything needed to write a Quant Charts indicator in Python, composed from the per-topic reference.

Decorators

Top-level annotations that turn a Python file into an indicator, strategy, script, or day-start hoist.

@indicator

@indicator(name, overlay?, description?, data_mode?, timeframe?)

Mark a Python class as a chart indicator.

The @indicator decorator transforms a Python class into a chart indicator that receives price data and draws visual output. The class must implement a calculate(self, df) method that receives the chart DataFrame.

Call plot(), hline(), or fill() inside calculate() to draw on the chart. Access price data via the global series: close, open, high, low, volume.

Python indicators run on OHLC bars. For TBBO tick-level indicators, use a Rust .rs file with the #[indicator] macro instead.

Parameters

  • name (str, default required): Display name shown in the indicator panel
  • overlay (bool, default False): If True, draws on price chart. If False, separate pane
  • description (str, default None): Optional tooltip description
  • data_mode (str, default 'ohlc'): Always 'ohlc' for Python indicators. Use Rust for tick.
  • timeframe (Timeframe, default None): Target timeframe for the indicator

Returns

None. Use plot() inside calculate() to draw output.

Example

from quant_charts import indicator, input, plot, close

@indicator("SMA", overlay=True)
class SMA:
    period = input.int(20, "Period", min=1, max=500)
    color = input.color("#2962FF", "Color")

    def calculate(self, df):
        result = close.rolling(self.period).mean()
        plot(result, f"SMA({self.period})", color=self.color)

Notes

  • calculate() is called every time the chart data updates.
  • Use input.* class variables to create user-configurable parameters.
  • Multiple plot() calls create multiple series on the same indicator.

@strategy

@strategy(name, overlay?, timeframe?, description?, data_mode?, uses_sltp?, emit_sltp?, required_columns?)

Mark a Python class as a backtestable trading strategy.

The @strategy decorator creates a trading strategy that returns entry/exit signals for backtesting. The class must implement calculate(self, df) which returns a dict of boolean signal Series.

The backtester uses these signals to simulate trades and compute equity curves, win rates, drawdowns, and other performance metrics.

Python strategies run on OHLC bars only. For tick-level TBBO strategies use a Rust .rs file.

Parameters

  • name (str, default required): Display name shown in the strategy panel
  • overlay (bool, default True): If True, draws on the price chart
  • timeframe (Timeframe, default None): Default execution timeframe
  • description (str, default None): Optional tooltip description
  • data_mode (str, default 'ohlc'): Always 'ohlc' for Python strategies
  • uses_sltp (bool, default False): If True, the strategy returns sl_long/tp_long/sl_short/tp_short arrays
  • emit_sltp (str, default 'entry_only'): 'entry_only' (set once at entry) or 'per_tick' (re-evaluated each bar)
  • required_columns (list[str], default auto): Columns the strategy reads. SHM only ships these to workers.

Returns

A dict with keys: "entry_long", "exit_long", "entry_short", "exit_short". With uses_sltp=True, also "sl_long", "tp_long", "sl_short", "tp_short".

Example

from quant_charts import strategy, input, indicators, cross_above, cross_below, Timeframe

@strategy("MA Cross", overlay=True, timeframe=Timeframe.M1)
class MACross:
    fast = input.int(10, "Fast", min=1, max=100)
    slow = input.int(20, "Slow", min=2, max=200)

    def calculate(self, df):
        fast_ma = indicators.sma(period=self.fast, color="#26A69A")
        slow_ma = indicators.sma(period=self.slow, color="#EF5350")

        return {
            'entry_long': cross_above(fast_ma, slow_ma),
            'exit_long': cross_below(fast_ma, slow_ma),
            'entry_short': cross_below(fast_ma, slow_ma),
            'exit_short': cross_above(fast_ma, slow_ma),
        }

Notes

  • Use indicators.sma() / indicators.ema() to add visual overlays alongside your strategy.
  • Signal Series must be boolean. Use cross_above() / cross_below() for crossovers.
  • Conflicting signals on the same bar: exit is resolved before entry.
  • Hoist param-independent work into a @day_start method for fast optimization sweeps.

@day_start

@day_start(method)

Mark a method to run once per day per worker, before the parameter sweep.

Hoists parameter-independent computation out of the per-combo calculate() body. The decorated method runs once per trading day per worker process; results stored on self are visible inside calculate() for every parameter combination.

Use this for any heavy work that does not depend on swept params: full-series ta calls with literal periods, day-level summary stats, regime detection, cached indicator outputs.

Parameters

  • method (callable, default required): Method on the strategy/indicator class with signature (self, df) -> None

Returns

None. Store hoisted arrays as self.<name> for use inside calculate().

Example

from quant_charts import strategy, day_start, input, ta, close, cross_above, cross_below

@strategy("Hoisted EMA Cross")
class HoistedCross:
    fast = input.int(10, "Fast", min=2, max=50)
    slow = input.int(30, "Slow", min=5, max=200)

    @day_start
    def prep(self, df):
        # hoisted: param-independent, runs once per day not once per combo
        self.atr = ta.atr(df['high'], df['low'], df['close'], 14)

    def calculate(self, df):
        fast_ma = close.rolling(self.fast).mean()
        slow_ma = close.rolling(self.slow).mean()
        return {
            'entry_long': cross_above(fast_ma, slow_ma),
            'exit_long':  cross_below(fast_ma, slow_ma),
            'entry_short': cross_below(fast_ma, slow_ma),
            'exit_short':  cross_above(fast_ma, slow_ma),
        }

Notes

  • Critical for fast optimization sweeps: a 100-combo sweep with hoisted ATR runs the ATR once instead of 100 times.
  • Anything assigned to self.* inside @day_start is visible in calculate().
  • Calls inside @day_start should use literal periods, not swept parameters.

@script

@script(name, description?, version?)

Mark a Python class as a utility script for data analysis. Used in .py files only (not notebooks).

The @script decorator creates a standalone script that runs once when executed. Unlike indicators and strategies, scripts do not draw on the chart. Instead they process data, export files, or produce analysis output.

Note: Scripts are standalone .py files executed from the file explorer. For notebook-based analysis, use regular Python cells instead.

Scripts have access to script_helpers for exporting data, reading chart state, and accessing indicator values.

Parameters

  • name (str, default required): Display name for the script
  • description (str, default None): Optional description
  • version (str, default None): Optional version string

Returns

Optional dict, displayed in the output panel.

Example

from quant_charts import script, input
from quant_charts.script_helpers import get_chart_data, export_csv

@script("Data Export")
class DataExporter:
    filename = input.string("export.csv", "Filename")

    def execute(self, df):
        df.to_csv(self.filename)
        return {"status": "success", "rows": len(df)}

Output

>>> Output
{'status': 'success', 'rows': 14523}

Notes

  • Scripts implement execute(self, df) instead of calculate(self, df).
  • Import from quant_charts.script_helpers for data access and export.

Inputs

Per-strategy parameters that surface in the analyzer UI for tuning and sweeping.

input.int

input.int(default, label, min?, max?, step?, tooltip?)

Integer parameter with optional range constraints.

Creates an integer input that appears in the settings panel when the user configures your indicator or strategy. The value is accessible as a class attribute via self.<field_name>.

Parameters

  • default (int, default required): Default value
  • label (str, default required): Display label in settings panel
  • min (int, default None): Minimum allowed value
  • max (int, default None): Maximum allowed value
  • step (int, default 1): Increment step for the slider
  • tooltip (str, default None): Hover tooltip text

Returns

int

Example

period = input.int(14, "RSI Period", min=2, max=100)
length = input.int(20, "Length", min=1, max=500, step=5)

input.float

input.float(default, label, min?, max?, step?, tooltip?)

Decimal parameter for multipliers, thresholds, and ratios.

Parameters

  • default (float, default required): Default value
  • label (str, default required): Display label in settings panel
  • min (float, default None): Minimum allowed value
  • max (float, default None): Maximum allowed value
  • step (float, default 0.1): Increment step
  • tooltip (str, default None): Hover tooltip text

Returns

float

Example

multiplier = input.float(2.0, "Std Dev", min=0.5, max=5.0, step=0.1)

input.color

input.color(default, label, tooltip?)

Color picker for line and fill colors.

Creates a color picker input. The value is a hex color string (e.g. "#2962FF") passed to plot(), hline(), and fill().

Parameters

  • default (str, default required): Default hex color string
  • label (str, default required): Display label in settings panel
  • tooltip (str, default None): Hover tooltip text

Returns

str (hex color)

Example

color = input.color("#2962FF", "Line Color")

input.bool

input.bool(default, label, tooltip?)

Toggle checkbox for enabling/disabling features.

Parameters

  • default (bool, default required): Default value
  • label (str, default required): Display label in settings panel
  • tooltip (str, default None): Hover tooltip text

Returns

bool

Example

show_fill = input.bool(True, "Show Fill")

input.string

input.string(default, label, options?, tooltip?)

Text input or dropdown selector.

When options is provided, renders as a dropdown. Without options, renders as a free-text input field.

Parameters

  • default (str, default required): Default value
  • label (str, default required): Display label in settings panel
  • options (list[str], default None): Allowed values, renders as dropdown
  • tooltip (str, default None): Hover tooltip text

Returns

str

Example

ma_type = input.string("SMA", "Type", options=["SMA", "EMA", "WMA"])

input.source

input.source(default, label, tooltip?)

Price source selector dropdown.

Creates a dropdown to select a price source. The value resolves to the corresponding pandas Series at runtime.

Parameters

  • default (Source, default required): Default Source enum value
  • label (str, default required): Display label in settings panel
  • tooltip (str, default None): Hover tooltip text

Returns

pandas Series (the selected price source)

Example

from quant_charts import Source
src = input.source(Source.CLOSE, "Price Source")

Notes

  • Sources: Source.CLOSE, .OPEN, .HIGH, .LOW, .HL2, .HLC3, .OHLC4

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:

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 calling calculate(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_mode accepts '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_vol columns 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

Technical Analysis

Vectorized ta.* namespace: moving averages, RSI, MACD, Bollinger, ATR, and friends.

ta.sma

ta.sma(source, period)

Simple Moving Average.

Calculates the arithmetic mean of source over a rolling window of period bars. Uses Numba JIT compilation for datasets > 10,000 values.

Parameters

  • source (array-like, default required): Price data (pandas Series or numpy array)
  • period (int, default required): Number of bars in the lookback window

Returns

numpy array

Example

from quant_charts import ta, close
sma = ta.sma(close, 20)
# Smooth an existing result (numpy -> numpy)
smoothed = ta.sma(sma, 5)

Notes

  • Returns a numpy array, NOT a pandas Series.
  • Use ta.sma() to smooth other ta.* results instead of .rolling().mean().

ta.ema

ta.ema(source, period)

Exponential Moving Average.

Gives more weight to recent values. Faster to react than SMA.

Parameters

  • source (array-like, default required): Price data
  • period (int, default required): Lookback period (span)

Returns

numpy array

Example

ema = ta.ema(close, 12)

ta.wma

ta.wma(source, period)

Weighted Moving Average.

Linearly weights recent values more heavily than older ones.

Parameters

  • source (array-like, default required): Price data
  • period (int, default required): Lookback period

Returns

numpy array

Example

wma = ta.wma(close, 20)

ta.rsi

ta.rsi(source, period)

Relative Strength Index (0-100).

Momentum oscillator that measures the speed and magnitude of price changes. Values above 70 indicate overbought, below 30 oversold.

Parameters

  • source (array-like, default required): Price data
  • period (int, default 14): Lookback period

Returns

numpy array

Example

rsi = ta.rsi(close, 14)
# Smooth RSI with SMA (correct numpy approach)
smooth_rsi = ta.sma(rsi, 5)

Notes

  • The result is a numpy array. Do NOT call .rolling() on it.

ta.macd

ta.macd(source, fast?, slow?, signal?)

Moving Average Convergence Divergence.

Returns a tuple of three numpy arrays: MACD line, signal line, and histogram. Use tuple unpacking.

Parameters

  • source (array-like, default required): Price data
  • fast (int, default 12): Fast EMA period
  • slow (int, default 26): Slow EMA period
  • signal (int, default 9): Signal line EMA period

Returns

tuple: (macd_line, signal_line, histogram), all numpy arrays

Example

macd_line, signal_line, histogram = ta.macd(close)
buy = cross_above(macd_line, signal_line)

ta.stochastic

ta.stochastic(high, low, close, k_period?, d_period?)

Stochastic Oscillator (%K and %D).

Parameters

  • high (array-like, default required): High prices
  • low (array-like, default required): Low prices
  • close (array-like, default required): Close prices
  • k_period (int, default 14): %K lookback period
  • d_period (int, default 3): %D smoothing period

Returns

tuple: (k, d), both numpy arrays

Example

k, d = ta.stochastic(high, low, close, 14, 3)
buy = cross_above(k, d) & below(k, 20)

ta.bollinger_bands

ta.bollinger_bands(source, period?, std?)

Bollinger Bands (upper, middle, lower).

Parameters

  • source (array-like, default required): Price data
  • period (int, default 20): SMA period
  • std (float, default 2.0): Standard deviation multiplier

Returns

tuple: (upper, middle, lower), all numpy arrays

Example

upper, mid, lower = ta.bollinger_bands(close, 20, 2.0)
plot(upper, "Upper BB")
plot(lower, "Lower BB")
fill("Upper BB", "Lower BB", color="#2962FF", opacity=10)

ta.atr

ta.atr(high, low, close, period?)

Average True Range, a volatility measure.

Parameters

  • high (array-like, default required): High prices
  • low (array-like, default required): Low prices
  • close (array-like, default required): Close prices
  • period (int, default 14): Lookback period

Returns

numpy array

Example

atr = ta.atr(high, low, close, 14)
avg_atr = ta.sma(atr, 50)
high_vol = atr > avg_atr

ta.stddev

ta.stddev(source, period)

Rolling standard deviation.

Parameters

  • source (array-like, default required): Input data
  • period (int, default required): Lookback window

Returns

numpy array

Example

vol = ta.stddev(close, 20)

ta.highest

ta.highest(source, period)

Rolling maximum over a lookback window.

Parameters

  • source (array-like, default required): Input data
  • period (int, default required): Lookback window

Returns

numpy array

Example

resistance = ta.highest(high, 20)

ta.lowest

ta.lowest(source, period)

Rolling minimum over a lookback window.

Parameters

  • source (array-like, default required): Input data
  • period (int, default required): Lookback window

Returns

numpy array

Example

support = ta.lowest(low, 20)

ta.change

ta.change(source, length?)

Difference between current and N bars ago.

Equivalent to pandas .diff(length) but works on numpy arrays.

Parameters

  • source (array-like, default required): Input data
  • length (int, default 1): Lookback distance

Returns

numpy array

Example

momentum = ta.change(close, 10)

Notes

  • Use this instead of .diff() on numpy arrays from ta.* results.

ta.roc

ta.roc(source, length?)

Rate of change in percent.

Calculates 100 * (current - previous) / previous. Equivalent to pandas .pct_change() * 100.

Parameters

  • source (array-like, default required): Input data
  • length (int, default 1): Lookback distance

Returns

numpy array (percentage values)

Example

pct_change = ta.roc(close, 5)

Notes

  • Returns percentage (e.g. 2.5 not 0.025). Divide by 100 for decimal.

Plotting

Lines, histograms with per-bar colors, fills, hlines, and shape markers.

plot

plot(series, name, color?, linewidth?, plot_type?, opacity?, colors?, align?, width_px?)

Draw a data series on the chart.

Draws a line, histogram, area, or step line from a pandas Series. Each plot() call creates a named series visible in the chart legend.

For per-bar coloring (e.g. yellow for block trades, gray for normal), pass a colors= array the same length as series. Per-bar colors are only valid for HISTOGRAM, COLUMNS, CROSS, CIRCLES. Lines, areas, and step lines stay single-color.

align= reshapes the geometry instead of laying bars along the time axis:

  • pinned_top / pinned_bottom - horizontal strip glued to chart top/bottom (volume-pane layout). Bars time-align to candles via timeToCoordinate; height proportional to value normalized to visible range.
  • pinned_left / pinned_right - vertical strip glued to chart left/right edge (HUD layout). Anchored to the price axis.
  • left_of_range / right_of_range - anchored to the first/last visible bar.
  • over_range - stretches across the visible range.

Pair with width_px= to control the pinned strip width (left/right) or thickness (top/bottom).

Parameters

  • series (Series, default required): pandas Series of values to plot
  • name (str, default required): Legend label (must be unique per indicator)
  • color (str, default "#2962FF"): Hex color string (fallback when colors[i] is None). Accepts 6-char #rrggbb or 8-char #rrggbbaa.
  • linewidth (int, default 2): Line thickness in pixels
  • plot_type (PlotType, default LINE): LINE, HISTOGRAM, COLUMNS, CROSS, CIRCLES, AREA, or STEPLINE
  • opacity (int, default 100): Opacity 0-100 for area fills
  • colors (list[str | None], default None): Per-bar color override array. Same length as series. None entries fall back to color. HISTOGRAM/COLUMNS/CROSS/CIRCLES only.
  • align (str, default None): pinned_top, pinned_bottom, pinned_left, pinned_right, left_of_range, right_of_range, or over_range. HISTOGRAM/COLUMNS/AREA only.
  • width_px (int, default 60): CSS pixels for the pinned region. Strip width for pinned_left/pinned_right; strip thickness for pinned_top/pinned_bottom.

Returns

None

Example

sma = close.rolling(20).mean()
plot(sma, "SMA(20)", color="#2962FF", linewidth=2)

# Per-bar histogram coloring: yellow on big trades, gray otherwise
import numpy as np
big = volume > volume.rolling(50).mean() * 3
colors = np.where(big, "#e0af68", "#3a3a45").tolist()
plot(volume, "Volume", color="#3a3a45", plot_type=PlotType.HISTOGRAM, colors=colors)

Notes

  • colors= is the per-bar override. Pass a list of hex strings or None (None falls back to color).
  • Convenience helpers: plot_histogram_colored, plot_columns_colored, plot_cross_colored, plot_circles_colored.
  • Mismatched length between colors and series raises ValueError.
  • plot() has no style or linestyle parameter (this is not Pine Script). Use plot_type for line shape; linestyle exists only on hline. Passing style= or linestyle= to plot() raises a TypeError.

plot_histogram_colored

plot_histogram_colored(series, name, base_color, colors)

Histogram with per-bar color overrides.

Convenience wrapper for plot(..., plot_type=HISTOGRAM, colors=...). Same shape as the Rust plot_histogram_colored builder.

Parameters

  • series (Series, default required): Values to plot
  • name (str, default required): Legend label
  • base_color (str, default required): Fallback color for bars where colors[i] is None
  • colors (list[str | None], default required): Per-bar color overrides

Returns

None

Example

from quant_charts import plot_histogram_colored
colors = ["#e0af68" if x > thresh else None for x in trade_size]
plot_histogram_colored(trade_size, "Trade Size", "#3a3a45", colors)

hline

hline(value, name, color?, linewidth?, linestyle?)

Draw a horizontal reference line at a fixed value.

Draws a horizontal line at a constant Y-axis value. Common for overbought/oversold levels in oscillators.

Parameters

  • value (float, default required): Y-axis value
  • name (str, default required): Legend label
  • color (str, default "#787B86"): Hex color string
  • linewidth (int, default 1): Line thickness in pixels
  • linestyle (str, default "solid"): "solid", "dashed", or "dotted"

Returns

None

Example

hline(70, "Overbought", color="#EF5350", linestyle="dashed")
hline(30, "Oversold", color="#26A69A", linestyle="dashed")

fill

fill(series1_name, series2_name, color?, opacity?)

Fill the area between two plotted series.

Fills the space between two previously plotted series. Both must have been drawn with plot() first, referenced by their name string.

Parameters

  • series1_name (str, default required): Name of the first plot() series
  • series2_name (str, default required): Name of the second plot() series
  • color (str, default "#2962FF"): Fill color as hex string
  • opacity (int, default 10): Fill opacity 0-100

Returns

None

Example

plot(upper, "Upper", color="#2962FF")
plot(lower, "Lower", color="#2962FF")
fill("Upper", "Lower", color="#2962FF", opacity=10)

vp_visual

vp_visual(anchor_ts, end_ts, price_min, price_step, bins, poc_price, vah, val, ...)

Emit a horizontal volume profile histogram (POC + value area).

Pure-Python parity with the Rust push_vp_visual(...) builder. The renderer draws bars at each price row, an accent line at the Point of Control, and the Value Area High / Low as a translucent zone.

anchor_ts and end_ts are Unix milliseconds (the executor converts to seconds for Lightweight Charts). bins[i] is the volume in the price row starting at price_min + i * price_step. align defaults to right_of_range; pass pinned_right to glue to the chart edge regardless of pan.

Progressive trails (poc_trail, value_area_trail) draw a moving POC/VA line across each session anchor instead of a single static profile.

Parameters

  • anchor_ts (int, default required): Anchor timestamp (Unix ms). Where the histogram baseline starts.
  • end_ts (int, default required): End timestamp (Unix ms).
  • price_min (float, default required): Lower edge of the lowest bin.
  • price_step (float, default required): Row height in price units. Must be > 0.
  • bins (list[float], default required): Volume per row, length = number of rows.
  • poc_price (float, default required): Point of Control (highest-volume row center).
  • vah (float, default required): Value Area High.
  • val (float, default required): Value Area Low.
  • color (str, default "#7aa2f7"): Bar color (overridden per-bin by bin_colors[i]).
  • poc_color (str, default "#e0af68"): POC accent line color.
  • value_area_color (str, default "#73daca"): Value-area zone color.
  • opacity (int, default 60): Bar opacity 0-100.
  • width_px (int, default 80): Histogram width in CSS pixels.
  • align (str, default "right_of_range"): right_of_range, left_of_range, over_range, pinned_right, pinned_left, pinned_top, pinned_bottom.
  • style (str, default "bars"): bars, line, or area.
  • bin_colors (list[str | None], default None): Per-row color override (same length as bins).
  • hvn_levels (list[float], default None): High-volume node prices (drawn as bright lines).
  • lvn_levels (list[float], default None): Low-volume node prices.
  • poc_trail (list[dict], default None): List of {ts: ms, price: float} for a moving POC line.
  • value_area_trail (list[dict], default None): List of {ts: ms, vah: float, val: float} for VA bands.
  • draw_level_lines (bool, default True): Draw POC/VAH/VAL horizontal lines across the range.

Returns

None

Example

from quant_charts import vp_visual
import numpy as np

# bin all session ticks into 0.25 price rows
bins = np.histogram(typical, range=(lo, hi), bins=int((hi-lo)/0.25))[0]
poc_idx = int(np.argmax(bins))
poc_price = lo + (poc_idx + 0.5) * 0.25

vp_visual(
    anchor_ts=int(ts[0]), end_ts=int(ts[-1]),
    price_min=lo, price_step=0.25,
    bins=bins.tolist(),
    poc_price=poc_price, vah=poc_price + 4.0, val=poc_price - 4.0,
    width_px=80, opacity=55,
    align="right_of_range",
)

Notes

  • Timestamps are Unix MILLISECONDS; the executor converts to seconds.
  • opacity is rejected if outside 0-100. NaN/Inf in any price field is rejected.
  • align validates against the five known values; unknown strings raise.
  • Calling vp_visual() multiple times in one calculate() emits multiple histograms (one per anchor).
Machine-readable: full API at /llms-full.txt · examples on GitHub.