From ab55fb21ae2570190613c477fc8b50bf205f8df0 Mon Sep 17 00:00:00 2001 From: Nazim Date: Sat, 20 Mar 2021 02:07:08 -0400 Subject: [PATCH 01/11] ENH: Add tqdm to skopt --- backtesting/backtesting.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index d4535f44..3cb011ae 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -39,6 +39,18 @@ def _tqdm(seq, **_): } +class SkoptProgressBar: + """ + Progress bar using tqdm for scikit-optimize + Open feature request: https://github.com/scikit-optimize/scikit-optimize/issues/674 + """ + def __init__(self, **kwargs): + self._tqdm = _tqdm(**kwargs) + + def __call__(self, result): + self._tqdm.update() + + class Strategy(metaclass=ABCMeta): """ A trading strategy base class. Extend this class and @@ -1446,7 +1458,7 @@ def objective_function(**params): kappa=3, n_initial_points=min(max_tries, 20 + 3 * len(kwargs)), initial_point_generator='lhs', # 'sobel' requires n_initial_points ~ 2**N - callback=DeltaXStopper(9e-7), + callback=[DeltaXStopper(9e-7), SkoptProgressBar(desc="Sequential optimisation using decision trees.")], random_state=random_state) stats = self.run(**dict(zip(kwargs.keys(), res.x))) From b190520bc369b42115e70fb4c23fc52682a3c471 Mon Sep 17 00:00:00 2001 From: Nazim Date: Sat, 20 Mar 2021 02:15:26 -0400 Subject: [PATCH 02/11] MNT: Format long line --- backtesting/backtesting.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 3cb011ae..8dcfd8ff 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1458,7 +1458,10 @@ def objective_function(**params): kappa=3, n_initial_points=min(max_tries, 20 + 3 * len(kwargs)), initial_point_generator='lhs', # 'sobel' requires n_initial_points ~ 2**N - callback=[DeltaXStopper(9e-7), SkoptProgressBar(desc="Sequential optimisation using decision trees.")], + callback=[ + DeltaXStopper(9e-7), + SkoptProgressBar(desc="Sequential optimisation using decision trees.") + ], random_state=random_state) stats = self.run(**dict(zip(kwargs.keys(), res.x))) From 093b5c7a7011d0f1b0fb7c74dce60ea7d6728e37 Mon Sep 17 00:00:00 2001 From: Nazim Date: Sat, 20 Mar 2021 14:17:07 -0400 Subject: [PATCH 03/11] ENH: Pass max_tries as total len, update desc wording --- backtesting/backtesting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 8dcfd8ff..7b096d40 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1460,7 +1460,7 @@ def objective_function(**params): initial_point_generator='lhs', # 'sobel' requires n_initial_points ~ 2**N callback=[ DeltaXStopper(9e-7), - SkoptProgressBar(desc="Sequential optimisation using decision trees.") + SkoptProgressBar(total=max_tries, desc="Skopt optimizations") ], random_state=random_state) From 5a5851f284703022b9a581bd0924da9a45213dbc Mon Sep 17 00:00:00 2001 From: Nazim Date: Sun, 21 Mar 2021 12:36:00 -0400 Subject: [PATCH 04/11] ENH: Replace skopt class with variable --- backtesting/backtesting.py | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 7b096d40..4b56f3f3 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -39,18 +39,6 @@ def _tqdm(seq, **_): } -class SkoptProgressBar: - """ - Progress bar using tqdm for scikit-optimize - Open feature request: https://github.com/scikit-optimize/scikit-optimize/issues/674 - """ - def __init__(self, **kwargs): - self._tqdm = _tqdm(**kwargs) - - def __call__(self, result): - self._tqdm.update() - - class Strategy(metaclass=ABCMeta): """ A trading strategy base class. Extend this class and @@ -1432,9 +1420,11 @@ def _optimize_skopt() -> Union[pd.Series, # np.inf/np.nan breaks sklearn, np.finfo(float).max breaks skopt.plots.plot_objective INVALID = 1e300 + skopt_pbar = _tqdm(total=max_tries, desc="Skopt optimizations") @use_named_args(dimensions=dimensions) def objective_function(**params): + skopt_pbar.update(1) # Check constraints # TODO: Adjust after https://github.com/scikit-optimize/scikit-optimize/pull/971 if not constraint(AttrDict(params)): @@ -1458,10 +1448,7 @@ def objective_function(**params): kappa=3, n_initial_points=min(max_tries, 20 + 3 * len(kwargs)), initial_point_generator='lhs', # 'sobel' requires n_initial_points ~ 2**N - callback=[ - DeltaXStopper(9e-7), - SkoptProgressBar(total=max_tries, desc="Skopt optimizations") - ], + callback=[DeltaXStopper(9e-7)], random_state=random_state) stats = self.run(**dict(zip(kwargs.keys(), res.x))) From dc7ee3141bff593c973e72490c8376725d4b5edf Mon Sep 17 00:00:00 2001 From: Nazim Date: Sun, 21 Mar 2021 12:37:51 -0400 Subject: [PATCH 05/11] ENH: Pass single skopt callback directly instead of in a list --- backtesting/backtesting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 4b56f3f3..b0e31a99 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1448,7 +1448,7 @@ def objective_function(**params): kappa=3, n_initial_points=min(max_tries, 20 + 3 * len(kwargs)), initial_point_generator='lhs', # 'sobel' requires n_initial_points ~ 2**N - callback=[DeltaXStopper(9e-7)], + callback=DeltaXStopper(9e-7), random_state=random_state) stats = self.run(**dict(zip(kwargs.keys(), res.x))) From 4fdb3c941361858d04db5168eb0e717c1f0c48e6 Mon Sep 17 00:00:00 2001 From: Nazim Date: Sun, 21 Mar 2021 14:20:52 -0400 Subject: [PATCH 06/11] ENH: Check if tqdm object has update attr --- backtesting/backtesting.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index b0e31a99..d8931031 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1420,11 +1420,12 @@ def _optimize_skopt() -> Union[pd.Series, # np.inf/np.nan breaks sklearn, np.finfo(float).max breaks skopt.plots.plot_objective INVALID = 1e300 - skopt_pbar = _tqdm(total=max_tries, desc="Skopt optimizations") + skopt_pbar = _tqdm(dimensions, total=max_tries, desc="Skopt optimizations") @use_named_args(dimensions=dimensions) def objective_function(**params): - skopt_pbar.update(1) + if hasattr(skopt_pbar, "update"): + skopt_pbar.update(1) # Check constraints # TODO: Adjust after https://github.com/scikit-optimize/scikit-optimize/pull/971 if not constraint(AttrDict(params)): From 0deb7830527cc52539331aa6d45279d839f7fd67 Mon Sep 17 00:00:00 2001 From: crazy25000 Date: Tue, 23 Mar 2021 21:43:17 -0400 Subject: [PATCH 07/11] MNT: Update tqdm description text --- backtesting/backtesting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index d8931031..14e1e3fb 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1352,7 +1352,7 @@ def _batch(seq): with ProcessPoolExecutor() as executor: futures = [executor.submit(Backtest._mp_task, backtest_uuid, i) for i in range(len(param_batches))] - for future in _tqdm(as_completed(futures), total=len(futures)): + for future in _tqdm(as_completed(futures), total=len(futures), description="Backtest.grid"): batch_index, values = future.result() for value, params in zip(values, param_batches[batch_index]): heatmap[tuple(params.values())] = value @@ -1420,7 +1420,7 @@ def _optimize_skopt() -> Union[pd.Series, # np.inf/np.nan breaks sklearn, np.finfo(float).max breaks skopt.plots.plot_objective INVALID = 1e300 - skopt_pbar = _tqdm(dimensions, total=max_tries, desc="Skopt optimizations") + skopt_pbar = _tqdm(dimensions, total=max_tries, desc="Backtest.optimize") @use_named_args(dimensions=dimensions) def objective_function(**params): From 547ded58244704aa5712d50bebfecde4bc79298e Mon Sep 17 00:00:00 2001 From: crazy25000 Date: Tue, 23 Mar 2021 21:47:00 -0400 Subject: [PATCH 08/11] FMT: Use single quotes --- backtesting/backtesting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 14e1e3fb..14c442ae 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1352,7 +1352,7 @@ def _batch(seq): with ProcessPoolExecutor() as executor: futures = [executor.submit(Backtest._mp_task, backtest_uuid, i) for i in range(len(param_batches))] - for future in _tqdm(as_completed(futures), total=len(futures), description="Backtest.grid"): + for future in _tqdm(as_completed(futures), total=len(futures), description='Backtest.grid'): batch_index, values = future.result() for value, params in zip(values, param_batches[batch_index]): heatmap[tuple(params.values())] = value @@ -1420,7 +1420,7 @@ def _optimize_skopt() -> Union[pd.Series, # np.inf/np.nan breaks sklearn, np.finfo(float).max breaks skopt.plots.plot_objective INVALID = 1e300 - skopt_pbar = _tqdm(dimensions, total=max_tries, desc="Backtest.optimize") + skopt_pbar = _tqdm(dimensions, total=max_tries, desc='Backtest.optimize') @use_named_args(dimensions=dimensions) def objective_function(**params): From 5c4f0470a279146ca5d34836e5c726d7d1235170 Mon Sep 17 00:00:00 2001 From: Nazim Date: Tue, 23 Mar 2021 21:57:19 -0400 Subject: [PATCH 09/11] MNT: Refactor pbar to use iter --- backtesting/backtesting.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 14c442ae..8b2c8f17 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1352,7 +1352,7 @@ def _batch(seq): with ProcessPoolExecutor() as executor: futures = [executor.submit(Backtest._mp_task, backtest_uuid, i) for i in range(len(param_batches))] - for future in _tqdm(as_completed(futures), total=len(futures), description='Backtest.grid'): + for future in _tqdm(as_completed(futures), total=len(futures), desc='Backtest.grid'): batch_index, values = future.result() for value, params in zip(values, param_batches[batch_index]): heatmap[tuple(params.values())] = value @@ -1420,12 +1420,11 @@ def _optimize_skopt() -> Union[pd.Series, # np.inf/np.nan breaks sklearn, np.finfo(float).max breaks skopt.plots.plot_objective INVALID = 1e300 - skopt_pbar = _tqdm(dimensions, total=max_tries, desc='Backtest.optimize') + progress = iter(_tqdm(repeat(None), total=max_tries, desc='Backtest.optimize')) @use_named_args(dimensions=dimensions) def objective_function(**params): - if hasattr(skopt_pbar, "update"): - skopt_pbar.update(1) + next(progress) # Check constraints # TODO: Adjust after https://github.com/scikit-optimize/scikit-optimize/pull/971 if not constraint(AttrDict(params)): From 23029be6b23676f07d034261799144723fd90172 Mon Sep 17 00:00:00 2001 From: Nazim Date: Tue, 23 Mar 2021 22:03:59 -0400 Subject: [PATCH 10/11] MNT: Refactor to meet max line length --- backtesting/backtesting.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 8b2c8f17..726bcbc5 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1352,7 +1352,11 @@ def _batch(seq): with ProcessPoolExecutor() as executor: futures = [executor.submit(Backtest._mp_task, backtest_uuid, i) for i in range(len(param_batches))] - for future in _tqdm(as_completed(futures), total=len(futures), desc='Backtest.grid'): + for future in _tqdm( + as_completed(futures), + total=len(futures), + desc='Backtest.grid' + ): batch_index, values = future.result() for value, params in zip(values, param_batches[batch_index]): heatmap[tuple(params.values())] = value From bfa2e780beb701fd6ddcc17235acf400b5ed4f5a Mon Sep 17 00:00:00 2001 From: Kernc Date: Wed, 31 Mar 2021 21:41:44 +0200 Subject: [PATCH 11/11] bikeshedding --- backtesting/backtesting.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/backtesting/backtesting.py b/backtesting/backtesting.py index 726bcbc5..d8cce8a9 100644 --- a/backtesting/backtesting.py +++ b/backtesting/backtesting.py @@ -1352,11 +1352,8 @@ def _batch(seq): with ProcessPoolExecutor() as executor: futures = [executor.submit(Backtest._mp_task, backtest_uuid, i) for i in range(len(param_batches))] - for future in _tqdm( - as_completed(futures), - total=len(futures), - desc='Backtest.grid' - ): + for future in _tqdm(as_completed(futures), total=len(futures), + desc='Backtest.optimize'): batch_index, values = future.result() for value, params in zip(values, param_batches[batch_index]): heatmap[tuple(params.values())] = value