From cf974168e97a2e3c279a77acc764e7f18919c05d Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 12:37:15 +0100 Subject: [PATCH 01/18] Edge cli drafted --- freqtrade/arguments.py | 84 ++++++++++++++++++++++++++++++------- freqtrade/edge/__init__.py | 2 +- freqtrade/optimize/edge.py | 86 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 16 deletions(-) create mode 100644 freqtrade/optimize/edge.py diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index bb571b4ea..2b369561a 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -128,6 +128,22 @@ class Arguments(object): """ Parses given arguments for Backtesting scripts. """ + parser.add_argument( + '--eps', '--enable-position-stacking', + help='Allow buying the same pair multiple times (position stacking)', + action='store_true', + dest='position_stacking', + default=False + ) + + parser.add_argument( + '--dmmp', '--disable-max-market-positions', + help='Disable applying `max_open_trades` during backtest ' + '(same as setting `max_open_trades` to a very high number)', + action='store_false', + dest='use_max_market_positions', + default=True + ) parser.add_argument( '-l', '--live', help='using live data', @@ -171,6 +187,38 @@ class Arguments(object): metavar='PATH', ) + @staticmethod + def edge_options(parser: argparse.ArgumentParser) -> None: + """ + Parses given arguments for Backtesting scripts. + """ + parser.add_argument( + '-r', '--refresh-pairs-cached', + help='refresh the pairs files in tests/testdata with the latest data from the ' + 'exchange. Use it if you want to run your backtesting with up-to-date data.', + action='store_true', + dest='refresh_pairs', + ) + parser.add_argument( + '--export', + help='export backtest results, argument are: trades\ + Example --export=trades', + type=str, + default=None, + dest='export', + ) + parser.add_argument( + '--export-filename', + help='Save backtest results to this filename \ + requires --export to be set as well\ + Example --export-filename=user_data/backtest_data/backtest_today.json\ + (default: %(default)s)', + type=str, + default=os.path.join('user_data', 'backtest_data', 'backtest-result.json'), + dest='exportfilename', + metavar='PATH', + ) + @staticmethod def optimizer_shared_options(parser: argparse.ArgumentParser) -> None: """ @@ -184,6 +232,20 @@ class Arguments(object): dest='ticker_interval', type=str, ) + + parser.add_argument( + '--timerange', + help='specify what timerange of data to use.', + default=None, + type=str, + dest='timerange', + ) + + @staticmethod + def hyperopt_options(parser: argparse.ArgumentParser) -> None: + """ + Parses given arguments for Hyperopt scripts. + """ parser.add_argument( '--eps', '--enable-position-stacking', help='Allow buying the same pair multiple times (position stacking)', @@ -200,20 +262,6 @@ class Arguments(object): dest='use_max_market_positions', default=True ) - - parser.add_argument( - '--timerange', - help='specify what timerange of data to use.', - default=None, - type=str, - dest='timerange', - ) - - @staticmethod - def hyperopt_options(parser: argparse.ArgumentParser) -> None: - """ - Parses given arguments for Hyperopt scripts. - """ parser.add_argument( '-e', '--epochs', help='specify number of epochs (default: %(default)d)', @@ -237,7 +285,7 @@ class Arguments(object): Builds and attaches all subcommands :return: None """ - from freqtrade.optimize import backtesting, hyperopt + from freqtrade.optimize import backtesting, hyperopt, edge subparsers = self.parser.add_subparsers(dest='subparser') @@ -247,6 +295,12 @@ class Arguments(object): self.optimizer_shared_options(backtesting_cmd) self.backtesting_options(backtesting_cmd) + # Add edge subcommand + edge_cmd = subparsers.add_parser('edge', help='edge module') + edge_cmd.set_defaults(func=edge.start) + self.optimizer_shared_options(edge_cmd) + self.edge_options(edge_cmd) + # Add hyperopt subcommand hyperopt_cmd = subparsers.add_parser('hyperopt', help='hyperopt module') hyperopt_cmd.set_defaults(func=hyperopt.start) diff --git a/freqtrade/edge/__init__.py b/freqtrade/edge/__init__.py index 7b25a8306..bb1cd118f 100644 --- a/freqtrade/edge/__init__.py +++ b/freqtrade/edge/__init__.py @@ -35,7 +35,7 @@ class Edge(): 'pair_info', ['stoploss', 'winrate', 'risk_reward_ratio', 'required_risk_reward', 'expectancy']) - def __init__(self, config: Dict[str, Any], exchange, strategy) -> None: + def __init__(self, config: Dict[str, Any], exchange, strategy, refresh_pairs=True) -> None: self.config = config self.exchange = exchange diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py new file mode 100644 index 000000000..49c58987b --- /dev/null +++ b/freqtrade/optimize/edge.py @@ -0,0 +1,86 @@ +# pragma pylint: disable=missing-docstring, W0212, too-many-arguments + +""" +This module contains the backtesting logic +""" +import logging +import operator +from argparse import Namespace +from copy import deepcopy +from datetime import datetime, timedelta +from pathlib import Path +from typing import Any, Dict, List, NamedTuple, Optional, Tuple +from freqtrade.edge import Edge + +import freqtrade.optimize as optimize +from freqtrade import DependencyException, constants +from freqtrade.arguments import Arguments +from freqtrade.configuration import Configuration +from freqtrade.exchange import Exchange +from freqtrade.misc import file_dump_json +from freqtrade.persistence import Trade +from freqtrade.strategy.interface import SellType +from freqtrade.strategy.resolver import IStrategy, StrategyResolver +import pdb + +logger = logging.getLogger(__name__) + + +class EdgeCli(object): + """ + Backtesting class, this class contains all the logic to run a backtest + + To run a backtest: + backtesting = Backtesting(config) + backtesting.start() + """ + + def __init__(self, config: Dict[str, Any]) -> None: + self.config = config + + # Reset keys for edge + self.config['exchange']['key'] = '' + self.config['exchange']['secret'] = '' + self.config['exchange']['password'] = '' + self.config['exchange']['uid'] = '' + self.config['dry_run'] = True + self.exchange = Exchange(self.config) + self.strategy = StrategyResolver(self.config).strategy + + self.edge = Edge(config, self.exchange, self.strategy) + + def start(self) -> None: + self.edge.calculate() + # pair_info(stoploss=-0.01, winrate=0.08333333333333333, risk_reward_ratio=0.6399436929988924, required_risk_reward=11.0, expectancy=-0.8633380255834255) + pdb.set_trace() + + +def setup_configuration(args: Namespace) -> Dict[str, Any]: + """ + Prepare the configuration for the backtesting + :param args: Cli args from Arguments() + :return: Configuration + """ + configuration = Configuration(args) + config = configuration.get_config() + + # Ensure we do not use Exchange credentials + config['exchange']['key'] = '' + config['exchange']['secret'] = '' + + return config + + +def start(args: Namespace) -> None: + """ + Start Edge script + :param args: Cli args from Arguments() + :return: None + """ + # Initialize configuration + config = setup_configuration(args) + logger.info('Starting freqtrade in Edge mode') + print('edge talking here...') + # Initialize Edge object + edge_cli = EdgeCli(config) + edge_cli.start() From 95cbbf1cb5e1baa9b7657b631fa4c29c9e50a987 Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 12:53:20 +0100 Subject: [PATCH 02/18] adding edge configuration to cli --- freqtrade/configuration.py | 42 ++++++++++++++++++++++++++++++++++++++ freqtrade/edge/__init__.py | 5 +++-- freqtrade/optimize/edge.py | 3 ++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index e043525a7..163581f84 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -58,6 +58,9 @@ class Configuration(object): # Load Backtesting config = self._load_backtesting_config(config) + # Load Edge + config = self._load_edge_config(config) + # Load Hyperopt config = self._load_hyperopt_config(config) @@ -213,6 +216,45 @@ class Configuration(object): return config + def _load_edge_config(self, config: Dict[str, Any]) -> Dict[str, Any]: + """ + Extract information for sys.argv and load Edge configuration + :return: configuration as dictionary + """ + + # If --timerange is used we add it to the configuration + if 'timerange' in self.args and self.args.timerange: + config.update({'timerange': self.args.timerange}) + logger.info('Parameter --timerange detected: %s ...', self.args.timerange) + + # If --datadir is used we add it to the configuration + if 'datadir' in self.args and self.args.datadir: + config.update({'datadir': self.args.datadir}) + else: + config.update({'datadir': self._create_default_datadir(config)}) + logger.info('Using data folder: %s ...', config.get('datadir')) + + # If -r/--refresh-pairs-cached is used we add it to the configuration + if 'refresh_pairs' in self.args and self.args.refresh_pairs: + config.update({'refresh_pairs': True}) + logger.info('Parameter -r/--refresh-pairs-cached detected ...') + + if 'ticker_interval' in self.args and self.args.ticker_interval: + config.update({'ticker_interval': self.args.ticker_interval}) + logger.info('Overriding ticker interval with Command line argument') + + # If --export is used we add it to the configuration + if 'export' in self.args and self.args.export: + config.update({'export': self.args.export}) + logger.info('Parameter --export detected: %s ...', self.args.export) + + # If --export-filename is used we add it to the configuration + if 'export' in config and 'exportfilename' in self.args and self.args.exportfilename: + config.update({'exportfilename': self.args.exportfilename}) + logger.info('Storing backtest results to %s ...', self.args.exportfilename) + + return config + def _load_hyperopt_config(self, config: Dict[str, Any]) -> Dict[str, Any]: """ Extract information for sys.argv and load Hyperopt configuration diff --git a/freqtrade/edge/__init__.py b/freqtrade/edge/__init__.py index bb1cd118f..55c59b644 100644 --- a/freqtrade/edge/__init__.py +++ b/freqtrade/edge/__init__.py @@ -35,7 +35,7 @@ class Edge(): 'pair_info', ['stoploss', 'winrate', 'risk_reward_ratio', 'required_risk_reward', 'expectancy']) - def __init__(self, config: Dict[str, Any], exchange, strategy, refresh_pairs=True) -> None: + def __init__(self, config: Dict[str, Any], exchange, strategy) -> None: self.config = config self.exchange = exchange @@ -53,6 +53,7 @@ class Edge(): self._allowed_risk: float = self.edge_config.get('allowed_risk') self._since_number_of_days: int = self.edge_config.get('calculate_since_number_of_days', 14) self._last_updated: int = 0 # Timestamp of pairs last updated time + self._refresh_pairs = True self._stoploss_range_min = float(self.edge_config.get('stoploss_range_min', -0.01)) self._stoploss_range_max = float(self.edge_config.get('stoploss_range_max', -0.05)) @@ -86,7 +87,7 @@ class Edge(): self.config['datadir'], pairs=pairs, ticker_interval=self.ticker_interval, - refresh_pairs=True, + refresh_pairs=self._refresh_pairs, exchange=self.exchange, timerange=self._timerange ) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py index 49c58987b..585c397fd 100644 --- a/freqtrade/optimize/edge.py +++ b/freqtrade/optimize/edge.py @@ -48,6 +48,7 @@ class EdgeCli(object): self.strategy = StrategyResolver(self.config).strategy self.edge = Edge(config, self.exchange, self.strategy) + self.edge._refresh_pairs = self.config.get('refresh_pairs', False) def start(self) -> None: self.edge.calculate() @@ -80,7 +81,7 @@ def start(args: Namespace) -> None: # Initialize configuration config = setup_configuration(args) logger.info('Starting freqtrade in Edge mode') - print('edge talking here...') + # Initialize Edge object edge_cli = EdgeCli(config) edge_cli.start() From 5de3f1d9dd837b90d2d7b2571580b290e4a884ee Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 13:25:44 +0100 Subject: [PATCH 03/18] showing result in tabular --- freqtrade/optimize/edge.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py index 585c397fd..2c276687b 100644 --- a/freqtrade/optimize/edge.py +++ b/freqtrade/optimize/edge.py @@ -11,6 +11,7 @@ from datetime import datetime, timedelta from pathlib import Path from typing import Any, Dict, List, NamedTuple, Optional, Tuple from freqtrade.edge import Edge +from tabulate import tabulate import freqtrade.optimize as optimize from freqtrade import DependencyException, constants @@ -50,10 +51,28 @@ class EdgeCli(object): self.edge = Edge(config, self.exchange, self.strategy) self.edge._refresh_pairs = self.config.get('refresh_pairs', False) + def _generate_edge_table(self, results: dict) -> str: + + floatfmt = ('s', '.2f', '.2f', '.2f', '.2f', '.2f') + tabular_data = [] + headers = ['pair', 'stoploss', 'win rate', 'risk reward ratio', + 'required risk reward', 'expectancy'] + + for result in results.items(): + tabular_data.append([ + result[0], + result[1].stoploss, + result[1].winrate, + result[1].risk_reward_ratio, + result[1].required_risk_reward, + result[1].expectancy + ]) + + return tabulate(tabular_data, headers=headers, floatfmt=floatfmt, tablefmt="pipe") + def start(self) -> None: self.edge.calculate() - # pair_info(stoploss=-0.01, winrate=0.08333333333333333, risk_reward_ratio=0.6399436929988924, required_risk_reward=11.0, expectancy=-0.8633380255834255) - pdb.set_trace() + print(self._generate_edge_table(self.edge._cached_pairs)) def setup_configuration(args: Namespace) -> Dict[str, Any]: From ac0c93149231daa8d3f10d6d9a7be16c9c44b428 Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 13:38:04 +0100 Subject: [PATCH 04/18] adding number of trades + average trade duration to edge info --- freqtrade/edge/__init__.py | 8 ++++++-- freqtrade/tests/edge/test_edge.py | 12 ++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/freqtrade/edge/__init__.py b/freqtrade/edge/__init__.py index 55c59b644..dedaa19a3 100644 --- a/freqtrade/edge/__init__.py +++ b/freqtrade/edge/__init__.py @@ -33,7 +33,9 @@ class Edge(): # pair info data type _pair_info = namedtuple( 'pair_info', - ['stoploss', 'winrate', 'risk_reward_ratio', 'required_risk_reward', 'expectancy']) + ['stoploss', 'winrate', 'risk_reward_ratio', 'required_risk_reward', 'expectancy', + 'nb_trades', 'avg_trade_duration'] + ) def __init__(self, config: Dict[str, Any], exchange, strategy) -> None: @@ -297,7 +299,9 @@ class Edge(): 'winrate': x.winrate, 'risk_reward_ratio': x.risk_reward_ratio, 'required_risk_reward': x.required_risk_reward, - 'expectancy': x.expectancy + 'expectancy': x.expectancy, + 'nb_trades': x.nb_trades, + 'avg_trade_duration': x.avg_trade_duration } final[x.pair] = self._pair_info(**info) diff --git a/freqtrade/tests/edge/test_edge.py b/freqtrade/tests/edge/test_edge.py index a7b1882a5..14c9114c3 100644 --- a/freqtrade/tests/edge/test_edge.py +++ b/freqtrade/tests/edge/test_edge.py @@ -128,9 +128,9 @@ def test_adjust(mocker, default_conf): edge = Edge(default_conf, freqtrade.exchange, freqtrade.strategy) mocker.patch('freqtrade.edge.Edge._cached_pairs', mocker.PropertyMock( return_value={ - 'E/F': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71), - 'C/D': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71), - 'N/O': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71) + 'E/F': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71, 10, 60), + 'C/D': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71, 10, 60), + 'N/O': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71, 10, 60) } )) @@ -143,9 +143,9 @@ def test_stoploss(mocker, default_conf): edge = Edge(default_conf, freqtrade.exchange, freqtrade.strategy) mocker.patch('freqtrade.edge.Edge._cached_pairs', mocker.PropertyMock( return_value={ - 'E/F': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71), - 'C/D': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71), - 'N/O': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71) + 'E/F': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71, 10, 60), + 'C/D': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71, 10, 60), + 'N/O': Edge._pair_info(-0.01, 0.66, 3.71, 0.50, 1.71, 10, 60) } )) From 36030176bb21ab247e8e27bd1a62a79ce48940ba Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 13:38:23 +0100 Subject: [PATCH 05/18] nb_trades and avg_trade_duration added to cli --- freqtrade/optimize/edge.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py index 2c276687b..0c4d4c29f 100644 --- a/freqtrade/optimize/edge.py +++ b/freqtrade/optimize/edge.py @@ -53,20 +53,23 @@ class EdgeCli(object): def _generate_edge_table(self, results: dict) -> str: - floatfmt = ('s', '.2f', '.2f', '.2f', '.2f', '.2f') + floatfmt = ('s', '.2f', '.2f', '.2f', '.2f', '.2f', 'd', '.d') tabular_data = [] headers = ['pair', 'stoploss', 'win rate', 'risk reward ratio', - 'required risk reward', 'expectancy'] + 'required risk reward', 'expectancy', 'total number of trades', 'average duration (min)'] for result in results.items(): - tabular_data.append([ - result[0], - result[1].stoploss, - result[1].winrate, - result[1].risk_reward_ratio, - result[1].required_risk_reward, - result[1].expectancy - ]) + if result[1].nb_trades > 0: + tabular_data.append([ + result[0], + result[1].stoploss, + result[1].winrate, + result[1].risk_reward_ratio, + result[1].required_risk_reward, + result[1].expectancy, + result[1].nb_trades, + round(result[1].avg_trade_duration) + ]) return tabulate(tabular_data, headers=headers, floatfmt=floatfmt, tablefmt="pipe") From b0e4aa8eff128b2cec7164f08bd48e8fa546037a Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 16:31:23 +0100 Subject: [PATCH 06/18] stop loss range added to args --- freqtrade/arguments.py | 7 +++++++ freqtrade/configuration.py | 8 ++++++++ freqtrade/optimize/edge.py | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 2b369561a..d8a8bf472 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -199,6 +199,13 @@ class Arguments(object): action='store_true', dest='refresh_pairs', ) + parser.add_argument( + '--stoplosses', + help='defines a range of stoploss against which edge will assess the strategy' + 'the format is "min, max, step". example: -0.01, -0.1, -0.001', + type=str, + dest='stoploss_range', + ) parser.add_argument( '--export', help='export backtest results, argument are: trades\ diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 163581f84..760057c7d 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -227,6 +227,14 @@ class Configuration(object): config.update({'timerange': self.args.timerange}) logger.info('Parameter --timerange detected: %s ...', self.args.timerange) + # If --timerange is used we add it to the configuration + if 'stoploss_range' in self.args and self.args.stoploss_range: + txt_range = eval(self.args.stoploss_range) + config['edge'].update({'stoploss_range_min': txt_range[0]}) + config['edge'].update({'stoploss_range_max': txt_range[1]}) + config['edge'].update({'stoploss_range_step': txt_range[2]}) + logger.info('Parameter --stoplosses detected: %s ...', self.args.stoploss_range) + # If --datadir is used we add it to the configuration if 'datadir' in self.args and self.args.datadir: config.update({'datadir': self.args.datadir}) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py index 0c4d4c29f..c64456131 100644 --- a/freqtrade/optimize/edge.py +++ b/freqtrade/optimize/edge.py @@ -53,7 +53,7 @@ class EdgeCli(object): def _generate_edge_table(self, results: dict) -> str: - floatfmt = ('s', '.2f', '.2f', '.2f', '.2f', '.2f', 'd', '.d') + floatfmt = ('s', '.10g', '.2f', '.2f', '.2f', '.2f', 'd', '.d') tabular_data = [] headers = ['pair', 'stoploss', 'win rate', 'risk reward ratio', 'required risk reward', 'expectancy', 'total number of trades', 'average duration (min)'] From dd47d7adb407d048273482f95bcfeb927845d15d Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 16:37:26 +0100 Subject: [PATCH 07/18] cli blank line added to readability --- freqtrade/optimize/edge.py | 1 + 1 file changed, 1 insertion(+) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py index c64456131..6f3fe7940 100644 --- a/freqtrade/optimize/edge.py +++ b/freqtrade/optimize/edge.py @@ -75,6 +75,7 @@ class EdgeCli(object): def start(self) -> None: self.edge.calculate() + print('') # blank like for readability print(self._generate_edge_table(self.edge._cached_pairs)) From 0767718a179aac64f2ef059cc96f62f8974d4b2d Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 16:38:55 +0100 Subject: [PATCH 08/18] clear help added to stop losses arg --- freqtrade/arguments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index d8a8bf472..594a01e78 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -202,7 +202,7 @@ class Arguments(object): parser.add_argument( '--stoplosses', help='defines a range of stoploss against which edge will assess the strategy' - 'the format is "min, max, step". example: -0.01, -0.1, -0.001', + 'the format is "min,max,step" (without any space). example: --stoplosses=-0.01,-0.1,-0.001', type=str, dest='stoploss_range', ) From 5d73b303fe28cfa89fb0f2d2fb337dc15a137287 Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 16:49:16 +0100 Subject: [PATCH 09/18] unnecessary libraries removed + arg help enriched --- freqtrade/arguments.py | 3 ++- freqtrade/optimize/edge.py | 20 +++++--------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 594a01e78..a071f0dd6 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -202,7 +202,8 @@ class Arguments(object): parser.add_argument( '--stoplosses', help='defines a range of stoploss against which edge will assess the strategy' - 'the format is "min,max,step" (without any space). example: --stoplosses=-0.01,-0.1,-0.001', + 'the format is "min,max,step" (without any space).' + 'example: --stoplosses=-0.01,-0.1,-0.001', type=str, dest='stoploss_range', ) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py index 6f3fe7940..f2b75770b 100644 --- a/freqtrade/optimize/edge.py +++ b/freqtrade/optimize/edge.py @@ -4,25 +4,14 @@ This module contains the backtesting logic """ import logging -import operator from argparse import Namespace -from copy import deepcopy -from datetime import datetime, timedelta -from pathlib import Path -from typing import Any, Dict, List, NamedTuple, Optional, Tuple -from freqtrade.edge import Edge +from typing import Dict, Any from tabulate import tabulate +from freqtrade.edge import Edge -import freqtrade.optimize as optimize -from freqtrade import DependencyException, constants -from freqtrade.arguments import Arguments from freqtrade.configuration import Configuration from freqtrade.exchange import Exchange -from freqtrade.misc import file_dump_json -from freqtrade.persistence import Trade -from freqtrade.strategy.interface import SellType -from freqtrade.strategy.resolver import IStrategy, StrategyResolver -import pdb +from freqtrade.strategy.resolver import StrategyResolver logger = logging.getLogger(__name__) @@ -56,7 +45,8 @@ class EdgeCli(object): floatfmt = ('s', '.10g', '.2f', '.2f', '.2f', '.2f', 'd', '.d') tabular_data = [] headers = ['pair', 'stoploss', 'win rate', 'risk reward ratio', - 'required risk reward', 'expectancy', 'total number of trades', 'average duration (min)'] + 'required risk reward', 'expectancy', 'total number of trades', + 'average duration (min)'] for result in results.items(): if result[1].nb_trades > 0: From ca22a116ad6db58d71d7db095e12bc430a695c34 Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 17:14:37 +0100 Subject: [PATCH 10/18] timerange added to args --- freqtrade/optimize/edge.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge.py index f2b75770b..59bcbc098 100644 --- a/freqtrade/optimize/edge.py +++ b/freqtrade/optimize/edge.py @@ -10,6 +10,7 @@ from tabulate import tabulate from freqtrade.edge import Edge from freqtrade.configuration import Configuration +from freqtrade.arguments import Arguments from freqtrade.exchange import Exchange from freqtrade.strategy.resolver import StrategyResolver @@ -40,6 +41,11 @@ class EdgeCli(object): self.edge = Edge(config, self.exchange, self.strategy) self.edge._refresh_pairs = self.config.get('refresh_pairs', False) + self.timerange = Arguments.parse_timerange(None if self.config.get( + 'timerange') is None else str(self.config.get('timerange'))) + + self.edge._timerange = self.timerange + def _generate_edge_table(self, results: dict) -> str: floatfmt = ('s', '.10g', '.2f', '.2f', '.2f', '.2f', 'd', '.d') From 9698eee93408c8684492e974026681eeaabc6408 Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 17:14:44 +0100 Subject: [PATCH 11/18] documentation added --- docs/edge.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/docs/edge.md b/docs/edge.md index f74f8fdcc..94b6c65ac 100644 --- a/docs/edge.md +++ b/docs/edge.md @@ -9,6 +9,7 @@ This page explains how to use Edge Positioning module in your bot in order to en - [Introduction](#introduction) - [How does it work?](#how-does-it-work?) - [Configurations](#configurations) +- [Running Edge independently](#running-edge-independently) ## Introduction Trading is all about probability. No one can claim that he has a strategy working all the time. You have to assume that sometimes you lose.

