Features
Indicator development
Build, search, express, and parallelize custom indicator pipelines
✅ VBT implements or integrates more than 500 indicators, making it hard to keep track of them all. To make indicators easier to find, several new methods are available for globally searching for indicators.
vbt.IF.list_indicators("*ma")[
'vbt:MA',
'talib:DEMA',
'talib:EMA',
'talib:KAMA',
'talib:MA',
...
'technical:ZEMA',
'technical:ZLEMA',
'technical:ZLHMA',
'technical:ZLMA'
]vbt.indicator("technical:ZLMA") vectorbtpro.indicators.factory.technical.ZLMA✅ Want to feed indicators as features to a machine-learning model? There is no need to run them individually: you can tell VBT to run all indicators from an indicator package on the given data instance. The data instance will recognize the input names of each indicator and supply the required data. You can also easily change the defaults for each indicator.
data = vbt.YFData.pull("BTC-USD")
features = data.run("talib", mavp=vbt.run_arg_dict(periods=14))
features.shape(3046, 175)✅ Previously, custom indicators could only be created by accepting two-dimensional input arrays, which forced users to adapt all functions accordingly. Now, the indicator factory can split each input array along columns and pass one column at a time, making it much easier to design indicators that are meant to be run natively on one-dimensional data (such as TA-Lib!).
import talib
params = dict(
rsi_period=14,
fastk_period=5,
slowk_period=3,
slowk_matype=0,
slowd_period=3,
slowd_matype=0
)
def stochrsi_1d(close, *args):
rsi = talib.RSI(close, args[0])
k, d = talib.STOCH(rsi, rsi, rsi, *args[1:])
return rsi, k, d
STOCHRSI = vbt.IF(
input_names=["close"],
param_names=list(params.keys()),
output_names=["rsi", "k", "d"]
).with_apply_func(stochrsi_1d, takes_1d=True, **params)
data = vbt.YFData.pull("BTC-USD", start="2022-01", end="2022-06")
stochrsi = STOCHRSI.run(data.close)
fig = stochrsi.k.rename("%K").vbt.plot()
stochrsi.d.rename("%D").vbt.plot(fig=fig)
fig.show()✅ Processing parameter combinations with the indicator factory can be distributed across multiple threads, processes, or even in the cloud. This is a huge help when working with slow indicators 🐌
@njit
def minmax_nb(close, window):
return (
vbt.nb.rolling_min_nb(close, window),
vbt.nb.rolling_max_nb(close, window)
)
MINMAX = vbt.IF(
class_name="MINMAX",
input_names=["close"],
param_names=["window"],
output_names=["min", "max"]
).with_apply_func(minmax_nb, window=14)
data = vbt.YFData.pull("BTC-USD")%%timeit
minmax = MINMAX.run(
data.close,
np.arange(2, 200),
jitted_loop=True
)420 ms ± 2.05 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)%%timeit
minmax = MINMAX.run(
data.close,
np.arange(2, 200),
jitted_loop=True,
jitted_warmup=True,
execute_kwargs=dict(engine="threadpool", n_chunks="auto")
)120 ms ± 355 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)✅ Indicators can now be created from expressions. An indicator expression is a regular string representing Python code enhanced with various extensions. The indicator factory automatically derives all required information, such as inputs, parameters, outputs, NumPy, VBT, and TA-Lib functions, and even complex indicators, thanks to a unique format and built-in matching mechanism. Designing indicators has never been easier!
data = vbt.YFData.pull("BTC-USD", start="2020", end="2021")
expr = """
MACD:
fast_ema = @talib_ema(close, @p_fast_w)
slow_ema = @talib_ema(close, @p_slow_w)
macd = fast_ema - slow_ema
signal = @talib_ema(macd, @p_signal_w)
macd, signal
"""
MACD = vbt.IF.from_expr(expr, fast_w=12, slow_w=26, signal_w=9)
macd = MACD.run(data.close)
fig = macd.macd.rename("MACD").vbt.plot()
macd.signal.rename("Signal").vbt.plot(fig=fig)
fig.show()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.