# Глубокое погружение: Пайплайн анализатора зон

> 💡 **Для кого это руководство?**
>
> Этот документ предназначен для разработчиков и аналитиков, которые хотят понять **внутреннюю логику и механику** универсального пайплайна `analyze_zones`. Если вы ищете справочник по функциям и параметрам, обратитесь к [API документации](../api/analysis/zones.md).

### Импорт

Рекомендуемый импорт (через публичный API модуля):

```python
from bquant.analysis.zones import analyze_zones
```

---

## 1. Главная идея: Универсальность и Контекст

Основная цель пайплайна `analyze_zones` — предоставить **универсальный** инструмент для исследования рыночных "зон". Зона — это не просто отрезок времени, а период, выделенный по определенному правилу, основанному на поведении технического индикатора.

Ключевая инновация — **контекст**. Каждая найденная зона "знает", как она была обнаружена: какой индикатор использовался, по какой стратегии (пересечение нуля, выход из зоны перекупленности и т.д.) и с какими параметрами. Это позволяет анализировать и визуализировать зоны от **любого индикатора** (MACD, RSI, Stochastic или даже вашего собственного) единым образом, без необходимости переписывать код.

---

## 2. Пошаговый процесс анализа

Пайплайн представляет собой "конструктор" (builder), где вы по шагам настраиваете каждый аспект анализа.

**Обязательные и опциональные методы:**
- **Обязательно:** `detect_zones()` — без него `build()` вызовет ошибку.
- **Опционально:** `with_indicator()`, `with_strategies()`, `with_swing_preset()`, `with_swing_scope()`, `with_cache()`, `with_auto_swing_thresholds()`, `analyze()`.
- Если `with_strategies()` не вызван, используется `UniversalZoneAnalyzer` с дефолтными стратегиями из конфигурации.

#### Шаг 1: Инициализация (`analyze_zones(df)`)

-   **Что происходит?** Вы передаете в пайплайн исходные данные — DataFrame с колонками `open`, `high`, `low`, `close`, `volume`.
-   **Результат:** Создается объект-конструктор `ZoneAnalysisBuilder`, который готов к дальнейшей настройке.

#### Шаг 2: Расчет индикатора (`.with_indicator(...)`)

-   **Что происходит?** На этом шаге вы "сообщаете" пайплайну, какой индикатор использовать. Это может быть:
    -   **Встроенный индикатор**: Например, `.with_indicator('custom', 'macd', ...)` рассчитает MACD.
    -   **Индикатор из библиотеки `pandas-ta`**: Например, `.with_indicator('pandas_ta', 'rsi', length=14)` рассчитает RSI.
    -   **Уже существующий индикатор**: Если в вашем DataFrame уже есть колонка с индикатором, этот шаг можно пропустить.
-   **Результат:** В DataFrame добавляются новые колонки с рассчитанными значениями индикатора (например, `macd_hist`, `RSI_14`).

#### Шаг 3: Детекция зон (`.detect_zones(...)`)

-   **Что происходит?** Это ядро процесса. Здесь пайплайн ищет на графике индикатора отрезки, соответствующие заданной **стратегии детекции**.
-   **Доступные стратегии:**
    -   `'zero_crossing'`: Находит зоны, где индикатор-осциллятор (например, гистограмма MACD) находится выше или ниже нуля. Требует `indicator_col` в правилах.
    -   `'threshold'`: Находит зоны, где индикатор (например, RSI) выходит за пределы заданных порогов (например, выше 70 или ниже 30). Требует `indicator_col`, `upper_threshold`, `lower_threshold`.
    -   `'line_crossing'`: Находит зоны между пересечениями двух линий индикатора (например, основной и сигнальной линий Stochastic). Требует `line1_col`, `line2_col`.
    -   `'preloaded'`: Загружает зоны из внешнего DataFrame. Полезно для анализа заранее определённых зон.
    -   `'combined'`: Объединяет несколько правил детекции в одну стратегию.
-   **Результат:** Создается предварительный список зон. Каждая зона — это объект с временем начала, временем конца, индексами (`start_idx`, `end_idx`) и типом (`bull`/`bear`).

