"""
定制风控组件实现

这些风控组件继承framework.core.risk.RiskControl
"""

from framework.risk import RiskControl, Position, CallbackHook


class StopLossControl(RiskControl):
    """止损控制（定制实现）"""
    
    name = "stop_loss"
    
    def __init__(self, threshold: float = -0.05, trailing: bool = False, trailing_percent: float = 0.03):
        super().__init__(threshold=threshold, trailing=trailing, trailing_percent=trailing_percent)
        self.threshold = threshold
        self.trailing = trailing
        self.trailing_percent = trailing_percent
        self._highest_price = {}
    
    def check(self, position: Position, **kwargs) -> bool:
        """检查是否触发止损"""
        if position is None:
            return True
        
        if self.trailing:
            if position.code not in self._highest_price:
                self._highest_price[position.code] = position.entry_price
            self._highest_price[position.code] = max(
                self._highest_price[position.code],
                position.current_price
            )
        
        if self.trailing:
            highest = self._highest_price[position.code]
            drawdown = (position.current_price - highest) / highest
            return drawdown > -self.trailing_percent
        else:
            return position.profit_ratio > self.threshold
    
    def apply(self, position: Position):
        """返回止损价格"""
        if self.trailing:
            highest = self._highest_price.get(position.code, position.entry_price)
            return highest * (1 - self.trailing_percent)
        else:
            return position.entry_price * (1 + self.threshold)


class PositionLimitControl(RiskControl):
    """仓位限制控制（定制实现）"""
    
    name = "position_limit"
    
    def __init__(self, max_position: float = 0.33, max_total: float = 1.0):
        super().__init__(max_position=max_position, max_total=max_total)
        self.max_position = max_position
        self.max_total = max_total
    
    def check(self, position: Position, **kwargs) -> bool:
        """检查仓位是否超限"""
        if position is None:
            return True
        
        if position.weight > self.max_position:
            return False
        
        return True
    
    def apply(self, position: Position):
        """返回建议仓位"""
        return min(position.weight, self.max_position)


class PremiumControl(RiskControl):
    """溢价控制（定制实现）"""
    
    name = "premium"
    
    def __init__(self, threshold: float = 0.10, mode: str = 'filter'):
        super().__init__(threshold=threshold, mode=mode)
        self.threshold = threshold
        self.mode = mode
    
    def check(self, position: Position, **kwargs) -> bool:
        """检查溢价是否超限"""
        premium = kwargs.get('premium', 0)
        
        if self.mode == 'filter':
            return premium <= self.threshold
        else:
            return True
    
    def apply(self, position: Position):
        """返回溢价惩罚系数"""
        if self.mode == 'penalize':
            return 0.5
        return None


# 定制回调函数
def premium_filter_callback(threshold: float = 0.10):
    """溢价过滤回调（定制实现）"""
    def callback(code: str, price: float, **kwargs) -> bool:
        premium = kwargs.get('premium', 0)
        if premium > threshold:
            print(f"溢价过高，拒绝入场: {code} (溢价={premium:.2%})")
            return False
        return True
    return callback


def crash_filter_callback(lookback: int = 3, crash_threshold: float = 0.05):
    """崩盘过滤回调（定制实现）"""
    def callback(code: str, price: float, **kwargs) -> bool:
        history = kwargs.get('history', None)
        if history is None:
            return True
        
        recent = history.tail(lookback)
        if len(recent) < lookback:
            return True
        
        returns = recent['close'].pct_change()
        min_return = returns.min()
        
        if min_return < -crash_threshold:
            print(f"崩盘检测，拒绝入场: {code} (最大跌幅={min_return:.2%})")
            return False
        return True
    return callback


def holding_time_stoploss_callback(day_5_stoploss: float = -0.05, day_10_stoploss: float = -0.03):
    """持仓时间动态止损回调（定制实现）"""
    def callback(position: Position) -> float:
        if position.holding_days >= 10:
            return day_10_stoploss
        elif position.holding_days >= 5:
            return day_5_stoploss
        return -0.10
    return callback