ФИНАЛЬНАЯ СТРАТЕГИЯ: отказ от custom_plot_additions. Используем единственный 100% рабочий метод: N колонок в DataFrame + plot_config.
Timeframe
5m
Direction
Long Only
Stoploss
-100.0%
Trailing Stop
No
ROI
0m: 10000.0%
Interface Version
3
Startup Candles
200
Indicators
0
freqtrade/freqtrade-strategies
author@: lenik
# user_data/strategies/PolusFinalVisualization.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 PolusFinalVisualization(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