Everything needed to write a Quant Charts indicator in Python, composed from the per-topic reference.
Quant Charts Indicator API Reference (Python)
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, defaultrequired): Display name shown in the indicator paneloverlay(bool, defaultFalse): IfTrue, draws on price chart. IfFalse, separate panedescription(str, defaultNone): Optional tooltip descriptiondata_mode(str, default'ohlc'): Always'ohlc'for Python indicators. Use Rust for tick.timeframe(Timeframe, defaultNone): 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, defaultrequired): Display name shown in the strategy paneloverlay(bool, defaultTrue): IfTrue, draws on the price charttimeframe(Timeframe, defaultNone): Default execution timeframedescription(str, defaultNone): Optional tooltip descriptiondata_mode(str, default'ohlc'): Always'ohlc'for Python strategiesuses_sltp(bool, defaultFalse): IfTrue, the strategy returnssl_long/tp_long/sl_short/tp_shortarraysemit_sltp(str, default'entry_only'):'entry_only'(set once at entry) or'per_tick'(re-evaluated each bar)required_columns(list[str], defaultauto): 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_startmethod 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, defaultrequired): 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_startis visible incalculate(). - Calls inside
@day_startshould 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, defaultrequired): Display name for the scriptdescription(str, defaultNone): Optional descriptionversion(str, defaultNone): 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 ofcalculate(self, df). - Import from
quant_charts.script_helpersfor 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, defaultrequired): Default valuelabel(str, defaultrequired): Display label in settings panelmin(int, defaultNone): Minimum allowed valuemax(int, defaultNone): Maximum allowed valuestep(int, default1): Increment step for the slidertooltip(str, defaultNone): 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, defaultrequired): Default valuelabel(str, defaultrequired): Display label in settings panelmin(float, defaultNone): Minimum allowed valuemax(float, defaultNone): Maximum allowed valuestep(float, default0.1): Increment steptooltip(str, defaultNone): 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, defaultrequired): Default hex color stringlabel(str, defaultrequired): Display label in settings paneltooltip(str, defaultNone): 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, defaultrequired): Default valuelabel(str, defaultrequired): Display label in settings paneltooltip(str, defaultNone): 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, defaultrequired): Default valuelabel(str, defaultrequired): Display label in settings paneloptions(list[str], defaultNone): Allowed values, renders as dropdowntooltip(str, defaultNone): 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, defaultrequired): Default Source enum valuelabel(str, defaultrequired): Display label in settings paneltooltip(str, defaultNone): 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:
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
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, defaultrequired): Price data (pandas Series or numpy array)period(int, defaultrequired): 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 otherta.*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, defaultrequired): Price dataperiod(int, defaultrequired): 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, defaultrequired): Price dataperiod(int, defaultrequired): 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, defaultrequired): Price dataperiod(int, default14): 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, defaultrequired): Price datafast(int, default12): Fast EMA periodslow(int, default26): Slow EMA periodsignal(int, default9): 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, defaultrequired): High priceslow(array-like, defaultrequired): Low pricesclose(array-like, defaultrequired): Close pricesk_period(int, default14): %K lookback periodd_period(int, default3): %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, defaultrequired): Price dataperiod(int, default20): SMA periodstd(float, default2.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, defaultrequired): High priceslow(array-like, defaultrequired): Low pricesclose(array-like, defaultrequired): Close pricesperiod(int, default14): 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, defaultrequired): Input dataperiod(int, defaultrequired): 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, defaultrequired): Input dataperiod(int, defaultrequired): 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, defaultrequired): Input dataperiod(int, defaultrequired): 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, defaultrequired): Input datalength(int, default1): Lookback distance
Returns
numpy array
Example
momentum = ta.change(close, 10)
Notes
- Use this instead of
.diff()on numpy arrays fromta.*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, defaultrequired): Input datalength(int, default1): 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 viatimeToCoordinate; 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, defaultrequired): pandas Series of values to plotname(str, defaultrequired): Legend label (must be unique per indicator)color(str, default"#2962FF"): Hex color string (fallback whencolors[i]is None). Accepts 6-char#rrggbbor 8-char#rrggbbaa.linewidth(int, default2): Line thickness in pixelsplot_type(PlotType, defaultLINE):LINE,HISTOGRAM,COLUMNS,CROSS,CIRCLES,AREA, orSTEPLINEopacity(int, default100): Opacity 0-100 for area fillscolors(list[str | None], defaultNone): Per-bar color override array. Same length asseries. None entries fall back tocolor. HISTOGRAM/COLUMNS/CROSS/CIRCLES only.align(str, defaultNone):pinned_top,pinned_bottom,pinned_left,pinned_right,left_of_range,right_of_range, orover_range. HISTOGRAM/COLUMNS/AREA only.width_px(int, default60): CSS pixels for the pinned region. Strip width forpinned_left/pinned_right; strip thickness forpinned_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 orNone(None falls back tocolor).- Convenience helpers:
plot_histogram_colored,plot_columns_colored,plot_cross_colored,plot_circles_colored. - Mismatched length between
colorsandseriesraisesValueError. plot()has nostyleorlinestyleparameter (this is not Pine Script). Useplot_typefor line shape;linestyleexists only onhline. Passingstyle=orlinestyle=toplot()raises aTypeError.
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, defaultrequired): Values to plotname(str, defaultrequired): Legend labelbase_color(str, defaultrequired): Fallback color for bars wherecolors[i]is Nonecolors(list[str | None], defaultrequired): 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, defaultrequired): Y-axis valuename(str, defaultrequired): Legend labelcolor(str, default"#787B86"): Hex color stringlinewidth(int, default1): Line thickness in pixelslinestyle(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, defaultrequired): Name of the firstplot()seriesseries2_name(str, defaultrequired): Name of the secondplot()seriescolor(str, default"#2962FF"): Fill color as hex stringopacity(int, default10): 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, defaultrequired): Anchor timestamp (Unix ms). Where the histogram baseline starts.end_ts(int, defaultrequired): End timestamp (Unix ms).price_min(float, defaultrequired): Lower edge of the lowest bin.price_step(float, defaultrequired): Row height in price units. Must be > 0.bins(list[float], defaultrequired): Volume per row, length = number of rows.poc_price(float, defaultrequired): Point of Control (highest-volume row center).vah(float, defaultrequired): Value Area High.val(float, defaultrequired): Value Area Low.color(str, default"#7aa2f7"): Bar color (overridden per-bin bybin_colors[i]).poc_color(str, default"#e0af68"): POC accent line color.value_area_color(str, default"#73daca"): Value-area zone color.opacity(int, default60): Bar opacity 0-100.width_px(int, default80): 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, orarea.bin_colors(list[str | None], defaultNone): Per-row color override (same length asbins).hvn_levels(list[float], defaultNone): High-volume node prices (drawn as bright lines).lvn_levels(list[float], defaultNone): Low-volume node prices.poc_trail(list[dict], defaultNone): List of{ts: ms, price: float}for a moving POC line.value_area_trail(list[dict], defaultNone): List of{ts: ms, vah: float, val: float}for VA bands.draw_level_lines(bool, defaultTrue): 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.
opacityis rejected if outside 0-100. NaN/Inf in any price field is rejected.alignvalidates against the five known values; unknown strings raise.- Calling
vp_visual()multiple times in one calculate() emits multiple histograms (one per anchor).