# source: https://raw.githubusercontent.com/remiotore/freqtrade/44beaeb6a420cd8e9f2e4ea93e11d6cfa192ee03/strategies/dip.py




import numpy as np
import pandas as pd
from pandas import DataFrame
from datetime import datetime
from typing import Optional, Union
from freqtrade.persistence import Trade

from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
                                IntParameter, IStrategy, merge_informative_pair)


import talib.abstract as ta
import pandas_ta as pta
from technical import qtpylib
from  datetime import timedelta
import math

class Github_remiotore_freqtrade__dip__20260111_210550(IStrategy):
    """
    // 
    // Dip / Retracement Catcher
      https://github.com/Haehnchen/crypto-trading-bot/tree/master/src/modules/strategy/strategies/Github_remiotore_freqtrade__dip__20260111_210550_catcher
      https://github.com/Haehnchen/crypto-trading-bot/blob/master/src/modules/strategy/strategies/Github_remiotore_freqtrade__dip__20260111_210550_catcher/Github_remiotore_freqtrade__dip__20260111_210550_catcher.js
       translated for freqtrade: viksal1982  viktors.s@gmail.com  
       https://github.com/viktors1982/trading/tree/main/freqtrade/strategies
    """ 

 
    INTERFACE_VERSION = 3

    timeframe = '5m'

    can_short: bool = True

    minimal_roi = {
        "60": 0.01,
        "30": 0.02,
        "0": 0.03
    }

    stoploss = -0.08
    trailing_stop = False
    trailing_stop_positive = 0.01
    trailing_stop_positive_offset = 0.0
    trailing_only_offset_is_reached = False

    process_only_new_candles = True

    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False

    startup_candle_count: int = 30


    length_hma = IntParameter(4, 20, default=9, space="buy", optimize=True)
    length_hma_high = IntParameter(4, 20, default=9, space="buy", optimize=True)
    length_hma_low = IntParameter(4, 20, default=9, space="buy", optimize=True)
    bollinger_window = IntParameter(2, 40, default=20, space="buy", optimize=True)
    trend_cloud_multiplier = IntParameter(1, 10, default=4, space="buy", optimize=True)

    order_types = {
        'entry': 'limit',
        'exit': 'limit',
        'stoploss': 'market',
        'stoploss_on_exchange': False
    }

    order_time_in_force = {
        'entry': 'GTC',
        'exit': 'GTC'
    }
    
    @property
    def plot_config(self):
        return {
            'main_plot': {

            },
            'subplots': {
            }
        }

    def informative_pairs(self):

        return []
    
    def ichimoku_cloud(self, dataframe, conversion_periods=9, base_periods=26, lagging_span2_periods=52, displacement=26):
        
        def donchian_channel(series, length):
            return (series.rolling(length).min() + series.rolling(length).max()) / 2
        dataframe['conversion_line'] = (donchian_channel(dataframe['high'], conversion_periods) + donchian_channel(dataframe['low'], conversion_periods)) / 2
        dataframe['base_line'] = (donchian_channel(dataframe['high'], base_periods) + donchian_channel(dataframe['low'], base_periods)) / 2
        dataframe['lead_line1'] = ((dataframe['conversion_line'] + dataframe['base_line']) / 2).shift(displacement)
        dataframe['lead_line2'] = ((donchian_channel(dataframe['high'], lagging_span2_periods) + donchian_channel(dataframe['low'], lagging_span2_periods)) / 2).shift(displacement)
        dataframe['lagging_span'] = dataframe['close'].shift(displacement)
        return dataframe[['conversion_line', 'base_line', 'lead_line1', 'lead_line2', 'lagging_span']]

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

        return dataframe
    

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
       
        
        dataframe['hma'] = ta.WMA(
                    2 * ta.WMA(dataframe['close'], int(math.floor(int(self.length_hma.value)/2))) - ta.WMA(dataframe['close'], int(self.length_hma.value)), int(round(np.sqrt(int(self.length_hma.value))))
                    )
     
        dataframe['hma_high'] = ta.WMA(
                    2 * ta.WMA(dataframe['close'], int(math.floor(int(self.length_hma_high.value/2)))) - ta.WMA(dataframe['close'], int(self.length_hma_high.value)), int(round(np.sqrt(int(self.length_hma_high.value))))
                    )
 
        dataframe['hma_low'] = ta.WMA(
                    2 * ta.WMA(dataframe['close'], int(math.floor(int(self.length_hma_low.value/2)))) - ta.WMA(dataframe['close'], int(self.length_hma_low.value)), int(round(np.sqrt(int(self.length_hma_low.value))))
                    )
        

        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=int(self.bollinger_window.value), stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
 
        dataframe[['conversion_line', 'base_line', 'spanA', 'spanB', 'lagging_span']] = self.ichimoku_cloud(dataframe, conversion_periods= (9 * int(self.trend_cloud_multiplier.value)), base_periods=(26 * int(self.trend_cloud_multiplier.value)) , lagging_span2_periods=(52* int(self.trend_cloud_multiplier.value)), displacement=(10* int(self.trend_cloud_multiplier.value)))


        dataframe.loc[
            (

                (dataframe['hma_low'] > dataframe['bb_lowerband']) &
                (dataframe['hma'] > dataframe['spanB'])   
            ),
            'enter_long'] = 1

        dataframe.loc[
            (

                (dataframe['hma_high'] < dataframe['bb_upperband']) &
                (dataframe['hma'] < dataframe['spanB'])   
            ),
            'enter_short'] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
       
        return dataframe
    