@@ -149,3 +150,57 @@ Edge will filter out trades with long duration. If a trade is profitable after 1 #### remove_pumps Edge will remove sudden pumps in a given market while going through historical data. However, given that pumps happen very often in crypto markets, we recommend you keep this off.
(default to false) + + +## Running Edge independently +You can run Edge independently in order to see in details the result. Here is an example: +```bash +python3 ./freqtrade/main.py edge +``` + +An example of its output: + +| pair | stoploss | win rate | risk reward ratio | required risk reward | expectancy | total number of trades | average duration (min) | +|:----------|-----------:|-----------:|--------------------:|-----------------------:|-------------:|-------------------------:|-------------------------:| +| AGI/BTC | -0.02 | 0.64 | 5.86 | 0.56 | 3.41 | 14 | 54 | +| NXS/BTC | -0.03 | 0.64 | 2.99 | 0.57 | 1.54 | 11 | 26 | +| LEND/BTC | -0.02 | 0.82 | 2.05 | 0.22 | 1.50 | 11 | 36 | +| VIA/BTC | -0.01 | 0.55 | 3.01 | 0.83 | 1.19 | 11 | 48 | +| MTH/BTC | -0.09 | 0.56 | 2.82 | 0.80 | 1.12 | 18 | 52 | +| ARDR/BTC | -0.04 | 0.42 | 3.14 | 1.40 | 0.73 | 12 | 42 | +| BCPT/BTC | -0.01 | 0.71 | 1.34 | 0.40 | 0.67 | 14 | 30 | +| WINGS/BTC | -0.02 | 0.56 | 1.97 | 0.80 | 0.65 | 27 | 42 | +| VIBE/BTC | -0.02 | 0.83 | 0.91 | 0.20 | 0.59 | 12 | 35 | +| MCO/BTC | -0.02 | 0.79 | 0.97 | 0.27 | 0.55 | 14 | 31 | +| GNT/BTC | -0.02 | 0.50 | 2.06 | 1.00 | 0.53 | 18 | 24 | +| HOT/BTC | -0.01 | 0.17 | 7.72 | 4.81 | 0.50 | 209 | 7 | +| SNM/BTC | -0.03 | 0.71 | 1.06 | 0.42 | 0.45 | 17 | 38 | +| APPC/BTC | -0.02 | 0.44 | 2.28 | 1.27 | 0.44 | 25 | 43 | +| NEBL/BTC | -0.03 | 0.63 | 1.29 | 0.58 | 0.44 | 19 | 59 | + +### Update cached pairs with the latest data +```bash +python3 ./freqtrade/main.py edge --refresh-pairs-cached +``` + +### Precising stoploss range +```bash +python3 ./freqtrade/main.py edge --stoplosses=-0.01,-0.1,-0.001 #min,max,step +``` + +### Advanced use of timerange +```bash +python3 ./freqtrade/main.py edge --timerange=20181110-20181113 +``` + +Doing --timerange=-200 will get the last 200 timeframes from your inputdata. You can also specify specific dates, or a range span indexed by start and stop. + +The full timerange specification: + +* Use last 123 tickframes of data: --timerange=-123 +* Use first 123 tickframes of data: --timerange=123- +* Use tickframes from line 123 through 456: --timerange=123-456 +* Use tickframes till 2018/01/31: --timerange=-20180131 +* Use tickframes since 2018/01/31: --timerange=20180131- +* Use tickframes since 2018/01/31 till 2018/03/01 : --timerange=20180131-20180301 +* Use tickframes between POSIX timestamps 1527595200 1527618600: --timerange=1527595200-1527618600 \ No newline at end of file From bb9a1e5f9f1a324099114a58ce31b51db1b73b52 Mon Sep 17 00:00:00 2001 From: misagh Date: Wed, 14 Nov 2018 19:14:34 +0100 Subject: [PATCH 12/18] edge cli tests added --- freqtrade/tests/edge/test_edge_cli.py | 140 ++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 freqtrade/tests/edge/test_edge_cli.py diff --git a/freqtrade/tests/edge/test_edge_cli.py b/freqtrade/tests/edge/test_edge_cli.py new file mode 100644 index 000000000..e73507a55 --- /dev/null +++ b/freqtrade/tests/edge/test_edge_cli.py @@ -0,0 +1,140 @@ +# pragma pylint: disable=missing-docstring, C0103, C0330 +# pragma pylint: disable=protected-access, too-many-lines, invalid-name, too-many-arguments + +from unittest.mock import MagicMock +import json +from typing import List +from freqtrade.edge import Edge +from freqtrade.arguments import Arguments +from freqtrade.optimize.edge import (EdgeCli, setup_configuration, start) +from freqtrade.tests.conftest import log_has, patch_exchange + + +def get_args(args) -> List[str]: + return Arguments(args, '').get_parsed_arg() + + +def test_setup_configuration_without_arguments(mocker, default_conf, caplog) -> None: + mocker.patch('freqtrade.configuration.open', mocker.mock_open( + read_data=json.dumps(default_conf) + )) + + args = [ + '--config', 'config.json', + '--strategy', 'DefaultStrategy', + 'edge' + ] + + config = setup_configuration(get_args(args)) + assert 'max_open_trades' in config + assert 'stake_currency' in config + assert 'stake_amount' in config + assert 'exchange' in config + assert 'pair_whitelist' in config['exchange'] + assert 'datadir' in config + assert log_has( + 'Using data folder: {} ...'.format(config['datadir']), + caplog.record_tuples + ) + assert 'ticker_interval' in config + assert not log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + + assert 'refresh_pairs' not in config + assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) + + assert 'timerange' not in config + assert 'stoploss_range' not in config + + +def test_setup_configuration_with_arguments(mocker, edge_conf, caplog) -> None: + mocker.patch('freqtrade.configuration.open', mocker.mock_open( + read_data=json.dumps(edge_conf) + )) + + args = [ + '--config', 'config.json', + '--strategy', 'DefaultStrategy', + '--datadir', '/foo/bar', + 'edge', + '--ticker-interval', '1m', + '--refresh-pairs-cached', + '--timerange', ':100', + '--stoplosses=-0.01,-0.10,-0.001' + ] + + config = setup_configuration(get_args(args)) + assert 'max_open_trades' in config + assert 'stake_currency' in config + assert 'stake_amount' in config + assert 'exchange' in config + assert 'pair_whitelist' in config['exchange'] + assert 'datadir' in config + assert log_has( + 'Using data folder: {} ...'.format(config['datadir']), + caplog.record_tuples + ) + assert 'ticker_interval' in config + assert log_has('Parameter -i/--ticker-interval detected ...', caplog.record_tuples) + assert log_has( + 'Using ticker_interval: 1m ...', + caplog.record_tuples + ) + + assert 'refresh_pairs' in config + assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) + assert 'timerange' in config + assert log_has( + 'Parameter --timerange detected: {} ...'.format(config['timerange']), + caplog.record_tuples + ) + + +def test_start(mocker, fee, edge_conf, caplog) -> None: + start_mock = MagicMock() + mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) + patch_exchange(mocker) + mocker.patch('freqtrade.optimize.edge.EdgeCli.start', start_mock) + mocker.patch('freqtrade.configuration.open', mocker.mock_open( + read_data=json.dumps(edge_conf) + )) + args = [ + '--config', 'config.json', + '--strategy', 'DefaultStrategy', + 'edge' + ] + args = get_args(args) + start(args) + assert log_has( + 'Starting freqtrade in Edge mode', + caplog.record_tuples + ) + assert start_mock.call_count == 1 + + +def test_edge_init(mocker, edge_conf) -> None: + patch_exchange(mocker) + edge_cli = EdgeCli(edge_conf) + assert edge_cli.config == edge_conf + assert callable(edge_cli.edge.calculate) + + +def test_generate_edge_table(edge_conf, mocker): + patch_exchange(mocker) + edge_cli = EdgeCli(edge_conf) + + results = {} + info = { + 'stoploss': -0.01, + 'winrate': 0.60, + 'risk_reward_ratio': 2, + 'required_risk_reward': 1, + 'expectancy': 3, + 'nb_trades': 10, + 'avg_trade_duration': 60 + } + + results['ETH/BTC'] = Edge._pair_info(**info) + assert edge_cli._generate_edge_table(results).count(':|') == 7 + assert edge_cli._generate_edge_table(results).count('| ETH/BTC |') == 1 + assert edge_cli._generate_edge_table(results).count( + '| risk reward ratio | required risk reward | expectancy |') == 1 From f666d1596ba468d26edd941e04e939908cea1bc7 Mon Sep 17 00:00:00 2001 From: misagh Date: Thu, 15 Nov 2018 10:31:56 +0100 Subject: [PATCH 13/18] renaming edge to edge_cli for command line version --- freqtrade/arguments.py | 4 ++-- freqtrade/optimize/{edge.py => edge_cli.py} | 0 freqtrade/tests/{edge => optimize}/test_edge_cli.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename freqtrade/optimize/{edge.py => edge_cli.py} (100%) rename freqtrade/tests/{edge => optimize}/test_edge_cli.py (96%) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index a071f0dd6..db5e4cb5e 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -293,7 +293,7 @@ class Arguments(object): Builds and attaches all subcommands :return: None """ - from freqtrade.optimize import backtesting, hyperopt, edge + from freqtrade.optimize import backtesting, hyperopt, edge_cli subparsers = self.parser.add_subparsers(dest='subparser') @@ -305,7 +305,7 @@ class Arguments(object): # Add edge subcommand edge_cmd = subparsers.add_parser('edge', help='edge module') - edge_cmd.set_defaults(func=edge.start) + edge_cmd.set_defaults(func=edge_cli.start) self.optimizer_shared_options(edge_cmd) self.edge_options(edge_cmd) diff --git a/freqtrade/optimize/edge.py b/freqtrade/optimize/edge_cli.py similarity index 100% rename from freqtrade/optimize/edge.py rename to freqtrade/optimize/edge_cli.py diff --git a/freqtrade/tests/edge/test_edge_cli.py b/freqtrade/tests/optimize/test_edge_cli.py similarity index 96% rename from freqtrade/tests/edge/test_edge_cli.py rename to freqtrade/tests/optimize/test_edge_cli.py index e73507a55..f8db3dec4 100644 --- a/freqtrade/tests/edge/test_edge_cli.py +++ b/freqtrade/tests/optimize/test_edge_cli.py @@ -6,7 +6,7 @@ import json from typing import List from freqtrade.edge import Edge from freqtrade.arguments import Arguments -from freqtrade.optimize.edge import (EdgeCli, setup_configuration, start) +from freqtrade.optimize.edge_cli import (EdgeCli, setup_configuration, start) from freqtrade.tests.conftest import log_has, patch_exchange @@ -93,7 +93,7 @@ def test_start(mocker, fee, edge_conf, caplog) -> None: start_mock = MagicMock() mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) patch_exchange(mocker) - mocker.patch('freqtrade.optimize.edge.EdgeCli.start', start_mock) + mocker.patch('freqtrade.optimize.edge_cli.EdgeCli.start', start_mock) mocker.patch('freqtrade.configuration.open', mocker.mock_open( read_data=json.dumps(edge_conf) )) From 1cfd19aee34f3eb5602b876b60225088817bd0ee Mon Sep 17 00:00:00 2001 From: misagh Date: Thu, 15 Nov 2018 10:44:33 +0100 Subject: [PATCH 14/18] removing unnecessary args for edge --- freqtrade/arguments.py | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index db5e4cb5e..3d1f61dbe 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -195,7 +195,7 @@ class Arguments(object): parser.add_argument( '-r', '--refresh-pairs-cached', help='refresh the pairs files in tests/testdata with the latest data from the ' - 'exchange. Use it if you want to run your backtesting with up-to-date data.', + 'exchange. Use it if you want to run your edge with up-to-date data.', action='store_true', dest='refresh_pairs', ) @@ -207,25 +207,6 @@ class Arguments(object): type=str, dest='stoploss_range', ) - parser.add_argument( - '--export', - help='export backtest results, argument are: trades\ - Example --export=trades', - type=str, - default=None, - dest='export', - ) - parser.add_argument( - '--export-filename', - help='Save backtest results to this filename \ - requires --export to be set as well\ - Example --export-filename=user_data/backtest_data/backtest_today.json\ - (default: %(default)s)', - type=str, - default=os.path.join('user_data', 'backtest_data', 'backtest-result.json'), - dest='exportfilename', - metavar='PATH', - ) @staticmethod def optimizer_shared_options(parser: argparse.ArgumentParser) -> None: From 03e6caa501460781711dbc7b47de382e53409008 Mon Sep 17 00:00:00 2001 From: misagh Date: Thu, 15 Nov 2018 10:46:36 +0100 Subject: [PATCH 15/18] adding notice about Edge ignoring ROI and TSL in doc --- docs/edge.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/edge.md b/docs/edge.md index 94b6c65ac..e5575554b 100644 --- a/docs/edge.md +++ b/docs/edge.md @@ -3,6 +3,7 @@ This page explains how to use Edge Positioning module in your bot in order to enter into a trade only if the trade has a reasonable win rate and risk reward ratio, and consequently adjust your position size and stoploss. **NOTICE:** Edge positioning is not compatible with dynamic whitelist. it overrides dynamic whitelist. +**NOTICE2:** Edge won't consider anything else than buy/sell/stoploss signals. So trailing stoploss, ROI, and everything else will be ignored in its calculation. ## Table of Contents From 69619030f3596757c6f5a6b0e52c4bd583a236ac Mon Sep 17 00:00:00 2001 From: misagh Date: Thu, 15 Nov 2018 10:50:40 +0100 Subject: [PATCH 16/18] removing unnecessary args from config --- freqtrade/configuration.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/freqtrade/configuration.py b/freqtrade/configuration.py index 760057c7d..ab70a5fb9 100644 --- a/freqtrade/configuration.py +++ b/freqtrade/configuration.py @@ -235,32 +235,11 @@ class Configuration(object): config['edge'].update({'stoploss_range_step': txt_range[2]}) logger.info('Parameter --stoplosses detected: %s ...', self.args.stoploss_range) - # If --datadir is used we add it to the configuration - if 'datadir' in self.args and self.args.datadir: - config.update({'datadir': self.args.datadir}) - else: - config.update({'datadir': self._create_default_datadir(config)}) - logger.info('Using data folder: %s ...', config.get('datadir')) - # If -r/--refresh-pairs-cached is used we add it to the configuration if 'refresh_pairs' in self.args and self.args.refresh_pairs: config.update({'refresh_pairs': True}) logger.info('Parameter -r/--refresh-pairs-cached detected ...') - if 'ticker_interval' in self.args and self.args.ticker_interval: - config.update({'ticker_interval': self.args.ticker_interval}) - logger.info('Overriding ticker interval with Command line argument') - - # If --export is used we add it to the configuration - if 'export' in self.args and self.args.export: - config.update({'export': self.args.export}) - logger.info('Parameter --export detected: %s ...', self.args.export) - - # If --export-filename is used we add it to the configuration - if 'export' in config and 'exportfilename' in self.args and self.args.exportfilename: - config.update({'exportfilename': self.args.exportfilename}) - logger.info('Storing backtest results to %s ...', self.args.exportfilename) - return config def _load_hyperopt_config(self, config: Dict[str, Any]) -> Dict[str, Any]: From d05c671a7e5b506cf598d1194fd704cf60596e54 Mon Sep 17 00:00:00 2001 From: misagh Date: Thu, 15 Nov 2018 19:54:17 +0100 Subject: [PATCH 17/18] adding edge args to bot-usage --- docs/bot-usage.md | 63 +++++++++++++++++++++++++++++++++-------------- docs/index.md | 1 + 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/docs/bot-usage.md b/docs/bot-usage.md index 83a8ee833..31fea17fc 100644 --- a/docs/bot-usage.md +++ b/docs/bot-usage.md @@ -44,11 +44,11 @@ optional arguments: ### How to use a different config file? -The bot allows you to select which config file you want to use. Per +The bot allows you to select which config file you want to use. Per default, the bot will load the file `./config.json` ```bash -python3 ./freqtrade/main.py -c path/far/far/away/config.json +python3 ./freqtrade/main.py -c path/far/far/away/config.json ``` ### How to use --strategy? @@ -61,7 +61,7 @@ The bot will search your strategy file within `user_data/strategies` and `freqtr To load a strategy, simply pass the class name (e.g.: `CustomStrategy`) in this parameter. -**Example:** +**Example:** In `user_data/strategies` you have a file `my_awesome_strategy.py` which has a strategy class called `AwesomeStrategy` to load it: @@ -69,7 +69,7 @@ a strategy class called `AwesomeStrategy` to load it: python3 ./freqtrade/main.py --strategy AwesomeStrategy ``` -If the bot does not find your strategy file, it will display in an error +If the bot does not find your strategy file, it will display in an error message the reason (File not found, or errors in your code). Learn more about strategy file in [optimize your bot](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-optimization.md). @@ -84,37 +84,37 @@ python3 ./freqtrade/main.py --strategy AwesomeStrategy --strategy-path /some/fol #### How to install a strategy? -This is very simple. Copy paste your strategy file into the folder +This is very simple. Copy paste your strategy file into the folder `user_data/strategies` or use `--strategy-path`. And voila, the bot is ready to use it. ### How to use --dynamic-whitelist? -Per default `--dynamic-whitelist` will retrieve the 20 currencies based +Per default `--dynamic-whitelist` will retrieve the 20 currencies based on BaseVolume. This value can be changed when you run the script. -**By Default** -Get the 20 currencies based on BaseVolume. +**By Default** +Get the 20 currencies based on BaseVolume. ```bash python3 ./freqtrade/main.py --dynamic-whitelist ``` -**Customize the number of currencies to retrieve** -Get the 30 currencies based on BaseVolume. +**Customize the number of currencies to retrieve** +Get the 30 currencies based on BaseVolume. ```bash python3 ./freqtrade/main.py --dynamic-whitelist 30 ``` -**Exception** +**Exception** `--dynamic-whitelist` must be greater than 0. If you enter 0 or a negative value (e.g -2), `--dynamic-whitelist` will use the default value (20). ### How to use --db-url? -When you run the bot in Dry-run mode, per default no transactions are -stored in a database. If you want to store your bot actions in a DB +When you run the bot in Dry-run mode, per default no transactions are +stored in a database. If you want to store your bot actions in a DB using `--db-url`. This can also be used to specify a custom database in production mode. Example command: @@ -170,15 +170,15 @@ optional arguments: ### How to use --refresh-pairs-cached parameter? -The first time your run Backtesting, it will take the pairs you have -set in your config file and download data from Bittrex. +The first time your run Backtesting, it will take the pairs you have +set in your config file and download data from Bittrex. -If for any reason you want to update your data set, you use -`--refresh-pairs-cached` to force Backtesting to update the data it has. +If for any reason you want to update your data set, you use +`--refresh-pairs-cached` to force Backtesting to update the data it has. **Use it only if you want to update your data set. You will not be able to come back to the previous version.** -To test your strategy with latest data, we recommend continuing using +To test your strategy with latest data, we recommend continuing using the parameter `-l` or `--live`. ## Hyperopt commands @@ -211,6 +211,31 @@ optional arguments: ``` +## Edge commands + +To know your trade expectacny and winrate against historical data, you can use Edge. + +``` +usage: main.py edge [-h] [-i TICKER_INTERVAL] [--timerange TIMERANGE] [-r] + [--stoplosses STOPLOSS_RANGE] + +optional arguments: + -h, --help show this help message and exit + -i TICKER_INTERVAL, --ticker-interval TICKER_INTERVAL + specify ticker interval (1m, 5m, 30m, 1h, 1d) + --timerange TIMERANGE + specify what timerange of data to use. + -r, --refresh-pairs-cached + refresh the pairs files in tests/testdata with the + latest data from the exchange. Use it if you want to + run your edge with up-to-date data. + --stoplosses STOPLOSS_RANGE + defines a range of stoploss against which edge will + assess the strategythe format is "min,max,step" + (without any space).example: + --stoplosses=-0.01,-0.1,-0.001 +``` + ## A parameter missing in the configuration? All parameters for `main.py`, `backtesting`, `hyperopt` are referenced @@ -218,5 +243,5 @@ in [misc.py](https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/misc. ## Next step -The optimal strategy of the bot will change with time depending of the market trends. The next step is to +The optimal strategy of the bot will change with time depending of the market trends. The next step is to [optimize your bot](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-optimization.md). diff --git a/docs/index.md b/docs/index.md index e6e643ba7..c64b9c188 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,6 +21,7 @@ Pull-request. Do not hesitate to reach us on - [Bot commands](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-usage.md#bot-commands) - [Backtesting commands](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-usage.md#backtesting-commands) - [Hyperopt commands](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-usage.md#hyperopt-commands) + - [Edge commands](https://github.com/mishaker/freqtrade/blob/develop/docs/bot-usage.md#edge-commands) - [Bot Optimization](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-optimization.md) - [Change your strategy](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-optimization.md#change-your-strategy) - [Add more Indicator](https://github.com/freqtrade/freqtrade/blob/develop/docs/bot-optimization.md#add-more-indicator) From db8c8ea4a42d6d90a00c7b63c401e73b8bd25b1f Mon Sep 17 00:00:00 2001 From: misagh Date: Thu, 15 Nov 2018 20:02:07 +0100 Subject: [PATCH 18/18] added a space in help --- freqtrade/arguments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/arguments.py b/freqtrade/arguments.py index 3d1f61dbe..8e26752fe 100644 --- a/freqtrade/arguments.py +++ b/freqtrade/arguments.py @@ -201,7 +201,7 @@ class Arguments(object): ) parser.add_argument( '--stoplosses', - help='defines a range of stoploss against which edge will assess the strategy' + help='defines a range of stoploss against which edge will assess the strategy ' 'the format is "min,max,step" (without any space).' 'example: --stoplosses=-0.01,-0.1,-0.001', type=str,