# source: https://raw.githubusercontent.com/kevenbazile/booki/a5c626a13ce29dfc1663a8d74326d84c406803a3/SimplePortfolio.py
from freqtrade.strategy import IStrategy
from pandas import DataFrame
import talib.abstract as ta
import logging
import numpy as np

logger = logging.getLogger(__name__)

class Github_kevenbazile_booki__SimplePortfolio__20250614_094946(IStrategy):
    INTERFACE_VERSION = 3
    
    # FAST profit targets - DCA bots must take profits quickly
    minimal_roi = {
        "0": 0.08,      # 8% immediate profit target  
        "60": 0.06,     # 6% after 1 hour
        "180": 0.04,    # 4% after 3 hours
        "360": 0.03,    # 3% after 6 hours
        "720": 0.02     # 2% after 12 hours - TAKE ANY PROFIT
    }
    
    stoploss = -0.15           # Wider stop for DCA (should never hit this)
    timeframe = '5m'           
    process_only_new_candles = True
    startup_candle_count = 30
    can_short = False
    
    # AGGRESSIVE DCA but fewer total entries
    position_adjustment_enable = True
    max_entry_position_adjustment = 4  # Keep same as original
    
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        SIMPLE indicators for DCA signals
        """
        # RSI - simple and effective
        dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        
        # EMAs for trend
        dataframe['ema_9'] = ta.EMA(dataframe, timeperiod=9)
        dataframe['ema_21'] = ta.EMA(dataframe, timeperiod=21)
        
        # Volume for confirmation
        dataframe['volume_avg'] = dataframe['volume'].rolling(window=20).mean()
        
        # Price momentum
        dataframe['price_change'] = dataframe['close'].pct_change(periods=5) * 100
        
        # Support levels (buying opportunities)
        dataframe['low_5'] = dataframe['low'].rolling(window=5).min()
        dataframe['low_20'] = dataframe['low'].rolling(window=20).min()
        
        return dataframe
    
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        MUCH MORE SELECTIVE buying - only on big dips
        """
        dataframe.loc[
            (
                # ONLY BUY MAJOR DIPS - be very selective
                (
                    (dataframe['rsi'] < 30) &  # Very oversold (was 45)
                    (dataframe['close'] <= dataframe['low_5'] * 1.005) &  # Very near recent low
                    (dataframe['volume'] > dataframe['volume_avg'] * 1.2) &  # Volume surge
                    (dataframe['price_change'] < -3)  # Big price drop
                )
            ),
            'enter_long'] = 1
        
        return dataframe
    
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        TAKE PROFITS FAST - this is critical for DCA success
        """
        dataframe.loc[
            (
                # EXIT ON SMALL PROFITS - don't be greedy
                (dataframe['rsi'] > 55) &  # Not even overbought (was 75)
                (dataframe['close'] > dataframe['ema_9'])  # Above short-term trend
            ) |
            (
                # EXIT ON ANY DECENT BOUNCE
                (dataframe['price_change'] > 2) &  # Small bounce up
                (dataframe['rsi'] > 50)  # Neutral RSI
            ),
            'exit_long'] = 1
        
        return dataframe
    
    def adjust_trade_position(self, trade, current_time, current_rate, current_profit, 
                            min_stake, max_stake, **kwargs):
        """
        AGGRESSIVE DCA - this is where DCA bots make their money
        """
        if current_profit >= -0.01:  # Only add when down 3%+ (was 1%)
            return None  
        
        # BIGGER DCA amounts - go heavy when losing
        if current_profit < -0.15:  # Down 15%+
            additional_stake = min_stake * 3.0  # Massive add (was 2.0)
            logger.info(f"🔥 MASSIVE DCA: Adding ${additional_stake:.2f} to {trade.pair} (down {current_profit:.1%})")
        elif current_profit < -0.10:  # Down 10-15%
            additional_stake = min_stake * 2.5  # Big add (was 1.5)
            logger.info(f"💪 BIG DCA: Adding ${additional_stake:.2f} to {trade.pair} (down {current_profit:.1%})")
        elif current_profit < -0.06:  # Down 6-10%
            additional_stake = min_stake * 2.0  # Medium add (was 1.0)
            logger.info(f"📈 MEDIUM DCA: Adding ${additional_stake:.2f} to {trade.pair} (down {current_profit:.1%})")
        elif current_profit < -0.03:  # Down 3-6%
            additional_stake = min_stake * 1.0  # Small add (was 0.8)
            logger.info(f"💰 SMALL DCA: Adding ${additional_stake:.2f} to {trade.pair} (down {current_profit:.1%})")
        else:
            return None
        
        # Check if we can still add more positions
        if trade.nr_of_successful_entries >= (self.max_entry_position_adjustment + 1):
            logger.info(f"⚠️ Max DCA entries reached for {trade.pair}")
            return None
        
        return min(additional_stake, max_stake)
    
    def custom_stake_amount(self, pair: str, current_time, current_rate: float,
                          proposed_stake: float, min_stake: float, max_stake: float,
                          entry_tag: str, **kwargs) -> float:
        """
        MUCH SMALLER initial stakes - save money for DCA
        """
        # Use only 25% for initial entry (was 60%) - save 75% for DCA
        initial_stake = proposed_stake * 0.25
        
        logger.info(f"💰 Small initial stake for {pair}: ${initial_stake:.2f} (25% - saving for DCA)")
        
        return max(initial_stake, min_stake)
    
    def custom_exit_price(self, pair: str, trade, current_time, proposed_rate: float,
                         current_profit: float, **kwargs) -> float:
        """
        SELL IMMEDIATELY when profitable - don't wait for better prices
        """
        if current_profit > 0.02:  # If up even 2%, sell at market (was 8%)
            logger.info(f"💰 TAKING PROFIT: {pair} up {current_profit:.1%} - selling at market")
            return proposed_rate  # Take the market price immediately
        
        return proposed_rate
    
    def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
                          time_in_force: str, current_time, entry_tag, **kwargs) -> bool:
        """
        Log all entries for tracking
        """
        trade_value = amount * rate
        logger.info(f"🎯 DCA BUY: {pair} | {amount:.4f} @ ${rate:.4f} = ${trade_value:.2f}")
        return True
    
    def confirm_trade_exit(self, pair: str, trade, order_type: str, amount: float, 
                          rate: float, time_in_force: str, exit_reason: str, 
                          current_time, **kwargs) -> bool:
        """
        Log all exits with profit tracking
        """
        profit_pct = trade.calc_profit_ratio(rate) * 100
        profit_usd = trade.calc_profit(rate)
        
        if profit_pct > 0:
            logger.info(f"💰 DCA PROFIT: {pair} | SOLD {amount:.4f} @ ${rate:.4f} | +{profit_pct:.2f}% (+${profit_usd:.2f})")
        else:
            logger.info(f"🛑 DCA LOSS: {pair} | SOLD {amount:.4f} @ ${rate:.4f} | {profit_pct:.2f}% (${profit_usd:.2f})")
        
        logger.info(f"   Duration: {current_time - trade.open_date} | Reason: {exit_reason}")
        
        return True
    
    def leverage(self, pair: str, current_time, current_rate: float,
                proposed_leverage: float, max_leverage: float, entry_tag: str, 
                side: str, **kwargs) -> float:
        """
        Spot trading only
        """
        return 1.0
