Merge pull request #1037 from freqtrade/fix/backtest-comment

replace --realistic with 2 separate flags
This commit is contained in:
Janne Sinivirta 2018-07-19 17:33:19 +03:00 committed by GitHub
commit 0cc1b66ae7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 57 deletions

View File

@ -29,25 +29,25 @@ The backtesting is very easy with freqtrade.
#### With 5 min tickers (Per default) #### With 5 min tickers (Per default)
```bash ```bash
python3 ./freqtrade/main.py backtesting --realistic-simulation python3 ./freqtrade/main.py backtesting
``` ```
#### With 1 min tickers #### With 1 min tickers
```bash ```bash
python3 ./freqtrade/main.py backtesting --realistic-simulation --ticker-interval 1m python3 ./freqtrade/main.py backtesting --ticker-interval 1m
``` ```
#### Update cached pairs with the latest data #### Update cached pairs with the latest data
```bash ```bash
python3 ./freqtrade/main.py backtesting --realistic-simulation --refresh-pairs-cached python3 ./freqtrade/main.py backtesting --refresh-pairs-cached
``` ```
#### With live data (do not alter your testdata files) #### With live data (do not alter your testdata files)
```bash ```bash
python3 ./freqtrade/main.py backtesting --realistic-simulation --live python3 ./freqtrade/main.py backtesting --live
``` ```
#### Using a different on-disk ticker-data source #### Using a different on-disk ticker-data source

View File

