Pass analyzed dataframe to get_signal
This commit is contained in:
parent
48225e0d80
commit
f1993fb2f4
@ -424,7 +424,8 @@ class FreqtradeBot:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# running get_signal on historical data fetched
|
# running get_signal on historical data fetched
|
||||||
(buy, sell) = self.strategy.get_signal(pair, self.strategy.timeframe)
|
analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(pair, self.strategy.timeframe)
|
||||||
|
(buy, sell) = self.strategy.get_signal(pair, self.strategy.timeframe, analyzed_df)
|
||||||
|
|
||||||
if buy and not sell:
|
if buy and not sell:
|
||||||
stake_amount = self.get_trade_stake_amount(pair)
|
stake_amount = self.get_trade_stake_amount(pair)
|
||||||
@ -705,7 +706,10 @@ class FreqtradeBot:
|
|||||||
|
|
||||||
if (config_ask_strategy.get('use_sell_signal', True) or
|
if (config_ask_strategy.get('use_sell_signal', True) or
|
||||||
config_ask_strategy.get('ignore_roi_if_buy_signal', False)):
|
config_ask_strategy.get('ignore_roi_if_buy_signal', False)):
|
||||||
(buy, sell) = self.strategy.get_signal(trade.pair, self.strategy.timeframe)
|
analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair,
|
||||||
|
self.strategy.timeframe)
|
||||||
|
|
||||||
|
(buy, sell) = self.strategy.get_signal(trade.pair, self.strategy.timeframe, analyzed_df)
|
||||||
|
|
||||||
if config_ask_strategy.get('use_order_book', False):
|
if config_ask_strategy.get('use_order_book', False):
|
||||||
order_book_min = config_ask_strategy.get('order_book_min', 1)
|
order_book_min = config_ask_strategy.get('order_book_min', 1)
|
||||||
|
@ -406,19 +406,15 @@ class IStrategy(ABC):
|
|||||||
else:
|
else:
|
||||||
raise StrategyError(f"Dataframe returned from strategy has mismatching {message}.")
|
raise StrategyError(f"Dataframe returned from strategy has mismatching {message}.")
|
||||||
|
|
||||||
def get_signal(self, pair: str, timeframe: str) -> Tuple[bool, bool]:
|
def get_signal(self, pair: str, timeframe: str, dataframe: DataFrame) -> Tuple[bool, bool]:
|
||||||
"""
|
"""
|
||||||
Calculates current signal based based on the buy / sell columns of the dataframe.
|
Calculates current signal based based on the buy / sell columns of the dataframe.
|
||||||
Used by Bot to get the signal to buy or sell
|
Used by Bot to get the signal to buy or sell
|
||||||
:param pair: pair in format ANT/BTC
|
:param pair: pair in format ANT/BTC
|
||||||
:param timeframe: timeframe to use
|
:param timeframe: timeframe to use
|
||||||
|
:param dataframe: Analyzed dataframe to get signal from.
|
||||||
:return: (Buy, Sell) A bool-tuple indicating buy/sell signal
|
:return: (Buy, Sell) A bool-tuple indicating buy/sell signal
|
||||||
"""
|
"""
|
||||||
if not self.dp:
|
|
||||||
raise OperationalException("DataProvider not found.")
|
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, timeframe)
|
|
||||||
|
|
||||||
if not isinstance(dataframe, DataFrame) or dataframe.empty:
|
if not isinstance(dataframe, DataFrame) or dataframe.empty:
|
||||||
logger.warning(f'Empty candle (OHLCV) data for pair {pair}')
|
logger.warning(f'Empty candle (OHLCV) data for pair {pair}')
|
||||||
return False, False
|
return False, False
|
||||||
|
@ -163,7 +163,7 @@ def patch_get_signal(freqtrade: FreqtradeBot, value=(True, False)) -> None:
|
|||||||
:param value: which value IStrategy.get_signal() must return
|
:param value: which value IStrategy.get_signal() must return
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
freqtrade.strategy.get_signal = lambda e, s: value
|
freqtrade.strategy.get_signal = lambda e, s, x: value
|
||||||
freqtrade.exchange.refresh_latest_ohlcv = lambda p: None
|
freqtrade.exchange.refresh_latest_ohlcv = lambda p: None
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,40 +31,15 @@ def test_returns_latest_signal(mocker, default_conf, ohlcv_history):
|
|||||||
mocked_history['buy'] = 0
|
mocked_history['buy'] = 0
|
||||||
mocked_history.loc[1, 'sell'] = 1
|
mocked_history.loc[1, 'sell'] = 1
|
||||||
|
|
||||||
mocker.patch.object(
|
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, True)
|
||||||
_STRATEGY.dp, 'get_analyzed_dataframe',
|
|
||||||
return_value=(mocked_history, 0)
|
|
||||||
)
|
|
||||||
|
|
||||||
assert _STRATEGY.get_signal('ETH/BTC', '5m') == (False, True)
|
|
||||||
mocked_history.loc[1, 'sell'] = 0
|
mocked_history.loc[1, 'sell'] = 0
|
||||||
mocked_history.loc[1, 'buy'] = 1
|
mocked_history.loc[1, 'buy'] = 1
|
||||||
|
|
||||||
mocker.patch.object(
|
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False)
|
||||||
_STRATEGY.dp, 'get_analyzed_dataframe',
|
|
||||||
return_value=(mocked_history, 0)
|
|
||||||
)
|
|
||||||
assert _STRATEGY.get_signal('ETH/BTC', '5m') == (True, False)
|
|
||||||
mocked_history.loc[1, 'sell'] = 0
|
mocked_history.loc[1, 'sell'] = 0
|
||||||
mocked_history.loc[1, 'buy'] = 0
|
mocked_history.loc[1, 'buy'] = 0
|
||||||
|
|
||||||
mocker.patch.object(
|
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, False)
|
||||||
_STRATEGY.dp, 'get_analyzed_dataframe',
|
|
||||||
return_value=(mocked_history, 0)
|
|
||||||
)
|
|
||||||
assert _STRATEGY.get_signal('ETH/BTC', '5m') == (False, False)
|
|
||||||
|
|
||||||
|
|
||||||
def test_trade_no_dataprovider(default_conf, mocker, caplog):
|
|
||||||
strategy = DefaultStrategy({})
|
|
||||||
# Delete DP for sure (suffers from test leakage, as this is updated in the base class)
|
|
||||||
if strategy.dp is not None:
|
|
||||||
strategy.dp = None
|
|
||||||
with pytest.raises(OperationalException, match="DataProvider not found."):
|
|
||||||
strategy.get_signal('ETH/BTC', '5m')
|
|
||||||
|
|
||||||
with pytest.raises(OperationalException, match="DataProvider not found."):
|
|
||||||
strategy.analyze_pair('ETH/BTC')
|
|
||||||
|
|
||||||
|
|
||||||
def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):
|
def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):
|
||||||
@ -81,18 +56,15 @@ def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):
|
|||||||
|
|
||||||
|
|
||||||
def test_get_signal_empty(default_conf, mocker, caplog):
|
def test_get_signal_empty(default_conf, mocker, caplog):
|
||||||
mocker.patch.object(_STRATEGY.dp, 'get_analyzed_dataframe', return_value=(DataFrame(), 0))
|
assert (False, False) == _STRATEGY.get_signal('foo', default_conf['timeframe'], DataFrame())
|
||||||
assert (False, False) == _STRATEGY.get_signal('foo', default_conf['timeframe'])
|
|
||||||
assert log_has('Empty candle (OHLCV) data for pair foo', caplog)
|
assert log_has('Empty candle (OHLCV) data for pair foo', caplog)
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
|
|
||||||
mocker.patch.object(_STRATEGY.dp, 'get_analyzed_dataframe', return_value=(None, 0))
|
assert (False, False) == _STRATEGY.get_signal('bar', default_conf['timeframe'], None)
|
||||||
assert (False, False) == _STRATEGY.get_signal('bar', default_conf['timeframe'])
|
|
||||||
assert log_has('Empty candle (OHLCV) data for pair bar', caplog)
|
assert log_has('Empty candle (OHLCV) data for pair bar', caplog)
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
|
|
||||||
mocker.patch.object(_STRATEGY.dp, 'get_analyzed_dataframe', return_value=(DataFrame([]), 0))
|
assert (False, False) == _STRATEGY.get_signal('baz', default_conf['timeframe'], DataFrame([]))
|
||||||
assert (False, False) == _STRATEGY.get_signal('baz', default_conf['timeframe'])
|
|
||||||
assert log_has('Empty candle (OHLCV) data for pair baz', caplog)
|
assert log_has('Empty candle (OHLCV) data for pair baz', caplog)
|
||||||
|
|
||||||
|
|
||||||
@ -126,10 +98,9 @@ def test_get_signal_old_dataframe(default_conf, mocker, caplog, ohlcv_history):
|
|||||||
mocked_history.loc[1, 'buy'] = 1
|
mocked_history.loc[1, 'buy'] = 1
|
||||||
|
|
||||||
caplog.set_level(logging.INFO)
|
caplog.set_level(logging.INFO)
|
||||||
mocker.patch.object(_STRATEGY.dp, 'get_analyzed_dataframe', return_value=(mocked_history, 0))
|
|
||||||
mocker.patch.object(_STRATEGY, 'assert_df')
|
mocker.patch.object(_STRATEGY, 'assert_df')
|
||||||
|
|
||||||
assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['timeframe'])
|
assert (False, False) == _STRATEGY.get_signal('xyz', default_conf['timeframe'], mocked_history)
|
||||||
assert log_has('Outdated history for pair xyz. Last tick is 16 minutes old', caplog)
|
assert log_has('Outdated history for pair xyz. Last tick is 16 minutes old', caplog)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user