Skip to content
New: Star-import, signal unraveling, Python 3.12 support, and more

#
Indicators

Question

Learn more in Indicators documentation.

## Listing

To list the currently supported indicators, use IndicatorFactory.list_indicators. The returned indicator names can be filtered by location, which can be listed with IndicatorFactory.list_locations, or by evaluating a glob or regex pattern.

List supported indicators and locations

    indicator_names = vbt.IF.list_indicators()  # (1)!
    indicator_names = vbt.IF.list_indicators("vbt")  # (2)!
    indicator_names = vbt.IF.list_indicators("talib")  # (3)!
    indicator_names = vbt.IF.list_indicators("RSI*")  # (4)!
    indicator_names = vbt.IF.list_indicators("*ma")  # (5)!
    indicator_names = vbt.IF.list_indicators("[a-z]+ma$", use_regex=True)  # (6)!
    indicator_names = vbt.IF.list_indicators("*ma", location="pandas_ta")  # (7)!

    location_names = vbt.IF.list_locations()  # (8)!

1. List all indicators
2. List all custom implemented VBT indicators
3. List all TA-Lib indicators
4. List any indicators that start with "RSI", such as "RSI" and "RSIIndicator"
5. List any indicators that end with "ma", such as "MA" and "SMA"
6. Same as above but as a regular expression
7. Same as above but only offered by Pandas TA
8. List all locations

Note

Without specifying a location, indicators across all the locations will be parsed, which may take some time. Thus, make sure to not repeatedly call this function; instead, save the results to a variable.

To get the class of an indicator, use IndicatorFactory.get_indicator.

Various ways to get the indicator class

    vbt.BBANDS  # (1)!

    BBANDS = vbt.IF.get_indicator("pandas_ta:BBANDS")  # (2)!
    BBANDS = vbt.indicator("pandas_ta:BBANDS")  # (3)!
    BBANDS = vbt.IF.from_pandas_ta("BBANDS")  # (4)!
    BBANDS = vbt.pandas_ta("BBANDS")  # (5)!

    RSI = vbt.indicator("RSI")  # (6)!

1. Custom implemented VBT indicators can be accessed directly
2. Get the indicator class by name as returned by `list_indicators`
3. Same as above
4. Same as above by calling the respective function
5. Same as above
6. Search for an indicator with the name "RSI" and return the first found. Custom, TA-LIB, and Pandas-TA indicators are preferred, in this order.

To get familiar with an indicator class, call phelp on the `run` class method, which is used to run the indicator. Alternatively, the specification such as input names is also available via various properties to be accessed in a programmable fashion.

Various ways to get the specification of an indicator class

    vbt.phelp(vbt.OLS.run)  # (1)!

    print(vbt.OLS.input_names)  # (2)!
    print(vbt.OLS.param_names)  # (3)!
    print(vbt.OLS.param_defaults)  # (4)!
    print(vbt.OLS.in_output_names)  # (5)!
    print(vbt.OLS.output_names)  # (6)!
    print(vbt.OLS.lazy_output_names)  # (7)!

1. Get the signature of the `run` class method along with the specification
2. Get the input names, such as "close" in `talib:SMA`. These are the arrays based on which the indicator is computed.
3. Get the parameter names, such as "timeperiod" in `talib:SMA`. These are the parameters that are being tested.
4. Get the parameter defaults
5. Get the in-output names, such as "stop_ts" in `vbt:STX`. These are the arrays that are written in-place by the indicator.
6. Get the output names, such as "entries" and "exits" in `vbt:RANDNX`. These are the arrays that are returned by the indicator.
7. Get the lazy output names, such as "bandwidth" in `vbt:BBANDS`. These are the arrays that can be optionally calculated after the indicator has finished computing.

## Running

To run an indicator, call the IndicatorBase.run class method of its class by manually passing the input arrays (which can be any array-like objects such as Pandas DataFrames and NumPy arrays), parameters (which can be single values and lists for testing multiple parameter combinations), and other arguments expected by the indicator. The result of running the indicator is an indicator instance (not the actual arrays!).

Various ways to run an indicator

    bbands = vbt.BBANDS.run(close)  # (1)!
    bbands = vbt.BBANDS.run(open)  # (2)!
    bbands = vbt.BBANDS.run(close, window=20)  # (3)!
    bbands = vbt.BBANDS.run(close, window=vbt.Default(20))  # (4)!
    bbands = vbt.BBANDS.run(close, window=20, hide_params=["window"])  # (5)!
    bbands = vbt.BBANDS.run(close, window=20, hide_params=True)  # (6)!
    bbands = vbt.BBANDS.run(close, window=[10, 20, 30])  # (7)!
    bbands = vbt.BBANDS.run(close, window=[10, 20, 30], alpha=[2, 3, 4])  # (8)!
    bbands = vbt.BBANDS.run(close, window=[10, 20, 30], alpha=[2, 3, 4], param_product=True)  # (9)!