#### Шаг 4: Глубокий анализ характеристик

Это самый насыщенный этап анализа, состоящий из трех логических частей: подключение стратегий, запуск анализа и сборка результата.

##### 4.1. Подключение стратегий анализа (`.with_strategies(...)`)

На этом шаге вы сообщаете пайплайну, какие именно характеристики (метрики) нужно извлечь из каждой зоны. Это делается путем передачи строковых идентификаторов для каждого типа анализа.

-   **Что происходит?** Вы выбираете и настраиваете "анализаторы", которые будут применяться к каждой зоне.
-   **Доступные стратегии:**
    -   **Анализ внутренних колебаний (`swing`):**
        -   `swing='find_peaks'`: Поиск пиков и впадин на основе `scipy.signal.find_peaks`. Требует подбора порогов или пресета.
        -   `swing='pivot_points'`: Классические точки разворота. Может давать низкое покрытие зон на коротких таймфреймах.
        -   `swing='zigzag'`: Поиск экстремумов с помощью индикатора ZigZag. **Рекомендуется для исследовательского анализа и проверки гипотез** — обеспечивает стабильное покрытие ≥60% зон и воспроизводимые статистически значимые результаты. См. [Кейс по состоятельности MACD-зон](../analytics/zones/macd_zone_consistency_case_study.md).
    -   **Анализ формы (`shape`):**
        -   `shape='statistical'`: Расчет статистических моментов (асимметрия, эксцесс) для формы индикатора.
    -   **Анализ дивергенций (`divergence`):**
        -   `divergence='classic'`: Поиск классических бычьих и медвежьих дивергенций.
    -   **Анализ волатильности (`volatility`):**
        -   `volatility='combined'`: Расчет составного индекса волатильности внутри зоны.
    -   **Анализ объема (`volume`):**
        -   `volume='standard'`: Расчет метрик, связанных с объемом.

##### 4.2. Запуск анализа и доп. процессов (`.analyze(...)`)

Этот метод запускает извлечение всех метрик, настроенных на предыдущем шаге. Кроме того, он может запускать дополнительные высокоуровневые аналитические процессы.

**Параметры:**
-   `clustering` (bool, по умолчанию `True`): Включить кластеризацию зон.
-   `n_clusters` (int, по умолчанию `3`): Количество кластеров для KMeans.
-   `regression` (bool, по умолчанию `False`): Запустить регрессионный анализ (прогноз длительности зоны, доходности).
-   `validation` (bool, по умолчанию `False`): Запустить валидацию моделей.

-   **Что происходит?**
    1.  Пайплайн проходит по каждой зоне и применяет к ней все стратегии, указанные в `.with_strategies()`. Результаты сохраняются в словарь `zone.features`.
    2.  **Кластеризация:** Если передан аргумент `clustering=True`, запускается алгоритм кластеризации (например, KMeans) для группировки похожих зон. Результаты доступны в `result.clustering`.
    3.  **Статистические тесты:** Пайплайн **автоматически** запускает набор тестов гипотез (например, t-тест для сравнения доходностей бычьих и медвежьих зон). Результаты доступны в `result.hypothesis_tests`.

##### 4.3. Ключевые метрики (Features), генерируемые стратегиями

Главный результат этого шага — наполнение словаря `features` для каждой зоны. Ниже приведены примеры ключевых метрик, которые генерируют разные стратегии.

| Стратегия (`.with_strategies(...)`) | Ключевая метрика в `zone.features` | Описание |
| :--- | :--- | :--- |
| `swing='*'` (любая) | `num_peaks`, `num_troughs` | Количество пиков и впадин внутри зоны. |
| | `peak_time_ratio` | Положение главного пика в зоне (0.0 - начало, 1.0 - конец). |
| | `drawdown_from_peak` | Максимальная просадка цены от пика внутри зоны. |
| | `metadata['swing_metrics']` | Словарь: `rally_count`, `drop_count`, `avg_rally_pct`, `avg_drop_pct`, `num_swings`, `rally_to_drop_ratio`. |
| `divergence='classic'` | `has_classic_divergence` | `True`, если найдена классическая дивергенция. |
| `volatility='combined'`| `volatility_score` | Составная оценка волатильности в зоне (например, от 0 до 10). |
| `volume='standard'` | `volume_indicator_corr` | Корреляция между объемом и индикатором в зоне. |
| `shape='statistical'` | `skewness`, `kurtosis` | Асимметрия и эксцесс распределения значений индикатора. |

**Структура `zone.features` и вложенные метрики:**

Часть метрик хранится на верхнем уровне `zone.features`, а часть — во вложенном словаре `metadata`. Метрики свингов (rally/drop counts, avg_rally_pct, avg_drop_pct) находятся в `metadata['swing_metrics']`:

```python
# Метрики верхнего уровня (напрямую)
num_peaks = zone.features.get('num_peaks')
peak_time_ratio = zone.features.get('peak_time_ratio')

# Метрики свингов (через metadata)
metadata = zone.features.get('metadata', {})
swing_metrics = metadata.get('swing_metrics', {})
rally_count = swing_metrics.get('rally_count')
drop_count = swing_metrics.get('drop_count')
avg_rally_pct = swing_metrics.get('avg_rally_pct')
avg_drop_pct = swing_metrics.get('avg_drop_pct')
num_swings = swing_metrics.get('num_swings')
```

Аналогично: `metadata['shape_metrics']`, `metadata['divergence_metrics']`, `metadata['volatility_metrics']`, `metadata['volume_metrics']` — для соответствующих стратегий.

##### 4.4. Опциональная настройка пайплайна

Эти методы вызываются **до** `.build()` в любом порядке и позволяют fine-tune поведение пайплайна:

| Метод | Описание |
| :--- | :--- |
| `.with_swing_preset(name)` | Применить именованный пресет параметров для свингов (`'narrow_zone'`, `'wide_zone'` и др.). Фиксирует пороги для `find_peaks`, `pivot_points`, `zigzag`. |
| `.with_swing_scope(scope)` | Режим расчёта свингов. **По умолчанию** `'global'` — свинги вычисляются один раз по всему датасету и «нарезаются» по зонам. `'per_zone'` — свинги считаются отдельно внутри каждой зоны. `global` часто даёт выше покрытие (см. кейс по состоятельности). |
| `.with_cache(enable=True, ttl=3600)` | Включить/отключить кэширование результата. `ttl` — время жизни кэша в секундах. Отключайте кэш (`enable=False`) при экспериментировании с разными параметрами. |
| `.with_auto_swing_thresholds(enable=True)` | Включить адаптивные пороги для `find_peaks` и `pivot_points`. Для `zigzag` не влияет. **Внимание:** при текущих настройках авто-пороги могут обнулять покрытие для `find_peaks`/`pivot_points` — требуется тюнинг. |

Пример исследовательского пайплайна с настройкой свингов:

```python
result = (
    analyze_zones(df)
    .with_indicator('custom', 'macd', fast_period=12, slow_period=26, signal_period=9)
    .detect_zones('zero_crossing', indicator_col='macd_hist')
    .with_strategies(swing='zigzag')
    .with_swing_preset('narrow_zone')
    .with_swing_scope('global')
    .with_cache(enable=False)  # отключить кэш при сравнении стратегий
    .analyze(clustering=False)
    .build()
)
```

#### Шаг 5: Сборка (`.build()`)

-   **Что происходит?** Финальный вызов, который запускает весь настроенный конвейер в правильном порядке: `.with_indicator` -> `.detect_zones` -> `.analyze`.
-   **Результат:** Возвращается единый, полностью готовый объект `ZoneAnalysisResult`.

---
#### Пример полного пайплайна

Вот как выглядит полный цикл анализа в коде, объединяющий все шаги:

