Skip to content

Commit 17131a3

Browse files
committed
BUG: Fix bt.plot(resample=True) with categorical indicators
Fixes #309
1 parent 8b88e81 commit 17131a3

File tree

2 files changed

+17
-5
lines changed

2 files changed

+17
-5
lines changed

backtesting/_plotting.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
from bokeh.palettes import Category10
4141
from bokeh.transform import factor_cmap
4242

43-
from backtesting._util import _data_period, _as_list, _Indicator
43+
from backtesting._util import _data_period, _as_list, _Indicator, try_
4444

4545
with open(os.path.join(os.path.dirname(__file__), 'autoscale_cb.js'),
4646
encoding='utf-8') as _f:
@@ -128,8 +128,15 @@ def _maybe_resample_data(resample_rule, df, indicators, equity_data, trades):
128128
from .lib import OHLCV_AGG, TRADES_AGG, _EQUITY_AGG
129129
df = df.resample(freq, label='right').agg(OHLCV_AGG).dropna()
130130

131-
indicators = [_Indicator(i.df.resample(freq, label='right').mean()
132-
.dropna().reindex(df.index).values.T,
131+
def try_mean_first(indicator):
132+
nonlocal freq
133+
resampled = indicator.df.fillna(np.nan).resample(freq, label='right')
134+
try:
135+
return resampled.mean()
136+
except Exception:
137+
return resampled.first()
138+
139+
indicators = [_Indicator(try_mean_first(i).dropna().reindex(df.index).values.T,
133140
**dict(i._opts, name=i.name,
134141
# Replace saved index with the resampled one
135142
index=df.index))
@@ -586,7 +593,7 @@ def __eq__(self, other):
586593
legend_label=legend_labels[j], line_color=color,
587594
line_width=1.3)
588595
# Add dashed centerline just because
589-
mean = float(pd.Series(arr).mean())
596+
mean = try_(lambda: float(pd.Series(arr).mean()), default=np.nan)
590597
if not np.isnan(mean) and (abs(mean) < .1 or
591598
round(abs(mean), 1) == .5 or
592599
round(abs(mean), -1) in (50, 100, 200)):

backtesting/test/_test.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,12 @@ def next(self):
767767
time.sleep(1)
768768

769769
def test_resample(self):
770-
bt = Backtest(GOOG, SmaCross)
770+
class S(SmaCross):
771+
def init(self):
772+
self.I(lambda: ['x'] * len(self.data)) # categorical indicator, GH-309
773+
super().init()
774+
775+
bt = Backtest(GOOG, S)
771776
bt.run()
772777
import backtesting._plotting
773778
with _tempfile() as f, \

0 commit comments

Comments
 (0)