# source: https://raw.githubusercontent.com/Nichenggan/trade_suck/c2214fe8c70c7b113b6760bd9ef1dbdd7b07bfc1/user_data/strategies/AlphaStrategy.py
from freqtrade.strategy import IStrategy, IntParameter
import pandas as pd
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from datetime import datetime

class Github_Nichenggan_trade_suck__AlphaStrategy__20260305_121123(IStrategy):
    INTERFACE_VERSION = 3
    timeframe = '5m'
    can_short = True
    startup_candle_count = 200
    # 仓位管理参数
    stake_percentage = 0.10      # 账户总额的 10%
    min_stake_amount = 100.0     # 最低开仓金额 100 USDT

    # --- 策略核心参数 ---
    # 定义杠杆参数，默认5倍，可通过 Hyperopt 优化 (范围 1-10)
    leverage_num = IntParameter(1, 20, default=10, space='buy', optimize=True)
    


    # --- 进场指标参数 ---
    buy_rsi = IntParameter(20, 45, default=30, space='buy')
    sell_rsi = IntParameter(60, 85, default=70, space='sell')

    # --- 止盈止损与移动止盈 (适配 5 倍杠杆) ---
    # 5倍杠杆下给 5m 波动留空间，设 5% 初始止损 (即标的波动 1%)
    stoploss = -0.5 

    # ROI 阶梯止盈
    minimal_roi = {
        "0": 0.1,    
        "10": 0.05,  
        "30": 0.02,  
        "60": 0       
    }

    # 移动止损 (Trailing stop)
    trailing_stop = True
    trailing_stop_positive = 0.02  
    trailing_stop_positive_offset = 0.03 
    trailing_only_offset_is_reached = True

    def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
                            proposed_stake: float, min_stake: float, max_stake: float,
                            leverage: float, entry_tag: str, side: str, **kwargs) -> float:
        """
        仓位管理：每次开仓占当前账户总额的 10%，但最低不少于 100 USDT。
        """
        calculated_stake = self.wallets.get_total_stake_amount() * self.stake_percentage
        
        # 确保不低于 100U，且不超过账户当前可用最大倍数限制
        final_stake = max(calculated_stake, self.min_stake_amount)
        
        # 如果当前可用金额不足 100U，Freqtrade 会自动处理或报错，这里返回 calculated 值
        return final_stake

    def leverage(self, pair: str, current_time: datetime, current_rate: float,
                 proposed_leverage: float, max_leverage: float, entry_tag: str,
                 side: str, **kwargs) -> float:
        """
        使用参数化杠杆
        """
        return float(self.leverage_num.value)

    def populate_indicators(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
        """
        计算复杂波段指标：RSI + 布林带 + 威廉指标
        """
        # 1. RSI
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        
        # 2. 布林带 (Bollinger Bands) - 捕捉价格通道边界
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2.2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        
        # 3. 威廉指标 (Williams %R) - 极其灵敏的超买超卖指标，适合吃波段
        dataframe['willr'] = ta.WILLR(dataframe, timeperiod=14)

        # 4. 指数移动平均线 (EMA 200) - 大级别趋势过滤
        dataframe['ema_200'] = ta.EMA(dataframe, timeperiod=200)

        return dataframe

    def populate_entry_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
        """
        进场逻辑：多重指标共振 + 大级别趋势过滤
        """
        # 做多：价格在 EMA 200 之上 (多头趋势) + 价格跌破布林带下轨 + RSI超卖 + 威廉指标极度超卖
        dataframe.loc[
            (
                (dataframe['close'] > dataframe['ema_200']) &  # 顺大势
                (dataframe['close'] < dataframe['bb_lowerband']) & 
                (dataframe['rsi'] < self.buy_rsi.value) &
                (dataframe['willr'] < -80) &
                (dataframe['volume'] > 0)
            ),
            ['enter_long', 'enter_tag']] = (1, 'swing_bottom_long')
            
        # 做空：价格在 EMA 200 之下 (空头趋势) + 价格突破布林带上轨 + RSI超买 + 威廉指标极度超买
        dataframe.loc[
            (
                (dataframe['close'] < dataframe['ema_200']) &  # 顺大势
                (dataframe['close'] > dataframe['bb_upperband']) & 
                (dataframe['rsi'] > self.sell_rsi.value) &
                (dataframe['willr'] > -20) &
                (dataframe['volume'] > 0)
            ),
            ['enter_short', 'enter_tag']] = (1, 'swing_top_short')

        return dataframe

    def populate_exit_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
        """
        离场交由 ROI 和 Trailing stop 自动处理
        """
        return dataframe