@ -117,18 +117,21 @@ python3 ./freqtrade/main.py -c config.json --db-url sqlite:///tradesv3.dry_run.s
Backtesting also uses the config specified via `-c/--config`. Backtesting also uses the config specified via `-c/--config`.
``` ```
usage: main.py backtesting [-h] [-i TICKER_INTERVAL] [--realistic-simulation] usage: main.py backtesting [-h] [-i TICKER_INTERVAL] [--eps] [--dmmp]
[--timerange TIMERANGE] [-l] [-r] [--export EXPORT] [--timerange TIMERANGE] [-l] [-r]
[--export-filename EXPORTFILENAME] [--export EXPORT] [--export-filename PATH]
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
-i TICKER_INTERVAL, --ticker-interval TICKER_INTERVAL -i TICKER_INTERVAL, --ticker-interval TICKER_INTERVAL
specify ticker interval (1m, 5m, 30m, 1h, 1d) specify ticker interval (1m, 5m, 30m, 1h, 1d)
--realistic-simulation --eps, --enable-position-stacking
uses max_open_trades from config to simulate real Allow buying the same pair multiple times (position
world limitations stacking)
--dmmp, --disable-max-market-positions
Disable applying `max_open_trades` during backtest
(same as setting `max_open_trades` to a very high
number)
--timerange TIMERANGE --timerange TIMERANGE
specify what timerange of data to use. specify what timerange of data to use.
-l, --live using live data -l, --live using live data
@ -138,11 +141,13 @@ optional arguments:
run your backtesting with up-to-date data. run your backtesting with up-to-date data.
--export EXPORT export backtest results, argument are: trades Example --export EXPORT export backtest results, argument are: trades Example
--export=trades --export=trades
--export-filename EXPORTFILENAME --export-filename PATH
Save backtest results to this filename requires Save backtest results to this filename requires
--export to be set as well Example --export- --export to be set as well Example --export-
filename=backtest_today.json (default: backtest- filename=user_data/backtest_data/backtest_today.json
result.json (default: user_data/backtest_data/backtest-
result.json)
``` ```
### How to use --refresh-pairs-cached parameter? ### How to use --refresh-pairs-cached parameter?
@ -164,22 +169,28 @@ To optimize your strategy, you can use hyperopt parameter hyperoptimization
to find optimal parameter values for your stategy. to find optimal parameter values for your stategy.
``` ```
usage: main.py hyperopt [-h] [-i TICKER_INTERVAL] [--realistic-simulation] usage: freqtrade hyperopt [-h] [-i TICKER_INTERVAL] [--eps] [--dmmp]
[--timerange TIMERANGE] [-e INT] [--timerange TIMERANGE] [-e INT]
[-s {all,buy,roi,stoploss} [{all,buy,roi,stoploss} ...]] [-s {all,buy,roi,stoploss} [{all,buy,roi,stoploss} ...]]
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
-i TICKER_INTERVAL, --ticker-interval TICKER_INTERVAL -i TICKER_INTERVAL, --ticker-interval TICKER_INTERVAL
specify ticker interval (1m, 5m, 30m, 1h, 1d) specify ticker interval (1m, 5m, 30m, 1h, 1d)
--realistic-simulation --eps, --enable-position-stacking
uses max_open_trades from config to simulate real Allow buying the same pair multiple times (position
world limitations stacking)
--timerange TIMERANGE specify what timerange of data to use. --dmmp, --disable-max-market-positions
Disable applying `max_open_trades` during backtest
(same as setting `max_open_trades` to a very high
number)
--timerange TIMERANGE
specify what timerange of data to use.
-e INT, --epochs INT specify number of epochs (default: 100) -e INT, --epochs INT specify number of epochs (default: 100)
-s {all,buy,roi,stoploss} [{all,buy,roi,stoploss} ...], --spaces {all,buy,roi,stoploss} [{all,buy,roi,stoploss} ...] -s {all,buy,roi,stoploss} [{all,buy,roi,stoploss} ...], --spaces {all,buy,roi,stoploss} [{all,buy,roi,stoploss} ...]
Specify which parameters to hyperopt. Space separate Specify which parameters to hyperopt. Space separate
list. Default: all list. Default: all
``` ```
## A parameter missing in the configuration? ## A parameter missing in the configuration?

View File

@ -176,11 +176,22 @@ class Arguments(object):
type=str, type=str,
) )
parser.add_argument( parser.add_argument(
'--realistic-simulation', '--eps', '--enable-position-stacking',
help='uses max_open_trades from config to simulate real world limitations', help='Allow buying the same pair multiple times (position stacking)',
action='store_true', action='store_true',
dest='realistic_simulation', 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( parser.add_argument(
'--timerange', '--timerange',
help='specify what timerange of data to use.', help='specify what timerange of data to use.',

View File

@ -155,11 +155,18 @@ class Configuration(object):
config.update({'live': True}) config.update({'live': True})
logger.info('Parameter -l/--live detected ...') logger.info('Parameter -l/--live detected ...')
# If --realistic-simulation is used we add it to the configuration # If --enable-position-stacking is used we add it to the configuration
if 'realistic_simulation' in self.args and self.args.realistic_simulation: if 'position_stacking' in self.args and self.args.position_stacking:
config.update({'realistic_simulation': True}) config.update({'position_stacking': True})
logger.info('Parameter --realistic-simulation detected ...') logger.info('Parameter --enable-position-stacking detected ...')
logger.info('Using max_open_trades: %s ...', config.get('max_open_trades'))
# If --disable-max-market-positions is used we add it to the configuration
if 'use_max_market_positions' in self.args and not self.args.use_max_market_positions:
config.update({'use_max_market_positions': False})
logger.info('Parameter --disable-max-market-positions detected ...')
logger.info('max_open_trades set to unlimited ...')
else:
logger.info('Using max_open_trades: %s ...', config.get('max_open_trades'))
# If --timerange is used we add it to the configuration # If --timerange is used we add it to the configuration
if 'timerange' in self.args and self.args.timerange: if 'timerange' in self.args and self.args.timerange:
@ -195,7 +202,7 @@ class Configuration(object):
Extract information for sys.argv and load Hyperopt configuration Extract information for sys.argv and load Hyperopt configuration
:return: configuration as dictionary :return: configuration as dictionary
""" """
# If --realistic-simulation is used we add it to the configuration # If --epochs is used we add it to the configuration
if 'epochs' in self.args and self.args.epochs: if 'epochs' in self.args and self.args.epochs:
config.update({'epochs': self.args.epochs}) config.update({'epochs': self.args.epochs})
logger.info('Parameter --epochs detected ...') logger.info('Parameter --epochs detected ...')

View File

@ -202,13 +202,13 @@ class Backtesting(object):
stake_amount: btc amount to use for each trade stake_amount: btc amount to use for each trade
processed: a processed dictionary with format {pair, data} processed: a processed dictionary with format {pair, data}
max_open_trades: maximum number of concurrent trades (default: 0, disabled) max_open_trades: maximum number of concurrent trades (default: 0, disabled)
realistic: do we try to simulate realistic trades? (default: True) position_stacking: do we allow position stacking? (default: False)
:return: DataFrame :return: DataFrame
""" """
headers = ['date', 'buy', 'open', 'close', 'sell'] headers = ['date', 'buy', 'open', 'close', 'sell']
processed = args['processed'] processed = args['processed']
max_open_trades = args.get('max_open_trades', 0) max_open_trades = args.get('max_open_trades', 0)
realistic = args.get('realistic', False) position_stacking = args.get('position_stacking', False)
trades = [] trades = []
trade_count_lock: Dict = {} trade_count_lock: Dict = {}
for pair, pair_data in processed.items(): for pair, pair_data in processed.items():
@ -232,7 +232,7 @@ class Backtesting(object):
if row.buy == 0 or row.sell == 1: if row.buy == 0 or row.sell == 1:
continue # skip rows where no buy signal or that would immediately sell off continue # skip rows where no buy signal or that would immediately sell off
if realistic: if not position_stacking:
if lock_pair_until is not None and row.date <= lock_pair_until: if lock_pair_until is not None and row.date <= lock_pair_until:
continue continue
if max_open_trades > 0: if max_open_trades > 0:
@ -286,11 +286,11 @@ class Backtesting(object):
if not data: if not data:
logger.critical("No data found. Terminating.") logger.critical("No data found. Terminating.")
return return
# Ignore max_open_trades in backtesting, except realistic flag was passed # Use max_open_trades in backtesting, except --disable-max-market-positions is set
if self.config.get('realistic_simulation', False): if self.config.get('use_max_market_positions', True):
max_open_trades = self.config['max_open_trades'] max_open_trades = self.config['max_open_trades']
else: else:
logger.info('Ignoring max_open_trades (realistic_simulation not set) ...') logger.info('Ignoring max_open_trades (--disable-max-market-positions was used) ...')
max_open_trades = 0 max_open_trades = 0
preprocessed = self.tickerdata_to_dataframe(data) preprocessed = self.tickerdata_to_dataframe(data)
@ -310,7 +310,7 @@ class Backtesting(object):
'stake_amount': self.config.get('stake_amount'), 'stake_amount': self.config.get('stake_amount'),
'processed': preprocessed, 'processed': preprocessed,
'max_open_trades': max_open_trades, 'max_open_trades': max_open_trades,
'realistic': self.config.get('realistic_simulation', False), 'position_stacking': self.config.get('position_stacking', False),
} }
) )

