Features

Developer tools

Search the API, read source, draw reference graphs, and extend classes with factories

How do you find your way around a library with thousands of classes and functions, and extend it? VBT includes developer tools for API search and Python object inspection: search the package, read any object's source and documentation, and draw what each function depends on.

Find every function that takes freq, read one, and graph its dependencies
import inspect
from vectorbtpro.utils.module_ import search_package
from vectorbtpro.utils.source import get_source

def accepts_freq(name, obj):
    return inspect.isfunction(obj) and "freq" in inspect.signature(obj).parameters

found = search_package("vectorbtpro", accepts_freq)  
names = sorted({f"{func.__module__}.{func.__name__}" for func in found.values()})
len(names)
14
print("\n".join(names[-6:]))
vectorbtpro.utils.datetime_.readable_datetime
vectorbtpro.utils.datetime_.to_freq
vectorbtpro.utils.datetime_.to_offset
vectorbtpro.utils.datetime_.to_timedelta
vectorbtpro.utils.datetime_.to_timedelta64
vectorbtpro.utils.schedule_.wait
from vectorbtpro.utils.datetime_ import infer_index_freq
print("\n".join(get_source(infer_index_freq).splitlines()[:7]))
def infer_index_freq(
    index: tp.Index,
    freq: tp.Optional[tp.FrequencyLike] = None,
    allow_offset: bool = True,
    allow_numeric: bool = True,
    freq_from_n: tp.Union[None, bool, int] = None,
) -> tp.Union[None, int, float, tp.PandasFrequency]:
ref_index = vbt.RefIndex(incl_modules="vectorbtpro")
graph = ref_index.build_graph(infer_index_freq)  
print("\n".join(graph.get_dependencies(graph.root, relation="direct")))
vectorbtpro._typing.FrequencyLike
vectorbtpro._typing.PandasFrequency
vectorbtpro.utils.checks.is_number
vectorbtpro.utils.datetime_.auto_detect_freq
vectorbtpro.utils.datetime_.freq_depends_on_index
vectorbtpro.utils.datetime_.parse_index_freq
vectorbtpro.utils.datetime_.to_freq
fig = graph.plot(interactive=False, showlegend=False)
for trace in fig.data:  
    if trace.name.endswith("_nodes_hl") and len(trace.x) > 0:
        labels = [info[1] or info[0] for info in trace.customdata]
        trace.update(mode="markers+text", text=labels, textposition="top center")
fig.show()
Reference graph of the infer_index_freq function and the functions and types it uses Figure data (JSON)

Fourteen module-level functions accept a freq argument. The graph places infer_index_freq and the seven names it uses inside the modules that define them, which shows where to look when a frequency is not what you expected.

Discovery

Most questions about VBT can be answered from Python itself:

ToolAnswers
vbt.phelp(obj)What a function takes and what its docstring says
vbt.pdir(obj)Which attributes an object has, their kinds, and where each is defined
vbt.pprint(obj)What an object holds, formatted as readable nested text
vbt.ptable(obj)What an array, DataFrame, or record array holds, as a table
get_source(obj)The source code of any function, class, or module
vbt.get_api_ref(obj), vbt.open_api_ref(obj)The API documentation page for an object
vbt.RefIndexWhat an object uses, what uses it, and how modules connect
vbt.get_capabilities()How many indicators, data sources, metrics, and engines are installed

deep_getattr resolves a dotted path of attributes and method calls, such as pf.deep_getattr("trades.expectancy"). For questions in plain language, the Knowledge search page covers vbt.find_api and vbt.search.

These tools work together when an unfamiliar object or argument blocks your research. Start with phelp for the call signature, use pdir to find the relevant property or method, then open the source or API reference for the details. Configured objects expose their constructor arguments in config, so you can inspect the settings that created a data instance, indicator, or portfolio.

Formatting and annotations

The formatting engine behind vbt.pprint and vbt.phelp renders configured objects, dictionaries, arrays, and signatures the same way in a terminal and in a notebook, as the Formatting engine highlight below shows. Annotations carry meaning in a function's signature: vbt.Param, vbt.Takeable, and vbt.MergeFunc tell the parameterization and splitting decorators how to treat each argument, as the Annotations highlight below shows.

