Features
Configuration and persistence
Configure, format, serialize, compress, and reload reusable research objects
✅ 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.
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")
)Online explorer
Explore the VBT's reference graph in the API → Reference graph.
✅ 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.
@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✅ Serialized VBT objects can sometimes use a lot of disk space. With this update, VBT now supports a variety of compression algorithms to make files as light as possible! 🪶
data = vbt.RandomOHLCData.pull(
"RAND",
start="2022",
end="2023",
timeframe="1 minute",
seed=42
)
file_path = data.save()
print(vbt.file_size(file_path))21.0 MBfile_path = data.save(compression="blosc")
print(vbt.file_size(file_path))13.3 MB✅ If your pipeline does not need accessors, Plotly graphs, or most other optional features, you can disable the auto-import feature entirely to reduce VBT's loading time to under a second ⏳
[importing]
auto_import = Falsestart = utc_time()
from vectorbtpro import *
end = utc_time()
end - start0.580937910079956✅ Just like machine learning models, every native VBT object can be serialized and saved to a binary file. It has never been easier to share data and insights! Another benefit is that only the actual content of each object is serialized, not its class definition, so the loaded object always uses the most up-to-date class definition. There is also special logic implemented to help you "reconstruct" objects if VBT introduces any breaking API changes 🏗️
data = vbt.YFData.pull("BTC-USD", start="2022-01-01", end="2022-06-01")
def backtest_month(close):
return vbt.PF.from_random_signals(close, n=10, seed=42)
month_pfs = data.close.resample(vbt.offset("M")).apply(backtest_month)
month_pfsDate
2022-01-01 00:00:00+00:00 Portfolio(\n wrapper=ArrayWrapper(\n ...
2022-02-01 00:00:00+00:00 Portfolio(\n wrapper=ArrayWrapper(\n ...
2022-03-01 00:00:00+00:00 Portfolio(\n wrapper=ArrayWrapper(\n ...
2022-04-01 00:00:00+00:00 Portfolio(\n wrapper=ArrayWrapper(\n ...
2022-05-01 00:00:00+00:00 Portfolio(\n wrapper=ArrayWrapper(\n ...
Freq: MS, Name: Close, dtype: objectvbt.save(month_pfs, "month_pfs")
month_pfs = vbt.load("month_pfs")
month_pfs.apply(lambda pf: pf.total_return)Date
2022-01-01 00:00:00+00:00 -0.083672
2022-02-01 00:00:00+00:00 0.173909
2022-03-01 00:00:00+00:00 -0.006249
2022-04-01 00:00:00+00:00 -0.057868
2022-05-01 00:00:00+00:00 0.019209
Freq: MS, Name: Close, 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? 😉
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.PandasIndexervbt.phelp(data.get) YFData.get(
columns=None,
symbols=None,
**kwargs
):
Get one or more columns of one or more symbols of data.✅ It is easy to extend classes, but since VBT revolves around functions, how do we enhance them or change their workflow? The easiest way is to introduce a small function (i.e., callback) that the user can provide and that the main function calls at some point. However, this would require the main function to know what arguments to pass to the callback and how to handle its outputs. Here is a better idea: allow most arguments of the main function to become callbacks, then execute those to obtain their actual values. These arguments are called "templates" and this process is known as "substitution". Templates are especially useful when some arguments (such as arrays) should be built only once all required information is available, for example, when other arrays have already been broadcast. Each substitution opportunity has its own identifier so you can control when a template should be substituted. In VBT, templates are first-class citizens and are integrated into most functions for unmatched flexibility! 🧞
def resample_apply(index, by, apply_func, *args, template_context={}, **kwargs):
grouper = index.vbt.get_grouper(by)
results = {}
with vbt.ProgressBar() as pbar:
for group, group_idxs in grouper:
group_index = index[group_idxs]
context = {"group": group, "group_index": group_index, **template_context}
final_apply_func = vbt.substitute_templates(apply_func, context, eval_id="apply_func")
final_args = vbt.substitute_templates(args, context, eval_id="args")
final_kwargs = vbt.substitute_templates(kwargs, context, eval_id="kwargs")
results[group] = final_apply_func(*final_args, **final_kwargs)
pbar.update()
return pd.Series(results)
data = vbt.YFData.pull(["BTC-USD", "ETH-USD"], missing_index="drop")
resample_apply(
data.index, "Y",
lambda x, y: x.corr(y),
vbt.RepEval("btc_close[group_index]"),
vbt.RepEval("eth_close[group_index]"),
template_context=dict(
btc_close=data.get("Close", "BTC-USD"),
eth_close=data.get("Close", "ETH-USD")
)
)2017 0.808930
2018 0.897112
2019 0.753659
2020 0.940741
2021 0.553255
2022 0.975911
2023 0.974914
Freq: A-DEC, dtype: float64Copyright © 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.