View File

@ -280,7 +280,7 @@ class Hyperopt(Backtesting):
{ {
'stake_amount': self.config['stake_amount'], 'stake_amount': self.config['stake_amount'],
'processed': processed, 'processed': processed,
'realistic': self.config.get('realistic_simulation', False), 'position_stacking': self.config.get('position_stacking', True),
} }
) )
result_explanation = self.format_results(results) result_explanation = self.format_results(results)

View File

@ -96,7 +96,7 @@ def simple_backtest(config, contour, num_results, mocker) -> None:
'stake_amount': config['stake_amount'], 'stake_amount': config['stake_amount'],
'processed': processed, 'processed': processed,
'max_open_trades': 1, 'max_open_trades': 1,
'realistic': True 'position_stacking': False
} }
) )
# results :: <class 'pandas.core.frame.DataFrame'> # results :: <class 'pandas.core.frame.DataFrame'>
@ -127,7 +127,7 @@ def _make_backtest_conf(mocker, conf=None, pair='UNITTEST/BTC', record=None):
'stake_amount': conf['stake_amount'], 'stake_amount': conf['stake_amount'],
'processed': backtesting.tickerdata_to_dataframe(data), 'processed': backtesting.tickerdata_to_dataframe(data),
'max_open_trades': 10, 'max_open_trades': 10,
'realistic': True, 'position_stacking': False,
'record': record 'record': record
} }
@ -193,8 +193,8 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
assert 'live' not in config assert 'live' not in config
assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert 'realistic_simulation' not in config assert 'position_stacking' not in config
assert not log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert not log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert 'refresh_pairs' not in config assert 'refresh_pairs' not in config
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
@ -218,7 +218,8 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
'backtesting', 'backtesting',
'--ticker-interval', '1m', '--ticker-interval', '1m',
'--live', '--live',
'--realistic-simulation', '--enable-position-stacking',
'--disable-max-market-positions',
'--refresh-pairs-cached', '--refresh-pairs-cached',
'--timerange', ':100', '--timerange', ':100',
'--export', '/bar/foo', '--export', '/bar/foo',
@ -246,9 +247,12 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
assert 'live' in config assert 'live' in config
assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert 'realistic_simulation' in config assert 'position_stacking' in config
assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples)
assert 'use_max_market_positions' in config
assert log_has('Parameter --disable-max-market-positions detected ...', caplog.record_tuples)
assert log_has('max_open_trades set to unlimited ...', caplog.record_tuples)
assert 'refresh_pairs' in config assert 'refresh_pairs' in config
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
@ -491,7 +495,7 @@ def test_backtest(default_conf, fee, mocker) -> None:
'stake_amount': default_conf['stake_amount'], 'stake_amount': default_conf['stake_amount'],
'processed': data_processed, 'processed': data_processed,
'max_open_trades': 10, 'max_open_trades': 10,
'realistic': True 'position_stacking': False
} }
) )
assert not results.empty assert not results.empty
@ -539,7 +543,7 @@ def test_backtest_1min_ticker_interval(default_conf, fee, mocker) -> None:
'stake_amount': default_conf['stake_amount'], 'stake_amount': default_conf['stake_amount'],
'processed': backtesting.tickerdata_to_dataframe(data), 'processed': backtesting.tickerdata_to_dataframe(data),
'max_open_trades': 1, 'max_open_trades': 1,
'realistic': True 'position_stacking': False
} }
) )
assert not results.empty assert not results.empty
@ -714,7 +718,8 @@ def test_backtest_start_live(default_conf, mocker, caplog):
'--ticker-interval', '1m', '--ticker-interval', '1m',
'--live', '--live',
'--timerange', '-100', '--timerange', '-100',
'--realistic-simulation' '--enable-position-stacking',
'--disable-max-market-positions'
] ]
args = get_args(args) args = get_args(args)
start(args) start(args)
@ -723,14 +728,14 @@ def test_backtest_start_live(default_conf, mocker, caplog):
'Parameter -i/--ticker-interval detected ...', 'Parameter -i/--ticker-interval detected ...',
'Using ticker_interval: 1m ...', 'Using ticker_interval: 1m ...',
'Parameter -l/--live detected ...', 'Parameter -l/--live detected ...',
'Using max_open_trades: 1 ...', 'Ignoring max_open_trades (--disable-max-market-positions was used) ...',
'Parameter --timerange detected: -100 ...', 'Parameter --timerange detected: -100 ...',
'Using data folder: freqtrade/tests/testdata ...', 'Using data folder: freqtrade/tests/testdata ...',
'Using stake_currency: BTC ...', 'Using stake_currency: BTC ...',
'Using stake_amount: 0.001 ...', 'Using stake_amount: 0.001 ...',
'Downloading data for all pairs in whitelist ...', 'Downloading data for all pairs in whitelist ...',
'Measuring data from 2017-11-14T19:31:00+00:00 up to 2017-11-14T22:58:00+00:00 (0 days)..', 'Measuring data from 2017-11-14T19:31:00+00:00 up to 2017-11-14T22:58:00+00:00 (0 days)..',
'Parameter --realistic-simulation detected ...' 'Parameter --enable-position-stacking detected ...'
] ]
for line in exists: for line in exists:

