# source: https://raw.githubusercontent.com/DerSalvador/freqtrade-helm-chart/a669dc11b640b0eb63aa8f8b51e9f181fd7ee43c/chart/deployed_strategies/binance-michael-k8s-namespace/pcb20.py
import logging
import numpy as np  # noqa
import pandas as pd  # noqa
from pandas import DataFrame
from sqlalchemy.orm.base import RELATED_OBJECT_OK
from sqlalchemy.sql.elements import or_
import talib.abstract as ta
import pandas_ta as pta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.exchange import timeframe_to_minutes
from freqtrade.persistence import Trade
from technical import indicators
from datetime import datetime, timezone
from freqtrade.strategy import BooleanParameter, CategoricalParameter, DecimalParameter, RealParameter, IStrategy, IntParameter, merge_informative_pair

class Github_DerSalvador_freqtrade_helm_chart__pcb20__20260115_122204(IStrategy):
    # Add some logging
    logger = logging.getLogger(__name__)
    # Strategy interface version - allow new iterations of the strategy interface.
    # Check the documentation or the Sample strategy to get the latest version.
    INTERFACE_VERSION = 3
    # Minimal ROI designed for the strategy.
    # This attribute will be overridden if the config file contains "minimal_roi".
    # ROI1 table:
    minimal_roi = {'0': 0.309, '60': -0.01}
    # Optimal stoploss designed for the strategy.
    # This attribute will be overridden if the config file contains "stoploss".
    # use_custom_stoploss = True
    stoploss = -0.015
    # Number of candles the strategy requires before producing valid signals
    startup_candle_count: int = 30  #30
    # Optimal timeframe for the strategy.
    timeframe = '6h'
    # hyperopt params
    exit_rsil = DecimalParameter(45, 90, default=70)
    exit_rsiu = DecimalParameter(65, 100, default=80)
    exit_wavetrend = DecimalParameter(0, 5, default=0)
    entry_wavetrend = DecimalParameter(-10, -1, default=0)
    entry_rsil = DecimalParameter(0, 40, default=40)
    entry_rsiu = DecimalParameter(40, 65, default=50)

    @property
    def plot_config(self):
        return {'main_plot': {}, 'subplots': {'obv': {'OBV': {'color': '#1b61ab', 'type': 'line'}, 'OBVSlope': {'color': '#f18b7a', 'type': 'line'}}, 'wavetrend': {'wave_t1': {'color': '#1b61ab', 'type': 'line'}, 'wave_t2': {'color': '#f18b7a', 'type': 'line'}}}}

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # WaveTrend
        ap = 0.25 * (dataframe['high'] + dataframe['low'] + dataframe['close'] + dataframe['open'])
        esa = ta.EMA(ap, timeperiod=10)
        d = ta.EMA(abs(ap - esa), timeperiod=10)
        dataframe['wave_ci'] = (ap - esa) / (0.015 * d)
        dataframe['wave_t1'] = ta.EMA(dataframe['wave_ci'], timeperiod=21)
        dataframe['wave_t2'] = ta.SMA(dataframe['wave_t1'], timeperiod=4)
        dataframe['wave_t1_pc'] = round((dataframe['wave_t1'] - dataframe['wave_t1'].shift()) / abs(dataframe['wave_t1']) * 100, 2)
        # # Bollinger!
        # bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        # dataframe['bb.lower'] = bollinger['lower']
        # dataframe['bb.middle'] = bollinger['mid']
        # dataframe['bb.upper'] = bollinger['upper']
        # Added PCB Style OBV
        dataframe['OBV'] = ta.OBV(dataframe)
        dataframe['OBVSlope'] = pta.momentum.slope(dataframe['OBV'])
        # VWMA
        # vwma_period = 13
        # dataframe['vwma'] = ((dataframe["close"] * dataframe["volume"]).rolling(vwma_period).sum() / 
        # dataframe['volume'].rolling(vwma_period).sum())
        # VWAP
        # vwap_period = 20
        # dataframe['vwap'] = qtpylib.rolling_vwap(dataframe, window=vwap_period)
        # # VPCI
        # dataframe['vpci'] = indicators.vpci(dataframe, period_long=14)
        # #williamsR
        # dataframe['williamspercent'] = indicators.williams_percent(dataframe)
        # # ADX
        # dataframe['adx'] = ta.ADX(dataframe)
        # dataframe['plus.di'] = ta.PLUS_DI(dataframe)
        # dataframe['minus.di'] = ta.MINUS_DI(dataframe)
        # dataframe['plus.di.slope'] = pta.momentum.slope(dataframe['plus.di'])
        # RSI
        dataframe['rsi'] = ta.RSI(dataframe)
        dataframe['rsi_slope'] = pta.momentum.slope(dataframe['rsi'])
        dataframe['rsi_ma'] = ta.EMA(dataframe['rsi'], timeperiod=5)
        dataframe['rsi_ma_slope'] = pta.momentum.slope(dataframe['rsi_ma'])
        # # MACD
        # macd = ta.MACD(dataframe)
        # dataframe['macd'] = macd['macd']
        # dataframe['macdsignal'] = macd['macdsignal']
        # dataframe['macdhist'] = macd['macdhist']
        # # Stochastic Fast
        # stoch_fast = ta.STOCHF(dataframe)
        # dataframe['fastd'] = stoch_fast['fastd']
        # dataframe['fastk'] = stoch_fast['fastk']
        # # Stochastic Slow
        # stoch_slow = ta.STOCH(dataframe)
        # dataframe['slowd'] = stoch_slow['slowd']
        # dataframe['slowk'] = stoch_slow['slowk']
        # # Perc
        # dataframe['perc'] = ((dataframe['high'] - dataframe['low']) / dataframe['low']*100)
        # dataframe['avg3_perc'] = ta.EMA(dataframe['perc'], 3)
        # dataframe['perc_norm'] = (dataframe['perc'] - dataframe['perc'].rolling(50).min())/(dataframe['perc'].rolling(50).max() - dataframe['perc'].rolling(50).min())
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[(dataframe['wave_t1'] >= dataframe['wave_t2']) & (dataframe['rsi_ma'] <= self.entry_rsiu.value) & (dataframe['rsi_ma'] >= self.entry_rsil.value) & (dataframe['rsi_ma_slope'] > 0), 'enter_long'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # (dataframe['wave_t1'] <= dataframe['wave_t2'])
        dataframe.loc[(dataframe['wave_t1_pc'] <= self.exit_wavetrend.value) & (dataframe['rsi_ma'] >= self.exit_rsil.value) & (dataframe['rsi_ma'] <= self.exit_rsiu.value) & (dataframe['rsi_ma_slope'] <= 0), 'exit_long'] = 1
        return dataframe
# "All watched over by machines with loving grace..."