# bquant.analysis.zones.models — Модели глобальных свингов Этот раздел описывает новые структуры данных, которые поддерживают режим глобального расчёта свингов в пайплайне анализа зон. ## `SwingPoint` `SwingPoint` — дата-класс, описывающий одну точку свинга (пик или впадину), обнаруженную на **глобальном** ряду котировок. Экземпляры создаются стратегиями свингов один раз и переиспользуются для всех зон. ### Поля | Поле | Тип | Описание | | ---- | --- | -------- | | `point_id` | `int` | Уникальный идентификатор точки в последовательности свингов. | | `timestamp` | `datetime` | Метка времени, совпадающая со значением индекса исходного DataFrame. | | `index` | `int` | Позиция точки в полном датасете (iloc). | | `price` | `float` | Цена инструмента в момент свинга. | | `swing_type` | `str` | Тип точки: `'peak'` или `'trough'`. | | `amplitude_to_next` | `Optional[float]` | Процентное изменение до следующей точки свинга (если она существует). | | `duration_to_next` | `Optional[int]` | Количество баров до следующего свинга. | | `strategy_name` | `str` | Название стратегии, обнаружившей свинг. | | `strategy_params` | `Dict[str, Any]` | Параметры стратегии для трассируемости (по умолчанию пустой словарь). | ### Основные особенности - Структура полностью сериализуема: используется в `SwingContext.to_dict()` для кэширования. - Совместима с любыми стратегиями свингов — поля не зависят от конкретного алгоритма. - Позволяет сохранять не только геометрию свинга, но и метаданные стратегии (например, допуски ZigZag). ## `SwingContext` `SwingContext` агрегирует все `SwingPoint`, рассчитанные для полного набора данных. Контекст хранится на уровне пайплайна и передаётся в зоны, что устраняет повторные расчёты. ### Ключевые поля - `swing_points: List[SwingPoint]` — упорядоченный список свингов. - `indices: np.ndarray` — отсортированный массив `iloc`-индексов, используемый для быстрых срезов через `bisect`. - `full_data_length: int` — размер исходного датафрейма (для валидации). - `strategy_name: str` и `strategy_params: Dict[str, Any]` — метаданные стратегии. ### Методы - `slice(start_idx: int, end_idx: int) -> List[SwingPoint]` - Возвращает точки, попадающие в диапазон зоны, **с захватом соседей** слева и справа. Это обеспечивает корректные амплитуды при вычислении метрик. - `get_swings_for_zone(zone: ZoneInfo) -> List[SwingPoint]` - Удобный враппер над `slice`, использующий `zone.start_idx` и `zone.end_idx`. - `to_dict() -> Dict[str, Any]` - Сериализует весь контекст в словарь. Используется кэшем и для трассировки. ### Типичные сценарии ```python from bquant.analysis.zones.models import SwingContext context = strategy.calculate_global(prepared_df) first_zone = result.zones[0] zone_swings = context.get_swings_for_zone(first_zone) ``` ## `ZoneInfo` и глобальные свинги `ZoneInfo` теперь содержит поле `swing_context: Optional[SwingContext]`. Пайплайн вызывает `_inject_swing_context()` сразу после детекции зон (см. соответствующий раздел), поэтому каждая зона получает ссылку на общий контекст. ### Поле `swing_context` - Устанавливается только в режиме `swing_scope="global"`. - Остаётся `None` в режиме `per_zone`, что сохраняет обратную совместимость. - Попадает в метод `to_analyzer_format()`, поэтому все анализаторы признаков имеют доступ к глобальным свингам. ### Метод `get_zone_swings()` `ZoneInfo.get_zone_swings()` извлекает список `SwingPoint` для конкретной зоны. Если контекст не инъектирован, метод возвращает пустой список — таким образом старые сценарии не ломаются. ```python zone = result.zones[0] for point in zone.get_zone_swings(): print(point.timestamp, point.price, point.swing_type) ``` Используйте этот метод в пользовательских метриках и визуализациях, чтобы работать с уже рассчитанными глобальными свингами без повторных вычислений.