# Streaming indicators (/features/indicators/streaming-indicators)

## Streaming indicators \[#streaming-indicators]

New in v2026.9.5

(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.

=== "Python / Numba"
    ```python title="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(  # (1)
    ...         vbt.ind_enums.OBVAIS(close, prev_close, volume, obv)
    ...     )
    ...     prev_close, obv = close, out.cumsum  # (2)
    ...     print(out.value)
    10.0
    30.0
    25.0
    ```

    1.  The accumulator can also run inside a Numba-compiled loop or callback.
    2.  Carry the previous close and cumulative on-balance volume into the next update.

=== "Rust"
    ```rust title="Update Bollinger Bands and RSI for each price"
    use vectorbtpro_rust::error::VbtResult;
    use vectorbtpro_rust::indicators::streaming::{Bbands, Rsi};

    fn main() -> VbtResult<()> {
        let mut bands = Bbands::builder().window(3).build()?;
        let mut rsi = Rsi::builder().window(3).build()?;
        for price in [100.0, 101.0, 102.0, 99.0, 98.0, 103.0] {
            let band = bands.update(price); // (1)
            let strength = rsi.update(price).rsi;
            if strength.is_finite() { // (2)
                println!("${price:.0}: middle={:.2}, RSI={strength:.2}", band.middle);
            }
        }
        Ok(())
    }
    ```

    1.  The result also includes the upper and lower Bollinger bands.
    2.  Skip output until RSI has enough observations for its three-bar window.

    ```text title="Output"
    $99: middle=100.67, RSI=40.00
    $98: middle=99.67, RSI=30.77
    $103: middle=100.00, RSI=74.65
    ```

!!! info "Tutorial"
    Learn more in the
    [Live simulation](https://members.vectorbt.pro/tutorials/from-python-to-rust/live/) tutorial.

## Accumulators \[#accumulators]

New in 1.0.10

✅ 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](https://theboostcpplibraries.com/boost.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.

```python title="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
```
