Skip to content
New: Star-import, signal unraveling, Python 3.12 support, and more

#
Plotting

Any Pandas Series or DataFrame can be plotted via an accessor. There are two main pathways for plotting:

1. GenericAccessor offering methods tailored specifically for vectorbtpro-typical workflows, and
2. PXAccessor offering methods parsed from Plotly express.

Various ways to plot a Pandas object

    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)!

1. Create a line plot with visible markers. Each column will become a trace.
2. Create a scatter plot of a variable `x` against another variable `y`. Both must be one-dimensional.
3. Display equity as a line plot
4. Compare Sharpe ratio of various symbols or parameter combinations with a bar plot
5. Create a Q-Q plot to check whether returns are distributed normally. Only one column at a time.
6. Plot allocations as an area plot
7. Create a histogram plot of returns with 100 bins (remove `nbinsx` for auto-binning)
8. Create a box plot of monthly returns
9. Create a heatmap of time (y-axis) against monthly returns (x-axis)
10. Create a heatmap of monthly returns (y-axis) against time (x-axis)
11. 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.
12. 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.
13. For three to four parameters, create a volume plot instead
14. 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.

Set the dark theme

    vbt.settings.set_theme("dark")

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.

Change the color of the upper and lower line of a Bollinger Bands indicator

    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.

Make the width and height of the plot variable rather than fixed

    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.

Create two subplots - one per row

    fig = vbt.make_subplots(rows=2, cols=1)

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.

Plot the first and second DataFrame over the first and second subplot respectively

    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.

Plot the first and second DataFrame on the first and second y-axis respectively

    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.

Retrospectively change the title and the markers of the scatter plot

    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.

Change the background of any figure to black

    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"

Same by registering an own theme

    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.

Skip non-business hours and weekends

    fig = df.vbt.plot()
    fig.update_xaxes(
        rangebreaks=[
            dict(bounds=['sat', 'mon']),
            dict(bounds=[16, 9.5], pattern='hour'),
            # (1)!
        ]
    )

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.

Skip all gaps automatically

    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)!

1. Skip gaps based on the recognized frequency of the index
2. Skip gaps based on any other frequency. For example, use the daily frequency to skip weekends when the recognized frequency are business days.
3. Skip NaN rows, or provide any other index to skip
4. Run auto-rangebreaks before showing any figure
5. 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.

Save the figure to an HTML file

    fig.write_html("fig.html")

Save multiple figures to the same HTML file

    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.

Make browser the default renderer

    import plotly.io as pio
    pio.renderers.default = "browser"

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.

Enable plotly-resampler globally

    vbt.settings.plotting.use_resampler = True

#### Cookie consent

We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.

- Google Analytics
- GitHub

Manage settings