From 1340b71633b455fee16b88892b179cc54abdbe92 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 25 Dec 2018 14:23:59 +0100 Subject: [PATCH] Add RunMode setting to determine bot state --- freqtrade/configuration.py | 11 ++++++++++- freqtrade/data/dataprovider.py | 10 +++++----- freqtrade/main.py | 4 ++-- freqtrade/optimize/backtesting.py | 3 ++- freqtrade/optimize/edge_cli.py | 5 +++-- freqtrade/optimize/hyperopt.py | 3 ++- freqtrade/state.py | 13 +++++++++++++ freqtrade/tests/data/test_dataprovider.py | 8 +++----- scripts/plot_profit.py | 3 ++- 9 files changed, 42 insertions(+), 18 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 9fd93629f..d972f50b8 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -12,6 +12,7 @@ from jsonschema import Draft4Validator, validate from jsonschema.exceptions import ValidationError, best_match from freqtrade import OperationalException, constants +from freqtrade.state import RunMode logger = logging.getLogger(__name__) @@ -34,9 +35,10 @@ class Configuration(object): Reuse this class for the bot, backtesting, hyperopt and every script that required configuration """ - def __init__(self, args: Namespace) -> None: + def __init__(self, args: Namespace, runmode: RunMode = None) -> None: self.args = args self.config: Optional[Dict[str, Any]] = None + self.runmode = runmode def load_config(self) -> Dict[str, Any]: """ @@ -68,6 +70,13 @@ class Configuration(object): # Load Hyperopt config = self._load_hyperopt_config(config) + # Set runmode + if not self.runmode: + # Handle real mode, infer dry/live from config + self.runmode = RunMode.DRY_RUN if config.get('dry_run', True) else RunMode.LIVE + + config.update({'runmode': self.runmode}) + return config def _load_config_file(self, path: str) -> Dict[str, Any]: diff --git a/freqtrade/data/dataprovider.py b/freqtrade/data/dataprovider.py index 4d819a7d8..5df2f2fd9 100644 --- a/freqtrade/data/dataprovider.py +++ b/freqtrade/data/dataprovider.py @@ -6,12 +6,13 @@ Common Interface for bot and strategy to access data. """ import logging from pathlib import Path -from typing import List, Dict +from typing import List from pandas import DataFrame -from freqtrade.exchange import Exchange from freqtrade.data.history import load_pair_history +from freqtrade.exchange import Exchange +from freqtrade.state import RunMode logger = logging.getLogger(__name__) @@ -66,10 +67,9 @@ class DataProvider(object): pass @property - def runmode(self) -> str: + def runmode(self) -> RunMode: """ Get runmode of the bot can be "live", "dry-run", "backtest", "edgecli", "hyperopt". """ - # TODO: this needs to be set somewhere ... - return str(self._config.get('runmode')) + return self._config.get('runmode') diff --git a/freqtrade/main.py b/freqtrade/main.py index f27145b45..75b15915b 100755 --- a/freqtrade/main.py +++ b/freqtrade/main.py @@ -39,7 +39,7 @@ def main(sysargv: List[str]) -> None: return_code = 1 try: # Load and validate configuration - config = Configuration(args).get_config() + config = Configuration(args, None).get_config() # Init the bot freqtrade = FreqtradeBot(config) @@ -76,7 +76,7 @@ def reconfigure(freqtrade: FreqtradeBot, args: Namespace) -> FreqtradeBot: freqtrade.cleanup() # Create new instance - freqtrade = FreqtradeBot(Configuration(args).get_config()) + freqtrade = FreqtradeBot(Configuration(args, None).get_config()) freqtrade.rpc.send_msg({ 'type': RPCMessageType.STATUS_NOTIFICATION, 'status': 'config reloaded' diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 38bbe13d4..88ad4cc60 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -22,6 +22,7 @@ from freqtrade.data import history from freqtrade.misc import file_dump_json from freqtrade.persistence import Trade from freqtrade.resolvers import StrategyResolver +from freqtrade.state import RunMode from freqtrade.strategy.interface import SellType, IStrategy logger = logging.getLogger(__name__) @@ -452,7 +453,7 @@ def setup_configuration(args: Namespace) -> Dict[str, Any]: :param args: Cli args from Arguments() :return: Configuration """ - configuration = Configuration(args) + configuration = Configuration(args, RunMode.BACKTEST) config = configuration.get_config() # Ensure we do not use Exchange credentials diff --git a/freqtrade/optimize/edge_cli.py b/freqtrade/optimize/edge_cli.py index fdae47b99..9b628cf2e 100644 --- a/freqtrade/optimize/edge_cli.py +++ b/freqtrade/optimize/edge_cli.py @@ -9,10 +9,11 @@ from typing import Dict, Any from tabulate import tabulate from freqtrade.edge import Edge -from freqtrade.configuration import Configuration from freqtrade.arguments import Arguments +from freqtrade.configuration import Configuration from freqtrade.exchange import Exchange from freqtrade.resolvers import StrategyResolver +from freqtrade.state import RunMode logger = logging.getLogger(__name__) @@ -83,7 +84,7 @@ def setup_configuration(args: Namespace) -> Dict[str, Any]: :param args: Cli args from Arguments() :return: Configuration """ - configuration = Configuration(args) + configuration = Configuration(args, RunMode.EDGECLI) config = configuration.get_config() # Ensure we do not use Exchange credentials diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 6930bed04..f6d39f11c 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -25,6 +25,7 @@ from freqtrade.configuration import Configuration from freqtrade.data.history import load_data from freqtrade.optimize import get_timeframe from freqtrade.optimize.backtesting import Backtesting +from freqtrade.state import RunMode from freqtrade.resolvers import HyperOptResolver logger = logging.getLogger(__name__) @@ -306,7 +307,7 @@ def start(args: Namespace) -> None: # Initialize configuration # Monkey patch the configuration with hyperopt_conf.py - configuration = Configuration(args) + configuration = Configuration(args, RunMode.HYPEROPT) logger.info('Starting freqtrade in Hyperopt mode') config = configuration.load_config() diff --git a/freqtrade/state.py b/freqtrade/state.py index 4845b72f0..b69c26cb5 100644 --- a/freqtrade/state.py +++ b/freqtrade/state.py @@ -13,3 +13,16 @@ class State(Enum): RUNNING = 1 STOPPED = 2 RELOAD_CONF = 3 + + +class RunMode(Enum): + """ + Bot running mode (backtest, hyperopt, ...) + can be "live", "dry-run", "backtest", "edgecli", "hyperopt". + """ + LIVE = "live" + DRY_RUN = "dry_run" + BACKTEST = "backtest" + EDGECLI = "edgecli" + HYPEROPT = "hyperopt" + OTHER = "other" # Used for plotting scripts and test diff --git a/freqtrade/tests/data/test_dataprovider.py b/freqtrade/tests/data/test_dataprovider.py index 3eaa45abb..154ef07a5 100644 --- a/freqtrade/tests/data/test_dataprovider.py +++ b/freqtrade/tests/data/test_dataprovider.py @@ -1,10 +1,9 @@ -from unittest.mock import Mock, MagicMock, PropertyMock +from unittest.mock import MagicMock from pandas import DataFrame from freqtrade.data.dataprovider import DataProvider -from freqtrade.exchange import Exchange -from freqtrade.tests.conftest import get_patched_exchange, log_has +from freqtrade.tests.conftest import get_patched_exchange def test_ohlcv(mocker, default_conf, ticker_history): @@ -31,6 +30,5 @@ def test_historic_ohlcv(mocker, default_conf, ticker_history): assert isinstance(data, DataFrame) assert historymock.call_count == 1 assert historymock.call_args_list[0][1]['datadir'] is None - assert historymock.call_args_list[0][1]['refresh_pairs'] == False + assert historymock.call_args_list[0][1]['refresh_pairs'] is False assert historymock.call_args_list[0][1]['ticker_interval'] == '5m' - diff --git a/scripts/plot_profit.py b/scripts/plot_profit.py index a1561bc89..72ac4031a 100755 --- a/scripts/plot_profit.py +++ b/scripts/plot_profit.py @@ -29,6 +29,7 @@ from freqtrade.configuration import Configuration from freqtrade import constants from freqtrade.data import history from freqtrade.resolvers import StrategyResolver +from freqtrade.state import RunMode import freqtrade.misc as misc @@ -82,7 +83,7 @@ def plot_profit(args: Namespace) -> None: # to match the tickerdata against the profits-results timerange = Arguments.parse_timerange(args.timerange) - config = Configuration(args).get_config() + config = Configuration(args, RunMode.OTHER).get_config() # Init strategy try: