diff --git a/backtesting/_util.py b/backtesting/_util.py index a76a3ee2..408d764f 100644 --- a/backtesting/_util.py +++ b/backtesting/_util.py @@ -309,7 +309,9 @@ def __exit__(self, *args, **kwargs): def arr2shm(self, vals): """Array to shared memory. Returns (shm_name, shape, dtype) used for restore.""" assert vals.ndim == 1, (vals.ndim, vals.shape, vals) - shm = self.SharedMemory(size=vals.nbytes, create=True) + # Not `vals.nbytes`; lazy indexes (e.g. RangeIndex) report their own, + # constant size rather than that of the array they materialize into + shm = self.SharedMemory(size=vals.size * vals.dtype.base.itemsize, create=True) # np.array can't handle pandas' tz-aware datetimes # https://github.com/numpy/numpy/issues/18279 buf = np.ndarray(vals.shape, dtype=vals.dtype.base, buffer=shm.buf) diff --git a/backtesting/test/_test.py b/backtesting/test/_test.py index 7a6e5d1d..d74fde9f 100644 --- a/backtesting/test/_test.py +++ b/backtesting/test/_test.py @@ -1273,6 +1273,16 @@ def test_optimize_datetime_index_with_timezone(self): res = Backtest(data, SmaCross).optimize(fast=range(2, 3), slow=range(4, 5)) self.assertGreater(res['# Trades'], 0) + def test_optimize_range_index(self): + # Data is passed to the workers through shared memory sized by + # `.nbytes`, which a lazy RangeIndex under-reports, previously raising + # "TypeError: buffer is too small for requested array". See GH issue #1237. + data: pd.DataFrame = GOOG.iloc[:100].reset_index(drop=True) + with self.assertWarnsRegex(UserWarning, 'index is not datetime'): + bt = Backtest(data, SmaCross) + res = bt.optimize(fast=range(2, 3), slow=range(4, 5)) + self.assertGreater(res['# Trades'], 0) + def test_sl_tp_values_in_trades_df(self): class S(_S): def next(self):