Add --analyze-per-epoch - moving populate_analysis to the epoch process
This commit is contained in:
parent
09f8904545
commit
bc359675a2
@ -40,7 +40,8 @@ pip install -r requirements-hyperopt.txt
|
||||
```
|
||||
usage: freqtrade hyperopt [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH]
|
||||
[--userdir PATH] [-s NAME] [--strategy-path PATH]
|
||||
[--recursive-strategy-search] [-i TIMEFRAME]
|
||||
[--recursive-strategy-search] [--freqaimodel NAME]
|
||||
[--freqaimodel-path PATH] [-i TIMEFRAME]
|
||||
[--timerange TIMERANGE]
|
||||
[--data-format-ohlcv {json,jsongz,hdf5}]
|
||||
[--max-open-trades INT]
|
||||
@ -53,7 +54,7 @@ usage: freqtrade hyperopt [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH]
|
||||
[--print-all] [--no-color] [--print-json] [-j JOBS]
|
||||
[--random-state INT] [--min-trades INT]
|
||||
[--hyperopt-loss NAME] [--disable-param-export]
|
||||
[--ignore-missing-spaces]
|
||||
[--ignore-missing-spaces] [--analyze-per-epoch]
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
@ -129,6 +130,7 @@ optional arguments:
|
||||
--ignore-missing-spaces, --ignore-unparameterized-spaces
|
||||
Suppress errors for any requested Hyperopt spaces that
|
||||
do not contain any parameters.
|
||||
--analyze-per-epoch Run populate_indicators once per epoch.
|
||||
|
||||
Common arguments:
|
||||
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
|
||||
@ -154,6 +156,10 @@ Strategy arguments:
|
||||
--recursive-strategy-search
|
||||
Recursively search for a strategy in the strategies
|
||||
folder.
|
||||
--freqaimodel NAME Specify a custom freqaimodels.
|
||||
--freqaimodel-path PATH
|
||||
Specify additional lookup path for freqaimodels.
|
||||
|
||||
```
|
||||
|
||||
### Hyperopt checklist
|
||||
|
@ -34,7 +34,7 @@ ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path",
|
||||
"print_colorized", "print_json", "hyperopt_jobs",
|
||||
"hyperopt_random_state", "hyperopt_min_trades",
|
||||
"hyperopt_loss", "disableparamexport",
|
||||
"hyperopt_ignore_missing_space"]
|
||||
"hyperopt_ignore_missing_space", "analyze_per_epoch"]
|
||||
|
||||
ARGS_EDGE = ARGS_COMMON_OPTIMIZE + ["stoploss_range"]
|
||||
|
||||
|
@ -255,6 +255,13 @@ AVAILABLE_CLI_OPTIONS = {
|
||||
nargs='+',
|
||||
default='default',
|
||||
),
|
||||
"analyze_per_epoch": Arg(
|
||||
'--analyze-per-epoch',
|
||||
help='Run populate_indicators once per epoch.',
|
||||
action='store_true',
|
||||
default=False,
|
||||
),
|
||||
|
||||
"print_all": Arg(
|
||||
'--print-all',
|
||||
help='Print all results, not only the best ones.',
|
||||
|
@ -302,6 +302,9 @@ class Configuration:
|
||||
self._args_to_config(config, argname='spaces',
|
||||
logstring='Parameter -s/--spaces detected: {}')
|
||||
|
||||
self._args_to_config(config, argname='analyze_per_epoch',
|
||||
logstring='Parameter --analyze-per-epoch detected.')
|
||||
|
||||
self._args_to_config(config, argname='print_all',
|
||||
logstring='Parameter --print-all detected ...')
|
||||
|
||||
|
@ -24,13 +24,15 @@ from pandas import DataFrame
|
||||
from freqtrade.constants import DATETIME_PRINT_FORMAT, FTHYPT_FILEVERSION, LAST_BT_RESULT_FN
|
||||
from freqtrade.data.converter import trim_dataframes
|
||||
from freqtrade.data.history import get_timerange
|
||||
from freqtrade.enums import HyperoptState
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.misc import deep_merge_dicts, file_dump_json, plural
|
||||
from freqtrade.optimize.backtesting import Backtesting
|
||||
# Import IHyperOpt and IHyperOptLoss to allow unpickling classes from these modules
|
||||
from freqtrade.optimize.hyperopt_auto import HyperOptAuto
|
||||
from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss
|
||||
from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer
|
||||
from freqtrade.optimize.hyperopt_tools import (HyperoptStateContainer, HyperoptTools,
|
||||
hyperopt_serializer)
|
||||
from freqtrade.optimize.optimize_reports import generate_strategy_stats
|
||||
from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver
|
||||
|
||||
@ -74,10 +76,14 @@ class Hyperopt:
|
||||
self.dimensions: List[Dimension] = []
|
||||
|
||||
self.config = config
|
||||
self.min_date: datetime
|
||||
self.max_date: datetime
|
||||
|
||||
self.backtesting = Backtesting(self.config)
|
||||
self.pairlist = self.backtesting.pairlists.whitelist
|
||||
self.custom_hyperopt: HyperOptAuto
|
||||
self.analyze_per_epoch = self.config.get('analyze_per_epoch', False)
|
||||
HyperoptStateContainer.set_state(HyperoptState.STARTUP)
|
||||
|
||||
if not self.config.get('hyperopt'):
|
||||
self.custom_hyperopt = HyperOptAuto(self.config)
|
||||
@ -290,6 +296,7 @@ class Hyperopt:
|
||||
Called once per epoch to optimize whatever is configured.
|
||||
Keep this function as optimized as possible!
|
||||
"""
|
||||
HyperoptStateContainer.set_state(HyperoptState.OPTIMIZE)
|
||||
backtest_start_time = datetime.now(timezone.utc)
|
||||
params_dict = self._get_params_dict(self.dimensions, raw_params)
|
||||
|
||||
@ -321,6 +328,10 @@ class Hyperopt:
|
||||
|
||||
with self.data_pickle_file.open('rb') as f:
|
||||
processed = load(f, mmap_mode='r')
|
||||
if self.analyze_per_epoch:
|
||||
# Data is not yet analyzed, rerun populate_indicators.
|
||||
processed = self.advise_and_trim(processed)
|
||||
|
||||
bt_results = self.backtesting.backtest(
|
||||
processed=processed,
|
||||
start_date=self.min_date,
|
||||
@ -415,19 +426,24 @@ class Hyperopt:
|
||||
return processed
|
||||
|
||||
def prepare_hyperopt_data(self) -> None:
|
||||
data, timerange = self.backtesting.load_bt_data()
|
||||
HyperoptStateContainer.set_state(HyperoptState.DATALOAD)
|
||||
data, self.timerange = self.backtesting.load_bt_data()
|
||||
self.backtesting.load_bt_data_detail()
|
||||
logger.info("Dataload complete. Calculating indicators")
|
||||
|
||||
preprocessed = self.backtesting.strategy.advise_all_indicators(data)
|
||||
if not self.analyze_per_epoch:
|
||||
HyperoptStateContainer.set_state(HyperoptState.INDICATORS)
|
||||
|
||||
preprocessed = self.advise_and_trim(data)
|
||||
|
||||
logger.info(f'Hyperopting with data from {self.min_date.strftime(DATETIME_PRINT_FORMAT)} '
|
||||
logger.info(f'Hyperopting with data from '
|
||||
f'{self.min_date.strftime(DATETIME_PRINT_FORMAT)} '
|
||||
f'up to {self.max_date.strftime(DATETIME_PRINT_FORMAT)} '
|
||||
f'({(self.max_date - self.min_date).days} days)..')
|
||||
# Store non-trimmed data - will be trimmed after signal generation.
|
||||
dump(preprocessed, self.data_pickle_file)
|
||||
else:
|
||||
dump(data, self.data_pickle_file)
|
||||
|
||||
def get_asked_points(self, n_points: int) -> Tuple[List[List[Any]], List[bool]]:
|
||||
"""
|
||||
|
@ -7,6 +7,9 @@ from abc import ABC, abstractmethod
|
||||
from contextlib import suppress
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
|
||||
from freqtrade.enums.hyperoptstate import HyperoptState
|
||||
from freqtrade.optimize.hyperopt_tools import HyperoptStateContainer
|
||||
|
||||
|
||||
with suppress(ImportError):
|
||||
from skopt.space import Integer, Real, Categorical
|
||||
@ -61,6 +64,7 @@ class BaseParameter(ABC):
|
||||
return (
|
||||
self.in_space
|
||||
and self.optimize
|
||||
and HyperoptStateContainer.state != HyperoptState.OPTIMIZE
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user