freqtrade_origin/freqtrade/optimize/analysis/recursive_helpers.py

118 lines
4.3 KiB
Python
Raw Normal View History

2023-09-04 01:53:04 +00:00
import logging
import time
from pathlib import Path
from typing import Any
2023-09-04 01:53:04 +00:00
from freqtrade.constants import Config
from freqtrade.exceptions import OperationalException
2023-10-01 05:58:46 +00:00
from freqtrade.optimize.analysis.recursive import RecursiveAnalysis
2023-09-04 01:53:04 +00:00
from freqtrade.resolvers import StrategyResolver
from freqtrade.util import print_rich_table
2023-09-04 01:53:04 +00:00
logger = logging.getLogger(__name__)
class RecursiveAnalysisSubFunctions:
@staticmethod
def text_table_recursive_analysis_instances(recursive_instances: list[RecursiveAnalysis]):
2023-09-04 01:53:04 +00:00
startups = recursive_instances[0]._startup_candle
strat_scc = recursive_instances[0]._strat_scc
headers = ["Indicators"]
2023-09-04 01:53:04 +00:00
for candle in startups:
if candle == strat_scc:
headers.append(f"{candle} (from strategy)")
else:
headers.append(str(candle))
2023-09-04 01:53:04 +00:00
data = []
for inst in recursive_instances:
if len(inst.dict_recursive) > 0:
for indicator, values in inst.dict_recursive.items():
2023-09-20 13:43:01 +00:00
temp_data = [indicator]
2023-09-04 01:53:04 +00:00
for candle in startups:
2024-05-12 15:16:55 +00:00
temp_data.append(values.get(int(candle), "-"))
2023-09-04 01:53:04 +00:00
data.append(temp_data)
if len(data) > 0:
print_rich_table(data, headers, summary="Recursive Analysis")
2024-05-12 15:16:55 +00:00
return data
return data
2023-09-04 01:53:04 +00:00
@staticmethod
def calculate_config_overrides(config: Config):
2024-05-12 15:16:55 +00:00
if "timerange" not in config:
2023-09-13 02:58:28 +00:00
# setting a timerange is enforced here
raise OperationalException(
"Please set a timerange. "
2023-09-29 05:17:44 +00:00
"A timerange of 5000 candles are enough for recursive analysis."
2023-09-13 02:58:28 +00:00
)
2024-05-12 15:16:55 +00:00
if config.get("backtest_cache") is None:
config["backtest_cache"] = "none"
elif config["backtest_cache"] != "none":
logger.info(
f"backtest_cache = "
f"{config['backtest_cache']} detected. "
f"Inside recursive-analysis it is enforced to be 'none'. "
f"Changed it to 'none'"
)
config["backtest_cache"] = "none"
2023-09-04 01:53:04 +00:00
return config
@staticmethod
def initialize_single_recursive_analysis(config: Config, strategy_obj: dict[str, Any]):
2023-09-04 01:53:04 +00:00
logger.info(f"Recursive test of {Path(strategy_obj['location']).name} started.")
start = time.perf_counter()
current_instance = RecursiveAnalysis(config, strategy_obj)
current_instance.start()
elapsed = time.perf_counter() - start
2024-05-12 15:16:55 +00:00
logger.info(
f"Checking recursive and indicator-only lookahead bias of indicators "
f"of {Path(strategy_obj['location']).name} "
f"took {elapsed:.0f} seconds."
)
2023-09-04 01:53:04 +00:00
return current_instance
@staticmethod
def start(config: Config):
config = RecursiveAnalysisSubFunctions.calculate_config_overrides(config)
strategy_objs = StrategyResolver.search_all_objects(
2024-05-12 15:16:55 +00:00
config, enum_failed=False, recursive=config.get("recursive_strategy_search", False)
)
2023-09-04 01:53:04 +00:00
RecursiveAnalysis_instances = []
2023-09-28 19:01:37 +00:00
# unify --strategy and --strategy-list to one list
2024-05-12 15:16:55 +00:00
if not (strategy_list := config.get("strategy_list", [])):
if config.get("strategy") is None:
2023-09-04 01:53:04 +00:00
raise OperationalException(
"No Strategy specified. Please specify a strategy via --strategy"
2023-09-04 01:53:04 +00:00
)
2024-05-12 15:16:55 +00:00
strategy_list = [config["strategy"]]
2023-09-04 01:53:04 +00:00
# check if strategies can be properly loaded, only check them if they can be.
for strat in strategy_list:
for strategy_obj in strategy_objs:
2024-05-12 15:16:55 +00:00
if strategy_obj["name"] == strat and strategy_obj not in strategy_list:
2023-09-04 01:53:04 +00:00
RecursiveAnalysis_instances.append(
RecursiveAnalysisSubFunctions.initialize_single_recursive_analysis(
2024-05-12 15:16:55 +00:00
config, strategy_obj
)
)
2023-09-04 01:53:04 +00:00
break
# report the results
if RecursiveAnalysis_instances:
RecursiveAnalysisSubFunctions.text_table_recursive_analysis_instances(
2024-05-12 15:16:55 +00:00
RecursiveAnalysis_instances
)
2023-09-04 01:53:04 +00:00
else:
2024-05-12 15:16:55 +00:00
logger.error(
"There was no strategy specified through --strategy "
"or timeframe was not specified."
)