# source: https://raw.githubusercontent.com/DerSalvador/freqtrade-helm-chart/a669dc11b640b0eb63aa8f8b51e9f181fd7ee43c/chart/deployed_strategies/binance-michael-k8s-namespace/LuxOSC.py
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# --- Do not remove these libs ---
import numpy as np  # noqa
import pandas as pd  # noqa
from pandas import DataFrame
from freqtrade.strategy import IStrategy
from freqtrade.strategy import CategoricalParameter, DecimalParameter, IntParameter
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib

def LUX_SuperTrendOscillator(dtloc, source='close', length=6, mult=9, smooth=72):
    """
    // This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
    // © LuxAlgo
      https://www.tradingview.com/script/dVau7zqn-LUX-SuperTrend-Oscillator/
     :return: List of tuples in the format (osc, signal, histogram)   
     translated for freqtrade: viksal1982  viktors.s@gmail.com
    """
    def_proc_name = '_LUX_SuperTrendOscillator'
    atrcol = 'atr' + def_proc_name
    hl2col = 'hl2' + def_proc_name
    upcol = 'up' + def_proc_name
    dncol = 'dn' + def_proc_name
    uppercol = 'upper' + def_proc_name
    lowercol = 'lower' + def_proc_name
    trendcol = 'trend' + def_proc_name
    sptcol = 'spt' + def_proc_name
    osc1col = 'osc1' + def_proc_name
    osc2col = 'osc2' + def_proc_name
    osccol = 'osc' + def_proc_name
    alphacol = 'alpha' + def_proc_name
    amacol = 'ama' + def_proc_name
    histcol = 'hist' + def_proc_name
    dtS = dtloc.copy().fillna(0)
    dtS[atrcol] = ta.ATR(dtloc, timeperiod=length) * mult
    dtS[hl2col] = (dtS['high'] + dtS['low']) / 2
    dtS[upcol] = dtS[hl2col] + dtS[atrcol]
    dtS[dncol] = dtS[hl2col] - dtS[atrcol]

    def calc_upper(dfr, init=0):
        global calc_Lux_STO_upper
        global calc_Lux_STO_src
        if init == 1:
            calc_Lux_STO_upper = 0.0
            calc_Lux_STO_src = 0.0
            return
        if calc_Lux_STO_src < calc_Lux_STO_upper:
            calc_Lux_STO_upper = min(dfr[upcol], calc_Lux_STO_upper)
        else:
            calc_Lux_STO_upper = dfr[upcol]
        calc_Lux_STO_src = dfr[source]
        return calc_Lux_STO_upper
    calc_upper(None, init=1)
    dtS[uppercol] = dtS.apply(calc_upper, axis=1)

    def calc_lower(dfr, init=0):
        global calc_Lux_STO_lower
        global calc_Lux_STO_src
        if init == 1:
            calc_Lux_STO_lower = 0.0
            calc_Lux_STO_src = 0.0
            return
        if calc_Lux_STO_src > calc_Lux_STO_lower:
            calc_Lux_STO_lower = max(dfr[dncol], calc_Lux_STO_lower)
        else:
            calc_Lux_STO_lower = dfr[dncol]
        calc_Lux_STO_src = dfr[source]
        return calc_Lux_STO_lower
    calc_lower(None, init=1)
    dtS[lowercol] = dtS.apply(calc_lower, axis=1)

    def calc_trend(dfr, init=0):
        global calc_Lux_STO_trend
        global calc_Lux_STO_lower
        global calc_Lux_STO_upper
        if init == 1:
            calc_Lux_STO_trend = 0.0
            calc_Lux_STO_lower = 0.0
            calc_Lux_STO_upper = 0.0
            return
        if dfr[source] > calc_Lux_STO_upper:
            calc_Lux_STO_trend = 1
        elif dfr[source] < calc_Lux_STO_lower:
            calc_Lux_STO_trend = 0
        calc_Lux_STO_upper = dfr[uppercol]
        calc_Lux_STO_lower = dfr[lowercol]
        return calc_Lux_STO_trend
    calc_trend(None, init=1)
    dtS[trendcol] = dtS.apply(calc_trend, axis=1)
    dtS[sptcol] = dtS[trendcol] * dtS[lowercol] + (1 - dtS[trendcol]) * dtS[uppercol]
    dtS[osc1col] = (dtS[source] - dtS[sptcol]) / (dtS[uppercol] - dtS[lowercol])
    dtS[osc2col] = np.where(dtS[osc1col] < 1, dtS[osc1col], 1)
    dtS[osccol] = np.where(dtS[osc2col] > -1, dtS[osc2col], -1)
    dtS[alphacol] = dtS[osccol].pow(2) / length

    def calc_ama(dfr, init=0):
        global calc_Lux_STO_ama
        if init == 1:
            calc_Lux_STO_ama = 0.0
            return
        calc_Lux_STO_ama = calc_Lux_STO_ama + dfr[alphacol] * (dfr[osccol] - calc_Lux_STO_ama)
        return calc_Lux_STO_ama
    calc_ama(None, init=1)
    dtS[amacol] = dtS.apply(calc_ama, axis=1)
    dtS[histcol] = ta.EMA(dtS[osccol] - dtS[amacol], timeperiod=smooth)
    return (dtS[osccol] * 100, dtS[amacol] * 100, dtS[histcol] * 100, dtS[sptcol])