```python
from bquant.analysis.zones import analyze_zones

# Базовый пайплайн от данных до результата
result = (
    analyze_zones(df)
    .with_indicator('custom', 'macd', fast_period=12, slow_period=26, signal_period=9)
    .detect_zones('zero_crossing', indicator_col='macd_hist')
    .with_strategies(swing='zigzag', shape='statistical', divergence='classic')
    .with_swing_preset('narrow_zone')
    .with_swing_scope('global')
    .analyze(clustering=True, n_clusters=3)
    .build()
)

# Пример доступа к извлеченным метрикам
zone = result.zones[0]
print(f"Положение пика: {zone.features.get('peak_time_ratio')}")
print(f"Длительность: {zone.features.get('duration')}")

# Доступ к метрикам свингов (для анализа состоятельности зон)
swing_metrics = zone.features.get('metadata', {}).get('swing_metrics', {})
if swing_metrics:
    print(f"Ап-свингов: {swing_metrics.get('rally_count')}, "
          f"даун-свингов: {swing_metrics.get('drop_count')}")

# Результаты тестов гипотез
if result.hypothesis_tests:
    print(result.hypothesis_tests.results)
```

---

## 3. Итоговая информация (объект `ZoneAnalysisResult`)

В результате вы получаете не просто набор цифр, а структурированный объект, готовый к дальнейшему исследованию и визуализации.

-   **`result.zones`**: Это список объектов `ZoneInfo`. Каждый объект `ZoneInfo` — это исчерпывающее описание одной зоны:
    -   `zone_id`, `type`, `start_time`, `end_time`: Базовая информация.
    -   `start_idx`, `end_idx`, `duration`: Позиционные индексы и число баров в зоне.
    -   `data`: Срез DataFrame с OHLCV и индикаторами для зоны.
    -   **`features`**: Словарь со всеми численными метриками, извлеченными на Шаге 4 (например, `{'duration': 15, 'price_return': 0.012, 'num_peaks': 3, 'metadata': {...}}`). **Это и есть главные данные для анализа.** См. структуру `zone.features` и `metadata` выше.
    -   **`indicator_context`**: Словарь, описывающий, как зона была найдена (например, `{'detection_indicator': 'macd_hist', 'detection_strategy': 'zero_crossing'}`). Это ключ к универсальности.
    -   `swing_context` (при глобальном режиме, по умолчанию): Контекст свингов для метода `zone.get_zone_swings()`.

-   **`result.statistics`**: Агрегированная статистика по всем найденным зонам. Например, средняя длительность бычьих зон, медианное изменение цены в медвежьих зонах, распределение зон по часам и т.д.

-   **`result.clustering`**: Если была включена кластеризация, здесь хранятся ее результаты (например, какому кластеру принадлежит каждая зона).

-   **`result.visualize(...)`**: Встроенный метод, который использует всю собранную информацию (особенно `indicator_context`) для автоматического построения [графиков визуализации зон](../api/visualization/zones.md).

### Итог

Пайплайн `analyze_zones` — это конвейер, который превращает сырые ценовые данные в богатый, структурированный набор данных. Он не просто находит отрезки на графике, а **количественно описывает** их внутреннюю структуру (через `features`) и **сохраняет контекст** их обнаружения (через `indicator_context`), что делает результаты универсальными, воспроизводимыми и готовыми к немедленной визуализации и дальнейшему анализу.

---

### Шаг 6: Статистическая верификация

Поиск и описание зон — это первый шаг анализа. Однако, чтобы убедиться, что найденные закономерности (например, повышенная доходность в бычьих зонах) не являются случайностью, их необходимо проверить с помощью статистических тестов.

**Для подробного изучения методов валидации и проверки гипотез обратитесь к нашему руководству:**

**➡️ [Руководство по рабочему процессу статистического анализа](./statistical_analysis_workflow.md)**

---

## 🔗 См. также

- **[Технический справочник API (analysis.zones)](../api/analysis/zones.md)**: Полный список классов, методов и параметров.
- **[Документация по визуализации](../api/visualization/zones.md)**: Как визуализировать полученные зоны.
- **[Руководство пользователя по анализу зон](../user_guide/zone_analysis.md)**: Практические примеры использования.
- **[Кейс: Состоятельность бычьих зон MACD](../analytics/zones/macd_zone_consistency_case_study.md)**: Сравнение стратегий свингов, режимов `per_zone`/`global` и выводы по гипотезе H1.
