Who Should Use VectorBT?
VectorBT is an advanced backtesting library designed for traders and quantitative analysts. It is particularly beneficial for those who require a fast, flexible, and powerful tool for backtesting trading strategies. Its users typically include:
- Quantitative traders who need to test and optimize complex trading strategies.
- Data scientists seeking to incorporate financial data analysis into their workflows.
- Algorithmic traders looking for a library that can handle large datasets
- Who Should Use VectorBT?
- Speed Comparison with Other Backtesting Libraries
- List of Other Popular Python Backtesting Libraries
- Installing the VectorBT Library
- Simple EMA Crossover Backtesting with VectorBT
- Backtesting Metrics Output of the EMA Crossover Strategy
- Plotting Equity Curve and Drawdown Curve
- VectorBT Position Sizing Methods
- EMA Crossover Optimization with VectorBT
Speed Comparison with Other Backtesting Libraries
VectorBT is known for its high-speed performance, primarily due to its vectorized operations and the use of Numba, a JIT compiler that translates Python functions into optimized machine code. This makes it significantly faster than many other backtesting libraries, especially when dealing with large datasets.
When compared to other Python backtesting libraries like Backtrader or PyAlgoTrade, VectorBT can perform backtests significantly faster, especially for large datasets or complex strategies.
List of Other Popular Python Backtesting Libraries
- Backtrader: Popular for its simplicity and community support.
- PyAlgoTrade: Known for its flexibility and support for multiple data sources.
- Zipline: Used mainly for its integration with Quantopian for strategy development.
- QuantConnect: Offers cloud-based backtesting with a wide range of data.
- bt: Focuses on strategy combination and portfolio management.
The integration of Numba into VectorBT results in a performance that is orders of magnitude faster than traditional Python backtesting libraries. This speed is crucial in quantitative finance, where analyzing massive datasets and iterating over numerous strategies and parameters is the norm. It allows traders and analysts to test more hypotheses in less time, leading to more refined and tested trading strategies.
VectorBT supports multiprocessing, enabling the parallel processing of data and speeding up computations, especially useful for strategy optimization and parameter scanning.
Installing the VectorBT Library
VectorBT library supports Python 3.6 – 3.10 version and currently, it doesn’t support Python 3.11 at this moment and it is expected to support from 3.12 onwards. Here is the pip command to install the library and its dependencies. The entire VectorBT Backtesting and Optimization is tested using Google Colab
pip install vectorBT
However if in case you are using Python 3.11 or higher version and would like to install then here is the tutorial on Installing VectorBT in a Virtual environment
Simple EMA Crossover Backtesting with VectorBT
The following Python code fetches data from Yahoo Finance and a simple 10 and 20 EMA crossover strategy is applied with an Initial capital of Rs1,00,000/- with position sizing as 50% of the current equity and 0.01% as fixed trading commissions.
import vectorbt as vbt
import numpy as np
import pandas as pd
# Fetch historical data for HDFCBANK using VectorBT
hdfc_data = vbt.YFData.download('HDFCBANK.NS', start='2010-01-01', end='2023-01-01').get('Close')
# Calculate 10 and 20 days exponential moving averages
short_ema = vbt.MA.run(hdfc_data, 10, short_name='fast', ewm=True)
long_ema = vbt.MA.run(hdfc_data, 20, short_name='slow', ewm=True)
# Generate crossover signals
entries = short_ema.ma_crossed_above(long_ema)
exits = short_ema.ma_crossed_below(long_ema)
# Set initial capital
initial_capital = 100000
# Create and run the portfolio with 50% of equity position sizing
portfolio = vbt.Portfolio.from_signals(
hdfc_data, entries, exits,
direction = 'longonly',
size=0.5, # 50% of current equity
size_type='percent', # Use percent of equity for sizing
fees=0.001,
init_cash=initial_capital,
freq='1D',
min_size =1,
size_granularity = 1
)
# Retrieve and print the backtesting stats
stats = portfolio.stats()
print("Backtesting Stats:")
print(stats)
Backtesting Metrics Output of the EMA Crossover Strategy
Backtesting Stats:
Start 2010-01-03 18:30:00+00:00
End 2022-12-29 18:30:00+00:00
Period 3209 days 00:00:00
Start Value 100000.0
End Value 184053.173875
Total Return [%] 84.053174
Benchmark Return [%] 945.324187
Max Gross Exposure [%] 60.705702
Total Fees Paid 8736.891845
Max Drawdown [%] 19.285277
Max Drawdown Duration 1051 days 00:00:00
Total Trades 64
Total Closed Trades 63
Total Open Trades 1
Open Trade PnL 9825.657568
Win Rate [%] 39.68254
Best Trade [%] 50.972884
Worst Trade [%] -10.359501
Avg Winning Trade [%] 10.54576
Avg Losing Trade [%] -3.612213
Avg Winning Trade Duration 65 days 05:45:36
Avg Losing Trade Duration 10 days 11:22:06.315789473
Profit Factor 1.777249
Expectancy 1178.214545
Sharpe Ratio 0.7258
Calmar Ratio 0.372581
Omega Ratio 1.13629
Sortino Ratio 1.098154
dtype: object
Accessing Trade Details
# Accessing trade details
trades = portfolio.trades.records_readable
print("\nTrade Details:")
trades
Output
Trade Details:
Exit Trade Id Column Size Entry Timestamp Avg Entry Price Entry Fees Exit Timestamp Avg Exit Price Exit Fees PnL Return Direction Status Position Id
0 0 0 326.0 2010-02-21 18:30:00+00:00 153.168030 49.932778 2010-05-06 18:30:00+00:00 166.840836 54.390112 4353.011796 0.087177 Long Closed 0
1 1 0 292.0 2010-05-11 18:30:00+00:00 178.292801 52.061498 2010-05-17 18:30:00+00:00 171.151672 49.976288 -2187.247320 -0.042013 Long Closed 1
2 2 0 288.0 2010-06-10 18:30:00+00:00 176.839020 50.929638 2010-07-04 18:30:00+00:00 174.013275 50.115823 -914.859914 -0.017963 Long Closed 2
3 3 0 283.0 2010-07-05 18:30:00+00:00 178.447205 50.500559 2010-10-19 18:30:00+00:00 212.205887 60.054266 9443.152252 0.186991 Long Closed 3
4 4 0 253.0 2010-11-09 18:30:00+00:00 217.684738 55.074239 2010-11-11 18:30:00+00:00 210.329651 53.213402 -1969.124722 -0.035754 Long Closed 4
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
59 59 0 64.0 2022-02-15 18:30:00+00:00 1481.340942 94.805820 2022-02-23 18:30:00+00:00 1387.178345 88.779414 -6209.991484 -0.065502 Long Closed 59
60 60 0 63.0 2022-03-21 18:30:00+00:00 1460.231445 91.994581 2022-04-18 18:30:00+00:00 1311.730713 82.639035 -9530.179759 -0.103595 Long Closed 60
61 61 0 63.0 2022-05-29 18:30:00+00:00 1385.659424 87.296544 2022-06-13 18:30:00+00:00 1297.124756 81.718860 -5746.699485 -0.065830 Long Closed 61
62 62 0 63.0 2022-06-29 18:30:00+00:00 1332.716553 83.961143 2022-09-25 18:30:00+00:00 1410.474854 88.859916 4725.951891 0.056287 Long Closed 62
63 63 0 60.0 2022-10-23 18:30:00+00:00 1444.484863 86.669092 2022-12-29 18:30:00+00:00 1609.690308 0.000000 9825.657568 0.113370 Long Open 63
64 rows × 14 columns
VectorBT doesn’t just stop at backtesting; it integrates with Plotly and ipywidgets for advanced data visualization. This integration enables the creation of complex charts and interactive dashboards directly in Jupyter notebooks. This means that the plots are interactive, allowing for zooming, panning, and viewing data points in detail.
Plotting Equity Curve and Drawdown Curve
import plotly.graph_objs as go
# Extracting equity and drawdown data
equity_data = portfolio.value()
drawdown_data = portfolio.drawdown()*100
# Plotting the equity curve with Plotly
equity_trace = go.Scatter(x=equity_data.index, y=equity_data, mode='lines', name='Equity Curve')
equity_layout = go.Layout(title='Equity Curve', xaxis_title='Date', yaxis_title='Equity')
equity_fig = go.Figure(data=[equity_trace], layout=equity_layout)
equity_fig.show()
# Plotting the drawdown curve as a reddish-brown area plot with Plotly
drawdown_trace = go.Scatter(
x=drawdown_data.index,
y=drawdown_data,
mode='lines',
name='Drawdown Curve',
fill='tozeroy',
line=dict(color='brown')
)
drawdown_layout = go.Layout(
title='Drawdown Curve',
xaxis_title='Date',
yaxis_title='Drawdown %',
template='plotly_white'
)
drawdown_fig = go.Figure(data=[drawdown_trace], layout=drawdown_layout)
drawdown_fig.show()
Equity Curve

