# source: https://raw.githubusercontent.com/mlsys-io/PortfolioBench/e1328d8d091ed2f9baa99c7b6e989125b13eb31c/user_data/strategies/best_single_asset.py
from freqtrade.strategy import IStrategy
from pandas import DataFrame
import pandas as pd


class Github_mlsys_io_PortfolioBench__best_single_asset__20260311_040147(IStrategy):
    """
    Winner-takes-all momentum rotation strategy
    """
    INTERFACE_VERSION = 3
    timeframe = "1d"
    stoploss = -1.0

    # Portfolio-style behavior
    max_open_trades = 1
    REBALANCE_DATE = 1
    LOOKBACK = 90
    process_only_new_candles = True
    startup_candle_count = 90 # Ensure enough data for lookback

    minimal_roi = {}

    def informative_pairs(self):
        """
        Load all whitelist pairs as informative pairs
        so every pair can see every other pair.
        """
        return [(pair, self.timeframe) for pair in self.dp.current_whitelist()]

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        For each candle, determine which pair has the best return in LOOKBACK days.
        """
        
        dataframe["momentum"] = dataframe["close"] / dataframe["close"].shift(self.LOOKBACK) - 1
        dataframe["rebalance"] = pd.to_datetime(dataframe["date"]).dt.day == self.REBALANCE_DATE
        
        momentum_map = {}

        for pair in self.dp.current_whitelist():
            inf_df = self.dp.get_pair_dataframe(pair, self.timeframe)
            momentum_map[pair] = (
                inf_df["close"] / inf_df["close"].shift(self.LOOKBACK) - 1
            )

        momentum_df = pd.DataFrame(momentum_map)

        # --- determine best pair per candle
        dataframe["best_pair"] = momentum_df.idxmax(axis=1).reindex(dataframe.index)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["enter_long"] = (
            (dataframe["best_pair"] == metadata["pair"]) &
            (dataframe["rebalance"])
        ).astype(int)
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe["exit_long"] = (
            (dataframe["best_pair"] != metadata["pair"]) &
            (dataframe["rebalance"])
        ).astype(int)
        return dataframe