# source: https://raw.githubusercontent.com/Filimonov-Eremeyka/freqtrade/edf4ff8f6dc4d6617f318dd5ebaa0c3427654b1f/user_data/strategies/PolusFinalVisualization.py
# user_data/strategies/Github_Filimonov_Eremeyka_freqtrade__PolusFinalVisualization__20250905_154014.py
import numpy as np
import pandas as pd
from pandas import DataFrame
from freqtrade.strategy import IStrategy

# Импорт работает, т.к. polus_levels.py лежит в той же папке
from polus_levels import PolusLevels

class Github_Filimonov_Eremeyka_freqtrade__PolusFinalVisualization__20250905_154014(IStrategy):
    """
    ФИНАЛЬНАЯ СТРАТЕГИЯ: отказ от custom_plot_additions.
    Используем единственный 100% рабочий метод: N колонок в DataFrame + plot_config.
    """
    INTERFACE_VERSION = 3
    timeframe = '5m'
    startup_candle_count = 200

    minimal_roi = {"0": 100}
    stoploss = -1.0

    # --- КЛЮЧЕВОЙ МОМЕНТ: ЯВНО ПРОПИСЫВАЕМ ВСЕ КОЛОНКИ УРОВНЕЙ ---
    plot_config = {
        'main_plot': {
            # --- Уровни сопротивления (High) ---
            'level_high_0': {'color': 'blue', 'style': 'dash'},
            'level_high_1': {'color': 'blue', 'style': 'dash'},
            'level_high_2': {'color': 'blue', 'style': 'dash'},
            'level_high_3': {'color': 'blue', 'style': 'dash'},
            'level_high_4': {'color': 'blue', 'style': 'dash'},
            # --- Уровни поддержки (Low) ---
            'level_low_0': {'color': 'red', 'style': 'dash'},
            'level_low_1': {'color': 'red', 'style': 'dash'},
            'level_low_2': {'color': 'red', 'style': 'dash'},
            'level_low_3': {'color': 'red', 'style': 'dash'},
            'level_low_4': {'color': 'red', 'style': 'dash'},
        }
    }

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # 1. Получаем точечные сигналы от вашего индикатора
        polus = PolusLevels()
        high_signals, low_signals, _ = polus.calculate_levels(dataframe)

        dataframe['polus_high_signal'] = high_signals
        dataframe['polus_low_signal'] = low_signals

        # 2. Управляем жизненным циклом уровней и заполняем N колонок
        dataframe = self._manage_levels(dataframe, max_levels=5)
        
        return dataframe

        # ЗАМЕНИТЕ СТАРУЮ ФУНКЦИЮ _manage_levels НА ЭТУ:
    def _manage_levels(self, dataframe: DataFrame, max_levels: int) -> DataFrame:
        # Инициализируем все N колонок
        for i in range(max_levels):
            dataframe[f'level_high_{i}'] = np.nan
            dataframe[f'level_low_{i}'] = np.nan

        active_high_levels = {}  # {price: slot_index}
        active_low_levels = {}   # {price: slot_index}

        for i in range(len(dataframe)):
            # --- ВЕРХНИЕ УРОВНИ ---
            
            # 1. Проверяем пробой существующих уровней
            levels_to_remove = []
            for price, slot in active_high_levels.items():
                if dataframe.at[i, 'high'] >= price:
                    levels_to_remove.append((price, slot))
                    # ИСПРАВЛЕНИЕ: В момент пробоя, ставим NaN, чтобы "разорвать" линию
                    dataframe.loc[i, f'level_high_{slot}'] = np.nan

            # Удаляем пробитые уровни из активного списка
            for price, slot in levels_to_remove:
                del active_high_levels[price]

            # 2. Проверяем появление нового сигнала
            new_high_signal = dataframe.at[i, 'polus_high_signal']
            if pd.notna(new_high_signal) and new_high_signal not in active_high_levels:
                used_slots = active_high_levels.values()
                for slot in range(max_levels):
                    if slot not in used_slots:
                        active_high_levels[new_high_signal] = slot
                        break
            
            # 3. "Протягиваем" все еще активные уровни в их колонках
            for price, slot in active_high_levels.items():
                dataframe.loc[i, f'level_high_{slot}'] = price

            # --- НИЖНИЕ УРОВНИ (аналогичное исправление) ---
            levels_to_remove = []
            for price, slot in active_low_levels.items():
                if dataframe.at[i, 'low'] <= price:
                    levels_to_remove.append((price, slot))
                    # ИСПРАВЛЕНИЕ: В момент пробоя, ставим NaN, чтобы "разорвать" линию
                    dataframe.loc[i, f'level_low_{slot}'] = np.nan

            for price, slot in levels_to_remove:
                del active_low_levels[price]

            new_low_signal = dataframe.at[i, 'polus_low_signal']
            if pd.notna(new_low_signal) and new_low_signal not in active_low_levels:
                used_slots = active_low_levels.values()
                for slot in range(max_levels):
                    if slot not in used_slots:
                        active_low_levels[new_low_signal] = slot
                        break
            
            for price, slot in active_low_levels.items():
                dataframe.loc[i, f'level_low_{slot}'] = price

        return dataframe

    # Пустые методы
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['enter_long'] = 0
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['exit_long'] = 0
        return dataframe