Merge pull request #1700 from freqtrade/dataprovider/backtesting

Dataprovider during backtesting
This commit is contained in:
Misagh 2019-03-27 12:43:59 +01:00 committed by GitHub
commit 52012003e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 25 additions and 9 deletions

View File

@ -260,12 +260,9 @@ class Awesomestrategy(IStrategy):
The strategy provides access to the `DataProvider`. This allows you to get additional data to use in your strategy. The strategy provides access to the `DataProvider`. This allows you to get additional data to use in your strategy.
!!! Note
The DataProvier is currently not available during backtesting / hyperopt, but this is planned for the future.
All methods return `None` in case of failure (do not raise an exception). All methods return `None` in case of failure (do not raise an exception).
Please always check if the `DataProvider` is available to avoid failures during backtesting. Please always check the mode of operation to select the correct method to get data (samples see below).
#### Possible options for DataProvider #### Possible options for DataProvider
@ -292,6 +289,9 @@ if self.dp:
Be carefull when using dataprovider in backtesting. `historic_ohlcv()` provides the full time-range in one go, Be carefull when using dataprovider in backtesting. `historic_ohlcv()` provides the full time-range in one go,
so please be aware of it and make sure to not "look into the future" to avoid surprises when running in dry/live mode). so please be aware of it and make sure to not "look into the future" to avoid surprises when running in dry/live mode).
!!! Warning Warning in hyperopt
This option cannot currently be used during hyperopt.
#### Available Pairs #### Available Pairs
``` python ``` python

View File

@ -18,6 +18,7 @@ from freqtrade import DependencyException, constants
from freqtrade.arguments import Arguments from freqtrade.arguments import Arguments
from freqtrade.configuration import Configuration from freqtrade.configuration import Configuration
from freqtrade.data import history from freqtrade.data import history
from freqtrade.data.dataprovider import DataProvider
from freqtrade.misc import file_dump_json from freqtrade.misc import file_dump_json
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.resolvers import ExchangeResolver, StrategyResolver from freqtrade.resolvers import ExchangeResolver, StrategyResolver
@ -64,6 +65,15 @@ class Backtesting(object):
self.config['exchange']['uid'] = '' self.config['exchange']['uid'] = ''
self.config['dry_run'] = True self.config['dry_run'] = True
self.strategylist: List[IStrategy] = [] self.strategylist: List[IStrategy] = []
exchange_name = self.config.get('exchange', {}).get('name', 'bittrex').title()
self.exchange = ExchangeResolver(exchange_name, self.config).exchange
self.fee = self.exchange.get_fee()
if self.config.get('runmode') != RunMode.HYPEROPT:
self.dataprovider = DataProvider(self.config, self.exchange)
IStrategy.dp = self.dataprovider
if self.config.get('strategy_list', None): if self.config.get('strategy_list', None):
# Force one interval # Force one interval
self.ticker_interval = str(self.config.get('ticker_interval')) self.ticker_interval = str(self.config.get('ticker_interval'))
@ -78,15 +88,13 @@ class Backtesting(object):
self.strategylist.append(StrategyResolver(self.config).strategy) self.strategylist.append(StrategyResolver(self.config).strategy)
# Load one strategy # Load one strategy
self._set_strategy(self.strategylist[0]) self._set_strategy(self.strategylist[0])
exchange_name = self.config.get('exchange', {}).get('name', 'bittrex').title()
self.exchange = ExchangeResolver(exchange_name, self.config).exchange
self.fee = self.exchange.get_fee()
def _set_strategy(self, strategy): def _set_strategy(self, strategy):
""" """
Load strategy into backtesting Load strategy into backtesting
""" """
self.strategy = strategy self.strategy = strategy
self.ticker_interval = self.config.get('ticker_interval') self.ticker_interval = self.config.get('ticker_interval')
self.ticker_interval_mins = constants.TICKER_INTERVAL_MINUTES[self.ticker_interval] self.ticker_interval_mins = constants.TICKER_INTERVAL_MINUTES[self.ticker_interval]
self.tickerdata_to_dataframe = strategy.tickerdata_to_dataframe self.tickerdata_to_dataframe = strategy.tickerdata_to_dataframe

View File

@ -16,6 +16,7 @@ from freqtrade.arguments import Arguments, TimeRange
from freqtrade.data import history from freqtrade.data import history
from freqtrade.data.btanalysis import evaluate_result_multi from freqtrade.data.btanalysis import evaluate_result_multi
from freqtrade.data.converter import parse_ticker_dataframe from freqtrade.data.converter import parse_ticker_dataframe
from freqtrade.data.dataprovider import DataProvider
from freqtrade.optimize import get_timeframe from freqtrade.optimize import get_timeframe
from freqtrade.optimize.backtesting import (Backtesting, setup_configuration, from freqtrade.optimize.backtesting import (Backtesting, setup_configuration,
start) start)
@ -346,6 +347,7 @@ def test_backtesting_init(mocker, default_conf, order_types) -> None:
assert callable(backtesting.strategy.tickerdata_to_dataframe) assert callable(backtesting.strategy.tickerdata_to_dataframe)
assert callable(backtesting.advise_buy) assert callable(backtesting.advise_buy)
assert callable(backtesting.advise_sell) assert callable(backtesting.advise_sell)
assert isinstance(backtesting.strategy.dp, DataProvider)
get_fee.assert_called() get_fee.assert_called()
assert backtesting.fee == 0.5 assert backtesting.fee == 0.5
assert not backtesting.strategy.order_types["stoploss_on_exchange"] assert not backtesting.strategy.order_types["stoploss_on_exchange"]

View File

@ -13,12 +13,14 @@ import requests
from freqtrade import (DependencyException, OperationalException, from freqtrade import (DependencyException, OperationalException,
TemporaryError, constants) TemporaryError, constants)
from freqtrade.data.dataprovider import DataProvider
from freqtrade.freqtradebot import FreqtradeBot from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.rpc import RPCMessageType from freqtrade.rpc import RPCMessageType
from freqtrade.state import State from freqtrade.state import State
from freqtrade.strategy.interface import SellType, SellCheckTuple from freqtrade.strategy.interface import SellCheckTuple, SellType
from freqtrade.tests.conftest import log_has, log_has_re, patch_exchange, patch_edge, patch_wallet from freqtrade.tests.conftest import (log_has, log_has_re, patch_edge,
patch_exchange, patch_wallet)
# Functions for recurrent object patching # Functions for recurrent object patching
@ -88,6 +90,10 @@ def test_worker_running(mocker, default_conf, caplog) -> None:
assert state is State.RUNNING assert state is State.RUNNING
assert log_has('Changing state to: RUNNING', caplog.record_tuples) assert log_has('Changing state to: RUNNING', caplog.record_tuples)
assert mock_throttle.call_count == 1 assert mock_throttle.call_count == 1
# Check strategy is loaded, and received a dataprovider object
assert freqtrade.strategy
assert freqtrade.strategy.dp
assert isinstance(freqtrade.strategy.dp, DataProvider)
def test_worker_stopped(mocker, default_conf, caplog) -> None: def test_worker_stopped(mocker, default_conf, caplog) -> None: