# source: https://raw.githubusercontent.com/secondlinger/WinnieBari/818e7704f3eb430813e8abebea2dcae44176fc52/user_data/strategies/CustomRLStrategy.py
import numpy as np
import talib.abstract as ta
from pandas import DataFrame
from sklearn.preprocessing import StandardScaler

from freqtrade.strategy import IStrategy


class Github_secondlinger_WinnieBari__CustomRLStrategy__20251006_100904(IStrategy):
    """
    An effective Reinforcement Learning strategy for FreqAI.
    """
    timeframe = "5m"
    can_short = True

    # RL agent controls exits, so these are disabled.
    stoploss = -0.99
    minimal_roi = {"0": 100}
    trailing_stop = False

    process_only_new_candles = True
    startup_candle_count = 200

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Base indicators for the strategy.
        Keep this minimal as the RL model uses features from feature_engineering_*.
        The main purpose here is to start the FreqAI process.
        """
        # Start FreqAI processing
        dataframe = self.freqai.start(dataframe, metadata, self)
        return dataframe

    def feature_engineering_standard(self, dataframe: DataFrame, **kwargs) -> DataFrame:
        """
        Generate and NORMALIZE features for the RL model.t
        All feature columns must be prefixed with '%-'.
        """
        df = dataframe.copy()

        # === 既存の基本指標 ===
        df['%-adx'] = ta.ADX(df)
        df['%-rsi'] = ta.RSI(df, timeperiod=14)

        # === モメンタム指標の追加 ===
        df['%-momentum'] = ta.MOM(df, timeperiod=10)
        df['%-roc'] = ta.ROC(df, timeperiod=10)

        # === MACD（修正版） ===
        # ta.MACDは辞書を返すので、正しくアクセスする
        macd_result = ta.MACD(df, fastperiod=12, slowperiod=26, signalperiod=9)
        df['%-macd'] = macd_result['macd']
        df['%-macd_signal'] = macd_result['macdsignal']
        df['%-macd_hist'] = macd_result['macdhist']

        # === その他のモメンタム指標 ===
        df['%-momentum_5'] = ta.MOM(df, timeperiod=5)
        df['%-momentum_20'] = ta.MOM(df, timeperiod=20)
        df['%-momentum_50'] = ta.MOM(df, timeperiod=50)
        df['%-momentum_100'] = ta.MOM(df, timeperiod=100)

        # === Stochastic Oscillator ===
        stoch_result = ta.STOCH(df, fastk_period=14, slowk_period=3, slowd_period=3)
        df['%-stoch_k'] = stoch_result['slowk']
        df['%-stoch_d'] = stoch_result['slowd']

        # === Williams %R ===
        df['%-willr'] = ta.WILLR(df, timeperiod=14)

        # === モメンタムの方向性と強さ ===
        df['%-momentum_strength'] = df['close'].pct_change(10) * 100
        df['%-momentum_direction'] = np.where(df['%-momentum'] > 0, 1, -1)

        # === 既存の指標 ===
        ema_20 = ta.EMA(df, timeperiod=20)
        ema_50 = ta.EMA(df, timeperiod=50)

        df["%-raw_close"] = df["close"]
        df["%-raw_open"] = df["open"]
        df["%-raw_high"] = df["high"]
        df["%-raw_low"] = df["low"]

        for i in range(1, 5):
            df[f'%-return_shift_{i}'] = df['close'].pct_change(i)

        df['%-atr_14'] = ta.ATR(df, timeperiod=14)
        df['%-ema_20_dist'] = (df['close'] - ema_20) / ema_20
        df['%-ema_50_dist'] = (df['close'] - ema_50) / ema_50

        # === NaNの処理（正規化の前に） ===
        df.fillna(0, inplace=True)

        # === 正規化（修正版） ===
        feature_cols = [col for col in df.columns if col.startswith('%-')]

        # 数値型のみを選択
        feature_df = df[feature_cols].select_dtypes(include=[np.number])

        # 選択された列のみを正規化
        if not feature_df.empty:
            scaler = StandardScaler()
            df[feature_df.columns] = scaler.fit_transform(feature_df)

        return df

    def set_freqai_targets(self, dataframe: DataFrame, **kwargs) -> DataFrame:
        """
        This method is required by FreqAI.
        For RL, we simply initialize the action column.
        """
        dataframe["&-action"] = 0
        return dataframe

    def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
        """
        Interpret the RL agent's actions for entries.
        """
        # Long Entry: Action 1
        df.loc[
            (df["do_predict"] == 1) & (df["&-action"] == 1),
            ["enter_long", "enter_tag"]
        ] = (1, f"{metadata['pair']}_long")

        # Short Entry: Action 3
        df.loc[
            (df["do_predict"] == 1) & (df["&-action"] == 3),
            ["enter_short", "enter_tag"]
        ] = (1, f"{metadata['pair']}_short")

        return df

    def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
        """
        Interpret the RL agent's actions for exits.
        """
        # Long Exit: Action 2
        df.loc[
            (df["do_predict"] == 1) & (df["&-action"] == 2),
            "exit_long"
        ] = 1

        # Short Exit: Action 4
        df.loc[
            (df["do_predict"] == 1) & (df["&-action"] == 4),
            "exit_short"
        ] = 1

        return df
