from freqtrade.optimize.hyperopt import IHyperOptLoss
from pandas import DataFrame
import numpy as np
class TrendMomentumHyperopt(IHyperOptLoss):
"""
Custom hyperopt loss function.
Prioritizes:
1. Total profit (want it high)
2. Win rate (want it above 50%)
3. Number of trades (want enough trades for statistical significance)
4. Average trade duration (prefer shorter trades — faster turnover)
"""
@staticmethod
def hyperopt_loss_function(results: DataFrame, *args, **kwargs) -> float:
# Total profit in USD
total_profit = results['profit_abs'].sum()
# Number of trades
num_trades = len(results)
# Win rate
wins = (results['profit_abs'] > 0).sum()
win_rate = wins / num_trades if num_trades > 0 else 0
# Average trade duration in minutes
avg_duration = results['trade_duration'].mean()
# Penalize very few trades (need statistical significance)
if num_trades < 10:
return 1e10 # Massive penalty
# Reward total profit (negative = good for minimization)
profit_score = -total_profit
# Bonus for high win rate
win_rate_bonus = -(win_rate - 0.5) * total_profit * 0.5
# Penalize very long average trades (prefer faster turnover)
duration_penalty = (avg_duration / 1440) * 0.1 # Normalize to days
return profit_score + win_rate_bonus + duration_penalty