1. Run the indicator on close price and with default parameters
2. Run the indicator on open price. You can pass any time series if the indicator expects only "close". But as soon as it expects other time series such as "open", "high", or "low", use only "close".
3. Test a window of 20. If the close price is a DataFrame, this will append a new column level called "window". If the close price is a Series, it's name will become a tuple.
4. To avoid adding a new column level, wrap with `Default`
5. Alternatively, hide the parameter
6. Hide all parameters. Makes only sense when only one parameter combination is being tested, and you want the output arrays to have the same columns/name as the input arrays.
7. Test three windows. This will produce three Series/DataFrames stacked into one DataFrame along columns.
8. Test three parameter combinations: (10, 2), (20, 3) and (30, 4)
9. Test all combinations between both parameters, leading to overall 9 tests

Warning

Testing a wide grid of parameter combinations will produce wide arrays. For example, testing 10000 parameter combinations on one year of daily data would produce an array that takes 30MB of RAM. If the indicator returns three arrays, the RAM consumption would be at least 120MB. One year of minute data would result in staggering 40GB. Thus, for testing wide parameter grids it's recommended to test only a subset of combinations at a time, such as with the use of parameterization or chunking.

Often, there's a need to make an indicator skip missing values. For this, use `skipna=True`. This argument not only works for TA-Lib indicators but for any indicators, the only requirement: the jitted loop must be disabled. Also, when a two-dimensional input array is passed, you need to additionally pass `split_columns=True` to split its columns and process one column at once.

Run an indicator on valid values only

    bbands = vbt.BBANDS.run(close_1d, skipna=True)
    bbands = vbt.BBANDS.run(close_2d, split_columns=True, skipna=True)

Another way is to remove missing values altogether.

Remove missing values in an indicator

    bbands = bbands.dropna()  # (1)!
    bbands = bbands.dropna(how="all")  # (2)!

1. Remove any row that has at least one missing value across all outputs
2. Remove any row that has all values missing across all outputs

To retrieve the output arrays from an indicator instance, either access each as an attribute, or use various unpacking options such as IndicatorBase.unpack.

Various ways to retrieve output arrays

    bbands = vbt.talib("BBANDS").run(close)
    upperband_df = bbands.upperband  # (1)!
    middleband_df = bbands.middleband
    lowerband_df = bbands.lowerband
    upperband_df, middleband_df, lowerband_df = bbands.unpack()  # (2)!
    output_dict = bbands.to_dict()  # (3)!
    output_df = bbands.to_frame()  # (4)!

    sma = vbt.talib("SMA").run(close)
    sma_df = sma.real  # (5)!
    sma_df = sma.unpack()

1. Retrieve the upper band array from the indicator instance
2. Retrieve the output arrays in the same order as they are in `bbands.output_names`
3. Retrieve the dictionary with the output arrays
4. Retrieve a DataFrame with the output arrays stacked along columns
5. If a TA-Lib indicator has only one output array, it's usually named "real"

To keep outputs in the NumPy format and/or omit any shape checks, use `return_raw="outputs"`.

Keep NumPy format

    upperband, middleband, lowerband = vbt.talib("BBANDS").run(close, return_raw="outputs")

An even simpler way to run indicators is by using Data.run, which takes an indicator name or class, identifies what input names the indicator expects, and then runs the indicator while passing all the inputs found in the data instance automatically. This method also allows unpacking and running multiple indicators, which is very useful for feature engineering.

Various ways to run indicators automatically

    bbands = data.run("vbt:BBANDS")  # (1)!
    bbands = data.run("vbt:BBANDS", window=20)  # (2)!
    upper, middle, lower = data.run("vbt:BBANDS", unpack=True)  # (3)!

    features_df = data.run(["talib:BBANDS", "talib:RSI"])  # (4)!
    bbands, rsi = data.run(["talib:BBANDS", "talib:RSI"], concat=False)  # (5)!
    features_df = data.run(  # (6)!
        ["talib:BBANDS", "talib:RSI"],
        timeperiod=vbt.run_func_dict(talib_bbands=20, talib_rsi=30),
        hide_params=True
    )
    features_df = data.run(  # (7)!
        ["talib:BBANDS", "vbt:RSI"],
        talib_bbands=vbt.run_arg_dict(timeperiod=20),
        vbt_rsi=vbt.run_arg_dict(window=30),
        hide_params=True
    )
    features_df = data.run("talib_all")  # (8)!
    features_df = data.run("talib_all", execute_kwargs=dict(show_progress=True))  # (9)!

