diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index 6858deb69..3803beb70 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -435,7 +435,7 @@ def create_cum_profit(df: pd.DataFrame, trades: pd.DataFrame, col_name: str, def _calc_drawdown_series(profit_results: pd.DataFrame, *, date_col: str, value_col: str, - starting_balance : Optional[float] = 0.0) -> pd.DataFrame: + starting_balance: Optional[float] = 0.0) -> pd.DataFrame: max_drawdown_df = pd.DataFrame() max_drawdown_df['cumulative'] = profit_results[value_col].cumsum() max_drawdown_df['high_value'] = max_drawdown_df['cumulative'].cummax() @@ -446,13 +446,15 @@ def _calc_drawdown_series(profit_results: pd.DataFrame, *, date_col: str, value_ max_balance = starting_balance + max_drawdown_df['high_value'] max_drawdown_df['drawdown_relative'] = ((max_balance - cumulative_balance) / max_balance) else: - # This is not completely accurate, - max_drawdown_df['drawdown_relative'] = ((max_drawdown_df['high_value'] - max_drawdown_df['cumulative']) / max_drawdown_df['high_value']) + # This is not completely accurate + max_drawdown_df['drawdown_relative'] = ( + (max_drawdown_df['high_value'] - max_drawdown_df['cumulative']) + / max_drawdown_df['high_value']) return max_drawdown_df def calculate_underwater(trades: pd.DataFrame, *, date_col: str = 'close_date', - value_col: str = 'profit_ratio', starting_balance : Optional[float] = 0.0 + value_col: str = 'profit_ratio', starting_balance: Optional[float] = 0.0 ): """ Calculate max drawdown and the corresponding close dates @@ -466,7 +468,11 @@ def calculate_underwater(trades: pd.DataFrame, *, date_col: str = 'close_date', if len(trades) == 0: raise ValueError("Trade dataframe empty.") profit_results = trades.sort_values(date_col).reset_index(drop=True) - max_drawdown_df = _calc_drawdown_series(profit_results, date_col=date_col, value_col=value_col, starting_balance=starting_balance) + max_drawdown_df = _calc_drawdown_series( + profit_results, + date_col=date_col, + value_col=value_col, + starting_balance=starting_balance) return max_drawdown_df @@ -489,9 +495,15 @@ def calculate_max_drawdown(trades: pd.DataFrame, *, date_col: str = 'close_date' if len(trades) == 0: raise ValueError("Trade dataframe empty.") profit_results = trades.sort_values(date_col).reset_index(drop=True) - max_drawdown_df = _calc_drawdown_series(profit_results, date_col=date_col, value_col=value_col, starting_balance=starting_balance) + max_drawdown_df = _calc_drawdown_series( + profit_results, + date_col=date_col, + value_col=value_col, + starting_balance=starting_balance + ) - idxmin = max_drawdown_df['drawdown_relative'].idxmax() if relative else max_drawdown_df['drawdown'].idxmin() + idxmin = max_drawdown_df['drawdown_relative'].idxmax() if relative \ + else max_drawdown_df['drawdown'].idxmin() if idxmin == 0: raise ValueError("No losing trade, therefore no drawdown.") high_date = profit_results.loc[max_drawdown_df.iloc[:idxmin]['high_value'].idxmax(), date_col] diff --git a/freqtrade/optimize/hyperopt_loss_max_drawdown_relative.py b/freqtrade/optimize/hyperopt_loss_max_drawdown_relative.py index c4dd843b8..62fe76ee6 100644 --- a/freqtrade/optimize/hyperopt_loss_max_drawdown_relative.py +++ b/freqtrade/optimize/hyperopt_loss_max_drawdown_relative.py @@ -4,12 +4,11 @@ MaxDrawDownRelativeHyperOptLoss This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ -from datetime import datetime from typing import Dict from pandas import DataFrame -from freqtrade.data.btanalysis import calculate_underwater, calculate_max_drawdown +from freqtrade.data.btanalysis import calculate_underwater from freqtrade.optimize.hyperopt import IHyperOptLoss @@ -34,7 +33,11 @@ class MaxDrawDownRelativeHyperOptLoss(IHyperOptLoss): """ total_profit = results['profit_abs'].sum() try: - drawdown_df = calculate_underwater(results, value_col='profit_abs', starting_balance=config['available_capital']) + drawdown_df = calculate_underwater( + results, + value_col='profit_abs', + starting_balance=config['available_capital'] + ) max_drawdown = abs(min(drawdown_df['drawdown'])) relative_drawdown = max(drawdown_df['drawdown_relative']) if max_drawdown == 0: @@ -42,4 +45,3 @@ class MaxDrawDownRelativeHyperOptLoss(IHyperOptLoss): return -total_profit / max_drawdown / relative_drawdown except (Exception, ValueError): return -total_profit - diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 2d6e17468..32d16a235 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -769,7 +769,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: if 'max_drawdown_account' in strat_results else ( 'Drawdown', f"{strat_results['max_drawdown']:.2%}"), ('Absolute Drawdown', round_coin_value(strat_results['max_drawdown_abs'], - strat_results['stake_currency'])), + strat_results['stake_currency'])), ('Drawdown high', round_coin_value(strat_results['max_drawdown_high'], strat_results['stake_currency'])), ('Drawdown low', round_coin_value(strat_results['max_drawdown_low'], diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index 3d651c1d9..ed403e09f 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -164,7 +164,10 @@ def add_max_drawdown(fig, row, trades: pd.DataFrame, df_comb: pd.DataFrame, Add scatter points indicating max drawdown """ try: - _, highdate, lowdate, _, _, max_drawdown = calculate_max_drawdown(trades, starting_balance=starting_balance) + _, highdate, lowdate, _, _, max_drawdown = calculate_max_drawdown( + trades, + starting_balance=starting_balance + ) drawdown = go.Scatter( x=[highdate, lowdate], @@ -194,7 +197,11 @@ def add_underwater(fig, row, trades: pd.DataFrame, starting_balance: number) -> Add underwater plots """ try: - underwater = calculate_underwater(trades, value_col="profit_abs", starting_balance=starting_balance) + underwater = calculate_underwater( + trades, + value_col="profit_abs", + starting_balance=starting_balance + ) underwater_plot = go.Scatter( x=underwater['date'], @@ -213,9 +220,9 @@ def add_underwater(fig, row, trades: pd.DataFrame, starting_balance: number) -> fillcolor='green', line={'color': 'green'} ) - + fig.add_trace(underwater_plot, row, 1) - fig.add_trace(underwater_plot_relative, row+1, 1) + fig.add_trace(underwater_plot_relative, row + 1, 1) except ValueError: logger.warning("No trades found - not plotting underwater plot") return fig