# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
"""
Hyperopt loss function for SimpleStrategy.

Optimizes for:
- Total profit (primary)
- Win rate (secondary)
- Trade count (minimum 20 for significance)
- Drawdown control (penalty for >25% drawdown)
"""

from freqtrade.optimize.hyperopt import IHyperOptLoss
from datetime import datetime
from pandas import DataFrame
from typing import Any


class SimpleStrategyHyperopt(IHyperOptLoss):
    
    @staticmethod
    def hyperopt_loss_function(
        *,
        results: DataFrame,
        trade_count: int,
        min_date: datetime,
        max_date: datetime,
        config: dict[str, Any],
        processed: dict[str, DataFrame],
        backtest_stats: dict[str, Any],
        starting_balance: float,
        **kwargs,
    ) -> float:
        """
        Custom loss function — LOWER is better (we minimize this).
        
        Scoring priorities:
        1. Total profit (most important)
        2. Win rate bonus
        3. Trade count bonus (at least 20 trades)
        4. Drawdown penalty
        """
        if trade_count < 10:
            return 1e10  # Massive penalty for too few trades
        
        total_profit = backtest_stats['profit_total']
        wins = backtest_stats.get('wins', 0)
        
        # Win rate
        win_rate = wins / trade_count if trade_count > 0 else 0
        
        # Base score: negative profit (we minimize, so lower = better = more profit)
        score = -total_profit
        
        # Bonus for good win rate (>50% is good)
        if win_rate > 0.60:
            score -= 5
        elif win_rate > 0.50:
            score -= 2
        
        # Bonus for more trades (more data = more confidence)
        if trade_count > 50:
            score -= 2
        elif trade_count > 20:
            score -= 1
        
        # Drawdown penalty
        max_drawdown = backtest_stats.get('max_drawdown', 0)
        if max_drawdown and max_drawdown > 0.25:
            score += (max_drawdown - 0.25) * 50
        
        # Duration factor: prefer strategies that make money faster
        days = (max_date - min_date).days
        if days > 0:
            daily_rate = total_profit / days
            score -= daily_rate * 10  # Bonus for faster profits
        
        return score
