Merge pull request #5936 from rokups/rk/decorator-fix
Use market data to get base and quote currencies in @informative() decorator
This commit is contained in:
commit
259b95074f
@ -67,7 +67,7 @@ class Backtesting:
|
|||||||
self.all_results: Dict[str, Dict] = {}
|
self.all_results: Dict[str, Dict] = {}
|
||||||
|
|
||||||
self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config)
|
self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config)
|
||||||
self.dataprovider = DataProvider(self.config, None)
|
self.dataprovider = DataProvider(self.config, self.exchange)
|
||||||
|
|
||||||
if self.config.get('strategy_list', None):
|
if self.config.get('strategy_list', None):
|
||||||
for strat in list(self.config['strategy_list']):
|
for strat in list(self.config['strategy_list']):
|
||||||
|
@ -80,12 +80,11 @@ def _create_and_merge_informative_pair(strategy, dataframe: DataFrame, metadata:
|
|||||||
# Not specifying an asset will define informative dataframe for current pair.
|
# Not specifying an asset will define informative dataframe for current pair.
|
||||||
asset = metadata['pair']
|
asset = metadata['pair']
|
||||||
|
|
||||||
if '/' in asset:
|
market = strategy.dp.market(asset)
|
||||||
base, quote = asset.split('/')
|
if market is None:
|
||||||
else:
|
raise OperationalException(f'Market {asset} is not available.')
|
||||||
# When futures are supported this may need reevaluation.
|
base = market['base']
|
||||||
# base, quote = asset, ''
|
quote = market['quote']
|
||||||
raise OperationalException('Not implemented.')
|
|
||||||
|
|
||||||
# Default format. This optimizes for the common case: informative pairs using same stake
|
# Default format. This optimizes for the common case: informative pairs using same stake
|
||||||
# currency. When quote currency matches stake currency, column name will omit base currency.
|
# currency. When quote currency matches stake currency, column name will omit base currency.
|
||||||
|
@ -20,7 +20,7 @@ class InformativeDecoratorTest(IStrategy):
|
|||||||
startup_candle_count: int = 20
|
startup_candle_count: int = 20
|
||||||
|
|
||||||
def informative_pairs(self):
|
def informative_pairs(self):
|
||||||
return [('BTC/USDT', '5m')]
|
return [('NEO/USDT', '5m')]
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['buy'] = 0
|
dataframe['buy'] = 0
|
||||||
@ -38,8 +38,8 @@ class InformativeDecoratorTest(IStrategy):
|
|||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
# Simple informative test.
|
# Simple informative test.
|
||||||
@informative('1h', 'BTC/{stake}')
|
@informative('1h', 'NEO/{stake}')
|
||||||
def populate_indicators_btc_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_neo_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe['rsi'] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ class InformativeDecoratorTest(IStrategy):
|
|||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
# Formatting test.
|
# Formatting test.
|
||||||
@informative('30m', 'BTC/{stake}', '{column}_{BASE}_{QUOTE}_{base}_{quote}_{asset}_{timeframe}')
|
@informative('30m', 'NEO/{stake}', '{column}_{BASE}_{QUOTE}_{base}_{quote}_{asset}_{timeframe}')
|
||||||
def populate_indicators_btc_1h_2(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_btc_1h_2(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe['rsi'] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
@ -68,7 +68,7 @@ class InformativeDecoratorTest(IStrategy):
|
|||||||
dataframe['rsi_less'] = dataframe['rsi'] < dataframe['rsi_1h']
|
dataframe['rsi_less'] = dataframe['rsi'] < dataframe['rsi_1h']
|
||||||
|
|
||||||
# Mixing manual informative pairs with decorators.
|
# Mixing manual informative pairs with decorators.
|
||||||
informative = self.dp.get_pair_dataframe('BTC/USDT', '5m')
|
informative = self.dp.get_pair_dataframe('NEO/USDT', '5m')
|
||||||
informative['rsi'] = 14
|
informative['rsi'] = 14
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, '5m', ffill=True)
|
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, '5m', ffill=True)
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import pytest
|
|||||||
from freqtrade.data.dataprovider import DataProvider
|
from freqtrade.data.dataprovider import DataProvider
|
||||||
from freqtrade.strategy import (merge_informative_pair, stoploss_from_absolute, stoploss_from_open,
|
from freqtrade.strategy import (merge_informative_pair, stoploss_from_absolute, stoploss_from_open,
|
||||||
timeframe_to_minutes)
|
timeframe_to_minutes)
|
||||||
|
from tests.conftest import get_patched_exchange
|
||||||
|
|
||||||
|
|
||||||
def generate_test_data(timeframe: str, size: int, start: str = '2020-07-05'):
|
def generate_test_data(timeframe: str, size: int, start: str = '2020-07-05'):
|
||||||
@ -155,9 +156,9 @@ def test_informative_decorator(mocker, default_conf):
|
|||||||
('LTC/USDT', '5m'): test_data_5m,
|
('LTC/USDT', '5m'): test_data_5m,
|
||||||
('LTC/USDT', '30m'): test_data_30m,
|
('LTC/USDT', '30m'): test_data_30m,
|
||||||
('LTC/USDT', '1h'): test_data_1h,
|
('LTC/USDT', '1h'): test_data_1h,
|
||||||
('BTC/USDT', '30m'): test_data_30m,
|
('NEO/USDT', '30m'): test_data_30m,
|
||||||
('BTC/USDT', '5m'): test_data_5m,
|
('NEO/USDT', '5m'): test_data_5m,
|
||||||
('BTC/USDT', '1h'): test_data_1h,
|
('NEO/USDT', '1h'): test_data_1h,
|
||||||
('ETH/USDT', '1h'): test_data_1h,
|
('ETH/USDT', '1h'): test_data_1h,
|
||||||
('ETH/USDT', '30m'): test_data_30m,
|
('ETH/USDT', '30m'): test_data_30m,
|
||||||
('ETH/BTC', '1h'): test_data_1h,
|
('ETH/BTC', '1h'): test_data_1h,
|
||||||
@ -165,15 +166,16 @@ def test_informative_decorator(mocker, default_conf):
|
|||||||
from .strats.informative_decorator_strategy import InformativeDecoratorTest
|
from .strats.informative_decorator_strategy import InformativeDecoratorTest
|
||||||
default_conf['stake_currency'] = 'USDT'
|
default_conf['stake_currency'] = 'USDT'
|
||||||
strategy = InformativeDecoratorTest(config=default_conf)
|
strategy = InformativeDecoratorTest(config=default_conf)
|
||||||
strategy.dp = DataProvider({}, None, None)
|
exchange = get_patched_exchange(mocker, default_conf)
|
||||||
|
strategy.dp = DataProvider({}, exchange, None)
|
||||||
mocker.patch.object(strategy.dp, 'current_whitelist', return_value=[
|
mocker.patch.object(strategy.dp, 'current_whitelist', return_value=[
|
||||||
'XRP/USDT', 'LTC/USDT', 'BTC/USDT'
|
'XRP/USDT', 'LTC/USDT', 'NEO/USDT'
|
||||||
])
|
])
|
||||||
|
|
||||||
assert len(strategy._ft_informative) == 6 # Equal to number of decorators used
|
assert len(strategy._ft_informative) == 6 # Equal to number of decorators used
|
||||||
informative_pairs = [('XRP/USDT', '1h'), ('LTC/USDT', '1h'), ('XRP/USDT', '30m'),
|
informative_pairs = [('XRP/USDT', '1h'), ('LTC/USDT', '1h'), ('XRP/USDT', '30m'),
|
||||||
('LTC/USDT', '30m'), ('BTC/USDT', '1h'), ('BTC/USDT', '30m'),
|
('LTC/USDT', '30m'), ('NEO/USDT', '1h'), ('NEO/USDT', '30m'),
|
||||||
('BTC/USDT', '5m'), ('ETH/BTC', '1h'), ('ETH/USDT', '30m')]
|
('NEO/USDT', '5m'), ('ETH/BTC', '1h'), ('ETH/USDT', '30m')]
|
||||||
for inf_pair in informative_pairs:
|
for inf_pair in informative_pairs:
|
||||||
assert inf_pair in strategy.gather_informative_pairs()
|
assert inf_pair in strategy.gather_informative_pairs()
|
||||||
|
|
||||||
@ -186,8 +188,8 @@ def test_informative_decorator(mocker, default_conf):
|
|||||||
{p: data[(p, strategy.timeframe)] for p in ('XRP/USDT', 'LTC/USDT')})
|
{p: data[(p, strategy.timeframe)] for p in ('XRP/USDT', 'LTC/USDT')})
|
||||||
expected_columns = [
|
expected_columns = [
|
||||||
'rsi_1h', 'rsi_30m', # Stacked informative decorators
|
'rsi_1h', 'rsi_30m', # Stacked informative decorators
|
||||||
'btc_usdt_rsi_1h', # BTC 1h informative
|
'neo_usdt_rsi_1h', # NEO 1h informative
|
||||||
'rsi_BTC_USDT_btc_usdt_BTC/USDT_30m', # Column formatting
|
'rsi_NEO_USDT_neo_usdt_NEO/USDT_30m', # Column formatting
|
||||||
'rsi_from_callable', # Custom column formatter
|
'rsi_from_callable', # Custom column formatter
|
||||||
'eth_btc_rsi_1h', # Quote currency not matching stake currency
|
'eth_btc_rsi_1h', # Quote currency not matching stake currency
|
||||||
'rsi', 'rsi_less', # Non-informative columns
|
'rsi', 'rsi_less', # Non-informative columns
|
||||||
|
Loading…
Reference in New Issue
Block a user