View File

@ -276,8 +276,8 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
assert 'live' not in config assert 'live' not in config
assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert not log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert 'realistic_simulation' not in config assert 'position_stacking' not in config
assert not log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert not log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert 'refresh_pairs' not in config assert 'refresh_pairs' not in config
assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert not log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)
@ -301,7 +301,8 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
'backtesting', 'backtesting',
'--ticker-interval', '1m', '--ticker-interval', '1m',
'--live', '--live',
'--realistic-simulation', '--enable-position-stacking',
'--disable-max-market-positions',
'--refresh-pairs-cached', '--refresh-pairs-cached',
'--timerange', ':100', '--timerange', ':100',
'--export', '/bar/foo' '--export', '/bar/foo'
@ -331,9 +332,12 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
assert 'live' in config assert 'live' in config
assert log_has('Parameter -l/--live detected ...', caplog.record_tuples) assert log_has('Parameter -l/--live detected ...', caplog.record_tuples)
assert 'realistic_simulation'in config assert 'position_stacking'in config
assert log_has('Parameter --realistic-simulation detected ...', caplog.record_tuples) assert log_has('Parameter --enable-position-stacking detected ...', caplog.record_tuples)
assert log_has('Using max_open_trades: 1 ...', caplog.record_tuples)
assert 'use_max_market_positions' in config
assert log_has('Parameter --disable-max-market-positions detected ...', caplog.record_tuples)
assert log_has('max_open_trades set to unlimited ...', caplog.record_tuples)
assert 'refresh_pairs'in config assert 'refresh_pairs'in config
assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples) assert log_has('Parameter -r/--refresh-pairs-cached detected ...', caplog.record_tuples)