2019-05-25 18:00:31 +00:00
|
|
|
import logging
|
|
|
|
from typing import Any, Dict
|
|
|
|
|
2019-12-30 14:02:17 +00:00
|
|
|
from freqtrade import constants
|
2020-01-26 12:55:48 +00:00
|
|
|
from freqtrade.configuration import setup_utils_configuration
|
2021-06-08 19:20:35 +00:00
|
|
|
from freqtrade.enums import RunMode
|
2021-02-12 19:20:32 +00:00
|
|
|
from freqtrade.exceptions import OperationalException
|
2024-01-06 15:02:47 +00:00
|
|
|
from freqtrade.util import fmt_coin
|
2019-06-16 18:37:43 +00:00
|
|
|
|
2020-09-28 17:39:41 +00:00
|
|
|
|
2019-05-25 18:00:31 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2020-01-26 12:32:52 +00:00
|
|
|
def setup_optimize_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]:
|
2019-05-25 18:00:31 +00:00
|
|
|
"""
|
|
|
|
Prepare the configuration for the Hyperopt module
|
|
|
|
:param args: Cli args from Arguments()
|
2021-06-25 17:13:31 +00:00
|
|
|
:param method: Bot running mode
|
2019-05-25 18:00:31 +00:00
|
|
|
:return: Configuration
|
|
|
|
"""
|
2019-06-16 18:37:43 +00:00
|
|
|
config = setup_utils_configuration(args, method)
|
2019-05-25 18:00:31 +00:00
|
|
|
|
2020-03-10 09:02:23 +00:00
|
|
|
no_unlimited_runmodes = {
|
|
|
|
RunMode.BACKTEST: 'backtesting',
|
|
|
|
RunMode.HYPEROPT: 'hyperoptimization',
|
|
|
|
}
|
2021-02-26 18:48:06 +00:00
|
|
|
if method in no_unlimited_runmodes.keys():
|
2022-03-01 18:46:13 +00:00
|
|
|
wallet_size = config['dry_run_wallet'] * config['tradable_balance_ratio']
|
|
|
|
# tradable_balance_ratio
|
2021-02-26 18:48:06 +00:00
|
|
|
if (config['stake_amount'] != constants.UNLIMITED_STAKE_AMOUNT
|
2022-03-01 18:46:13 +00:00
|
|
|
and config['stake_amount'] > wallet_size):
|
2024-01-06 15:02:47 +00:00
|
|
|
wallet = fmt_coin(wallet_size, config['stake_currency'])
|
|
|
|
stake = fmt_coin(config['stake_amount'], config['stake_currency'])
|
2022-03-01 18:46:13 +00:00
|
|
|
raise OperationalException(
|
|
|
|
f"Starting balance ({wallet}) is smaller than stake_amount {stake}. "
|
|
|
|
f"Wallet is calculated as `dry_run_wallet * tradable_balance_ratio`."
|
|
|
|
)
|
2019-05-25 18:00:31 +00:00
|
|
|
|
|
|
|
return config
|
|
|
|
|
|
|
|
|
2019-09-12 18:16:39 +00:00
|
|
|
def start_backtesting(args: Dict[str, Any]) -> None:
|
2019-05-25 18:00:31 +00:00
|
|
|
"""
|
|
|
|
Start Backtesting script
|
|
|
|
:param args: Cli args from Arguments()
|
|
|
|
:return: None
|
|
|
|
"""
|
|
|
|
# Import here to avoid loading backtesting module when it's not used
|
|
|
|
from freqtrade.optimize.backtesting import Backtesting
|
|
|
|
|
|
|
|
# Initialize configuration
|
2020-01-26 12:32:52 +00:00
|
|
|
config = setup_optimize_configuration(args, RunMode.BACKTEST)
|
2019-05-25 18:00:31 +00:00
|
|
|
|
|
|
|
logger.info('Starting freqtrade in Backtesting mode')
|
|
|
|
|
|
|
|
# Initialize backtesting object
|
|
|
|
backtesting = Backtesting(config)
|
|
|
|
backtesting.start()
|
|
|
|
|
2021-10-30 08:50:40 +00:00
|
|
|
|
2021-10-31 08:55:19 +00:00
|
|
|
def start_backtesting_show(args: Dict[str, Any]) -> None:
|
2021-06-17 18:35:02 +00:00
|
|
|
"""
|
2021-10-30 08:50:40 +00:00
|
|
|
Show previous backtest result
|
2021-06-17 18:35:02 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
|
|
|
|
|
2021-10-30 15:05:12 +00:00
|
|
|
from freqtrade.data.btanalysis import load_backtest_stats
|
2021-10-31 08:55:19 +00:00
|
|
|
from freqtrade.optimize.optimize_reports import show_backtest_results, show_sorted_pairlist
|
2021-10-30 15:05:12 +00:00
|
|
|
|
2021-10-30 08:50:40 +00:00
|
|
|
results = load_backtest_stats(config['exportfilename'])
|
2021-06-17 18:35:02 +00:00
|
|
|
|
2021-10-30 08:50:40 +00:00
|
|
|
show_backtest_results(config, results)
|
2021-10-30 15:05:12 +00:00
|
|
|
show_sorted_pairlist(config, results)
|
2021-06-17 18:35:02 +00:00
|
|
|
|
2019-05-25 18:00:31 +00:00
|
|
|
|
2019-09-12 18:16:39 +00:00
|
|
|
def start_hyperopt(args: Dict[str, Any]) -> None:
|
2019-05-25 18:00:31 +00:00
|
|
|
"""
|
|
|
|
Start hyperopt script
|
|
|
|
:param args: Cli args from Arguments()
|
|
|
|
:return: None
|
|
|
|
"""
|
|
|
|
# Import here to avoid loading hyperopt module when it's not used
|
2019-09-24 12:39:28 +00:00
|
|
|
try:
|
|
|
|
from filelock import FileLock, Timeout
|
2020-09-28 17:39:41 +00:00
|
|
|
|
2019-09-24 12:39:28 +00:00
|
|
|
from freqtrade.optimize.hyperopt import Hyperopt
|
|
|
|
except ImportError as e:
|
|
|
|
raise OperationalException(
|
|
|
|
f"{e}. Please ensure that the hyperopt dependencies are installed.") from e
|
2019-05-25 18:00:31 +00:00
|
|
|
# Initialize configuration
|
2020-01-26 12:32:52 +00:00
|
|
|
config = setup_optimize_configuration(args, RunMode.HYPEROPT)
|
2019-05-25 18:00:31 +00:00
|
|
|
|
|
|
|
logger.info('Starting freqtrade in Hyperopt mode')
|
|
|
|
|
2019-07-21 14:07:06 +00:00
|
|
|
lock = FileLock(Hyperopt.get_lock_filename(config))
|
2019-05-25 18:00:31 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
with lock.acquire(timeout=1):
|
|
|
|
|
|
|
|
# Remove noisy log messages
|
|
|
|
logging.getLogger('hyperopt.tpe').setLevel(logging.WARNING)
|
|
|
|
logging.getLogger('filelock').setLevel(logging.WARNING)
|
|
|
|
|
|
|
|
# Initialize backtesting object
|
|
|
|
hyperopt = Hyperopt(config)
|
|
|
|
hyperopt.start()
|
|
|
|
|
|
|
|
except Timeout:
|
|
|
|
logger.info("Another running instance of freqtrade Hyperopt detected.")
|
|
|
|
logger.info("Simultaneous execution of multiple Hyperopt commands is not supported. "
|
2019-11-13 08:38:06 +00:00
|
|
|
"Hyperopt module is resource hungry. Please run your Hyperopt sequentially "
|
2019-05-25 18:00:31 +00:00
|
|
|
"or on separate machines.")
|
|
|
|
logger.info("Quitting now.")
|
|
|
|
# TODO: return False here in order to help freqtrade to exit
|
|
|
|
# with non-zero exit code...
|
|
|
|
# Same in Edge and Backtesting start() functions.
|
2019-05-25 18:05:19 +00:00
|
|
|
|
|
|
|
|
2019-09-12 18:16:39 +00:00
|
|
|
def start_edge(args: Dict[str, Any]) -> None:
|
2019-05-25 18:05:19 +00:00
|
|
|
"""
|
|
|
|
Start Edge script
|
|
|
|
:param args: Cli args from Arguments()
|
|
|
|
:return: None
|
|
|
|
"""
|
|
|
|
from freqtrade.optimize.edge_cli import EdgeCli
|
2020-09-28 17:39:41 +00:00
|
|
|
|
2019-05-25 18:05:19 +00:00
|
|
|
# Initialize configuration
|
2020-01-26 12:32:52 +00:00
|
|
|
config = setup_optimize_configuration(args, RunMode.EDGE)
|
2019-05-25 18:05:19 +00:00
|
|
|
logger.info('Starting freqtrade in Edge mode')
|
|
|
|
|
|
|
|
# Initialize Edge object
|
|
|
|
edge_cli = EdgeCli(config)
|
|
|
|
edge_cli.start()
|
2023-05-06 19:56:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
def start_lookahead_analysis(args: Dict[str, Any]) -> None:
|
|
|
|
"""
|
|
|
|
Start the backtest bias tester script
|
|
|
|
:param args: Cli args from Arguments()
|
|
|
|
:return: None
|
|
|
|
"""
|
2023-10-01 05:58:46 +00:00
|
|
|
from freqtrade.optimize.analysis.lookahead_helpers import LookaheadAnalysisSubFunctions
|
2023-05-20 09:28:52 +00:00
|
|
|
|
2023-05-06 19:56:11 +00:00
|
|
|
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
|
2023-05-20 09:45:06 +00:00
|
|
|
LookaheadAnalysisSubFunctions.start(config)
|
2023-09-04 01:53:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
def start_recursive_analysis(args: Dict[str, Any]) -> None:
|
|
|
|
"""
|
|
|
|
Start the backtest recursive tester script
|
|
|
|
:param args: Cli args from Arguments()
|
|
|
|
:return: None
|
|
|
|
"""
|
2023-10-01 05:58:46 +00:00
|
|
|
from freqtrade.optimize.analysis.recursive_helpers import RecursiveAnalysisSubFunctions
|
2023-09-04 01:53:04 +00:00
|
|
|
|
|
|
|
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
|
|
|
|
RecursiveAnalysisSubFunctions.start(config)
|