class Github_DerSalvador_freqtrade_helm_chart__LuxOSC__20260115_122204(IStrategy):
    INTERFACE_VERSION = 3
    # Buy hyperspace params:
    entry_params = {'cross_entry': -100, 'length_entry': 6, 'mult_entry': 9, 'smooth_entry': 72}
    # Sell hyperspace params:
    exit_params = {'cross_exit': 50}
    length_entry = IntParameter(2, 100, default=int(entry_params['length_entry']), space='entry')
    mult_entry = IntParameter(2, 100, default=int(entry_params['mult_entry']), space='entry')
    smooth_entry = IntParameter(2, 100, default=int(entry_params['smooth_entry']), space='entry')
    cross_entry = IntParameter(-100, 100, default=int(entry_params['cross_entry']), space='entry')
    cross_exit = IntParameter(-100, 100, default=int(exit_params['cross_exit']), space='exit')
    stoploss = -0.99
    # Trailing stoploss
    trailing_stop = False
    timeframe = '5m'
    custom_info = {}
    process_only_new_candles = False
    use_exit_signal = True
    exit_profit_only = False
    ignore_roi_if_entry_signal = False
    startup_candle_count: int = 30
    # Optional order type mapping.
    order_types = {'entry': 'limit', 'exit': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False}
    # Optional order time in force.
    order_time_in_force = {'entry': 'gtc', 'exit': 'gtc'}
    # Main plot indicators (Moving averages, ...)
    # Subplots - each dict defines one additional plot
    plot_config = {'main_plot': {'supertrend': {'color': 'green'}}, 'subplots': {'OSC': {'osc': {'color': 'blue'}, 'signal': {'color': 'orange'}, 'histogram': {'color': 'green'}}}}

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['osc'], dataframe['signal'], dataframe['histogram'], dataframe['supertrend'] = LUX_SuperTrendOscillator(dataframe, length=int(self.length_entry.value), mult=int(self.mult_entry.value), smooth=int(self.smooth_entry.value))
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[qtpylib.crossed_above(dataframe['osc'], int(self.cross_entry.value)) & (dataframe['supertrend'] > dataframe['close']) & (dataframe['volume'] > 0), 'enter_long'] = 1
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[qtpylib.crossed_below(dataframe['osc'], int(self.cross_exit.value)) & (dataframe['volume'] > 0), 'exit_long'] = 1
        return dataframe