Backtesting·Backtesting Libraries·Intermediate

Vectorbt Backtest

Leverage the vectorbt library for high-performance vectorized backtesting with built-in hyperparameter optimization, detailed signal analysis, interactive performance visualization, and comprehensive strategy tear-sheet generation.

backtestingbacktesting-libraries

Backtesting Libraries – vectorbt

This notebook demonstrates the capabilities of vectorbt, a powerful Python library for high-performance backtesting of quantitative trading strategies. It focuses on vectorized computation, enabling efficient parameter optimization and strategy screening.

1. Dependency Installation

This section outlines the necessary Python package installations required to run the examples provided in this notebook. These packages include pandas for data manipulation, numpy for numerical operations, vectorbt for backtesting functionalities, and plotly for interactive visualizations.

[15]
# Install necessary libraries: pandas, numpy, vectorbt, and plotly.
# `vectorbt` is the primary backtesting library.
# `pandas` and `numpy` are fundamental for data handling.
# `plotly` is used for interactive visualizations of backtest results.
!pip install pandas numpy vectorbt plotly
Requirement already satisfied: pandas in /usr/local/lib/python3.12/dist-packages (2.2.2)
Requirement already satisfied: numpy in /usr/local/lib/python3.12/dist-packages (2.0.2)
Requirement already satisfied: vectorbt in /usr/local/lib/python3.12/dist-packages (1.0.0)
Requirement already satisfied: plotly in /usr/local/lib/python3.12/dist-packages (5.24.1)
Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/dist-packages (from pandas) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/dist-packages (from pandas) (2026.2)
Requirement already satisfied: scipy in /usr/local/lib/python3.12/dist-packages (from vectorbt) (1.16.3)
Requirement already satisfied: matplotlib in /usr/local/lib/python3.12/dist-packages (from vectorbt) (3.10.0)
Requirement already satisfied: ipywidgets>=7.0.0 in /usr/local/lib/python3.12/dist-packages (from vectorbt) (7.7.1)
Requirement already satisfied: anywidget in /usr/local/lib/python3.12/dist-packages (from vectorbt) (0.9.21)
Requirement already satisfied: numba>=0.60 in /usr/local/lib/python3.12/dist-packages (from vectorbt) (0.60.0)
Requirement already satisfied: dill in /usr/local/lib/python3.12/dist-packages (from vectorbt) (0.3.8)
Requirement already satisfied: tqdm in /usr/local/lib/python3.12/dist-packages (from vectorbt) (4.67.3)
Requirement already satisfied: dateparser in /usr/local/lib/python3.12/dist-packages (from vectorbt) (1.4.1)
Requirement already satisfied: imageio in /usr/local/lib/python3.12/dist-packages (from vectorbt) (2.37.3)
Requirement already satisfied: scikit-learn in /usr/local/lib/python3.12/dist-packages (from vectorbt) (1.6.1)
Requirement already satisfied: schedule in /usr/local/lib/python3.12/dist-packages (from vectorbt) (1.2.2)
Requirement already satisfied: requests in /usr/local/lib/python3.12/dist-packages (from vectorbt) (2.32.4)
Requirement already satisfied: mypy_extensions in /usr/local/lib/python3.12/dist-packages (from vectorbt) (1.1.0)
Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.12/dist-packages (from plotly) (9.1.4)
Requirement already satisfied: packaging in /usr/local/lib/python3.12/dist-packages (from plotly) (26.2)
Requirement already satisfied: ipykernel>=4.5.1 in /usr/local/lib/python3.12/dist-packages (from ipywidgets>=7.0.0->vectorbt) (6.17.1)
Requirement already satisfied: ipython-genutils~=0.2.0 in /usr/local/lib/python3.12/dist-packages (from ipywidgets>=7.0.0->vectorbt) (0.2.0)
Requirement already satisfied: traitlets>=4.3.1 in /usr/local/lib/python3.12/dist-packages (from ipywidgets>=7.0.0->vectorbt) (5.7.1)
Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.12/dist-packages (from ipywidgets>=7.0.0->vectorbt) (3.6.10)
Requirement already satisfied: ipython>=4.0.0 in /usr/local/lib/python3.12/dist-packages (from ipywidgets>=7.0.0->vectorbt) (7.34.0)
Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.12/dist-packages (from ipywidgets>=7.0.0->vectorbt) (3.0.16)
Requirement already satisfied: llvmlite<0.44,>=0.43.0dev0 in /usr/local/lib/python3.12/dist-packages (from numba>=0.60->vectorbt) (0.43.0)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.8.2->pandas) (1.17.0)
Requirement already satisfied: psygnal>=0.8.1 in /usr/local/lib/python3.12/dist-packages (from anywidget->vectorbt) (0.15.1)
Requirement already satisfied: typing-extensions>=4.2.0 in /usr/local/lib/python3.12/dist-packages (from anywidget->vectorbt) (4.15.0)
Requirement already satisfied: regex>=2024.9.11 in /usr/local/lib/python3.12/dist-packages (from dateparser->vectorbt) (2025.11.3)
Requirement already satisfied: tzlocal>=0.2 in /usr/local/lib/python3.12/dist-packages (from dateparser->vectorbt) (5.3.1)
Requirement already satisfied: pillow>=8.3.2 in /usr/local/lib/python3.12/dist-packages (from imageio->vectorbt) (11.3.0)
Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->vectorbt) (1.3.3)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/dist-packages (from matplotlib->vectorbt) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib->vectorbt) (4.63.0)
Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->vectorbt) (1.5.0)
Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib->vectorbt) (3.3.2)
Requirement already satisfied: charset_normalizer<4,>=2 in /usr/local/lib/python3.12/dist-packages (from requests->vectorbt) (3.4.7)
Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.12/dist-packages (from requests->vectorbt) (3.18)
Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.12/dist-packages (from requests->vectorbt) (2.5.0)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.12/dist-packages (from requests->vectorbt) (2026.5.20)
Requirement already satisfied: joblib>=1.2.0 in /usr/local/lib/python3.12/dist-packages (from scikit-learn->vectorbt) (1.5.3)
Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.12/dist-packages (from scikit-learn->vectorbt) (3.6.0)
Requirement already satisfied: debugpy>=1.0 in /usr/local/lib/python3.12/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (1.8.15)
Requirement already satisfied: jupyter-client>=6.1.12 in /usr/local/lib/python3.12/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (7.4.9)
Requirement already satisfied: matplotlib-inline>=0.1 in /usr/local/lib/python3.12/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (0.2.2)
Requirement already satisfied: nest-asyncio in /usr/local/lib/python3.12/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (1.6.0)
Requirement already satisfied: psutil in /usr/local/lib/python3.12/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (5.9.5)
Requirement already satisfied: pyzmq>=17 in /usr/local/lib/python3.12/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (26.2.1)
Requirement already satisfied: tornado>=6.1 in /usr/local/lib/python3.12/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (6.5.7)
Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (75.2.0)
Requirement already satisfied: jedi>=0.16 in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (0.20.0)
Requirement already satisfied: decorator in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (4.4.2)
Requirement already satisfied: pickleshare in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (0.7.5)
Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (3.0.52)
Requirement already satisfied: pygments in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (2.20.0)
Requirement already satisfied: backcall in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (0.2.0)
Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.12/dist-packages (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (4.9.0)
Requirement already satisfied: notebook>=4.4.1 in /usr/local/lib/python3.12/dist-packages (from widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (6.5.7)
Requirement already satisfied: parso<0.9.0,>=0.8.6 in /usr/local/lib/python3.12/dist-packages (from jedi>=0.16->ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (0.8.7)
Requirement already satisfied: entrypoints in /usr/local/lib/python3.12/dist-packages (from jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (0.4)
Requirement already satisfied: jupyter-core>=4.9.2 in /usr/local/lib/python3.12/dist-packages (from jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (5.9.1)
Requirement already satisfied: jinja2 in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (3.1.6)
Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (25.1.0)
Requirement already satisfied: nbformat in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (5.10.4)
Requirement already satisfied: nbconvert>=5 in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (7.17.1)
Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (2.1.0)
Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.18.1)
Requirement already satisfied: prometheus-client in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.25.0)
Requirement already satisfied: nbclassic>=0.4.7 in /usr/local/lib/python3.12/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.3.3)
Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.12/dist-packages (from pexpect>4.3->ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (0.7.0)
Requirement already satisfied: wcwidth in /usr/local/lib/python3.12/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) (0.8.1)
Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.12/dist-packages (from jupyter-core>=4.9.2->jupyter-client>=6.1.12->ipykernel>=4.5.1->ipywidgets>=7.0.0->vectorbt) (4.10.0)
Requirement already satisfied: notebook-shim>=0.2.3 in /usr/local/lib/python3.12/dist-packages (from nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.2.4)
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.12/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (4.13.5)
Requirement already satisfied: bleach!=5.0.0 in /usr/local/lib/python3.12/dist-packages (from bleach[css]!=5.0.0->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (6.4.0)
Requirement already satisfied: defusedxml in /usr/local/lib/python3.12/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.7.1)
Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.12/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.3.0)
Requirement already satisfied: markupsafe>=2.0 in /usr/local/lib/python3.12/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (3.0.3)
Requirement already satisfied: mistune<4,>=2.0.3 in /usr/local/lib/python3.12/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (3.2.1)
Requirement already satisfied: nbclient>=0.5.0 in /usr/local/lib/python3.12/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.10.4)
Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.12/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.5.1)
Requirement already satisfied: fastjsonschema>=2.15 in /usr/local/lib/python3.12/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (2.21.2)
Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.12/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (4.26.0)
Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.12/dist-packages (from argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (25.1.0)
Requirement already satisfied: webencodings in /usr/local/lib/python3.12/dist-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.5.1)
Requirement already satisfied: tinycss2>=1.1.0 in /usr/local/lib/python3.12/dist-packages (from bleach[css]!=5.0.0->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.5.1)
Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (26.1.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (2025.9.1)
Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.37.0)
Requirement already satisfied: rpds-py>=0.25.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (2026.5.1)
Requirement already satisfied: jupyter-server<3,>=1.8 in /usr/local/lib/python3.12/dist-packages (from notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (2.18.2)
Requirement already satisfied: cffi>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (2.0.0)
Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.12/dist-packages (from beautifulsoup4->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (2.8.4)
Requirement already satisfied: pycparser in /usr/local/lib/python3.12/dist-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (3.0)
Requirement already satisfied: anyio>=3.1.0 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (4.13.0)
Requirement already satisfied: jupyter-events>=0.11.0 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.12.1)
Requirement already satisfied: jupyter-server-terminals>=0.4.4 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.5.4)
Requirement already satisfied: websocket-client>=1.7 in /usr/local/lib/python3.12/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.9.0)
Requirement already satisfied: python-json-logger>=2.0.4 in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (4.1.0)
Requirement already satisfied: pyyaml>=5.3 in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (6.0.3)
Requirement already satisfied: rfc3339-validator in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.1.4)
Requirement already satisfied: rfc3986-validator>=0.1.1 in /usr/local/lib/python3.12/dist-packages (from jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (0.1.1)
Requirement already satisfied: fqdn in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.5.1)
Requirement already satisfied: isoduration in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (20.11.0)
Requirement already satisfied: jsonpointer>1.13 in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (3.1.1)
Requirement already satisfied: rfc3987-syntax>=1.1.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.1.0)
Requirement already satisfied: uri-template in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.3.0)
Requirement already satisfied: webcolors>=24.6.0 in /usr/local/lib/python3.12/dist-packages (from jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (25.10.0)
Requirement already satisfied: lark>=1.2.2 in /usr/local/lib/python3.12/dist-packages (from rfc3987-syntax>=1.1.0->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.3.1)
Requirement already satisfied: arrow>=0.15.0 in /usr/local/lib/python3.12/dist-packages (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.0.0->vectorbt) (1.4.0)

2. Library Imports

This section imports all required Python libraries and modules. It also includes configuration for suppressing warnings to ensure cleaner output.

[16]
import warnings
warnings.filterwarnings("ignore") # Suppress warnings for cleaner output

import pandas as pd # Data manipulation and analysis
import numpy as np  # Numerical operations
import vectorbt as vbt # High-performance backtesting library
import plotly.graph_objects as go # Interactive charting library
from plotly.subplots import make_subplots # For creating subplots in Plotly figures

3. Understanding vectorbt

vectorbt is a robust Python library designed for high-performance portfolio backtesting, leveraging numpy and pandas for efficient computation. Its core strength lies in evaluating thousands of parameter combinations simultaneously through vectorized array operations, making it ideal for parameter optimization and strategy screening.

Key Features:

FeatureDescription
Vectorized ComputationEntire backtest logic executed via array operations, eliminating Python loops for speed.
Parameter SweepsSimultaneously test all combinations of parameters in a single function call.
Built-in IndicatorsAccess to over 100 pre-built technical indicators, including SMA, EMA, RSI, and MACD.
Portfolio SimulationComprehensive simulation capabilities, including fees, slippage, position sizing, and cash management.
Performance AnalyticsIntegrated metrics such as Sharpe Ratio, Sortino Ratio, Calmar Ratio, drawdown analysis, and detailed trade statistics.
Interactive PlottingPlotly-based charts for visualizing equity curves, trade markers, and parameter heatmaps.

When to Use vectorbt vs. Event-Driven Backtesters:

  • vectorbt: Optimal for rapid parameter optimization, signal screening, and fast iteration during the research and development phases of a strategy.
  • Event-Driven (e.g., as explored in Notebook 67): Preferred for final performance validation, detailed and realistic execution modeling, and development of live trading systems due to its granular control over events.

4. Data Generation

This section focuses on generating synthetic financial time series data to serve as input for the backtesting process. A custom function, generate_data, is defined to create a DataFrame resembling candlestick data (open, high, low, close) along with volume, for a specified number of periods. The generated close prices are then converted into a pandas.Series with a DatetimeIndex, which is the preferred format for vectorbt compatibility.

[17]
def generate_data(periods: int) -> pd.DataFrame:
    """Generates synthetic OHLCV (Open, High, Low, Close, Volume) data."""
    start_date     = pd.to_datetime("2024-01-01 00:00:00+00:00")
    datetime_index = pd.date_range(start_date, periods=periods, freq="1min", tz="UTC")
    price_data = []; last_close = 42000
    volatility_scale = 0.005; wick_scale = 0.002

    for _ in range(periods):
        # Simulate open and close prices with some volatility
        open_price  = last_close + np.random.normal(0, last_close * volatility_scale * 0.1)
        close_price = open_price + np.random.normal(0, last_close * volatility_scale)

        # Determine body high/low and then add wicks
        body_high   = max(open_price, close_price)
        body_low    = min(open_price, close_price)
        high_price  = max(body_high + abs(np.random.normal(0, last_close * wick_scale)),
                          open_price, close_price)
        low_price   = min(body_low  - abs(np.random.normal(0, last_close * wick_scale)),
                          open_price, close_price)

        # Ensure high is never less than low
        if high_price < low_price:
            high_price, low_price = low_price, high_price

        price_data.append({
            "open":  max(1, int(open_price)),
            "high":  max(1, int(high_price)),
            "low":   max(1, int(low_price)),
            "close": max(1, int(close_price)),
        })
        last_close = close_price # Update last_close for the next period

    df = pd.DataFrame(price_data, index=datetime_index)
    df.index.name = "datetime"
    df["volume"]   = np.random.uniform(100.0, 500.0, periods) # Simulate volume data
    df["datetime"] = df.index.to_series() # Add datetime column for plotting convenience
    return df.reset_index(drop=True)

df = generate_data(500) # Generate 500 periods of data

# Convert the 'close' column to an indexed Series for vectorbt compatibility.
# `vectorbt` indicators and portfolio functions typically expect a pandas Series with a DatetimeIndex.
close_series = pd.Series(
    df["close"].values,
    index=pd.DatetimeIndex(df["datetime"]),
    name="close", # Name the series 'close' for clarity
)

display(df.head()) # Display the first few rows of the generated DataFrame
print(f"Series length: {len(close_series)}") # Print the length of the close series
open high low close volume datetime
0 42014 42326 41970 42314 449.783093 2024-01-01 00:00:00+00:00
1 42345 42476 42020 42026 199.268131 2024-01-01 00:01:00+00:00
2 42003 42101 41996 42063 483.272336 2024-01-01 00:02:00+00:00
3 42103 42203 41617 41797 304.232952 2024-01-01 00:03:00+00:00
4 41802 42045 41762 41966 450.774516 2024-01-01 00:04:00+00:00
Series length: 500

5. Single-Parameter Backtest

This section demonstrates a basic backtest using a simple Moving Average (MA) crossover strategy with fixed parameters. It illustrates how to compute indicators, generate entry and exit signals, and simulate a portfolio using vectorbt's core functionalities. The results are then summarized through comprehensive performance statistics.

[18]
# --- Compute moving averages using vectorbt's built-in indicator engine ---
# `vbt.MA.run` calculates the Simple Moving Average (SMA) for the given 'close_series'.
# `window=10` specifies a 10-period SMA for the fast moving average.
fast_ma = vbt.MA.run(close_series, window=10)
# `window=30` specifies a 30-period SMA for the slow moving average.
slow_ma = vbt.MA.run(close_series, window=30)

# --- Generate entry and exit signals ---
# Entries occur when the fast MA crosses above the slow MA (bullish signal).
entries = fast_ma.ma_crossed_above(slow_ma)
# Exits occur when the fast MA crosses below the slow MA (bearish signal).
exits   = fast_ma.ma_crossed_below(slow_ma)

# --- Build and run portfolio simulation ---
# `vbt.Portfolio.from_signals` creates a portfolio based on the generated entry/exit signals.
# `close_series` provides the asset prices for trade execution.
# `init_cash` sets the starting capital for the portfolio.
# `fees` applies a transaction cost per trade (0.1% in this case).
# `freq='1min'` specifies the data frequency, crucial for annualizing performance metrics.
portfolio = vbt.Portfolio.from_signals(
    close_series,
    entries,
    exits,
    init_cash   = 10_000,
    fees        = 0.001,        # 0.1% per trade (round-trip = 0.2%)
    freq        = "1min",
)

print("--- vectorbt Portfolio Statistics ---")
# `portfolio.stats()` generates a detailed report of the portfolio's performance metrics.
print(portfolio.stats())
--- vectorbt Portfolio Statistics ---
Start                                                 2024-01-01 00:00:00+00:00
End                                                   2024-01-01 08:19:00+00:00
Period                                                          0 days 08:20:00
Start Value                                                             10000.0
End Value                                                          11451.662237
Total Return [%]                                                      14.516622
Benchmark Return [%]                                                  18.022404
Max Gross Exposure [%]                                                    100.0
Total Fees Paid                                                      203.163248
Max Drawdown [%]                                                       4.547096
Max Drawdown Duration                                           0 days 02:42:00
Total Trades                                                                 10
Total Closed Trades                                                          10
Total Open Trades                                                             0
Open Trade PnL                                                              0.0
Win Rate [%]                                                               60.0
Best Trade [%]                                                        10.639111
Worst Trade [%]                                                       -1.580561
Avg Winning Trade [%]                                                  3.083394
Avg Losing Trade [%]                                                  -1.054615
Avg Winning Trade Duration                                      0 days 00:41:20
Avg Losing Trade Duration                                       0 days 00:17:45
Profit Factor                                                          4.460934
Expectancy                                                           145.166224
Sharpe Ratio                                                          53.016368
Calmar Ratio                  1678281373142382224283974209531393359708152511...
Omega Ratio                                                            1.257145
Sortino Ratio                                                         80.497781
dtype: object

Explanation of Key Components:

  • vbt.MA.run(close_series, window=X): This function computes the Moving Average using vectorbt's optimized indicator engine. It returns a vectorbt indicator object that inherently supports advanced operations like crossover detection.

  • ma_crossed_above(slow_ma): This method, available on the indicator object, generates a boolean Series where True indicates the exact timestamp when the fast Moving Average crosses above the slow Moving Average. This is equivalent to the condition (fast > slow) & (fast.shift(1) <= slow.shift(1)), signifying a bullish signal.

  • ma_crossed_below(slow_ma): Similar to ma_crossed_above, this method identifies the exact timestamps where the fast Moving Average crosses below the slow Moving Average, signaling a bearish entry or an exit.

  • vbt.Portfolio.from_signals(close_series, entries, exits, ...): This is the core portfolio simulator within vectorbt. It takes the asset price Series and the boolean entry/exit signal Series as primary inputs. It systematically manages capital, applies user-defined fees, tracks the state of positions, and processes all trading logic in a single, vectorized pass. The freq parameter is essential for correctly annualizing various performance metrics.

  • portfolio.stats(): This method provides a comprehensive output of performance statistics for the simulated portfolio. Key metrics include total return, Sharpe ratio, maximum drawdown, win rate, and the total number of trades executed, offering a complete overview of the strategy's performance.

6. Parameter Optimization

This section demonstrates vectorbt's powerful capability for multi-parameter optimization. Instead of running individual backtests in a loop, vectorbt allows for simultaneously evaluating all combinations of a given set of parameters. This approach significantly speeds up the process of identifying optimal parameter sets for a trading strategy.

[19]
# --- Multi-parameter sweep: test all combinations of fast and slow moving average windows ---
# Define a list of window sizes for the fast moving average.
fast_windows = [5, 10, 15, 20]
# Define a list of window sizes for the slow moving average.
slow_windows = [20, 30, 40, 50]

# Run MA indicator for all fast window combinations. `short_name="fast"` labels the columns.
fast_ma_multi = vbt.MA.run(close_series, window=fast_windows, short_name="fast")
# Run MA indicator for all slow window combinations. `short_name="slow"` labels the columns.
slow_ma_multi = vbt.MA.run(close_series, window=slow_windows, short_name="slow")

# Generate entries: when any fast MA crosses above any slow MA.
entries_multi = fast_ma_multi.ma_crossed_above(slow_ma_multi)
# Generate exits: when any fast MA crosses below any slow MA.
exits_multi   = fast_ma_multi.ma_crossed_below(slow_ma_multi)

# Build and run portfolios for all parameter combinations.
# `init_cash`, `fees`, and `freq` are applied to each simulated portfolio.
portfolio_multi = vbt.Portfolio.from_signals(
    close_series,
    entries_multi,
    exits_multi,
    init_cash = 10_000,
    fees      = 0.001,
    freq      = "1min",
)

# Extract and display the total return for each parameter combination.
# The result is a multi-indexed Series, which is unstacked for better readability as a matrix.
returns_matrix = portfolio_multi.total_return()
print("--- Total Return Matrix (Fast Window × Slow Window) ---")
display(returns_matrix.unstack())
--- Total Return Matrix (Fast Window × Slow Window) ---
slow_window 20 30 40 50
fast_window
5 0.060002 NaN NaN NaN
10 NaN 0.145166 NaN NaN
15 NaN NaN 0.148511 NaN
20 NaN NaN NaN 0.086075

Explanation:

vectorbt excels at parameter optimization by evaluating all N parameter combinations (in this example, 4 fast MA windows × 4 slow MA windows = 16 combinations) simultaneously within a single, highly optimized function call. This vectorized approach eliminates the need for explicit loops, which would typically involve running 16 separate backtests in a traditional, loop-based framework.

The output is a matrix where each cell represents the total return achieved by a specific pairing of fast and slow moving average windows. This capability significantly streamlines the process of identifying the most performant parameter configurations for a given trading strategy, making vectorbt an indispensable tool for quantitative research and strategy development.

7. Visualization

This section demonstrates how to visualize the backtest results using plotly, an interactive charting library. It generates a multi-panel plot showcasing the asset price with moving averages and trade signals, alongside the portfolio's equity curve. This visualization provides a clear understanding of strategy performance and trade execution.

[20]
# Create a subplot figure with two rows and shared x-axes for time alignment.
# The top subplot is for price and indicators, the bottom for the equity curve.
fig = make_subplots(
    rows=2, cols=1, shared_xaxes=True,
    subplot_titles=[
        "Price + MA Crossover + Entry/Exit Signals", # Title for the top subplot
        "vectorbt Equity Curve", # Title for the bottom subplot
    ],
    row_heights=[0.55, 0.45], # Allocate more height to the price chart
)

# Add candlestick chart to the top subplot.
# This visualizes the open, high, low, and close prices over time.
fig.add_trace(go.Candlestick(
    x=df["datetime"],
    open=df["open"], high=df["high"],
    low=df["low"],   close=df["close"],
    name="Price"), row=1, col=1)

# Add the Fast Moving Average (10 periods) to the top subplot.
fig.add_trace(go.Scatter(
    x=close_series.index, y=fast_ma.ma.values,
    mode="lines", name="Fast MA (10)",
    line=dict(color="blue", width=1)), row=1, col=1)

# Add the Slow Moving Average (30 periods) to the top subplot.
fig.add_trace(go.Scatter(
    x=close_series.index, y=slow_ma.ma.values,
    mode="lines", name="Slow MA (30)",
    line=dict(color="orange", width=1)), row=1, col=1)

# Define buy and sell signal masks from the entries and exits Series
buy_signals_mask  = entries.loc[entries].index
sell_signals_mask = exits.loc[exits].index

# Filter the close series to get prices only at buy signal times.
buy_prices  = close_series.loc[buy_signals_mask]
# Filter the close series to get prices only at sell signal times.
sell_prices = close_series.loc[sell_signals_mask]

# Add 'Buy' markers (green triangles pointing up) to the top subplot.
# Multiplied by 0.999 to place them slightly below the close price for visibility.
fig.add_trace(go.Scatter(
    x=buy_prices.index,
    y=buy_prices.values  * 0.999,
    mode="markers",
    marker=dict(symbol="triangle-up",   size=10, color="green"),
    name="Buy Signal"), row=1, col=1)

# Add 'Sell' markers (red triangles pointing down) to the top subplot.
# Multiplied by 1.001 to place them slightly above the close price for visibility.
fig.add_trace(go.Scatter(
    x=sell_prices.index,
    y=sell_prices.values * 1.001,
    mode="markers",
    marker=dict(symbol="triangle-down", size=10, color="red"),
    name="Sell Signal"), row=1, col=1)

# Get the portfolio's equity curve values.
equity_values = portfolio.value()
# Add the portfolio equity curve to the bottom subplot.
fig.add_trace(go.Scatter(
    x=equity_values.index, y=equity_values.values,
    mode="lines", name="Portfolio Value ($)",
    line=dict(color="green", width=2)), row=2, col=1)

# Update layout settings for the entire figure.
fig.update_layout(
    title_text="vectorbt Backtest — MA Crossover Strategy", # Main title for the figure
    xaxis_rangeslider_visible=False, # Hide the range slider at the bottom of the x-axis
    height=800, # Set the overall height of the figure
    yaxis=dict(autorange=True), # Auto-scale the y-axis for the price chart
    xaxis2_title="Datetime", # Label for the shared x-axis (bottom)
    yaxis_title="Price", # Label for the y-axis of the top subplot
    yaxis2_title="Portfolio Value ($)", # Label for the y-axis of the bottom subplot
)
fig.show() # Display the generated interactive plot

8. Conclusion

This notebook provided a comprehensive introduction to vectorbt, a powerful Python library for high-performance backtesting of quantitative trading strategies. We covered:

  • Dependency Installation & Library Imports: Setting up the environment and importing essential libraries.
  • Understanding vectorbt: A detailed overview of its core features, including vectorized computation, parameter sweeps, built-in indicators, and performance analytics.
  • Data Generation: Creating synthetic OHLCV data suitable for backtesting.
  • Single-Parameter Backtest: Demonstrating a basic Moving Average crossover strategy, including signal generation and portfolio simulation.
  • Parameter Optimization: Showcasing vectorbt's ability to efficiently evaluate multiple parameter combinations simultaneously, streamlining strategy research.
  • Visualization: Generating interactive plots to visualize price action, trade signals, and portfolio equity curves.

vectorbt stands out as an invaluable tool for researchers and quantitative traders due to its focus on speed and efficiency, particularly for parameter optimization and initial strategy screening. By leveraging vectorized operations, it significantly reduces the time required to iterate on ideas and identify promising strategy parameters, making it an excellent complement to more granular event-driven backtesters for later-stage validation.

Vectorbt Backtest · BitPredict