Backtesting with vectorbt
Use the vectorbt library for high-performance portfolio backtesting with built-in metrics, portfolio simulation, and visualization.
Backtesting Libraries — vectorbt
1. Dependency Installation
!pip install pandas numpy vectorbt plotlyRequirement 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) Collecting vectorbt Downloading vectorbt-1.0.0-py3-none-any.whl.metadata (14 kB) 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.1) 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) Collecting dateparser (from vectorbt) Downloading dateparser-1.4.0-py3-none-any.whl.metadata (31 kB) 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) Collecting schedule (from vectorbt) Downloading schedule-1.2.2-py3-none-any.whl.metadata (3.8 kB) Requirement already satisfied: requests in /usr/local/lib/python3.12/dist-packages (from vectorbt) (2.32.4) Collecting mypy_extensions (from vectorbt) Downloading mypy_extensions-1.1.0-py3-none-any.whl.metadata (1.1 kB) 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.1) 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.62.1) 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.13) 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.4.22) 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.1) 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.1) 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) Collecting jedi>=0.16 (from ipython>=4.0.0->ipywidgets>=7.0.0->vectorbt) Downloading jedi-0.20.0-py2.py3-none-any.whl.metadata (23 kB) 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.6) 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.6.0) 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.9.6) 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.3.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.0) 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.5,>=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.4.0) 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) (0.30.0) 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.14.0) 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.3) 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.9.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: overrides>=5.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) (7.7.0) 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.9.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.9.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.9.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.9.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.9.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.9.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.9.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.9.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.9.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.9.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.9.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.9.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) Downloading vectorbt-1.0.0-py3-none-any.whl (451 kB) [2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m451.7/451.7 kB[0m [31m7.4 MB/s[0m eta [36m0:00:00[0m [?25hDownloading dateparser-1.4.0-py3-none-any.whl (300 kB) [2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m300.4/300.4 kB[0m [31m8.9 MB/s[0m eta [36m0:00:00[0m [?25hDownloading mypy_extensions-1.1.0-py3-none-any.whl (5.0 kB) Downloading schedule-1.2.2-py3-none-any.whl (12 kB) Downloading jedi-0.20.0-py2.py3-none-any.whl (4.9 MB) [2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m4.9/4.9 MB[0m [31m31.7 MB/s[0m eta [36m0:00:00[0m [?25hInstalling collected packages: schedule, mypy_extensions, jedi, dateparser, vectorbt Successfully installed dateparser-1.4.0 jedi-0.20.0 mypy_extensions-1.1.0 schedule-1.2.2 vectorbt-1.0.0
2. Library Imports
import warnings
warnings.filterwarnings("ignore")
import pandas as pd
import numpy as np
import vectorbt as vbt
import plotly.graph_objects as go
from plotly.subplots import make_subplots3. What Is vectorbt?
vectorbt is a Python library for high-performance portfolio backtesting
built on top of numpy and pandas. It is designed to evaluate thousands
of parameter combinations simultaneously using vectorized array operations,
making it the standard tool for parameter optimization and strategy screening.
Key features:
| Feature | Description | |---| | Vectorized computation | Entire backtest runs as array operations — no Python loops | | Parameter sweeps | Test all combinations of parameters in one call | | Built-in indicators | SMA, EMA, RSI, MACD, Bollinger Bands, and 100+ others | | Portfolio simulation | Fees, slippage, position sizing, and cash management in one API | | Performance analytics | Sharpe, Sortino, Calmar, drawdown, trade statistics built in | | Interactive plotting | Plotly-based charts for equity curves, trade markers, heatmaps |
When to use vectorbt vs event-driven:
- vectorbt: Parameter optimization, signal screening, fast iteration during research.
- Event-driven (Notebook 67): Final performance validation, realistic execution modeling, live system development.
4. Data Generation
def generate_data(periods: int) -> pd.DataFrame:
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):
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)
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)
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
df = pd.DataFrame(price_data, index=datetime_index)
df.index.name = "datetime"
df["volume"] = np.random.uniform(100.0, 500.0, periods)
df["datetime"] = df.index.to_series()
return df.reset_index(drop=True)
df = generate_data(500)
# Convert to indexed Series for vectorbt compatibility
close_series = pd.Series(
df["close"].values,
index=pd.DatetimeIndex(df["datetime"]),
name="close",
)
display(df.head())
print(f"Series length: {len(close_series)}")| open | high | low | close | volume | datetime | |
|---|---|---|---|---|---|---|
| 0 | 41983 | 42045 | 41972 | 41981 | 214.866516 | 2024-01-01 00:00:00+00:00 |
| 1 | 41986 | 42535 | 41820 | 42442 | 122.914521 | 2024-01-01 00:01:00+00:00 |
| 2 | 42425 | 43150 | 42363 | 43082 | 422.954606 | 2024-01-01 00:02:00+00:00 |
| 3 | 43097 | 43157 | 43002 | 43115 | 163.932242 | 2024-01-01 00:03:00+00:00 |
| 4 | 43097 | 43209 | 42713 | 42927 | 329.700926 | 2024-01-01 00:04:00+00:00 |
Series length: 500
5. Single-Parameter Backtest
# --- Compute moving averages using vectorbt's built-in indicator engine ---
fast_ma = vbt.MA.run(close_series, window=10)
slow_ma = vbt.MA.run(close_series, window=30)
# --- Generate entry and exit signals ---
entries = fast_ma.ma_crossed_above(slow_ma) # Fast MA crosses above slow MA
exits = fast_ma.ma_crossed_below(slow_ma) # Fast MA crosses below slow MA
# --- Build and run portfolio ---
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 ---")
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 9407.42885 Total Return [%] -5.925711 Benchmark Return [%] 2.012815 Max Gross Exposure [%] 100.0 Total Fees Paid 200.497049 Max Drawdown [%] 13.034522 Max Drawdown Duration 0 days 04:18:00 Total Trades 10 Total Closed Trades 10 Total Open Trades 0 Open Trade PnL 0.0 Win Rate [%] 20.0 Best Trade [%] 4.164551 Worst Trade [%] -2.68185 Avg Winning Trade [%] 3.832015 Avg Losing Trade [%] -1.687851 Avg Winning Trade Duration 0 days 01:07:30 Avg Losing Trade Duration 0 days 00:13:00 Profit Factor 0.565981 Expectancy -59.257115 Sharpe Ratio -23.85127 Calmar Ratio -7.671935 Omega Ratio 0.888054 Sortino Ratio -32.249531 dtype: object
Explanation:
vbt.MA.run(close_series, window=10): Computes the moving average using vectorbt's indicator pipeline. The result is a vectorbt indicator object that supports crossover detection directly.ma_crossed_above(slow_ma): Returns a boolean Series that is True only on the exact candle where the fast MA crosses above the slow MA — equivalent to(fast > slow) & (fast.shift(1) <= slow.shift(1)).vbt.Portfolio.from_signals: The core portfolio simulator. It processes the entry and exit boolean arrays, manages cash, applies fees, and tracks position state — all in a single vectorized pass. Thefreqparameter is used for annualizing performance metrics.portfolio.stats(): Returns a comprehensive dictionary of performance metrics including total return, Sharpe ratio, max drawdown, win rate, and trade count.
6. Parameter Optimization
# --- Multi-parameter sweep: test all combinations of fast and slow windows ---
fast_windows = [5, 10, 15, 20]
slow_windows = [20, 30, 40, 50]
fast_ma_multi = vbt.MA.run(close_series, window=fast_windows, short_name="fast")
slow_ma_multi = vbt.MA.run(close_series, window=slow_windows, short_name="slow")
entries_multi = fast_ma_multi.ma_crossed_above(slow_ma_multi)
exits_multi = fast_ma_multi.ma_crossed_below(slow_ma_multi)
portfolio_multi = vbt.Portfolio.from_signals(
close_series,
entries_multi,
exits_multi,
init_cash = 10_000,
fees = 0.001,
freq = "1min",
)
# Extract total return for each parameter combination
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.139453 | NaN | NaN | NaN |
| 10 | NaN | -0.059257 | NaN | NaN |
| 15 | NaN | NaN | -0.055753 | NaN |
| 20 | NaN | NaN | NaN | -0.048005 |
Explanation: vectorbt evaluates all 16 parameter combinations (4 fast × 4 slow) simultaneously in a single function call — no outer loop is required. The result is a matrix where each cell contains the total return for that fast/slow window pair. This capability is what makes vectorbt the standard tool for strategy parameter optimization — equivalent analysis in a loop-based framework would require 16 separate backtest runs.
7. Visualization
buy_signals_mask = entries[entries].index
sell_signals_mask = exits[exits].index
fig = make_subplots(
rows=2, cols=1, shared_xaxes=True,
subplot_titles=[
"Price + MA Crossover + Entry/Exit Signals",
"vectorbt Equity Curve",
],
row_heights=[0.55, 0.45],
)
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)
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)
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)
buy_prices = close_series.loc[buy_signals_mask]
sell_prices = close_series.loc[sell_signals_mask]
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)
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)
equity_values = portfolio.value()
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)
fig.update_layout(
title_text="vectorbt Backtest — MA Crossover Strategy",
xaxis_rangeslider_visible=False,
height=800,
yaxis=dict(autorange=True),
xaxis2_title="Datetime",
yaxis_title="Price",
yaxis2_title="Portfolio Value ($)",
)
fig.show()Task
I will update the notebook to improve its formality, clarity, and consistency. Specifically, I will:
- Refine the introductory markdown cells (
e5741ce3,eefdc1e3) for a more formal and technical presentation. - Add comments to the dependency installation code (
6a30bce5) to explain its purpose. - Modify the library imports markdown (
5ffcb3ab) and add detailed comments to the import code (4554082d) for documentation purposes. - Rewrite the 'What Is vectorbt?' markdown section (
b6da932e) to be concise, technically accurate, and formal. - Enhance the 'Data Generation' markdown introduction (
bf923033) and add technical comments to thegenerate_datafunction andclose_seriesconversion within the code cell (4c4965df). - Improve the 'Single-Parameter Backtest' markdown introduction (
9a218c0b), add technical comments to the backtest code (c03c38b8), and rewrite its 'Explanation' markdown (598b7240). - Refine the 'Parameter Optimization' markdown introduction (
2a617563), add technical comments to the multi-parameter sweep code (2426f084), and rewrite its 'Explanation' markdown (e6440eba). - Enhance the 'Visualization' markdown introduction (
00861abe) and add comments to the plotting code (da05a445) to explain each component.
I will confirm that all changes adhere to the specified rules upon completion.