Plotting¶
Any Pandas Series or DataFrame can be plotted via an accessor. There are two main pathways for plotting:
- GenericAccessor offering methods tailored specifically for vectorbtpro-typical workflows, and
- PXAccessor offering methods parsed from Plotly express.
fig = sr_or_df.vbt.plot() # (1)!
fig = pd.Series(
np.asarray(y),
index=np.asarray(x)
).vbt.scatterplot() # (2)!
fig = pf.value.vbt.lineplot() # (3)!
fig = pf.sharpe_ratio.vbt.barplot() # (4)!
fig = pf.returns.vbt.qqplot() # (5)!
fig = pf.allocations.vbt.areaplot(line_shape="hv") # (6)!
fig = pf.returns.vbt.histplot(trace_kwargs=dict(nbinsx=100)) # (7)!
monthly_returns = pf.returns_acc.resample("M").get()
fig = monthly_returns.vbt.boxplot() # (8)!
fig = monthly_returns.vbt.heatmap() # (9)!
fig = monthly_returns.vbt.ts_heatmap() # (10)!
fig = pf.sharpe_ratio.vbt.heatmap( # (11)!
x_level="fast_window",
y_level="slow_window",
symmetric=True
)
fig = pf.sharpe_ratio.vbt.heatmap( # (12)!
x_level="fast_window",
y_level="slow_window",
slider_level="symbol",
symmetric=True
)
fig = pf.sharpe_ratio.vbt.volume( # (13)!
x_level="timeperiod",
y_level="upper_threshold",
z_level="lower_threshold",
symmetric=True
)
# ______________________________________________________________
fig = sr_or_df.vbt.px.ecdf() # (14)!
- Create a line plot with visible markers. Each column will become a trace.
- Create a scatter plot of a variable
xagainst another variabley. Both must be one-dimensional. - Display equity as a line plot
- Compare Sharpe ratio of various symbols or parameter combinations with a bar plot
- Create a Q-Q plot to check whether returns are distributed normally. Only one column at a time.
- Plot allocations as an area plot
- Create a histogram plot of returns with 100 bins (remove
nbinsxfor auto-binning) - Create a box plot of monthly returns
- Create a heatmap of time (y-axis) against monthly returns (x-axis)
- Create a heatmap of monthly returns (y-axis) against time (x-axis)
- Create a symmetrical heatmap with Sharpe ratios where fast windows are displayed on the x-axis and slow windows are displayed on the y-axis. The Pandas object must be a Series with two index levels.
- Create a symmetrical heatmap with Sharpe ratios where fast windows are displayed on the x-axis, slow windows are displayed on the y-axis, and symbols are displayed as a slider. The Pandas object must be a Series with three index levels.
- For three to four parameters, create a volume plot instead
- Plot an Empirical Cumulative Distribution Plot with Plotly express
The default theme can be changed globally in the settings. Available themes are registered under themes in settings.plotting.
Trace parameters such as line color and marker shape can be changed with trace_kwargs. Some plotting methods have multiple of such arguments. For allowed parameters, see the Plotly documentation of the respective trace type, for example Scatter for lines.
fig = bbands.plot(
upper_trace_kwargs=dict(line=dict(color="green")),
lower_trace_kwargs=dict(line=dict(color="red"))
)
Layout parameters can be changed by passing them directly to the plot method as variable keyword arguments.
fig = df.vbt.plot(width=None, height=None)
A plot with multiple subplots can be constructed with vbt.make_subplots(), which takes the same arguments as Plotly.
Most plotting methods accept the argument add_trace_kwargs (see Figure.add_trace), which can be used to specify which subplot to plot the traces over.
df1.vbt.plot(add_trace_kwargs=dict(row=1, col=1), fig=fig)
df2.vbt.plot(add_trace_kwargs=dict(row=2, col=1), fig=fig)
Note
The provided figure fig must be created with vbt.make_subplots().
Traces with two different scales but similar time scale can also be plotted next to each other by creating a secondary y-axis.
fig = vbt.make_subplots(specs=[[{"secondary_y": True}]])
df1.vbt.plot(add_trace_kwargs=dict(secondary_y=False), fig=fig)
df2.vbt.plot(add_trace_kwargs=dict(secondary_y=True), fig=fig)
The figure can be changed manually after creation. Below, 0 is the index of the trace in the figure.
fig = df.vbt.scatterplot()
fig.layout.title.text = "Scatter"
fig.data[0].marker.line.width = 4
fig.data[0].marker.line.color = "black"
Note
A plotting method can add multiple traces to the figure.
Settings related to plotting can be defined or changed globally in settings.plotting.
vbt.settings["plotting"]["layout"]["paper_bgcolor"] = "rgb(0,0,0)"
vbt.settings["plotting"]["layout"]["plot_bgcolor"] = "rgb(0,0,0)"
vbt.settings["plotting"]["layout"]["template"] = "vbt_dark"
import plotly.io as pio
import plotly.graph_objects as go
pio.templates["my_black"] = go.layout.Template(
layout_paper_bgcolor="rgb(0,0,0)",
layout_plot_bgcolor="rgb(0,0,0)",
)
vbt.settings["plotting"]["layout"]["template"] = "vbt_dark+my_black"
Usually Plotly displays a homogeneous datetime index including time gaps such as non-business hours and weekends. To skip the gaps, we can use the rangebreaks property.
fig = df.vbt.plot()
fig.update_xaxes(
rangebreaks=[
dict(bounds=['sat', 'mon']),
dict(bounds=[16, 9.5], pattern='hour'),
# (1)!
]
)
- Pass
dict(values=df.isnull().all(axis=1).index)to also skip NaN rows, or any other index
Note
Make sure that your data has the correct timezone to apply the above approach.
fig = df.vbt.plot()
fig.auto_rangebreaks() # (1)!
fig.auto_rangebreaks(freq="D") # (2)!
# ______________________________________________________________
vbt.settings.plotting.auto_rangebreaks = True
vbt.settings.plotting.auto_rangebreaks = dict(freq="D")
# ______________________________________________________________
def pre_show_func(fig):
fig.auto_rangebreaks(freq="D")
vbt.settings.plotting.pre_show_func = pre_show_func # (4)!
fig = df.vbt.plot()
fig.show() # (5)!
- Skip gaps based on the recognized frequency of the index
- Skip gaps based on any other frequency. For example, use the daily frequency to skip weekends when the recognized frequency are business days.
- Skip NaN rows, or provide any other index to skip
- Run auto-rangebreaks before showing any figure
- This requires the method
show()to be called
Note
The above approach works only on figures produced by VBT methods.
To display a figure on an interactive HTML page, see Interactive HTML Export.
with open("fig.html", "a") as f:
f.write(fig1.to_html(full_html=False))
f.write(fig2.to_html(full_html=False))
f.write(fig3.to_html(full_html=False))
To display a figure in a separate browser tab, see Renderers.
If a figure takes too much time to display, maybe the amount of data is the problem? If this is the case, plotly-resampler may come to the rescue to resample any (primarily scatter) data on the fly.