1. Run `vbt.BBANDS` with the "close" input name automatically substituted by `data.close`
2. Any arguments will be passed down to the indicator's `run` class method
3. The output arrays can be directly unpacked. The argument `unpack` also accepts the options "dict" and "frame".
4. Run multiple indicators. By default, they will be concatenated into a DataFrame along columns. The function and output names will be visible in the column levels "run_func" and "output" respectively.
5. Do not concatenate indicators but return them as a list
6. Pass different values under the same parameter name using `run_func_dict`
7. Pass different keyword arguments to each indicator using `run_arg_dict`
8. Run all TA-Lib indicators
9. TA-Lib indicators are run using execute, which allows us to display the progress bar but also to parallelize the execution

To quickly run and plot a TA-Lib indicator on a single parameter combination without using the indicator factory, use talib_func and talib_plot_func respectively. In contrast to the official TA-Lib implementation, it can properly handle DataFrames, NaNs, broadcasting, and timeframes. The indicator factory's TA-Lib version is based on these two functions.

Quickly run and plot a TA-Lib indicator

    run_bbands = vbt.talib_func("BBANDS")
    upperband, middleband, lowerband = run_bbands(close, timeperiod=2)
    upperband, middleband, lowerband = data.run("talib_func:BBANDS", timeperiod=2)  # (1)!

    plot_bbands = vbt.talib_plot_func("BBANDS")
    fig = plot_bbands(upperband, middleband, lowerband)

1. Same as above

### Parallelization

Parameter combinations are processed using execute such that it's fairly easy to parallelize their execution.

Various parallelization configurations

    any_indicator.run(  # (1)!
        ...,
        execute_kwargs=dict(show_progress=True)
    )

    # ______________________________________________________________

    numba_indicator.run(  # (2)!
        ...,
        jitted_loop=True,  # (3)!
        jitted_warmup=True,    # (4)!
        execute_kwargs=dict(n_chunks="auto", engine="threadpool")
    )

    # ______________________________________________________________

    python_indicator.run(  # (5)!
        ...,
        execute_kwargs=dict(n_chunks="auto", distribute="chunks", engine="pathos")
    )

1. Process each parameter combination serially while showing the progress bar
2. If the indicator is compiled with Numba and `nogil` is enabled, divide parameter combinations into an optimal number of chunks and execute all chunks in parallel with multithreading (i.e., one chunk per thread)
3. Wrap the loop with Numba that goes over parameter combinations (required)
4. Dry-run one parameter combination to compile the indicator ahead of the distribution (optional)
5. If the indicator is not compiled with Numba, divide parameter combinations into an optimal number of chunks, and execute all chunks in parallel with multiprocessing (i.e., one chunk per process) while executing all parameter combinations within each chunk serially

## Registration

Custom indicators can be registered by the indicator factory to appear in the list of all indicators. This is convenient to be able to refer to the indicator by its name when running a data instance. Upon registration, you can assign the indicator to a custom location (the default location is "custom"), which acts as a tag or group; this can be used to build arbitrary indicator groups. One indicator can be assigned to multiple locations. Custom indicators have priority over built-in indicators.

    vbt.IF.register_custom_indicator(sma_indicator)  # (1)!
    vbt.IF.register_custom_indicator(sma_indicator, "SMA")  # (2)!
    vbt.IF.register_custom_indicator(sma_indicator, "SMA", location="rolling")  # (3)!
    vbt.IF.register_custom_indicator(sma_indicator, "rolling:SMA")
    vbt.IF.register_custom_indicator("talib:sma", location="rolling")  # (4)!

    vbt.IF.deregister_custom_indicator("SMA", location="rolling")  # (5)!
    vbt.IF.deregister_custom_indicator("rolling:SMA")
    vbt.IF.deregister_custom_indicator("SMA")  # (6)!
    vbt.IF.deregister_custom_indicator(location="rolling")  # (7)!
    vbt.IF.deregister_custom_indicator()  # (8)!

1. Register an indicator class. The class name will become the indicator name.
2. Register an indicator class with a specific name
3. Register an indicator class with a specific name and under a specific location
4. Assign a built-in indicator class to a custom location (i.e., tagging)
5. Deregister all indicators with a specific name under a specific location
6. Deregister all indicators with a specific name under all locations
7. Deregister all indicators under a specific location
8. Deregister all indicators under all locations

#### Cookie consent

We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.

- Google Analytics
- GitHub

Manage settings