diff --git a/docs/includes/protections.md b/docs/includes/protections.md index a8caf55b1..7378a590c 100644 --- a/docs/includes/protections.md +++ b/docs/includes/protections.md @@ -7,7 +7,7 @@ Protections will protect your strategy from unexpected events and market conditi All protection end times are rounded up to the next candle to avoid sudden, unexpected intra-candle buys. !!! Note - Not all Protections will work for all strategies, and parameters will need to be tuned for your strategy. + Not all Protections will work for all strategies, and parameters will need to be tuned for your strategy to improve performance. !!! Tip Each Protection can be configured multiple times with different parameters, to allow different levels of protection (short-term / long-term). diff --git a/freqtrade/mixins/logging_mixin.py b/freqtrade/mixins/logging_mixin.py index 2e1c20a52..06935d5f6 100644 --- a/freqtrade/mixins/logging_mixin.py +++ b/freqtrade/mixins/logging_mixin.py @@ -1,4 +1,5 @@ from typing import Callable + from cachetools import TTLCache, cached diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 5bb7eaf74..de9c52dad 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -18,6 +18,7 @@ from freqtrade.data.converter import trim_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.exceptions import OperationalException from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds +from freqtrade.mixins import LoggingMixin from freqtrade.optimize.optimize_reports import (generate_backtest_stats, show_backtest_results, store_backtest_stats) from freqtrade.pairlist.pairlistmanager import PairListManager @@ -25,7 +26,6 @@ from freqtrade.persistence import PairLocks, Trade from freqtrade.plugins.protectionmanager import ProtectionManager from freqtrade.resolvers import ExchangeResolver, StrategyResolver from freqtrade.strategy.interface import IStrategy, SellCheckTuple, SellType -from freqtrade.mixins import LoggingMixin logger = logging.getLogger(__name__) diff --git a/freqtrade/plugins/protections/max_drawdown_protection.py b/freqtrade/plugins/protections/max_drawdown_protection.py index f1c77d1d9..d54e6699b 100644 --- a/freqtrade/plugins/protections/max_drawdown_protection.py +++ b/freqtrade/plugins/protections/max_drawdown_protection.py @@ -54,7 +54,10 @@ class MaxDrawdown(IProtection): return False, None, None # Drawdown is always positive - drawdown, _, _ = calculate_max_drawdown(trades_df, value_col='close_profit') + try: + drawdown, _, _ = calculate_max_drawdown(trades_df, value_col='close_profit') + except ValueError: + return False, None, None if drawdown > self._max_allowed_drawdown: self.log_once( diff --git a/tests/plugins/test_protections.py b/tests/plugins/test_protections.py index 2ad03a97c..82b6e4500 100644 --- a/tests/plugins/test_protections.py +++ b/tests/plugins/test_protections.py @@ -304,6 +304,18 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): 'XRP/BTC', fee.return_value, False, sell_reason=SellType.STOP_LOSS.value, min_ago_open=1000, min_ago_close=900, profit_rate=1.1, )) + Trade.session.add(generate_mock_trade( + 'ETH/BTC', fee.return_value, False, sell_reason=SellType.STOP_LOSS.value, + min_ago_open=1000, min_ago_close=900, profit_rate=1.1, + )) + Trade.session.add(generate_mock_trade( + 'NEO/BTC', fee.return_value, False, sell_reason=SellType.STOP_LOSS.value, + min_ago_open=1000, min_ago_close=900, profit_rate=1.1, + )) + # No losing trade yet ... so max_drawdown will raise exception + assert not freqtrade.protections.global_stop() + assert not freqtrade.protections.stop_per_pair('XRP/BTC') + Trade.session.add(generate_mock_trade( 'XRP/BTC', fee.return_value, False, sell_reason=SellType.STOP_LOSS.value, min_ago_open=500, min_ago_close=400, profit_rate=0.9,