Features

Streaming indicators

Update stateful indicators incrementally as new market data arrives

Streaming indicators

Recently added

✅ Keep your indicators moving with the market. VBT's Numba and Rust accumulators update one observation at a time, using the same formulas as batch execution. Rust accumulators even manage their own rolling buffers, so you can feed in new data and get straight to the next value.

Update on-balance volume for each bar
prev_close = np.nan
obv = 0.0
for close, volume in [(100.0, 10.0), (102.0, 20.0), (101.0, 5.0)]:
    out = vbt.ind_nb.obv_acc_nb(  
        vbt.ind_enums.OBVAIS(close, prev_close, volume, obv)
    )
    prev_close, obv = close, out.cumsum  
    print(out.value)
10.0
30.0
25.0

Tutorial

Learn more in the Live simulation tutorial.

Accumulators

✅ Most rolling indicators implemented with Pandas and NumPy require multiple passes over the data. For example, calculating the sum of three arrays requires at least two passes. If you want to calculate such an indicator iteratively (bar by bar), you either need to pre-calculate everything and store it in memory or re-calculate each window, which can significantly impact performance. Accumulators, however, maintain an internal state that allows you to compute an indicator value as soon as a new data point arrives, resulting in the best possible performance.

Design a one-pass rolling z-score
@njit
def fastest_rolling_zscore_1d_nb(arr, window, minp=None, ddof=1):
    if minp is None:
        minp = window
    out = np.full(arr.shape, np.nan)
    cumsum = 0.0
    cumsum_sq = 0.0
    nancnt = 0

    for i in range(len(arr)):
        pre_window_value = arr[i - window] if i - window >= 0 else np.nan
        mean_in_state = vbt.nb.RollMeanAIS(
            i, arr[i], pre_window_value, cumsum, nancnt, window, minp
        )
        mean_out_state = vbt.nb.rolling_mean_acc_nb(mean_in_state)
        _, _, _, mean = mean_out_state
        std_in_state = vbt.nb.RollStdAIS(
            i, arr[i], pre_window_value, cumsum, cumsum_sq, nancnt, window, minp, ddof
        )
        std_out_state = vbt.nb.rolling_std_acc_nb(std_in_state)
        cumsum, cumsum_sq, nancnt, _, std = std_out_state
        out[i] = (arr[i] - mean) / std
    return out

data = vbt.YFData.pull("BTC-USD")
rolling_zscore = fastest_rolling_zscore_1d_nb(data.returns.values, 14)
data.symbol_wrapper.wrap(rolling_zscore)
Date
2014-09-17 00:00:00+00:00         NaN
2014-09-18 00:00:00+00:00         NaN
2014-09-19 00:00:00+00:00         NaN
                                  ...
2023-02-01 00:00:00+00:00    0.582381
2023-02-02 00:00:00+00:00   -0.705441
2023-02-03 00:00:00+00:00   -0.217880
Freq: D, Name: BTC-USD, Length: 3062, dtype: float64
(data.returns - data.returns.rolling(14).mean()) / data.returns.rolling(14).std()
Date
2014-09-17 00:00:00+00:00         NaN
2014-09-18 00:00:00+00:00         NaN
2014-09-19 00:00:00+00:00         NaN
                                  ...
2023-02-01 00:00:00+00:00    0.582381
2023-02-02 00:00:00+00:00   -0.705441
2023-02-03 00:00:00+00:00   -0.217880
Freq: D, Name: Close, Length: 3062, dtype: float64

Copyright © 2021–2026 Oleg Polakow. All rights reserved.

Site content and documentation are provided for using and evaluating VectorBT PRO and for educational purposes. Any other use, including building or supporting competing products or services, requires prior written consent.