Skip to content

Commit 3b9a294

Browse files
committed
REF: Plot: Simplify PL section, circle markers
1 parent 533c711 commit 3b9a294

File tree

1 file changed

+11
-18
lines changed

1 file changed

+11
-18
lines changed

backtesting/_plotting.py

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
CrosshairTool,
2424
CustomJS,
2525
ColumnDataSource,
26+
CustomJSTransform,
2627
Label, NumeralTickFormatter,
2728
Span,
2829
HoverTool,
@@ -39,7 +40,7 @@
3940
from bokeh.io.state import curstate
4041
from bokeh.layouts import gridplot
4142
from bokeh.palettes import Category10
42-
from bokeh.transform import factor_cmap
43+
from bokeh.transform import factor_cmap, transform
4344

4445
from backtesting._util import _data_period, _as_list, _Indicator, try_
4546

@@ -258,7 +259,6 @@ def plot(*, results: pd.Series,
258259
trade_source = ColumnDataSource(dict(
259260
index=trades['ExitBar'],
260261
datetime=trades['ExitTime'],
261-
exit_price=trades['ExitPrice'],
262262
size=trades['Size'],
263263
returns_positive=(trades['ReturnPct'] > 0).astype(int).astype(str),
264264
))
@@ -426,31 +426,24 @@ def _plot_pl_section():
426426
"""Profit/Loss markers section"""
427427
fig = new_indicator_figure(y_axis_label="Profit / Loss")
428428
fig.add_layout(Span(location=0, dimension='width', line_color='#666666',
429-
line_dash='dashed', line_width=1))
430-
returns_long = np.where(trades['Size'] > 0, trades['ReturnPct'], np.nan)
431-
returns_short = np.where(trades['Size'] < 0, trades['ReturnPct'], np.nan)
429+
line_dash='dashed', level='underlay', line_width=1))
430+
trade_source.add(trades['ReturnPct'], 'returns')
432431
size = trades['Size'].abs()
433432
size = np.interp(size, (size.min(), size.max()), (8, 20))
434-
trade_source.add(returns_long, 'returns_long')
435-
trade_source.add(returns_short, 'returns_short')
436433
trade_source.add(size, 'marker_size')
437434
if 'count' in trades:
438435
trade_source.add(trades['count'], 'count')
439436
trade_source.add(trades[['EntryBar', 'ExitBar']].values.tolist(), 'lines')
440-
trade_source.add([[0, r] for r in trades['ReturnPct'].values], 'returns_both')
441-
fig.multi_line(xs='lines', ys='returns_both',
442-
source=trade_source, color='#bbb', line_width=1)
443-
r1 = fig.scatter('index', 'returns_long', source=trade_source, fill_color=cmap,
444-
marker='triangle', line_color='black', size='marker_size')
445-
r2 = fig.scatter('index', 'returns_short', source=trade_source, fill_color=cmap,
446-
marker='inverted_triangle', line_color='black', size='marker_size')
437+
fig.multi_line(xs='lines',
438+
ys=transform('returns', CustomJSTransform(v_func='return [...xs].map(i => [0, i]);')),
439+
source=trade_source, color='#999', line_width=1)
440+
r1 = fig.scatter('index', 'returns', source=trade_source, fill_color=cmap,
441+
marker='circle', line_color='black', size='marker_size')
447442
tooltips = [("Size", "@size{0,0}")]
448443
if 'count' in trades:
449444
tooltips.append(("Count", "@count{0,0}"))
450-
set_tooltips(fig, tooltips + [("P/L", "@returns_long{+0.[000]%}")],
445+
set_tooltips(fig, tooltips + [("P/L", "@returns{+0.[000]%}")],
451446
vline=False, renderers=[r1])
452-
set_tooltips(fig, tooltips + [("P/L", "@returns_short{+0.[000]%}")],
453-
vline=False, renderers=[r2])
454447
fig.yaxis.formatter = NumeralTickFormatter(format="0.[00]%")
455448
return fig
456449

@@ -619,7 +612,7 @@ def __eq__(self, other):
619612
round(abs(mean), -1) in (50, 100, 200)):
620613
fig.add_layout(Span(location=float(mean), dimension='width',
621614
line_color='#666666', line_dash='dashed',
622-
line_width=.5))
615+
level='underlay', line_width=.5))
623616
if is_overlay:
624617
ohlc_tooltips.append((tooltip_label, NBSP.join(tooltips)))
625618
else:

0 commit comments

Comments
 (0)