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
