From f1ef537dfa0bb1a87a66404672c2807c95c6ca3f Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 12 May 2024 17:13:50 +0200 Subject: [PATCH] ruff format: hyperopt-loss --- .../hyperopt_loss/hyperopt_loss_calmar.py | 15 +++++--- .../hyperopt_loss_max_drawdown.py | 18 ++++++---- .../hyperopt_loss_max_drawdown_relative.py | 16 ++++----- .../hyperopt_loss/hyperopt_loss_onlyprofit.py | 6 ++-- .../hyperopt_loss_profit_drawdown.py | 1 + .../hyperopt_loss/hyperopt_loss_sharpe.py | 15 +++++--- .../hyperopt_loss_sharpe_daily.py | 30 ++++++++++------ .../hyperopt_loss_short_trade_dur.py | 10 +++--- .../hyperopt_loss/hyperopt_loss_sortino.py | 15 +++++--- .../hyperopt_loss_sortino_daily.py | 36 +++++++++++-------- 10 files changed, 100 insertions(+), 62 deletions(-) diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py index b8935b08e..f22d59e50 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py @@ -4,6 +4,7 @@ CalmarHyperOptLoss This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + from datetime import datetime from pandas import DataFrame @@ -21,15 +22,21 @@ class CalmarHyperOptLoss(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - min_date: datetime, max_date: datetime, - config: Config, *args, **kwargs) -> float: + def hyperopt_loss_function( + results: DataFrame, + trade_count: int, + min_date: datetime, + max_date: datetime, + config: Config, + *args, + **kwargs, + ) -> float: """ Objective function, returns smaller number for more optimal results. Uses Calmar Ratio calculation. """ - starting_balance = config['dry_run_wallet'] + starting_balance = config["dry_run_wallet"] calmar_ratio = calculate_calmar(results, min_date, max_date, starting_balance) # print(expected_returns_mean, max_drawdown, calmar_ratio) return -calmar_ratio diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py index a8af704cd..4d6a7efac 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py @@ -4,6 +4,7 @@ MaxDrawDownHyperOptLoss This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + from datetime import datetime from pandas import DataFrame @@ -13,7 +14,6 @@ from freqtrade.optimize.hyperopt import IHyperOptLoss class MaxDrawDownHyperOptLoss(IHyperOptLoss): - """ Defines the loss function for hyperopt. @@ -22,19 +22,23 @@ class MaxDrawDownHyperOptLoss(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - min_date: datetime, max_date: datetime, - *args, **kwargs) -> float: - + def hyperopt_loss_function( + results: DataFrame, + trade_count: int, + min_date: datetime, + max_date: datetime, + *args, + **kwargs, + ) -> float: """ Objective function. Uses profit ratio weighted max_drawdown when drawdown is available. Otherwise directly optimizes profit ratio. """ - total_profit = results['profit_abs'].sum() + total_profit = results["profit_abs"].sum() try: - max_drawdown = calculate_max_drawdown(results, value_col='profit_abs') + max_drawdown = calculate_max_drawdown(results, value_col="profit_abs") except ValueError: # No losing trade, therefore no drawdown. return -total_profit diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown_relative.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown_relative.py index 669d12ddf..ee7088d75 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown_relative.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown_relative.py @@ -4,6 +4,7 @@ MaxDrawDownRelativeHyperOptLoss This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + from pandas import DataFrame from freqtrade.constants import Config @@ -12,7 +13,6 @@ from freqtrade.optimize.hyperopt import IHyperOptLoss class MaxDrawDownRelativeHyperOptLoss(IHyperOptLoss): - """ Defines the loss function for hyperopt. @@ -21,24 +21,20 @@ class MaxDrawDownRelativeHyperOptLoss(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, config: Config, - *args, **kwargs) -> float: - + def hyperopt_loss_function(results: DataFrame, config: Config, *args, **kwargs) -> float: """ Objective function. Uses profit ratio weighted max_drawdown when drawdown is available. Otherwise directly optimizes profit ratio. """ - total_profit = results['profit_abs'].sum() + total_profit = results["profit_abs"].sum() try: drawdown_df = calculate_underwater( - results, - value_col='profit_abs', - starting_balance=config['dry_run_wallet'] + results, value_col="profit_abs", starting_balance=config["dry_run_wallet"] ) - max_drawdown = abs(min(drawdown_df['drawdown'])) - relative_drawdown = max(drawdown_df['drawdown_relative']) + max_drawdown = abs(min(drawdown_df["drawdown"])) + relative_drawdown = max(drawdown_df["drawdown_relative"]) if max_drawdown == 0: return -total_profit return -total_profit / max_drawdown / relative_drawdown diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_onlyprofit.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_onlyprofit.py index 4a3cf1b3b..dd4a448d5 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_onlyprofit.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_onlyprofit.py @@ -4,6 +4,7 @@ OnlyProfitHyperOptLoss This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + from pandas import DataFrame from freqtrade.optimize.hyperopt import IHyperOptLoss @@ -17,10 +18,9 @@ class OnlyProfitHyperOptLoss(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - *args, **kwargs) -> float: + def hyperopt_loss_function(results: DataFrame, trade_count: int, *args, **kwargs) -> float: """ Objective function, returns smaller number for better results. """ - total_profit = results['profit_abs'].sum() + total_profit = results["profit_abs"].sum() return -1 * total_profit diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py index ed689edba..99d28de0d 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py @@ -7,6 +7,7 @@ Drawdown objective which can be used for Hyperoptimization. Possible to change `DRAWDOWN_MULT` to penalize drawdown objective for individual needs. """ + from pandas import DataFrame from freqtrade.data.metrics import calculate_max_drawdown diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe.py index 8ebb90fc5..2c7042a8a 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe.py @@ -4,6 +4,7 @@ SharpeHyperOptLoss This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + from datetime import datetime from pandas import DataFrame @@ -21,15 +22,21 @@ class SharpeHyperOptLoss(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - min_date: datetime, max_date: datetime, - config: Config, *args, **kwargs) -> float: + def hyperopt_loss_function( + results: DataFrame, + trade_count: int, + min_date: datetime, + max_date: datetime, + config: Config, + *args, + **kwargs, + ) -> float: """ Objective function, returns smaller number for more optimal results. Uses Sharpe Ratio calculation. """ - starting_balance = config['dry_run_wallet'] + starting_balance = config["dry_run_wallet"] sharp_ratio = calculate_sharpe(results, min_date, max_date, starting_balance) # print(expected_returns_mean, up_stdev, sharp_ratio) return -sharp_ratio diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe_daily.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe_daily.py index 88c97989a..ea1efe0e1 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe_daily.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sharpe_daily.py @@ -4,6 +4,7 @@ SharpeHyperOptLossDaily This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + import math from datetime import datetime @@ -20,31 +21,38 @@ class SharpeHyperOptLossDaily(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - min_date: datetime, max_date: datetime, - *args, **kwargs) -> float: + def hyperopt_loss_function( + results: DataFrame, + trade_count: int, + min_date: datetime, + max_date: datetime, + *args, + **kwargs, + ) -> float: """ Objective function, returns smaller number for more optimal results. Uses Sharpe Ratio calculation. """ - resample_freq = '1D' + resample_freq = "1D" slippage_per_trade_ratio = 0.0005 days_in_year = 365 annual_risk_free_rate = 0.0 risk_free_rate = annual_risk_free_rate / days_in_year # apply slippage per trade to profit_ratio - results.loc[:, 'profit_ratio_after_slippage'] = \ - results['profit_ratio'] - slippage_per_trade_ratio + results.loc[:, "profit_ratio_after_slippage"] = ( + results["profit_ratio"] - slippage_per_trade_ratio + ) # create the index within the min_date and end max_date - t_index = date_range(start=min_date, end=max_date, freq=resample_freq, - normalize=True) + t_index = date_range(start=min_date, end=max_date, freq=resample_freq, normalize=True) sum_daily = ( - results.resample(resample_freq, on='close_date').agg( - {"profit_ratio_after_slippage": 'sum'}).reindex(t_index).fillna(0) + results.resample(resample_freq, on="close_date") + .agg({"profit_ratio_after_slippage": "sum"}) + .reindex(t_index) + .fillna(0) ) total_profit = sum_daily["profit_ratio_after_slippage"] - risk_free_rate @@ -55,7 +63,7 @@ class SharpeHyperOptLossDaily(IHyperOptLoss): sharp_ratio = expected_returns_mean / up_stdev * math.sqrt(days_in_year) else: # Define high (negative) sharpe ratio to be clear that this is NOT optimal. - sharp_ratio = -20. + sharp_ratio = -20.0 # print(t_index, sum_daily, total_profit) # print(risk_free_rate, expected_returns_mean, up_stdev, sharp_ratio) diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_short_trade_dur.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_short_trade_dur.py index 3712fd9a6..12565f10e 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_short_trade_dur.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_short_trade_dur.py @@ -3,6 +3,7 @@ ShortTradeDurHyperOptLoss This module defines the default HyperoptLoss class which is being used for Hyperoptimization. """ + from math import exp from pandas import DataFrame @@ -32,8 +33,7 @@ class ShortTradeDurHyperOptLoss(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - *args, **kwargs) -> float: + def hyperopt_loss_function(results: DataFrame, trade_count: int, *args, **kwargs) -> float: """ Objective function, returns smaller number for better results This is the Default algorithm @@ -42,10 +42,10 @@ class ShortTradeDurHyperOptLoss(IHyperOptLoss): * 0.25: Avoiding trade loss * 1.0 to total profit, compared to the expected value (`EXPECTED_MAX_PROFIT`) defined above """ - total_profit = results['profit_ratio'].sum() - trade_duration = results['trade_duration'].mean() + total_profit = results["profit_ratio"].sum() + trade_duration = results["trade_duration"].mean() - trade_loss = 1 - 0.25 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.8) + trade_loss = 1 - 0.25 * exp(-((trade_count - TARGET_TRADES) ** 2) / 10**5.8) profit_loss = max(0, 1 - total_profit / EXPECTED_MAX_PROFIT) duration_loss = 0.4 * min(trade_duration / MAX_ACCEPTED_TRADE_DURATION, 1) result = trade_loss + profit_loss + duration_loss diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino.py index a0122a0bf..32ff0c73f 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino.py @@ -4,6 +4,7 @@ SortinoHyperOptLoss This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + from datetime import datetime from pandas import DataFrame @@ -21,15 +22,21 @@ class SortinoHyperOptLoss(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - min_date: datetime, max_date: datetime, - config: Config, *args, **kwargs) -> float: + def hyperopt_loss_function( + results: DataFrame, + trade_count: int, + min_date: datetime, + max_date: datetime, + config: Config, + *args, + **kwargs, + ) -> float: """ Objective function, returns smaller number for more optimal results. Uses Sortino Ratio calculation. """ - starting_balance = config['dry_run_wallet'] + starting_balance = config["dry_run_wallet"] sortino_ratio = calculate_sortino(results, min_date, max_date, starting_balance) # print(expected_returns_mean, down_stdev, sortino_ratio) return -sortino_ratio diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino_daily.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino_daily.py index 5beacc6fc..321b89dc2 100644 --- a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino_daily.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_sortino_daily.py @@ -4,6 +4,7 @@ SortinoHyperOptLossDaily This module defines the alternative HyperOptLoss class which can be used for Hyperoptimization. """ + import math from datetime import datetime @@ -20,9 +21,14 @@ class SortinoHyperOptLossDaily(IHyperOptLoss): """ @staticmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, - min_date: datetime, max_date: datetime, - *args, **kwargs) -> float: + def hyperopt_loss_function( + results: DataFrame, + trade_count: int, + min_date: datetime, + max_date: datetime, + *args, + **kwargs, + ) -> float: """ Objective function, returns smaller number for more optimal results. @@ -31,30 +37,32 @@ class SortinoHyperOptLossDaily(IHyperOptLoss): Sortino Ratio calculated as described in http://www.redrockcapital.com/Sortino__A__Sharper__Ratio_Red_Rock_Capital.pdf """ - resample_freq = '1D' + resample_freq = "1D" slippage_per_trade_ratio = 0.0005 days_in_year = 365 minimum_acceptable_return = 0.0 # apply slippage per trade to profit_ratio - results.loc[:, 'profit_ratio_after_slippage'] = \ - results['profit_ratio'] - slippage_per_trade_ratio + results.loc[:, "profit_ratio_after_slippage"] = ( + results["profit_ratio"] - slippage_per_trade_ratio + ) # create the index within the min_date and end max_date - t_index = date_range(start=min_date, end=max_date, freq=resample_freq, - normalize=True) + t_index = date_range(start=min_date, end=max_date, freq=resample_freq, normalize=True) sum_daily = ( - results.resample(resample_freq, on='close_date').agg( - {"profit_ratio_after_slippage": 'sum'}).reindex(t_index).fillna(0) + results.resample(resample_freq, on="close_date") + .agg({"profit_ratio_after_slippage": "sum"}) + .reindex(t_index) + .fillna(0) ) total_profit = sum_daily["profit_ratio_after_slippage"] - minimum_acceptable_return expected_returns_mean = total_profit.mean() - sum_daily['downside_returns'] = 0.0 - sum_daily.loc[total_profit < 0, 'downside_returns'] = total_profit - total_downside = sum_daily['downside_returns'] + sum_daily["downside_returns"] = 0.0 + sum_daily.loc[total_profit < 0, "downside_returns"] = total_profit + total_downside = sum_daily["downside_returns"] # Here total_downside contains min(0, P - MAR) values, # where P = sum_daily["profit_ratio_after_slippage"] down_stdev = math.sqrt((total_downside**2).sum() / len(total_downside)) @@ -63,7 +71,7 @@ class SortinoHyperOptLossDaily(IHyperOptLoss): sortino_ratio = expected_returns_mean / down_stdev * math.sqrt(days_in_year) else: # Define high (negative) sortino ratio to be clear that this is NOT optimal. - sortino_ratio = -20. + sortino_ratio = -20.0 # print(t_index, sum_daily, total_profit) # print(minimum_acceptable_return, expected_returns_mean, down_stdev, sortino_ratio)