Features
Interactive charts
Plot backtests, candlesticks, indicators, signals, and parameter heatmaps with Plotly
How do you see what a strategy actually did? VBT plots backtests, prices, indicators, signals, and parameter results as interactive Plotly charts in Python: zoom into a single trade, hover for exact values, and combine any of them in one figure.
data = vbt.YFData.pull("BTC-USD", start="2023-01-01", end="2024-01-01")
rsi = data.run("rsi", window=14).rsi
pf = vbt.PF.from_signals(data, rsi.vbt.crossed_below(30), rsi.vbt.crossed_above(70))
def plot_rsi(pf, rsi, add_trace_kwargs=None, fig=None):
rsi.rename("RSI").vbt.plot(add_trace_kwargs=add_trace_kwargs, fig=fig)
pf.plot(
subplots=[
"orders",
"trade_pnl",
("rsi", dict(title="RSI", plot_func=plot_rsi, rsi=rsi)),
"drawdowns",
],
settings=dict(bm_returns=False),
).show()Portfolio and trade charts
pf.plot() draws a dashboard from named subplots. Built-in subplots include orders, trades,
trade_pnl, trade_signals, cumulative_returns, drawdowns, underwater, gross_exposure,
allocations, cash, assets, and value, and each can be configured through subplot_settings.
Every subplot also exists as its own method, such as pf.plot_cumulative_returns(),
pf.plot_underwater(), or pf.plot_allocations() for multi-asset weights over time.
Records plot themselves too: pf.trades.plot() shows each trade from entry to exit with its profit,
and pf.drawdowns.plot(top_n=5) shades the largest drawdowns. For returns, a calendar heatmap of
monthly returns is one line: pf.returns_acc.resample("M").ts_heatmap().
Price, indicator, and signal charts
Data objects plot as candlesticks or OHLC bars with volume. Indicators and signals are added to the
same figure by passing fig:
sub = data.loc["2023-04-01":"2023-08-31"]
fast = sub.close.rolling(10).mean()
slow = sub.close.rolling(30).mean()
entries = fast.vbt.crossed_above(slow)
exits = fast.vbt.crossed_below(slow)
fig = sub.plot(plot_volume=False)
fast.rename("SMA 10").vbt.plot(fig=fig)
slow.rename("SMA 30").vbt.plot(fig=fig)
entries.vbt.signals.plot_as_entries(fast, fig=fig)
exits.vbt.signals.plot_as_exits(fast, fig=fig)
fig.show()Indicators built with VBT have a plot method with sensible defaults, and TA-Lib indicators plot
according to their output types, for example as lines or histograms.
Heatmaps and other generic plots
Any Series or DataFrame gets plotting methods through its accessor: line, scatter, bar, histogram, box, heatmap, and 3D volume plots. A parameter grid with three parameters becomes a heatmap with a slider for the third:
btc = vbt.YFData.pull("BTC-USD", start="2020-01-01", end="2025-01-01")
rsi = btc.run("rsi", window=14).rsi
@vbt.parameterized(merge_func="concat")
def sharpe(lower, upper, sl_stop):
pf = vbt.PF.from_signals(
btc,
rsi.vbt.crossed_below(lower),
rsi.vbt.crossed_above(upper),
sl_stop=sl_stop,
)
return pf.sharpe_ratio
sharpes = sharpe(
vbt.Param([20, 25, 30, 35, 40]),
vbt.Param([60, 65, 70, 75, 80]),
vbt.Param([0.05, 0.1, 0.2]),
)
sharpes.vbt.heatmap(x_level="lower", y_level="upper", slider_level="sl_stop").show()When Plotly Express has a chart you need, call it from the accessor, for example
df.vbt.px.parallel_coordinates(). Cross-validation splits have their own plots that show the
training and test periods of every split.
Customization
Every plotting method takes trace_kwargs for the trace, add_trace_kwargs to place it in a
subplot, and layout keywords for the figure. For example,
slow.vbt.plot(trace_kwargs=dict(line=dict(color="orange", dash="dash")), fig=fig) draws one dashed
orange line. vbt.make_subplots creates figures with several panels, and since the result is a
regular Plotly figure, everything Plotly offers still works afterwards.
Themes and defaults live in vbt.settings.plotting, for example vbt.settings.set_theme("dark")
for dark charts. For markets that close overnight or on weekends, fig.auto_rangebreaks(freq="1D")
adds Plotly range breaks for the missing time, so candles sit next to each other instead of leaving
gaps.
Charts that update with new data
You can update the data in existing Plotly traces while keeping the figure's layout and styling.
Connect those updates to a DataUpdater to refresh a candlestick chart as new bars arrive, or
update lines for prices and indicators in a notebook widget. This is useful for watching the latest
part of a series without creating a new chart each time.
The Data pipelines page covers scheduled data updates,
and Live simulation covers continuing a portfolio on new
bars. You can also save successive chart images as frames in a GIF with imageio to replay how a
chart developed.
Large data and output
A minute chart over several years has millions of points, which a browser draws slowly. With
plotly-resampler installed, set vbt.settings.plotting["use_resampler"] = True and charts load a
downsampled view that refines as you zoom. Alternatively, select a shorter range before plotting, or
resample the portfolio first: pf.resample("1D") returns a daily portfolio with the same total
return, and its charts draw a point per day.
Share interactive charts and export images
Figures show interactively in notebooks and browsers with fig.show(), as static images with
fig.show_png() or fig.show_svg(), and save to files with fig.write_image() or
fig.write_html(). Static images are rendered by Plotly's kaleido package, so install it first,
and update it if an export hangs. The renderer can be set per figure or globally.
An HTML export keeps zoom, hover labels, and legend controls, so someone else can explore the results in a browser without installing Python or VBT. Plotly includes the chart data and its JavaScript library in the file by default. See Plotly's HTML export guide for saving a figure or combining several charts in one page. Use PNG or SVG when you need a fixed image for a report or presentation.
Related pages
- Indicators and signals › Technical indicatorsRun TA-Lib, pandas-ta, ta, SMC, WorldQuant Alphas, and native indicators at scale
- Indicators and signals › Trading signalsGenerate, combine, clean, and analyze entry and exit signals before backtesting
- Backtesting › Backtesting engineSimulate orders, signals, and callbacks across many assets and parameters at once
- Research toolkit › Multidimensional researchRun assets, parameters, and strategies as labeled columns, then index and stack them
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.