Validation and debugging

  • Equality: vbt.is_deep_equal compares nested objects, arrays, and their metadata, and every configured object has equals.
  • Warnings: VBT warnings share one format, and vbt.WarningsFiltered() silences them inside a with block.
  • Hashing: vbt.hdict and configured objects can be hashed, which is how VBT caches results by their arguments.
  • Bounds checks: an invalid array index in a custom Numba callback can return incorrect data or crash the kernel. Setting boundscheck under numba in a configuration file makes compiled functions raise an error instead, and Numba's NUMBA_DISABLE_JIT=1 environment variable disables Numba compilation for Python-level debugging. Set it before importing VBT.
  • Preparers: simulation methods split argument checking from execution. Pass return_preparer=True to inspect the prepared arguments of a portfolio before it runs, or return_prep_result=True to get the final arrays the simulator would receive, in target_args.

Inspect what the simulator will receive

Preparers let you check shapes, defaults, and converted arguments before running a long backtest. Here, two assets have different order values but share the same fee:

Inspect prepared order sizes and fees without running the simulation
close = pd.DataFrame(
    {"A": [100.0, 105.0, 103.0], "B": [50.0, 49.0, 52.0]},
    index=pd.date_range("2025-01-01", periods=3),
)
prepared = vbt.PF.from_orders(
    close,
    size=np.array([[100.0, 200.0]]),
    size_type="value",
    fees=0.001,
    return_prep_result=True,
)
print(prepared.pf_args["wrapper"].shape)
(3, 2)
print(prepared.target_args["size"])
[[100. 200.]]
print(prepared.target_args["fees"])
[[0.001]]

The target has three rows and two assets. Order values stay in a single row, and the shared fee stays in a single cell, ready for flexible indexing inside the simulator. This makes it easier to see whether an unexpected result starts with the inputs or with the trading logic. The Backtesting engine page shows how to modify a preparation result and run it.

Runtime checks also validate shapes, indexes, and data types. You can use the same assertion helpers in your own functions, while deep equality checks help compare nested outputs after a refactor. For a callback that behaves unexpectedly, inspect a small input slice first, then use bounds checking or Python-level debugging to follow its decisions.

Extending

VBT is built from the same factories it exposes. vbt.IF builds indicator classes, as the Custom indicators page shows, and vbt.SignalFactory builds signal generators. Configured classes get declarative fields, cached properties, and shortcut methods from decorators, and vbt.evaluate evaluates expressions against a context, which is how indicator expressions and templates find their inputs.

You can keep a custom calculation as a function, expose it as an indicator with named inputs and parameters, or register a compiled implementation and its chunking rules. This lets custom work participate in the same parameter searches and labeled results as built-in calculations. Compute backends and Parallel execution cover those execution choices. For logic that needs current positions and cash, extend the simulation through Event-driven callbacks.

Utilities

Smaller tools cover everyday tasks: searching and replacing values deep inside nested objects, reading and writing nested keys by path, matching names with regular expressions, managing files and folders, and rescaling arrays. They are the same helpers VBT uses internally. To save memory, vbt.settings.wrapping["max_precision"] = 32 casts results to 32-bit floats when they are wrapped into pandas, at the cost of precision.

Member pages with Python downloads provide examples in Jupytext format, so you can open them as notebooks and adapt them locally. The tutorials give you complete research workflows to inspect alongside the individual API objects.

Reference graphs

✅ When analyzing complex codebases like VBT, it can be challenging to keep track of all the interdependencies between modules, classes, and functions. To address this, VBT now includes a functionality that can index the source code of any codebase for object references and generate reference graphs from any specified entry point. These graphs provide a visual representation of how different components relate to each other, making it easier to understand the overall structure and flow of the code.

