diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 73af00fee..5872d95a6 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -79,6 +79,8 @@ class StrategyResolver(IResolver): ("sell_profit_only", False, 'ask_strategy'), ("ignore_roi_if_buy_signal", False, 'ask_strategy'), ("disable_dataframe_checks", False, None), + ("ignore_buying_expired_candle", None, 'ask_strategy'), + ("ignore_buying_expired_candle_after", 0, 'ask_strategy') ] for attribute, default, subkey in attributes: if subkey: diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index a1da3681d..8976b2fd5 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -15,7 +15,7 @@ from pandas import DataFrame from freqtrade.constants import ListPairsWithTimeframes from freqtrade.data.dataprovider import DataProvider from freqtrade.exceptions import OperationalException, StrategyError -from freqtrade.exchange import timeframe_to_minutes +from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange.exchange import timeframe_to_next_date from freqtrade.persistence import PairLocks, Trade from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper @@ -481,16 +481,16 @@ class IStrategy(ABC): (buy, sell) = latest[SignalType.BUY.value] == 1, latest[SignalType.SELL.value] == 1 logger.debug('trigger: %s (pair=%s) buy=%s sell=%s', latest['date'], pair, str(buy), str(sell)) - if self.ignore_expired_candle(dataframe=dataframe, buy=buy): + timeframe_seconds = timeframe_to_seconds(timeframe) + if self.ignore_expired_candle(latest_date=latest_date, timeframe_seconds=timeframe_seconds, buy=buy): return False, sell return buy, sell - def ignore_expired_candle(self, dataframe: DataFrame, buy: bool): + def ignore_expired_candle(self, latest_date: datetime, timeframe_seconds: int, buy: bool): if self.ignore_buying_expired_candle and buy: current_time = datetime.now(timezone.utc) - timedelta( seconds=self.ignore_buying_expired_candle_after) - candle_time = dataframe['date'].tail(1).iat[0] - time_delta = current_time - candle_time + time_delta = current_time - latest_date + timedelta(seconds=timeframe_seconds) return time_delta.total_seconds() > self.ignore_buying_expired_candle_after else: return False diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index f389be45b..af086b0da 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -112,15 +112,12 @@ def test_ignore_expired_candle(default_conf, ohlcv_history): strategy.ignore_buying_expired_candle = True strategy.ignore_buying_expired_candle_after = 60 - ohlcv_history.loc[-1, 'date'] = arrow.utcnow().shift(minutes=-3) + ohlcv_history.loc[-1, 'date'] = arrow.utcnow() # Take a copy to correctly modify the call mocked_history = ohlcv_history.copy() - mocked_history['sell'] = 0 - mocked_history['buy'] = 0 - mocked_history.loc[1, 'buy'] = 1 - mocked_history.loc[1, 'sell'] = 1 + latest_date = mocked_history['date'].max() - assert strategy.ignore_expired_candle(mocked_history, True) is True + assert strategy.ignore_expired_candle(latest_date=latest_date, timeframe_seconds=300, buy=True) is True def test_assert_df_raise(mocker, caplog, ohlcv_history):