Skip to content

Commit 17e9489

Browse files
committed
ENH: Add Backtest.plot(plot_return=), akin to plot_equity=
Fixes #178
1 parent 09e631a commit 17e9489

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

backtesting/_plotting.py

+16-8
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def plot(*, results: pd.Series,
147147
df: pd.DataFrame,
148148
indicators: List[_Indicator],
149149
filename='', plot_width=None,
150-
plot_equity=True, plot_pl=True,
150+
plot_equity=True, plot_return=False, plot_pl=True,
151151
plot_volume=True, plot_drawdown=False,
152152
smooth_equity=False, relative_equity=True,
153153
superimpose=True, resample=True,
@@ -172,6 +172,7 @@ def plot(*, results: pd.Series,
172172

173173
plot_volume = plot_volume and not df.Volume.isnull().all()
174174
plot_equity = plot_equity and not trades.empty
175+
plot_return = plot_return and not trades.empty
175176
plot_pl = plot_pl and not trades.empty
176177
is_datetime_index = df.index.is_all_dates
177178

@@ -274,7 +275,7 @@ def set_tooltips(fig, tooltips=(), vline=True, renderers=()):
274275
renderers=renderers, formatters=formatters,
275276
tooltips=tooltips, mode='vline' if vline else 'mouse'))
276277

277-
def _plot_equity_section():
278+
def _plot_equity_section(is_return=False):
278279
"""Equity section"""
279280
# Max DD Dur. line
280281
equity = equity_data['Equity'].copy()
@@ -307,10 +308,14 @@ def _plot_equity_section():
307308

308309
if relative_equity:
309310
equity /= equity.iloc[0]
311+
if is_return:
312+
equity -= equity.iloc[0]
310313

311-
source.add(equity, 'equity')
314+
yaxis_label = 'Return' if is_return else 'Equity'
315+
source_key = 'eq_return' if is_return else 'equity'
316+
source.add(equity, source_key)
312317
fig = new_indicator_figure(
313-
y_axis_label="Equity",
318+
y_axis_label=yaxis_label,
314319
**({} if plot_drawdown else dict(plot_height=110)))
315320

316321
# High-watermark drawdown dents
@@ -322,16 +327,16 @@ def _plot_equity_section():
322327
fill_color='#ffffea', line_color='#ffcb66')
323328

324329
# Equity line
325-
r = fig.line('index', 'equity', source=source, line_width=1.5, line_alpha=1)
330+
r = fig.line('index', source_key, source=source, line_width=1.5, line_alpha=1)
326331
if relative_equity:
327-
tooltip_format = '@equity{+0,0.[000]%}'
332+
tooltip_format = f'@{source_key}{{+0,0.[000]%}}'
328333
tick_format = '0,0.[00]%'
329334
legend_format = '{:,.0f}%'
330335
else:
331-
tooltip_format = '@equity{$ 0,0}'
336+
tooltip_format = f'@{source_key}{{$ 0,0}}'
332337
tick_format = '$ 0.0 a'
333338
legend_format = '${:,.0f}'
334-
set_tooltips(fig, [('Equity', tooltip_format)], renderers=[r])
339+
set_tooltips(fig, [(yaxis_label, tooltip_format)], renderers=[r])
335340
fig.yaxis.formatter = NumeralTickFormatter(format=tick_format)
336341

337342
# Peaks
@@ -569,6 +574,9 @@ def __eq__(self, other):
569574
if plot_equity:
570575
_plot_equity_section()
571576

577+
if plot_return:
578+
_plot_equity_section(is_return=True)
579+
572580
if plot_drawdown:
573581
figs_above_ohlc.append(_plot_drawdown_section())
574582

backtesting/backtesting.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ def __repr__(self):
14591459
return super().__repr__()
14601460

14611461
def plot(self, *, results: pd.Series = None, filename=None, plot_width=None,
1462-
plot_equity=True, plot_pl=True,
1462+
plot_equity=True, plot_return=False, plot_pl=True,
14631463
plot_volume=True, plot_drawdown=False,
14641464
smooth_equity=False, relative_equity=True,
14651465
superimpose: Union[bool, str] = True,
@@ -1483,7 +1483,12 @@ def plot(self, *, results: pd.Series = None, filename=None, plot_width=None,
14831483
currently non-adjustable.
14841484
14851485
If `plot_equity` is `True`, the resulting plot will contain
1486-
an equity (cash plus assets) graph section.
1486+
an equity (initial cash plus assets) graph section. This is the same
1487+
as `plot_return` plus initial 100%.
1488+
1489+
If `plot_return` is `True`, the resulting plot will contain
1490+
a cumulative return graph section. This is the same
1491+
as `plot_equity` minus initial 100%.
14871492
14881493
If `plot_pl` is `True`, the resulting plot will contain
14891494
a profit/loss (P/L) indicator section.
@@ -1548,6 +1553,7 @@ def plot(self, *, results: pd.Series = None, filename=None, plot_width=None,
15481553
filename=filename,
15491554
plot_width=plot_width,
15501555
plot_equity=plot_equity,
1556+
plot_return=plot_return,
15511557
plot_pl=plot_pl,
15521558
plot_volume=plot_volume,
15531559
plot_drawdown=plot_drawdown,

backtesting/test/_test.py

+1
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,7 @@ def test_params(self):
563563
with _tempfile() as f:
564564
for p in dict(plot_volume=False,
565565
plot_equity=False,
566+
plot_return=True,
566567
plot_pl=False,
567568
plot_drawdown=True,
568569
superimpose=False,

0 commit comments

Comments
 (0)