Generate a reference graph for Pandas and display it in a new browser tab
ref_index = vbt.RefIndex(container_kinds=["module", "class"], incl_modules="pandas")
ref_graph = ref_index.build_graph("pandas")
ref_graph.plot(
    interactive="dash",
    to_dash_kwargs=dict(fit_to_window=True),
    dash_run_kwargs=dict(jupyter_mode="tab")
)
Reference graph of Pandas modules, classes, callables, and data dependencies Figure data (JSON)

Online explorer

Explore the VBT's reference graph in the API → Reference graph.

Annotations

✅ When writing a function, you can specify the meaning of each argument using an annotation immediately next to the argument. VBT now provides a rich set of in-house annotations tailored to specific tasks. For example, whether an argument is a parameter can be specified directly in the function instead of in the parameterized decorator.

Test a cross-validation function with annotations
@vbt.cv_split(
    splitter="from_rolling",
    splitter_kwargs=dict(length=365, split=0.5, set_labels=["train", "test"]),
    parameterized_kwargs=dict(random_subset=100, seed=42),
)
def sma_crossover_cv(
    data: vbt.Takeable,  
    fast_period: vbt.Param(condition="x < slow_period"),  
    slow_period: vbt.Param,  
    metric
) -> vbt.MergeFunc("concat"):
    fast_sma = data.run("sma", fast_period, hide_params=True)
    slow_sma = data.run("sma", slow_period, hide_params=True)
    entries = fast_sma.real_crossed_above(slow_sma)
    exits = fast_sma.real_crossed_below(slow_sma)
    pf = vbt.PF.from_signals(data, entries, exits, direction="both")
    return pf.deep_getattr(metric)

sma_crossover_cv(
    vbt.YFData.pull("BTC-USD", start="4 years ago"),
    np.arange(20, 50),
    np.arange(20, 50),
    "trades.expectancy"
)
split  set    fast_period  slow_period
0      train  25           26               2.822879
       test   25           26               4.740533
1      train  22           37              16.967189
       test   22           37             -16.101936
2      train  30           41             308.879034
       test   30           41              14.445511
3      train  29           49              32.328702
       test   29           49              13.546335
4      train  27           48              20.695292
       test   27           48               6.539824
5      train  22           46              19.143686
       test   22           46              -4.664139
6      train  34           45               5.235739
       test   34           45              -2.697966
dtype: float64

✅ VBT is a comprehensive library that defines thousands of classes, functions, and objects. When working with these, you may want to "look inside" an object to better understand its attributes and contents. Fortunately, there is a formatting engine that can accurately format any in-house object as a human-readable string. Did you know the API documentation is partly powered by this engine? 😉

Introspect a data instance
data = vbt.YFData.pull("BTC-USD", start="2020", end="2021")

vbt.pprint(data)  
YFData(
    wrapper=ArrayWrapper(...),
    data=symbol_dict({
        'BTC-USD': <pandas.core.frame.DataFrame object at 0x7f7f1fbc6cd0 with shape (366, 7)>
    }),
    single_key=True,
    classes=symbol_dict(),
    fetch_kwargs=symbol_dict({
        'BTC-USD': dict(
            start='2020',
            end='2021'
        )
    }),
    returned_kwargs=symbol_dict({
        'BTC-USD': dict()
    }),
    last_index=symbol_dict({
        'BTC-USD': Timestamp('2020-12-31 00:00:00+0000', tz='UTC')
    }),
    tz_localize=datetime.timezone.utc,
    tz_convert='UTC',
    missing_index='nan',
    missing_columns='raise'
)
vbt.pdir(data)  
                                            type                                             path
attr
align_columns                        classmethod                       vectorbtpro.data.base.Data
align_index                          classmethod                       vectorbtpro.data.base.Data
build_feature_config_doc             classmethod                       vectorbtpro.data.base.Data
...                                          ...                                              ...
vwap                                    property                       vectorbtpro.data.base.Data
wrapper                                 property               vectorbtpro.base.wrapping.Wrapping
xs                                      function          vectorbtpro.base.indexing.PandasIndexer
vbt.phelp(data.get)  
YFData.get(
    columns=None,
    symbols=None,
    **kwargs
):
    Get one or more columns of one or more symbols of data.

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.