# Zone Visualization - Визуализация зон ## 📚 Обзор Модуль `bquant.visualization.zones` предоставляет комплексные инструменты для визуализации торговых зон, обнаруженных с помощью [Universal Zone Analysis Pipeline](../analysis/zones.md). Поддерживает два backend'а визуализации — **Plotly** (интерактивный) и **Matplotlib** (статический) — с автоматическим fallback при недоступности библиотек. **Ключевые возможности:** - 🎯 **Два основных подхода**: Встроенный вызов `result.visualize()` и прямое использование класса `ZoneVisualizer`. - 📊 **4 режима визуализации**: `overview`, `detail`, `comparison`, `statistics`. - 🕒 **Продвинутое управление осью времени**: Режимы `dense` (без разрывов) и `timeseries` (реальное время). - ⚙️ **Гибкая настройка индикаторов**: Автоматическое определение, явное указание и настройка типов графиков (`line`/`bar`). - 💾 **Удобный экспорт**: Встроенная функция `save_figure` с умными настройками по умолчанию для сохранения в PNG/HTML. - 🎨 **Полная кастомизация**: Управление контекстом, количеством тиков, отображением гэпов и панелями. --- ## 🚀 Рекомендуемый рабочий процесс Для большинства задач рекомендуется следующий двухэтапный процесс: 1. **Анализ**: Используйте [Universal Zone Analysis Pipeline](../analysis/zones.md) для обнаружения и анализа зон. ```python from bquant.analysis.zones import analyze_zones from bquant.data.samples import get_sample_data # Запускаем пайплайн result = ( analyze_zones(get_sample_data('tv_xauusd_1h')) .with_indicator('custom', 'macd') .detect_zones('zero_crossing', indicator_col='macd_hist') .analyze() .build() ) ``` 2. **Визуализация**: Используйте метод `result.visualize()` для создания графиков. Это самый простой и мощный способ. ```python # Общий обзор всех зон fig_overview = result.visualize('overview', title="MACD Zones Overview") # Детальный обзор одной зоны fig_detail = result.visualize('detail', zone_id=3, context_bars=15) # Сравнение нескольких зон fig_comparison = result.visualize('comparison', max_zones=4) # Показать график fig_overview.show() ``` --- ## 🎯 Встроенная визуализация из `ZoneAnalysisResult` Метод `result.visualize(mode, **kwargs)` — это основной и наиболее удобный интерфейс для визуализации. ### Режим `overview` Общий обзор всех зон на графике цены. ```python fig = result.visualize( 'overview', title="Zones Overview with Timeseries Axis", show_indicators=True, time_axis_mode='timeseries' # Отображение с учетом реального времени (включая выходные) ) ``` **Ключевые параметры `overview`:** - `show_indicators` (bool, default=`False`): Отобразить панель с индикаторами. - `indicator_chart_types` (dict, optional): Явно задать тип графика для индикатора. Пример: `{'macd_hist': 'bar'}`. - `time_axis_mode` (str, default=`'dense'`): Режим оси времени. - `'dense'`: Убирает разрывы (выходные), отображая только торговые дни. Быстро и компактно. - `'timeseries'`: Сохраняет временную шкалу, показывая разрывы. Идеально для анализа пропорций. - `xaxis_num_ticks` (int, default=16): Желаемое количество меток на оси X (только для `dense` режима). - `show_gap_lines` (bool, default=`False`): Показывать вертикальные линии в местах временных разрывов. - `date_range` (Tuple[datetime, datetime], optional): Фильтрация по диапазону дат. См. [раздел ниже](#фильтрация-по-диапазону-дат-date_range). - `show_aggregate_metrics` (bool, default=`False`): Отобразить агрегированные метрики по зонам. См. [раздел ниже](#агрегированные-метрики). - `aggregate_metrics_mode` (str, default=`'compact'`): Режим вывода метрик (`'compact'` или `'full'`). - `show_swings` (bool, default=`False`): Отобразить swing-точки (peaks/troughs) на графике. - `swing_marker_size` (int, default=8): Размер маркеров для swing-точек. #### Фильтрация по диапазону дат: `date_range` При использовании параметра `date_range` визуализатор автоматически фильтрует как данные, так и зоны: ```python import pandas as pd # Создаем диапазон дат start_date = pd.Timestamp('2025-06-25', tz='UTC') end_date = pd.Timestamp('2025-07-03', tz='UTC') # Визуализируем только этот период fig = result.visualize( 'overview', date_range=(start_date, end_date), title=f"Zones from {start_date.date()} to {end_date.date()}", show_aggregate_metrics=True, # Метрики будут считаться только для этого периода! show_swings=True ) ``` **⚠️ Важно**: Агрегированные метрики (если включены) рассчитываются **только для зон в выбранном диапазоне**, а не по всему датасету. Это позволяет анализировать характеристики зон в разные временные периоды. **Пример use case** - сравнение поведения зон по месяцам: ```python # Июнь fig_june = result.visualize('overview', date_range=(pd.Timestamp('2025-06-01'), pd.Timestamp('2025-06-30')), show_aggregate_metrics=True, aggregate_metrics_mode='full') # Июль fig_july = result.visualize('overview', date_range=(pd.Timestamp('2025-07-01'), pd.Timestamp('2025-07-31')), show_aggregate_metrics=True, aggregate_metrics_mode='full') # Метрики будут разные для каждого месяца! ``` #### Агрегированные метрики Параметр `show_aggregate_metrics` добавляет на график текстовую аннотацию с агрегированной статистикой по bull/bear зонам: ```python fig = result.visualize( 'overview', show_aggregate_metrics=True, # Включить метрики aggregate_metrics_mode='compact', # Режим: 'compact' (8 строк) или 'full' (~16 строк) ) ``` **Режимы вывода**: - **`compact`** (по умолчанию, 8 строк): ``` 📊 Bull Zones: 37/37 with swings (100%) Avg Rally: +1.11% ± 0.70% Avg Drop: -1.00% ± 0.64% Rally/Drop Ratio: 1.11x ``` - **`full`** (~16 строк, включает длительности): ``` 📊 Bull Zones: 37/37 with swings (100%) Avg Rally: +1.11% ± 0.70% (3.5 ± 1.2 bars) Avg Drop: -1.00% ± 0.64% (2.1 ± 0.8 bars) Rally/Drop Ratio: 1.11x Avg Swing Duration: 2.8 ± 1.5 bars ``` **Метрики включают** (v1.0): - Покрытие зон свингами (% зон с обнаруженными свингами) - Средняя амплитуда rally/drop (mean ± std) - Ratio (соотношение rally к drop) - Средняя длительность движений в барах (только в `full` режиме) **Примечание**: Текущая версия (v1.0) использует MVP-агрегацию с mean±std. Расширенная версия (v1.2) с median/IQR и shape метриками запланирована. См. [zomet_v1.2_advanced_aggregation.md](../../../devref/gaps/graph/zomet_v1.2_advanced_aggregation.md). --- ### Режим `detail` Детальный просмотр одной зоны с окружающим контекстом. ```python # Найти зону для анализа median_zone = min(result.zones, key=lambda z: abs(z.duration - 30)) fig = result.visualize( 'detail', zone_id=median_zone.zone_id, context_bars=20, show_indicators=True, show_volume=True, time_axis_mode='dense', xaxis_num_ticks=20, title=f"Detail for Zone #{median_zone.zone_id}" ) ``` **Ключевые параметры `detail`:** - `zone_id` (int, **required**): ID зоны для детального просмотра. - `context_bars` (int, default=20): Количество баров до и после зоны для контекста. - `show_indicators` (bool, default=`True`): Показать панель индикаторов. - `show_volume` (bool, default=`True`): Показать панель объема. - `time_axis_mode` (str, default=`'dense'`): Режим оси времени (`dense` или `timeseries`). - `xaxis_num_ticks` (int, default=16): Количество меток на оси X (для `dense` режима). --- ### Режим `comparison` Сравнение нескольких зон, каждая в своем "слоте" для удобного сопоставления. ```python fig = result.visualize( 'comparison', max_zones=4, comparison_context=10, # Меньше контекста для сравнения show_indicators=True, time_axis_mode='dense', title="Comparison of 4 Zones" ) ``` **Ключевые параметры `comparison`:** - `max_zones` (int, default=5): Максимальное количество зон для отображения. - `date_range` (Tuple[datetime, datetime], optional): Диапазон дат для фильтрации зон. - `comparison_context` (int, default=30): Количество баров до и после *каждой* зоны в режиме сравнения. - `time_axis_mode` (str, default=`'dense'`): Режим оси времени. --- ### Режим `statistics` Статистический анализ всех зон (распределения, типы и т.д.). ```python fig = result.visualize('statistics', title='Zone Statistics') ``` **Внутри вызывает:** `ZoneVisualizer.plot_zones_analysis()` --- ## 💾 Экспорт графиков: `save_figure` Вместо `fig.write_html()` или `fig.write_image()`, рекомендуется использовать универсальную функцию `save_figure` из `bquant.visualization.export`. ```python from bquant.visualization.export import save_figure # Создаем график fig = result.visualize('overview', time_axis_mode='timeseries') # Просто сохраняем # Автоматически создаст папку и выберет формат saved_path = save_figure(fig, "01_overview_timeseries") print(f"Chart saved to: {saved_path}") # Сохранение с кастомными параметрами saved_path_png = save_figure( fig, "01_overview_custom", output_dir="C:/Users/Ivan/Documents/pro/bquant/output/my_charts", prefer='png', # Предпочесть PNG, если возможно width=1600, height=900 ) ``` **Преимущества `save_figure`:** - **Умные пути**: Автоматически сохраняет в `output/vis/<имя_скрипта>/<имя_файла>`. - **Надежный экспорт**: Пытается сохранить в `PNG` (если установлен `kaleido`), при ошибке автоматически переключается на `HTML`. - **Простота**: Требует только фигуру и имя файла. --- ## 🏗️ Прямое использование `ZoneVisualizer` Для полного контроля над процессом можно использовать класс `ZoneVisualizer` напрямую. ```python from bquant.visualization import ZoneVisualizer # 1. Инициализация visualizer = ZoneVisualizer(backend='plotly') # 2. Вызов методов с полными параметрами fig_detail = visualizer.plot_zone_detail( price_data=result.data, zone=median_zone, context_bars=15, show_indicators=True, indicator_chart_types={'macd_hist': 'bar'}, # Явно задаем гистограмму time_axis_mode='dense', title="Detail from ZoneVisualizer" ) fig_detail.show() ``` ### Основные методы `ZoneVisualizer` - `plot_zones_on_price_chart()`: Основа для режима `overview`. - `plot_zone_detail()`: Основа для режима `detail`. - `plot_zones_comparison()`: Основа для режима `comparison`. Все эти методы принимают те же параметры, что и `result.visualize()`, но требуют явной передачи `price_data` и данных о зонах. --- ## 🔧 Convenience-функции Для быстрых построений без создания `ZoneVisualizer` или `ZoneAnalysisResult`. ```python from bquant.visualization import plot_zone_detail, plot_zones_comparison # Детальный график fig_detail = plot_zone_detail(result.data, median_zone, context_bars=10) # График сравнения fig_cmp = plot_zones_comparison(result.data, result.zones[:3], max_zones=3) ``` Эти функции являются обертками над методами `ZoneVisualizer`. ### Визуализация ZigZag индикатора: `plot_zigzag_verification` Функция для построения графика ZigZag индикатора с swing-точками для визуальной проверки параметров стратегии. Полезно для отладки и верификации настроек swing-стратегии. ```python from bquant.visualization import plot_zigzag_verification # Простой вариант - только параметры fig = plot_zigzag_verification( price_data=result.data, legs=10, deviation=0.05 ) # С swing_context для точных типов точек fig = plot_zigzag_verification( price_data=result.data, legs=10, deviation=0.05, swing_context=result.zones[0].swing_context ) ``` **Параметры:** - `price_data` (pd.DataFrame, **required**): DataFrame с OHLCV данными (должен содержать 'close', 'high', 'low'). - `legs` (int, **required**): Количество баров для подтверждения разворота (параметр ZigZag). - `deviation` (float, **required**): Минимальное процентное отклонение (например, 0.05 = 5%). - `swing_context` (SwingContext, optional): Опциональный SwingContext для точного определения типов точек (peaks/troughs). - `title` (str, optional): Заголовок графика (по умолчанию генерируется автоматически). - `height` (int, default=800): Высота графика в пикселях. - `show_rangeslider` (bool, default=False): Показывать ползунок диапазона (range slider) под графиком для навигации по большим датасетам. - `**kwargs`: Дополнительные параметры для Plotly figure (например, `width`). **Возвращает:** - `go.Figure` или `None` если Plotly недоступен. **Что показывает график:** - Свечной график (Candlestick) с ценой - Маркеры swing-точек поверх графика: - 🔴 Красные треугольники вниз (peaks) - 🟢 Зеленые треугольники вверх (troughs) - Опционально: ползунок диапазона (rangeslider) для навигации по большим датасетам **Пример использования в скрипте:** ```python # После анализа зон result = ( analyze_zones(df) .with_strategies(swing="zigzag") .with_auto_swing_thresholds(True) .analyze() .build() ) # Получаем параметры из первой зоны if result.zones: first_zone = result.zones[0] swing_context = first_zone.swing_context strategy_params = swing_context.strategy_params # Строим график для визуальной проверки fig_zigzag = plot_zigzag_verification( price_data=result.data, legs=strategy_params.get('legs', 10), deviation=strategy_params.get('deviation', 0.05), swing_context=swing_context, show_rangeslider=True # Включаем ползунок для навигации по большому датасету ) if fig_zigzag: save_figure(fig_zigzag, "zigzag_verification") ``` --- ## 📖 Полный пример использования Этот пример демонстрирует современный подход к визуализации, включая анализ, создание разных типов графиков и их сохранение. ```python from bquant.data.samples import get_sample_data from bquant.analysis.zones import analyze_zones from bquant.visualization.export import save_figure from datetime import datetime # 1. Загрузка данных и анализ data = get_sample_data('tv_xauusd_1h') result = ( analyze_zones(data) .with_indicator('custom', 'macd', fast_period=12, slow_period=26, signal_period=9) .detect_zones('zero_crossing', indicator_col='macd_hist', min_duration=3) .analyze(clustering=True) .build() ) print(f"Обнаружено {len(result.zones)} зон.") # 2. Создание и сохранение графика "overview" в режиме timeseries print("Создание overview-графика в режиме timeseries...") fig_overview = result.visualize( 'overview', title="Обзор зон MACD (режим Timeseries)", show_indicators=True, time_axis_mode='timeseries' # Сохраняем пропорции времени ) save_figure(fig_overview, "01_overview_timeseries_mode") # 3. Детальный анализ одной зоны # Находим зону с длительностью, близкой к медианной median_duration = result.statistics['duration_distribution']['overall']['median'] median_zone = min(result.zones, key=lambda z: abs(z.features['duration'] - median_duration)) print(f"Создание детального графика для зоны #{median_zone.zone_id}...") fig_detail = result.visualize( 'detail', zone_id=median_zone.zone_id, context_bars=25, show_indicators=True, indicator_chart_types={'macd_hist': 'bar'}, # Явное указание типа графика time_axis_mode='dense', # Компактный вид xaxis_num_ticks=20, title=f"Детализация зоны #{median_zone.zone_id}" ) save_figure(fig_detail, f"02_detail_zone_{median_zone.zone_id}") # 4. Сравнение первых 4 зон print("Создание графика для сравнения 4 зон...") fig_comparison = result.visualize( 'comparison', max_zones=4, comparison_context=5, # Небольшой контекст для сравнения show_indicators=True, title="Сравнение первых 4 зон" ) save_figure(fig_comparison, "03_comparison_4_zones") print("Все графики успешно созданы и сохранены в папку 'output/vis/'.") ``` --- ## 🔗 Связанные разделы - **[Zone Analysis](../analysis/zones.md)**: Документация по `ZoneAnalysisResult`. - **[research/notebooks/04_zones_sample.py](../../../research/notebooks/04_zones_sample.py)**: Актуальный скрипт с полным покрытием всех интерфейсов. --- ## 📝 Changelog - **v1.1** (2025-11-12): - ✨ **Новая функция `plot_zigzag_verification`**: Добавлена convenience-функция для визуализации ZigZag swing-точек на графике цены. Показывает candlestick-график с маркерами peaks/troughs для визуальной проверки параметров swing-стратегии. - ✨ **Параметр `show_rangeslider`**: Опциональный ползунок диапазона для навигации по большим датасетам (по умолчанию отключён для чистого отображения). - 📚 **Документация**: Добавлен раздел с описанием `plot_zigzag_verification` и примерами использования. - **v1.0** (2025-11-11): - ✨ **Агрегированные метрики**: Новые параметры `show_aggregate_metrics` и `aggregate_metrics_mode` для отображения статистики по зонам. - ✨ **Визуализация свингов**: Параметр `show_swings` для отображения swing-точек (peaks/troughs) на графике. - ✨ **Метрики зон в detail режиме**: Параметры `show_zone_metrics` и `show_zone_stats` для детального просмотра. - 🐛 **Исправлена агрегация**: Теперь корректно обрабатывает несбалансированные свинги и использует правильные ключи (`avg_rally_pct`). - 📚 **Документация**: Добавлены разделы по агрегированным метрикам и фильтрации по `date_range`. - **v0.0.1** (2025-11-05): - ✨ **Добавлен `time_axis_mode`**: Параметр для выбора между `dense` и `timeseries` режимами оси времени. - ✨ **Добавлен `xaxis_num_ticks`**: Параметр для контроля количества меток на оси X в `dense` режиме. - ✨ **Добавлен `indicator_chart_types`**: Позволяет явно задавать тип графика для индикаторов (`bar`/`line`). - ✨ **Добавлен `comparison_context`**: Специальный параметр контекста для режима `comparison`. - 📚 **Документация**: Полностью переработана для отражения новых возможностей и лучших практик. - **v0.0.0** (2025-10-28): - 🎉 **Начальная реализация**: Добавлены `plot_zone_detail()`, `plot_zones_comparison()`. - 🎉 **Встроенная визуализация**: `ZoneAnalysisResult.visualize()`. - 🎉 **Поддержка Backends**: Plotly и Matplotlib.