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

import logging
import talib.abstract as ta
import pandas as pd
from pandas import DataFrame
import arrow
from pathlib import Path
import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.arguments import TimeRange
from technical.indicator_helpers import fishers_inverse
from freqtrade.strategy.interface import IStrategy
from freqtrade.state import RunMode
from freqtrade.strategy.util import resample_to_interval, resampled_merge
from freqtrade.data.history import parse_ticker_dataframe, load_pair_history
import freqtrade.indicators as indicators

logger = logging.getLogger("IchimokuStrategy")

class Github_remiotore_freqtrade__ichimoku_2__20260111_210550(IStrategy):

    cache = {}
    min_days = 30

    def get_extend_historical(self, pair: str, dataframe: DataFrame) -> DataFrame:

        if hasattr(self, 'dp'):
            if self.dp.runmode in (RunMode.LIVE, RunMode.DRY_RUN):
                min_date = dataframe['date'].min()
                if pair not in self.cache or self.cache[pair]["date"].max() < min_date:
                    logger.info(f"Downloading historical ohlc for pair: {pair})")



                    self.cache[pair] = load_pair_history(pair, 
                                        ticker_interval=self.ticker_interval, 
                                        datadir= Path(f"user_data/data/history"),
                                        timerange=TimeRange(starttype ='date', startts=int(arrow.utcnow().shift(days=-60).float_timestamp)),
                                        refresh_pairs=True,
                                        exchange=self.dp._exchange)

                hist_df = self.cache[pair]
                min_date = dataframe['date'].min()
                return pd.concat([ hist_df[hist_df['date'] < min_date] , dataframe ])

        return dataframe

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        
        
        dataframe = self.get_extend_historical(metadata['pair'], dataframe)
        if (dataframe['date'].max() - dataframe['date'].min()).days < self.min_days:
            return dataframe


        macd = ta.MACD(dataframe, fastperiod=14, slowperiod=27, signalperiod=9)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']
        dataframe['sar'] = ta.SAR(dataframe)
        dataframe['rsi'] = ta.RSI(dataframe)


        dataframe_1d =  resample_to_interval(dataframe, '1d')
        macd = ta.MACD(dataframe_1d, fastperiod=14, slowperiod=27, signalperiod=15)
        dataframe_1d['macd_1d'] = macd['macd']
        dataframe_1d['macdsignal_1d'] = macd['macdsignal']
        dataframe_1d['macdhist_1d'] = macd['macdhist']
        dataframe_1d['sar_1d'] = ta.SAR(dataframe_1d, acceleration=0.15, maximum=1)
        dataframe_1d['close_1d'] = dataframe_1d['close']
        dataframe_1d['rsi_1d'] = ta.RSI(dataframe_1d)


        dataframe_4h =  resample_to_interval(dataframe, '4h')
        ichimoku = indicators.ichimoku(dataframe_4h, tenkan_sen_window=15, kijun_sen_window=27, senkou_span_offset=15, senkou_span_b_window=50)
        dataframe_4h['tenkan_sen_4h'] = ichimoku['tenkan_sen']
        dataframe_4h['kijun_sen_4h'] = ichimoku['kijun_sen']
        dataframe_4h['senkou_span_a_4h'] = ichimoku['senkou_span_a']
        dataframe_4h['senkou_span_b_4h'] = ichimoku['senkou_span_b']
        macd = ta.MACD(dataframe_4h, fastperiod=14, slowperiod=27, signalperiod=9)
        dataframe_4h['macd_4h'] = macd['macd']
        dataframe_4h['macdsignal_4h'] = macd['macdsignal']

        dataframe = resampled_merge(dataframe, dataframe_4h)
        dataframe = resampled_merge(dataframe, dataframe_1d)

        return dataframe

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

        if (dataframe['date'].max() - dataframe['date'].min()).days < self.min_days:
            dataframe['buy'] = 0
            return dataframe

        try:
            if self.dp:
                if self.dp.runmode in (RunMode.LIVE, RunMode.DRY_RUN):
                    ticker_data = self.dp._exchange.get_ticker(metadata['pair'])
                    symbol,bid,ask,last= ticker_data['symbol'],ticker_data['bid'],ticker_data['ask'],ticker_data['last']
                    
                    if(ask <=0 or bid <=0 or last <= 0):
                        dataframe['buy'] = 0
                        return dataframe

                    spread = ((ask - bid)/last) * 100
                    if(spread > 0.20):
                        dataframe['buy'] = 0
                        return dataframe
        except:
            print(f"could not get ticker for pair: {metadata['pair']}")
            dataframe['buy'] = 0
            return dataframe

        dataframe.loc[
            (
                (
                    (dataframe['macd'] > dataframe['macdsignal']) &
                    (dataframe['macd'].shift() > dataframe['macdsignal'].shift()) &
                    (dataframe['macd_4h'] > dataframe['macdsignal_4h']) &
                    (dataframe['sar_1d'] < dataframe['open']) &
                    (dataframe['sar'] < dataframe['open']) &

                    (dataframe['macd_1d'] > dataframe['macdsignal_1d']) &
                    (dataframe['rsi'] < 75) &
                    (dataframe['open'] > dataframe['senkou_span_a_4h']) &
                    (dataframe['open'] > dataframe['senkou_span_b_4h']) &
                    (dataframe['close'] > dataframe['senkou_span_a_4h']) &
                    (dataframe['close'] > dataframe['senkou_span_b_4h'])
                )
            ),
            'buy'] = 1

        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        
        if (dataframe['date'].max() - dataframe['date'].min()).days < self.min_days:
            dataframe['sell'] = 0
            return dataframe

        dataframe.loc[
            (

                 (dataframe['sar_1d'] > dataframe['open']) 
            ),
            'sell'] = 1
        return dataframe
