Quant Charts exposes order-flow primitives through cvd(), imbalance(), and delta_series(). The signal-helper reference plus complete CVD and imbalance indicators follow.
Quant Charts Order-Flow API (CVD, Imbalance, Delta)
Signal Helpers
Crossover detection, threshold checks, streak counting, and order-flow primitives (cvd, imbalance, vwap_band).
cross_above
cross_above(series1, series2)
Detect where series1 crosses above series2.
Returns a boolean Series that is True on bars where series1 crosses above series2. A crossover occurs when series1 was at or below series2 on the previous bar and is now above it.
Parameters
series1(Series, defaultrequired): The series crossing upseries2(Series, defaultrequired): The reference level (series or number)
Returns
numpy boolean array
Example
from quant_charts import cross_above, close
fast_ma = close.rolling(10).mean()
slow_ma = close.rolling(20).mean()
buy_signal = cross_above(fast_ma, slow_ma)
Notes
- Equivalent to:
(s1 > s2) & (s1.shift(1) <= s2.shift(1))
cross_below
cross_below(series1, series2)
Detect where series1 crosses below series2.
Returns a boolean Series that is True on bars where series1 crosses below series2.
Parameters
series1(Series, defaultrequired): The series crossing downseries2(Series, defaultrequired): The reference level (series or number)
Returns
numpy boolean array
Example
sell_signal = cross_below(fast_ma, slow_ma)
Notes
- Equivalent to:
(s1 < s2) & (s1.shift(1) >= s2.shift(1))
above
above(series, value)
True where series is strictly above value.
Element-wise comparison. Works with both numpy arrays and pandas Series. value can be a number or another series.
Parameters
series(array-like, defaultrequired): Input datavalue(number | array, defaultrequired): Threshold value or series
Returns
numpy boolean array
Example
from quant_charts import above, ta, close
rsi = ta.rsi(close, 14)
is_overbought = above(rsi, 70)
Notes
- Strict comparison:
series > value
below
below(series, value)
True where series is strictly below value.
Parameters
series(array-like, defaultrequired): Input datavalue(number | array, defaultrequired): Threshold value or series
Returns
numpy boolean array
Example
is_oversold = below(rsi, 30)
Notes
- Strict comparison:
series < value
between
between(series, lower, upper)
True where lower <= series <= upper (inclusive).
Parameters
series(array-like, defaultrequired): Input datalower(number, defaultrequired): Lower bound (inclusive)upper(number, defaultrequired): Upper bound (inclusive)
Returns
numpy boolean array
Example
is_neutral = between(rsi, 30, 70)
Notes
- Inclusive on both ends:
lower <= series <= upper
rising
rising(series, length)
True if series has been rising for N consecutive bars.
Parameters
series(array-like, defaultrequired): Input datalength(int, defaultrequired): Number of consecutive rising bars required
Returns
numpy boolean array
Example
from quant_charts import rising, close
uptrend = rising(close, 3) # 3 consecutive higher closes
falling
falling(series, length)
True if series has been falling for N consecutive bars.
Parameters
series(array-like, defaultrequired): Input datalength(int, defaultrequired): Number of consecutive falling bars required
Returns
numpy boolean array
Example
downtrend = falling(close, 3)
barssince
barssince(condition)
Count bars since condition was last True.
Returns an array where each element is the number of bars since condition was last True. Values before the first True are NaN.
Parameters
condition(bool array, defaultrequired): Boolean condition array
Returns
numpy float array (NaN before first occurrence)
Example
from quant_charts import barssince, cross_above
bars_since_buy = barssince(cross_above(fast, slow))
valuewhen
valuewhen(condition, source, occurrence?)
Get the value of source when condition was last True.
Returns the value of source at the most recent bar where condition was True. occurrence=0 is the most recent, occurrence=1 is the one before that.
Parameters
condition(bool array, defaultrequired): Boolean condition arraysource(array-like, defaultrequired): Values to sample fromoccurrence(int, default0): 0 = most recent, 1 = previous, etc.
Returns
numpy float array
Example
from quant_charts import valuewhen, cross_above, close
entry_price = valuewhen(cross_above(fast, slow), close, 0)
imbalance
imbalance(bid_size, ask_size)
Order-book imbalance: bid / (bid + ask).
Returns a value in [0, 1] where 0.5 is balanced, > 0.5 is bid-heavy (buy pressure), < 0.5 is ask-heavy. Safe on zero volume.
Parameters
bid_size(array-like, defaultrequired): Bid-side size seriesask_size(array-like, defaultrequired): Ask-side size series
Returns
numpy array of floats in [0, 1]
Example
from quant_charts import imbalance, bid_vol, ask_vol
imb = imbalance(bid_vol, ask_vol)
buy_pressure = imb > 0.6
cvd
cvd(delta)
Cumulative volume delta: running sum of signed volume.
Trends up when buyers lift the offer, down when sellers hit the bid.
Parameters
delta(array-like, defaultrequired): Per-bar signed delta (e.g.deltaseries)
Returns
numpy array of cumulative delta
Example
from quant_charts import cvd, delta
cumdelta = cvd(delta)
vwap_band
vwap_band(vwap, atr, mult?)
VWAP envelope: (upper, lower) at mult * ATR.
Parameters
vwap(array-like, defaultrequired): VWAP seriesatr(array-like, defaultrequired): ATR series (same length as vwap)mult(float, default1.0): Band width as multiple of ATR
Returns
(upper, lower) tuple of numpy arrays
Example
from quant_charts import vwap_band, vwap, ta, high, low, close
atr = ta.atr(high, low, close, 14)
upper, lower = vwap_band(vwap, atr, mult=1.5)
Cumulative volume delta: cvd.py
# qc-api: 1.0.7
# DISCLAIMER: This software is for educational and informational purposes only and does not constitute
# financial advice, investment advice, or trading advice. Past performance is not indicative of future
# results. Trading futures and other financial instruments involves substantial risk of loss. You are
# solely responsible for your own trading decisions. Quant Charts LLC assumes no liability for any
# losses incurred. All rights reserved. (c) Quant Charts LLC
"""CVD: standalone Cumulative Volume Delta (Python / OHLC).
Required columns: close.
Optional columns: open, volume, delta, bid_vol, ask_vol.
Data mode: OHLC. Built for TBBO-aggregated bars but degrades gracefully.
A focused cumulative-volume-delta indicator on its own pane. `delta_series`
resolves the per-bar signed volume via the fallback chain
delta -> (ask_vol - bid_vol) -> sign(close - open); `cvd` accumulates it.
Tags mark CVD trend so a strategy can filter on order-flow direction.
"""
import numpy as np
from quant_charts import (
indicator, input, plot, hline, define_tag,
cvd, delta_series, rising, falling, PlotType,
)
@indicator(
name="CVD",
description="Cumulative volume delta line with rising/falling trend tags",
overlay=False,
data_mode="ohlc",
required_columns=["close"],
)
class Cvd:
slope_lookback = input.int(5, "Slope Lookback", min=1, max=200,
tooltip="Bars used to classify CVD as rising or falling.")
line_color = input.color("#7AA2F7", "CVD Color")
def calculate(self, df):
delta = delta_series(df)
cvd_line = cvd(delta)
plot(cvd_line, "CVD", color=self.line_color, linewidth=2, plot_type=PlotType.LINE)
hline(0.0, "Zero", color="#63636e", linestyle="dashed")
cvd_rising = rising(cvd_line, self.slope_lookback)
cvd_falling = falling(cvd_line, self.slope_lookback)
define_tag("cvd_rising", f"CVD rising over {self.slope_lookback} bars", color="#73DACA")
define_tag("cvd_falling", f"CVD falling over {self.slope_lookback} bars", color="#F7768E")
return {
"cvd_rising": cvd_rising,
"cvd_falling": cvd_falling,
}
Bid/ask imbalance: imbalance.py
# qc-api: 1.0.7
# DISCLAIMER: This software is for educational and informational purposes only and does not constitute
# financial advice, investment advice, or trading advice. Past performance is not indicative of future
# results. Trading futures and other financial instruments involves substantial risk of loss. You are
# solely responsible for your own trading decisions. Quant Charts LLC assumes no liability for any
# losses incurred. All rights reserved. (c) Quant Charts LLC
"""Imbalance: standalone bid/ask volume imbalance (Python / OHLC).
Required columns: close.
Optional columns: bid_vol, ask_vol.
Data mode: OHLC. Needs TBBO-aggregated bars carrying bid_vol / ask_vol; on
plain OHLC the ratio is flat at 0.5 and the tags never fire.
Plots the imbalance ratio in [0, 1] on its own pane. `imbalance(bid, ask)`
returns bid / (bid + ask): values above 0.5 mean bid-side (buy) pressure,
below 0.5 mean ask-side (sell) pressure. Threshold inputs drive heavy_buy /
heavy_sell tags for use as strategy filters.
"""
import numpy as np
from quant_charts import (
indicator, input, plot, hline, define_tag,
imbalance, df_col_or, PlotType,
)
@indicator(
name="Imbalance",
description="Bid/ask volume imbalance ratio with heavy buy/sell tags",
overlay=False,
data_mode="ohlc",
required_columns=["close"],
)
class Imbalance:
threshold = input.float(0.65, "Imbalance Threshold", min=0.5, max=1.0, step=0.01,
tooltip="Ratio above this = heavy buy; below (1 - this) = heavy sell.")
line_color = input.color("#E0AF68", "Imbalance Color")
def calculate(self, df):
close = np.asarray(df["close"], dtype=np.float64)
n = len(close)
bid_vol = df_col_or(df, "bid_vol")
ask_vol = df_col_or(df, "ask_vol")
if bid_vol is not None and ask_vol is not None:
imb = imbalance(bid_vol, ask_vol)
else:
imb = np.full(n, 0.5, dtype=np.float64)
plot(imb, "Imbalance", color=self.line_color, linewidth=2, plot_type=PlotType.LINE)
hline(0.5, "Neutral", color="#63636e", linestyle="dashed")
hline(self.threshold, "Buy Threshold", color="#73DACA", linestyle="dotted")
hline(1.0 - self.threshold, "Sell Threshold", color="#F7768E", linestyle="dotted")
heavy_buy = imb > self.threshold
heavy_sell = imb < (1.0 - self.threshold)
define_tag("heavy_buy_pressure", f"Bid imbalance > {self.threshold:.2f}", color="#73DACA")
define_tag("heavy_sell_pressure", f"Ask imbalance > {self.threshold:.2f}", color="#F7768E")
return {
"heavy_buy_pressure": heavy_buy,
"heavy_sell_pressure": heavy_sell,
}