[SQUASH] Fix informatives for each pair not being created because dataprovider was not available.
Fix not being able to have informative dataframe of a pair in whitelist.
This commit is contained in:
parent
f2a1d9d2fc
commit
dfa61b7ad2
@ -702,9 +702,9 @@ def informative(timeframe: str, asset: str = '',
|
||||
:param fmt: Column format (str) or column formatter (callable(name, asset, timeframe)). When not
|
||||
specified, defaults to:
|
||||
* {base}_{column}_{timeframe} if asset is specified and quote currency does match stake
|
||||
curerncy.
|
||||
currency.
|
||||
* {base}_{quote}_{column}_{timeframe} if asset is specified and quote currency does not match
|
||||
stake curerncy.
|
||||
stake currency.
|
||||
* {column}_{timeframe} if asset is not specified.
|
||||
Format string supports these format variables:
|
||||
* {asset} - full name of the asset, for example 'BTC/USDT'.
|
||||
|
@ -83,10 +83,12 @@ class FreqtradeBot(LoggingMixin):
|
||||
|
||||
self.dataprovider = DataProvider(self.config, self.exchange, self.pairlists)
|
||||
|
||||
# Attach Dataprovider to Strategy baseclass
|
||||
IStrategy.dp = self.dataprovider
|
||||
# Attach Wallets to Strategy baseclass
|
||||
IStrategy.wallets = self.wallets
|
||||
# Attach Dataprovider to strategy instance
|
||||
self.strategy.dp = self.dataprovider
|
||||
# Attach Wallets to strategy instance
|
||||
self.strategy.wallets = self.wallets
|
||||
# Late initialization (may depend on dp/wallets)
|
||||
self.strategy._initialize()
|
||||
|
||||
# Initializing Edge only if enabled
|
||||
self.edge = Edge(self.config, self.exchange, self.strategy) if \
|
||||
|
@ -154,11 +154,12 @@ class Backtesting:
|
||||
self.strategy: IStrategy = strategy
|
||||
strategy.dp = self.dataprovider
|
||||
# Attach Wallets to Strategy baseclass
|
||||
IStrategy.wallets = self.wallets
|
||||
strategy.wallets = self.wallets
|
||||
# Set stoploss_on_exchange to false for backtesting,
|
||||
# since a "perfect" stoploss-sell is assumed anyway
|
||||
# And the regular "stoploss" function would not apply to that case
|
||||
self.strategy.order_types['stoploss_on_exchange'] = False
|
||||
strategy._initialize()
|
||||
|
||||
def _load_protections(self, strategy: IStrategy):
|
||||
if self.config.get('enable_protections', False):
|
||||
|
@ -8,6 +8,7 @@ from typing import Any, Dict
|
||||
|
||||
from freqtrade import constants
|
||||
from freqtrade.configuration import TimeRange, validate_config_consistency
|
||||
from freqtrade.data.dataprovider import DataProvider
|
||||
from freqtrade.edge import Edge
|
||||
from freqtrade.optimize.optimize_reports import generate_edge_table
|
||||
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
||||
@ -33,6 +34,8 @@ class EdgeCli:
|
||||
self.config['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT
|
||||
self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config)
|
||||
self.strategy = StrategyResolver.load_strategy(self.config)
|
||||
self.strategy.dp = DataProvider(config, None)
|
||||
self.strategy._initialize()
|
||||
|
||||
validate_config_consistency(self.config)
|
||||
|
||||
|
@ -137,9 +137,13 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
self._last_candle_seen_per_pair: Dict[str, datetime] = {}
|
||||
super().__init__(config)
|
||||
|
||||
def _initialize(self):
|
||||
"""
|
||||
Late initialization tasks, which may depend on availability of dataprovider/wallets/etc.
|
||||
"""
|
||||
# Gather informative pairs from @informative-decorated methods.
|
||||
self._ft_informative: Dict[
|
||||
Tuple[str, str], Tuple[InformativeData, PopulateIndicators]] = {}
|
||||
Tuple[str, str], List[Tuple[InformativeData, PopulateIndicators]]] = {}
|
||||
for attr_name in dir(self.__class__):
|
||||
cls_method = getattr(self.__class__, attr_name)
|
||||
if not callable(cls_method):
|
||||
@ -158,16 +162,19 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
'strategy timeframe!')
|
||||
if asset:
|
||||
pair = _format_pair_name(self.config, asset)
|
||||
if (pair, timeframe) in self._ft_informative:
|
||||
raise OperationalException(f'Informative pair {pair} {timeframe} can not '
|
||||
f'be defined more than once!')
|
||||
self._ft_informative[(pair, timeframe)] = (informative_data, cls_method)
|
||||
elif self.dp is not None:
|
||||
try:
|
||||
self._ft_informative[(pair, timeframe)].append(
|
||||
(informative_data, cls_method))
|
||||
except KeyError:
|
||||
self._ft_informative[(pair, timeframe)] = [(informative_data, cls_method)]
|
||||
else:
|
||||
for pair in self.dp.current_whitelist():
|
||||
if (pair, timeframe) in self._ft_informative:
|
||||
raise OperationalException(f'Informative pair {pair} {timeframe} can '
|
||||
f'not be defined more than once!')
|
||||
self._ft_informative[(pair, timeframe)] = (informative_data, cls_method)
|
||||
try:
|
||||
self._ft_informative[(pair, timeframe)].append(
|
||||
(informative_data, cls_method))
|
||||
except KeyError:
|
||||
self._ft_informative[(pair, timeframe)] = \
|
||||
[(informative_data, cls_method)]
|
||||
|
||||
@abstractmethod
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
@ -838,11 +845,12 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
logger.debug(f"Populating indicators for pair {metadata.get('pair')}.")
|
||||
|
||||
# call populate_indicators_Nm() which were tagged with @informative decorator.
|
||||
for (pair, timeframe), (informative_data, populate_fn) in self._ft_informative.items():
|
||||
if not informative_data.asset and pair != metadata['pair']:
|
||||
continue
|
||||
dataframe = _create_and_merge_informative_pair(
|
||||
self, dataframe, metadata, informative_data, populate_fn)
|
||||
for (pair, timeframe), informatives in self._ft_informative.items():
|
||||
for (informative_data, populate_fn) in informatives:
|
||||
if not informative_data.asset and pair != metadata['pair']:
|
||||
continue
|
||||
dataframe = _create_and_merge_informative_pair(
|
||||
self, dataframe, metadata, informative_data, populate_fn)
|
||||
|
||||
if self._populate_fun_len == 2:
|
||||
warnings.warn("deprecated - check out the Sample strategy to see "
|
||||
|
@ -139,9 +139,9 @@ def informative(timeframe: str, asset: str = '',
|
||||
:param fmt: Column format (str) or column formatter (callable(name, asset, timeframe)). When not
|
||||
specified, defaults to:
|
||||
* {base}_{column}_{timeframe} if asset is specified and quote currency does match stake
|
||||
curerncy.
|
||||
currency.
|
||||
* {base}_{quote}_{column}_{timeframe} if asset is specified and quote currency does not match
|
||||
stake curerncy.
|
||||
stake currency.
|
||||
* {column}_{timeframe} if asset is not specified.
|
||||
Format string supports these format variables:
|
||||
* {asset} - full name of the asset, for example 'BTC/USDT'.
|
||||
@ -203,11 +203,10 @@ def _create_and_merge_informative_pair(strategy, dataframe: DataFrame,
|
||||
# fmt='{base}_{quote}_{column}_{timeframe}' format or similar.
|
||||
if not fmt:
|
||||
fmt = '{column}_{timeframe}' # Informatives of current pair
|
||||
if asset != metadata['pair']:
|
||||
if quote == config['stake_currency']:
|
||||
fmt = '{base}_' + fmt # Informatives of other pair
|
||||
else:
|
||||
fmt = '{base}_{quote}_' + fmt # Informatives of different quote currency
|
||||
if quote != config['stake_currency']:
|
||||
fmt = '{quote}_' + fmt # Informatives of different quote currency
|
||||
if informative_data.asset:
|
||||
fmt = '{base}_' + fmt # Informatives of other pair
|
||||
|
||||
inf_metadata = {'pair': asset, 'timeframe': timeframe}
|
||||
inf_dataframe = dp.get_pair_dataframe(asset, timeframe)
|
||||
|
@ -155,11 +155,12 @@ def test_informative_decorator(mocker, default_conf):
|
||||
}
|
||||
from .strats.informative_decorator_strategy import InformativeDecoratorTest
|
||||
default_conf['stake_currency'] = 'USDT'
|
||||
InformativeDecoratorTest.dp = DataProvider({}, None, None)
|
||||
mocker.patch.object(InformativeDecoratorTest.dp, 'current_whitelist', return_value=[
|
||||
'XRP/USDT', 'LTC/USDT'
|
||||
])
|
||||
strategy = InformativeDecoratorTest(config=default_conf)
|
||||
strategy.dp = DataProvider({}, None, None)
|
||||
mocker.patch.object(strategy.dp, 'current_whitelist', return_value=[
|
||||
'XRP/USDT', 'LTC/USDT', 'BTC/USDT'
|
||||
])
|
||||
strategy._initialize()
|
||||
|
||||
assert len(strategy._ft_informative) == 8
|
||||
informative_pairs = [('XRP/USDT', '1h'), ('LTC/USDT', '1h'), ('XRP/USDT', '30m'),
|
||||
|
Loading…
Reference in New Issue
Block a user