ruff format: hyperopt-loss

This commit is contained in:
Matthias 2024-05-12 17:13:50 +02:00
parent ab3dbb7fbc
commit f1ef537dfa
10 changed files with 100 additions and 62 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)