Quant Charts Order-Flow API (CVD, Imbalance, Delta)

Quant Charts exposes order-flow primitives through cvd(), imbalance(), and delta_series(). The signal-helper reference plus complete CVD and imbalance indicators follow.

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, default required): The series crossing up
  • series2 (Series, default required): 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, default required): The series crossing down
  • series2 (Series, default required): 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, default required): Input data
  • value (number | array, default required): 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, default required): Input data
  • value (number | array, default required): 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, default required): Input data
  • lower (number, default required): Lower bound (inclusive)
  • upper (number, default required): 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, default required): Input data
  • length (int, default required): 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, default required): Input data
  • length (int, default required): 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, default required): 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, default required): Boolean condition array
  • source (array-like, default required): Values to sample from
  • occurrence (int, default 0): 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, default required): Bid-side size series
  • ask_size (array-like, default required): 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, default required): Per-bar signed delta (e.g. delta series)

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, default required): VWAP series
  • atr (array-like, default required): ATR series (same length as vwap)
  • mult (float, default 1.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,
        }
Machine-readable: full API at /llms-full.txt · examples on GitHub.