# source: https://raw.githubusercontent.com/DeepeshKalura/project-orca/5c6fc6c9c07d52071ba1782e9db82bcc108d3381/bot/user_data/strategies/MarketStructureStrategy.py
# --- Do not remove these libs ---
from freqtrade.strategy import IStrategy, IntParameter
from pandas import DataFrame
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np
from scipy.signal import argrelextrema

class Github_DeepeshKalura_project_orca__MarketStructureStrategy__20250807_111036(IStrategy):
    """
    This strategy is based on market structure, identifying pivot points (higher highs and lower lows)
    and trading based on demand zones created from these structures.
    """

    # Strategy interface version - attribute needed by Freqtrade
    INTERFACE_VERSION = 2

    # Minimal ROI designed for the strategy.
    minimal_roi = {
        "0": 0.15,
        "30": 0.10,
        "60": 0.05
    }

    # Stoploss:
    stoploss = -0.10

    # Trailing stop:
    trailing_stop = True
    trailing_stop_positive = 0.01
    trailing_stop_positive_offset = 0.02
    trailing_only_offset_is_reached = True

    # Optimal timeframe for the strategy
    timeframe = '5m'

    # Parameters for pivot points
    pivot_window = IntParameter(5, 20, default=8, space="buy")

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Adds several different TA indicators to the given DataFrame
        """
        # Pivot Points
        n = self.pivot_window.value
        dataframe['pivot_high'] = (dataframe['high'].rolling(window=2*n+1, center=True).max() == dataframe['high']).astype(int)
        dataframe['pivot_low'] = (dataframe['low'].rolling(window=2*n+1, center=True).min() == dataframe['low']).astype(int)

        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the entry signal for the given dataframe
        """
        dataframe['enter_long'] = 0

        pivots_high = dataframe[dataframe['pivot_high'] == 1]
        pivots_low = dataframe[dataframe['pivot_low'] == 1]

        if len(pivots_low) < 2 or len(pivots_high) < 2:
            return dataframe

        last_pivot_low = pivots_low.index[-1]
        second_last_pivot_low = pivots_low.index[-2]
        last_pivot_high = pivots_high.index[-1]
        second_last_pivot_high = pivots_high.index[-2]

        # Identify Higher High and Higher Low
        if (pivots_high.loc[last_pivot_high, 'high'] > pivots_high.loc[second_last_pivot_high, 'high'] and
                pivots_low.loc[last_pivot_low, 'low'] > pivots_low.loc[second_last_pivot_low, 'low']):

            # Find the demand zone (last bearish candle before the up-move)
            up_move_start_index = second_last_pivot_low
            demand_zone_candle = dataframe.loc[up_move_start_index - 1] # Previous candle

            if demand_zone_candle['close'] < demand_zone_candle['open']: # It's a bearish candle
                demand_zone_top = demand_zone_candle['open']
                demand_zone_bottom = demand_zone_candle['close']

                # Potential entry when price touches the demand zone
                for i in range(last_pivot_low, len(dataframe)):
                    if dataframe.loc[i, 'low'] <= demand_zone_top:
                        entry_price = demand_zone_top
                        stop_loss_price = demand_zone_bottom
                        take_profit_price = pivots_high.loc[last_pivot_high, 'high']

                        # Risk/Reward Ratio Check
                        if (entry_price - stop_loss_price) > 0:
                            rr_ratio = (take_profit_price - entry_price) / (entry_price - stop_loss_price)
                            if rr_ratio >= 2.5:
                                dataframe.loc[i, 'enter_long'] = 1
                                break # Exit loop after finding an entry

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the exit signal for the given dataframe
        """
        dataframe['exit_long'] = 0
        return dataframe
