diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 744c77844..8e354b2fc 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -127,10 +127,9 @@ class Backtesting: self.config['startup_candle_count'] = self.required_startup self.exchange.validate_required_startup_candles(self.required_startup, self.timeframe) - # TODO-lev: This should come from the configuration setting or better a - # TODO-lev: combination of config/strategy "use_shorts"(?) and "can_short" from the exchange self.trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT) self.margin_mode: MarginMode = config.get('margin_mode', MarginMode.NONE) + # strategies which define "can_short=True" will fail to load in Spot mode. self._can_short = self.trading_mode != TradingMode.SPOT self.progress = BTProgress() diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 4050dcbdb..61cdfb2bc 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -1382,6 +1382,7 @@ def test_api_strategies(botclient): 'InformativeDecoratorTest', 'StrategyTestV2', 'StrategyTestV3', + 'StrategyTestV3Futures', 'TestStrategyLegacyV1', ]} diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py index 962fd02e9..ee3ce5773 100644 --- a/tests/strategy/strats/strategy_test_v3.py +++ b/tests/strategy/strats/strategy_test_v3.py @@ -187,3 +187,7 @@ class StrategyTestV3(IStrategy): return round(orders[0].cost, 0) return None + + +class StrategyTestV3Futures(StrategyTestV3): + can_short = True diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index 8f407396c..b8fe90e23 100644 --- a/tests/strategy/test_strategy_loading.py +++ b/tests/strategy/test_strategy_loading.py @@ -35,7 +35,7 @@ def test_search_all_strategies_no_failed(): directory = Path(__file__).parent / "strats" strategies = StrategyResolver.search_all_objects(directory, enum_failed=False) assert isinstance(strategies, list) - assert len(strategies) == 5 + assert len(strategies) == 6 assert isinstance(strategies[0], dict) @@ -43,10 +43,10 @@ def test_search_all_strategies_with_failed(): directory = Path(__file__).parent / "strats" strategies = StrategyResolver.search_all_objects(directory, enum_failed=True) assert isinstance(strategies, list) - assert len(strategies) == 6 + assert len(strategies) == 7 # with enum_failed=True search_all_objects() shall find 2 good strategies # and 1 which fails to load - assert len([x for x in strategies if x['class'] is not None]) == 5 + assert len([x for x in strategies if x['class'] is not None]) == 6 assert len([x for x in strategies if x['class'] is None]) == 1 @@ -128,6 +128,22 @@ def test_strategy_pre_v3(result, default_conf, strategy_name): assert 'exit_long' in dataframe.columns +def test_strategy_can_short(caplog, default_conf): + caplog.set_level(logging.INFO) + default_conf.update({ + 'strategy': CURRENT_TEST_STRATEGY, + }) + strat = StrategyResolver.load_strategy(default_conf) + assert isinstance(strat, IStrategy) + default_conf['strategy'] = 'StrategyTestV3Futures' + with pytest.raises(ImportError, match=""): + StrategyResolver.load_strategy(default_conf) + + default_conf['trading_mode'] = 'futures' + strat = StrategyResolver.load_strategy(default_conf) + assert isinstance(strat, IStrategy) + + def test_strategy_override_minimal_roi(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({