Drawdown Curve

portfolio.plot().show()
in VectorBT is used to generate and display a graphical representation of a trading strategy’s performance, utilizing the capabilities of Plotly for interactive and detailed visualizations.
portfolio.plot().show()

VectorBT Position Sizing Methods
- Fixed Size: This is the simplest form of position sizing. A fixed number of shares or contracts are traded regardless of the account size or other factors. In VectorBT, this can be specified using the
size
parameter in thefrom_signals
orfrom_orders
method. - Percent of Equity: In this method, the size of the position is a fixed percentage of the current account equity. This means that as the account grows, the size of each trade in terms of the number of shares or contracts also grows. This is useful for compounding growth. In VectorBT, this is achieved using the
size_type='percent'
parameter, combined with thesize
parameter representing the percentage. - Target Percent of Equity: Similar to Percent of Equity, but here the size is calculated to adjust the portfolio to a target percentage allocation for each asset. For instance, if you wish to maintain a certain asset at 30% of your portfolio, the sizing will automatically adjust to achieve this target.
- Fixed Cash Amount: This method involves allocating a fixed cash amount for each trade. No matter the price of the asset, the same amount of money is invested. In VectorBT, this can be set using
size_type='value'
, wheresize
would be the cash amount per trade.
EMA Crossover Optimization with VectorBT
Optimizing the EMA crossover strategy involves testing various combinations of short and long EMA spans:
import vectorbt as vbt
import numpy as np
import pandas as pd
# Fetch data from yahoo finance
hdfc_data = vbt.YFData.download('HDFCBANK.NS', start='2010-01-01', end='2023-01-01').get('Close')
# Parameter grid
short_spans = np.arange(5, 15, 1) # Test spans from 5 to 14
long_spans = np.arange(15, 30, 1) # Test spans from 15 to 29
# Backtesting with different EMA spans
results = []
for short_span in short_spans:
for long_span in long_spans:
# Calculate 10 and 20 days exponential moving averages
short_ema = vbt.MA.run(hdfc_data, short_span, short_name='fast', ewm=True)
long_ema = vbt.MA.run(hdfc_data, long_span, short_name='slow', ewm=True)
# Generate crossover signals
entries = short_ema.ma_crossed_above(long_ema)
exits = short_ema.ma_crossed_below(long_ema)
portfolio = vbt.Portfolio.from_signals(
hdfc_data, entries, exits,
size=0.5, size_type='percent', fees=0.001,
init_cash=100000,freq='1D',
min_size =1, size_granularity = 1
)
results.append((short_span, long_span, portfolio.total_return()))
# Find the best performing parameter set
best_params = max(results, key=lambda x: x[2])
print("Best Parameters:", best_params)
Output
Best Parameters: (14, 24, 1.1464926467324832)
VectorBT emerges as a powerful tool for backtesting and optimizing trading strategies in Python. Its speed and flexibility make it a superior choice for quantitative analysts and algorithmic traders. Through this guide, we explored a basic EMA Crossover strategy, visualized its performance, and performed optimization to find the best parameters. In the next part, we will delve deeper into the advanced features of VectorBT. Stay tuned to further enhance your trading strategy development skills with VectorBT.
In the next tutorial, we will be exploring Portfolio Backtesting and Rebalancing using VectorBT