Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 209ce63

Browse filesBrowse files
committed
BUG: Fix optimization hanging on MS Windows
Fixes #1256
1 parent 68f6478 commit 209ce63
Copy full SHA for 209ce63

4 files changed

+24-6Lines changed: 24 additions & 6 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎backtesting/__init__.py‎

Copy file name to clipboardExpand all lines: backtesting/__init__.py
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,23 @@
6868
from . import lib # noqa: F401
6969
from ._plotting import set_bokeh_output # noqa: F401
7070
from .backtesting import Backtest, Strategy # noqa: F401
71+
72+
73+
# Add overridable backtesting.Pool used for parallel optimization
74+
def Pool(processes=None, initializer=None, initargs=()):
75+
import multiprocessing as mp
76+
if mp.get_start_method() == 'spawn':
77+
import warnings
78+
warnings.warn(
79+
"If you want to use multi-process optimization with "
80+
"`multiprocessing.get_start_method() == 'spawn'` (e.g. on Windows),"
81+
"set `backtesting.Pool = multiprocessing.Pool` (or of the desired context) "
82+
"and hide `bt.optimize()` call behind a `if __name__ == '__main__'` guard. "
83+
"Currently using thread-based paralellism, "
84+
"which might be slightly slower for non-numpy / non-GIL-releasing code. "
85+
"See https://github.com/kernc/backtesting.py/issues/1256",
86+
category=RuntimeWarning, stacklevel=3)
87+
from multiprocessing.dummy import Pool
88+
return Pool(processes, initializer, initargs)
89+
else:
90+
return mp.Pool(processes, initializer, initargs)
Collapse file

‎backtesting/backtesting.py‎

Copy file name to clipboardExpand all lines: backtesting/backtesting.py
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
from __future__ import annotations
1010

11-
import multiprocessing as mp
1211
import sys
1312
import warnings
1413
from abc import ABCMeta, abstractmethod
@@ -1501,9 +1500,9 @@ def _optimize_grid() -> Union[pd.Series, Tuple[pd.Series, pd.Series]]:
15011500
[p.values() for p in param_combos],
15021501
names=next(iter(param_combos)).keys()))
15031502

1504-
with mp.Pool() as pool, \
1503+
from . import Pool
1504+
with Pool() as pool, \
15051505
SharedMemoryManager() as smm:
1506-
15071506
with patch(self, '_data', None):
15081507
bt = copy(self) # bt._data will be reassigned in _mp_task worker
15091508
results = _tqdm(
Collapse file

‎backtesting/lib.py‎

Copy file name to clipboardExpand all lines: backtesting/lib.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
from __future__ import annotations
1515

16-
import multiprocessing as mp
1716
import warnings
1817
from collections import OrderedDict
1918
from inspect import currentframe
@@ -569,7 +568,8 @@ def run(self, **kwargs):
569568
Wraps `backtesting.backtesting.Backtest.run`. Returns `pd.DataFrame` with
570569
currency indexes in columns.
571570
"""
572-
with mp.Pool() as pool, \
571+
from . import Pool
572+
with Pool() as pool, \
573573
SharedMemoryManager() as smm:
574574
shm = [smm.df2shm(df) for df in self._dfs]
575575
results = _tqdm(
Collapse file

‎backtesting/test/_test.py‎

Copy file name to clipboardExpand all lines: backtesting/test/_test.py
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,6 @@ def test_indicators_picklable(self):
10011001
class TestDocs(TestCase):
10021002
DOCS_DIR = os.path.join(os.path.dirname(__file__), '..', '..', 'doc')
10031003

1004-
@unittest.skipIf('win' in sys.platform, "Locks up with `ModuleNotFoundError: No module named '<run_path>'`")
10051004
@unittest.skipUnless(os.path.isdir(DOCS_DIR), "docs dir doesn't exist")
10061005
def test_examples(self):
10071006
examples = glob(os.path.join(self.DOCS_DIR, 'examples', '*.py'))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.