BUG: Avoid multiprocessing trouble on Windos (#6)

* BUG: Avoid BrokenProcessPool error on Windos

* REF: Avoid any multiprocessing exceptions in `Backtest.optimize()`

... and instead switch to non-parallel computation.

* REF: Support parallelism only if start method is 'fork'

* REF: In case of non-'fork' multiprocessing, use a simple loop

* MNT: quiet codecov

* TST: Remove redundant test

The code path is covered by any other Backtest.optimize() test.

* fix flake8 warning
This commit is contained in:
kernc
2019-09-23 02:25:43 +02:00
committed by GitHub
parent 0444313734
commit 2145e0146a
2 changed files with 20 additions and 6 deletions

View File

@@ -1,10 +1,12 @@
comment: off
coverage:
range: 75..95
precision: 0
status:
patch:
default:
target: '95'
target: 90
project:
default:
target: auto
threshold: 5

View File

@@ -5,6 +5,7 @@ module directly, e.g.
from backtesting import Backtest, Strategy
"""
import multiprocessing as mp
import os
import re
import sys
@@ -812,11 +813,22 @@ class Backtest:
for i in range(0, len(seq), n):
yield seq[i:i + n]
with ProcessPoolExecutor() as executor:
futures = [executor.submit(self._mp_task, params)
for params in _batch(param_combos)]
for future in _tqdm(as_completed(futures), total=len(futures)):
for params, stats in future.result():
# If multiprocessing start method is 'fork' (i.e. on POSIX), use
# a pool of processes to compute results in parallel.
# Otherwise (i.e. on Windos), sequential computation will be "faster".
if mp.get_start_method(allow_none=False) == 'fork':
with ProcessPoolExecutor() as executor:
futures = [executor.submit(self._mp_task, params)
for params in _batch(param_combos)]
for future in _tqdm(as_completed(futures), total=len(futures)):
for params, stats in future.result():
heatmap[tuple(params.values())] = maximize(stats)
else:
if os.name == 'posix':
warnings.warn("For multiprocessing support in `Backtest.optimize()` "
"set multiprocessing start method to 'fork'.")
for params in _tqdm(param_combos):
for _, stats in self._mp_task([params]):
heatmap[tuple(params.values())] = maximize(stats)
best_params = heatmap.idxmax()