# Developer Guide - Руководство разработчика BQuant

## 📚 Обзор

Руководство разработчика собирает практические рекомендации по архитектуре Universal Pipeline v2.1, расширяемым точкам входа и качественным стандартам кода. Все примеры проверены на совместимость с текущими модулями `bquant`.

## 🗂️ Содержание

### 🏗️ Architecture — Universal Pipeline v2.1
- **Двухслойная архитектура** (детекция зон + универсальный анализатор) — см. [docs/api/analysis/pipeline.md](../api/analysis/pipeline.md)
- **Fluent Builder Pattern** — цепочка `.with_indicator().detect_zones().analyze().build()` из [ZoneAnalysisPipeline](../api/analysis/pipeline.md)
- **Strategy Pattern** — пять стратегий детекции и набор анализаторов подключаются через протоколы (`bquant.analysis.zones.detection`)
- **Dependency Injection** — `UniversalZoneAnalyzer` принимает кастомные компоненты (features, hypotheses, regression)
- **Registry Pattern** — стратегии и индикаторы регистрируются через реестры, что упрощает расширение
- **Open/Closed Principle** — основные модули закрыты для правок, но открыты для внедрения новых стратегий и индикаторов

### 🧠 Extension Playbooks
- [Создание собственной стратегии детекции зон](zone_detection_strategies.md)

### 🔧 Contributing — Как внести вклад
- Настройка среды разработки и зависимостей из `pyproject.toml`
- Процесс ветвления и ревью (см. раздел «🤝 Вклад» ниже)
- Code Style и стандарты (`black`, `flake8`, `mypy`)
- Создание качественных Pull Request с проверками `pytest`, `pre-commit`

### 🧪 Testing — Universal Pipeline Validation
- **Unit-тесты** проверяют зоны, индикаторы и модели (`tests/unit/`)
- **Integration-тесты** запускают пайплайн end-to-end (`tests/integration/`)
- **Backward compatibility** покрывает legacy API (`tests/unit/test_macd_backward_compatibility.py`)
- **Coverage** отслеживается через `pytest --cov` и HTML отчёт (`tests/` → `htmlcov/`)
- **Запуск локально:** `pytest`, `pytest --cov`, `pytest tests/unit/`, `pytest tests/integration/`

### ⚡ Performance — Caching & Optimization
- **Automatic Caching** — декораторы и `ZoneAnalysisPipeline` используют кеш на память/диск
- **Performance Benchmarks** — пример измерений в `bquant/core/performance.py`
- **Code Simplification** — модули анализа зон избавлены от дублирования, расчёты перенесены в универсальные компоненты
- **Lazy Loading** — показатели и анализаторы инициализируются по требованию

### 🔍 Debugging — Отладка и логирование
- Инструменты для расследования проблем в `bquant/core/logging_config.py`
- Централизованное логирование и форматирование (`setup_logging`)
- Обработка исключений через `bquant.core.exceptions`
- Диагностика пайплайна на основе контекстных логов и предупреждений

### 📦 Packaging — Упаковка и релизы
- Структура пакета описана в `pyproject.toml` и `bquant/__init__.py`
- Настройка `setuptools` и extras (`dev`, `docs`, `full`)
- Создание дистрибутивов: `python -m build`, публикация через `twine`
- Версионирование и CHANGELOG в каталоге `changelogs/`

### 🔄 CI/CD — Непрерывная интеграция
- GitHub Actions конфигурируются в `.github/workflows/` (после подключения CI)
- Автоматические тесты и статический анализ (`pytest`, `flake8`, `mypy`)
- Отслеживание качества: отчёты покрытия, статус чеков, контроль зависимостей

## 🎯 Целевая аудитория

### 👨‍💻 Разработчики
- **Новички** — начните с секций Contributing и Testing
- **Опытные** — изучите архитектуру и производительность
- **Эксперты** — сфокусируйтесь на CI/CD и Packaging

### 🏢 Команды
- **Open Source** — вклад в развитие проекта и обсуждения
- **Enterprise** — адаптация пайплайна под корпоративные требования
- **Research** — расширение аналитических компонентов для исследований

## 📋 Предварительные требования

### Технические навыки
- Python 3.10+
- Git и GitHub
- Тестирование (pytest)
- Документирование (Sphinx + MyST)

### Инструменты
```bash
# Основные инструменты
pip install pytest black flake8 mypy sphinx

# Дополнительные
pip install pre-commit tox coverage
```

## 🚀 Быстрый старт для разработчиков

### 1. Клонирование и настройка

```bash
# Клонируем репозиторий
git clone https://github.com/bquant-team/bquant.git
cd bquant

# Создаем виртуальное окружение
python -m venv venv_dev
source venv_dev/bin/activate  # Linux/Mac
# или
venv_dev\Scripts\activate     # Windows

# Устанавливаем в режиме разработки
pip install -e .[dev]
```

### 2. Запуск тестов

```bash
# Все тесты
pytest

# С покрытием
pytest --cov=bquant

# Только unit тесты
pytest tests/unit/

# Только integration тесты
pytest tests/integration/
```

### 3. Проверка качества кода

```bash
# Форматирование
black bquant/

# Линтинг
flake8 bquant/

# Типизация
mypy bquant/

# Все проверки
pre-commit run --all-files
```

## 🏗️ Архитектурные принципы

### Модульность
- **Разделение ответственности** — каждый модуль решает свою задачу (`core`, `data`, `analysis`, `visualization`)
- **Слабая связанность** — зависимости инкапсулированы через протоколы и фабрики
- **Высокая когезия** — логика зон, индикаторов и визуализации сгруппирована в соответствующих пакетах

### Расширяемость
- **Universal Pipeline** — работает с любым индикатором через `IndicatorFactory`
- **Strategy Pattern** — стратегии детекции и анализа подключаются через протоколы
- **Dependency Injection** — `UniversalZoneAnalyzer` принимает внешние анализаторы
- **Registry Pattern** — автоматическая регистрация стратегий и индикаторов

### Производительность
- **Automatic Caching** — кеширование в `ZoneAnalysisPipeline` и `performance_monitor`
- **Performance Benchmarks** — метрики `zones/sec` и отчёты в `bquant/core/performance.py`
- **Code Simplification** — переписанные на v2.1 модули минимизируют повторение кода
- **Lazy Loading** — компоненты и визуализаторы создаются по требованию

### Надежность
- **Обработка ошибок** — исключения из `bquant.core.exceptions`
- **Валидация данных** — схемы и валидаторы в `bquant/data/`
- **Тестирование** — покрытие критических путей unit и integration тестами

## 🔧 Extension Points

### Custom Detection Strategies
```python
from typing import List
from datetime import datetime

import pandas as pd

from bquant.analysis.zones.detection import ZoneDetectionConfig
from bquant.analysis.zones.models import ZoneInfo


class PositiveCloseStrategy:
    """Пример собственной стратегии на основе ZoneDetectionStrategy."""

    # NOTE: пример обновлен под контракт ZoneDetectionStrategy v2.1
    def detect_zones(self, data: pd.DataFrame, config: ZoneDetectionConfig) -> List[ZoneInfo]:
        config.validate(["indicator_col"])
        indicator = config.rules["indicator_col"]

        positives = data[data[indicator] > 0]
        if positives.empty:
            return []

        start_label = positives.index[0]
        end_label = positives.index[-1]
        start_idx = data.index.get_loc(start_label)
        end_idx = data.index.get_loc(end_label)

        zone = ZoneInfo(
            zone_id=0,
            type="bull",
            start_idx=start_idx,
            end_idx=end_idx,
            start_time=start_label.to_pydatetime(),
            end_time=end_label.to_pydatetime(),
            duration=end_idx - start_idx + 1,
            data=data.iloc[start_idx : end_idx + 1],
            indicator_context={
                "detection_strategy": "positive_close",
                "detection_indicator": indicator,
                "detection_rules": config.rules,
            },
        )
        return [zone]


strategy = PositiveCloseStrategy()
config = ZoneDetectionConfig(strategy_name="positive_close", rules={"indicator_col": "close"})
sample = pd.DataFrame(
    {"close": [-1.0, 0.2, 0.4, -0.1]}, index=pd.date_range("2024-01-01", periods=4, freq="H")
)
custom_zones = strategy.detect_zones(sample, config)
print(f"Зон найдено: {len(custom_zones)}")
```

> ℹ️  Подробный алгоритм реализации новых стратегий с шаблонами и чеклистами см. в документе
> [«Zone Detection Strategies — Developer Guide»](zone_detection_strategies.md).

### Custom Analysis Components
```python
from datetime import datetime
from typing import List

import pandas as pd

from bquant.analysis.zones.analyzer import UniversalZoneAnalyzer
from bquant.analysis.zones.models import ZoneInfo


class _DemoFeaturesAnalyzer:
    """Минимальная реализация извлечения признаков."""

    # NOTE: пример обновлен для демонстрации Dependency Injection
    def extract_all_zones_features(self, zones: List[ZoneInfo]):
        return [pd.Series({"zone_id": zone.zone_id, "duration": zone.duration}) for zone in zones]

    def analyze_zones_distribution(self, features):
        return {"zones_count": len(features)}


class _DemoHypothesisSuite:
    def run_all_tests(self, features):
        return {"duration_vs_return": {"significant": False, "alpha": 0.05}}


index = pd.date_range("2024-01-01", periods=3, freq="H")
data = pd.DataFrame({"close": [1.0, 1.2, 1.1]}, index=index)
zone = ZoneInfo(
    zone_id=1,
    type="bull",
    start_idx=0,
    end_idx=2,
    start_time=index[0].to_pydatetime(),
    end_time=index[-1].to_pydatetime(),
    duration=3,
    data=data,
    indicator_context={"detection_strategy": "demo", "detection_indicator": "close"},
)

analyzer = UniversalZoneAnalyzer(
    features_analyzer=_DemoFeaturesAnalyzer(),
    hypothesis_suite=_DemoHypothesisSuite(),
    sequence_analyzer=None,
    regression_analyzer=None,
    validation_suite=None,
)
analysis_result = analyzer.analyze_zones([zone], data, perform_clustering=False)
print(analysis_result.statistics["zones_count"])
```

### Custom Indicators
```python
import pandas as pd

from bquant.indicators.base import CustomIndicator, IndicatorFactory, IndicatorResult


class SpreadIndicator(CustomIndicator):
    """Пользовательский индикатор, рассчитывающий разницу между ценами."""

    # NOTE: пример обновлен под актуальный API IndicatorFactory.register_indicator
    def __init__(self):
        super().__init__("spread_indicator")

    def get_output_columns(self):
        return ["spread"]

    def get_description(self):
        return "Разница текущей цены и сглаженного значения"

    def calculate(self, data: pd.DataFrame, **kwargs) -> IndicatorResult:
        spread = data["close"].diff().fillna(0.0)
        frame = pd.DataFrame({"spread": spread}, index=data.index)
        return IndicatorResult(name=self.name, data=frame, config=self.config)


IndicatorFactory.register_indicator("spread_indicator", SpreadIndicator)
indicator = IndicatorFactory.create("custom", "spread_indicator")
sample_prices = pd.DataFrame({"close": [1.0, 1.2, 1.1]})
spread_result = indicator.calculate(sample_prices)
print(spread_result.data.tail(1))
```

## 📏 Code Quality Standards

### Type Hints
```python
from typing import Any, Dict

import pandas as pd

from bquant.analysis.zones.models import ZoneAnalysisResult


def analyze_zones(
    data: pd.DataFrame,
    indicator_config: Dict[str, Any],
    detection_config: Dict[str, Any],
) -> ZoneAnalysisResult:
    """Полная типизация публичного API."""
    # NOTE: пример возвращает пустой результат с метаданными
    return ZoneAnalysisResult(
        zones=[],
        statistics={"zones_count": 0, "indicator_config": indicator_config},
        hypothesis_tests={"executed": False},
    )


typed_result = analyze_zones(pd.DataFrame(), {}, {})
print(typed_result.statistics["zones_count"])
```

### Documentation
```python
class UniversalZoneAnalyzer:
    """Universal Zone Analyzer для анализа зон любого индикатора.

    Args:
        features_analyzer: Анализатор признаков зон
        hypothesis_analyzer: Анализатор статистических тестов
        sequence_analyzer: Анализатор последовательностей зон

    Example:
        >>> analyzer = UniversalZoneAnalyzer()
        >>> result = analyzer.analyze(data, config)
    """
    ...
```

### Error Handling
```python
import logging
from typing import Any

from bquant.core.exceptions import BQuantError


logger = logging.getLogger("bquant.docs.error_handling")


class OptionalModuleError(BQuantError):
    """Ошибка, возникающая при недоступности опционального компонента."""


def full_analysis(data: Any, config: dict) -> dict:
    raise OptionalModuleError("demo optional module is unavailable")


def basic_analysis(data: Any, config: dict) -> dict:
    return {"status": "fallback", "data_length": len(getattr(data, "index", []))}


def analyze_with_graceful_degradation(data, config):
    """Graceful degradation для опциональных компонентов."""

    # NOTE: пример использует BQuantError для отработки деградации
    try:
        return full_analysis(data, config)
    except BQuantError:
        logger.warning("Optional component is unavailable, switching to basic analysis")
        return basic_analysis(data, config)
```

### Performance
```python
import time
from functools import lru_cache

from bquant.core.performance import performance_context, performance_monitor


@performance_monitor()
def cached_indicator(value: int) -> int:
    """Декоратор профилирования фиксирует вызовы функции."""
    # NOTE: пример обновлен для совместимости с performance_monitor()
    return value * 2


@lru_cache(maxsize=128)
def expensive_calculation(params: int) -> int:
    """Кэширование сложных расчётов."""
    time.sleep(0.01)
    return params * 2


def create_analyzer():
    return {"name": "lazy_analyzer"}


class LazyZoneAnalyzer:
    def __init__(self):
        self._analyzer = None

    @property
    def analyzer(self):
        if self._analyzer is None:
            self._analyzer = create_analyzer()
        return self._analyzer


with performance_context("demo_operation"):
    cached_indicator(5)
    expensive_calculation(10)
```

## 🔧 Процесс разработки

### 1. Планирование
- **Issue creation** — создание задачи на GitHub
- **Requirements** — определение требований и критериев
- **Design** — проектирование решения и API

### 2. Разработка
- **Branch creation** — именование веток по шаблону `feature/` или `fix/`
- **Implementation** — реализация функциональности с покрытием тестами
- **Testing** — локальный запуск тестов и линтеров

### 3. Code Review
- **Self-review** — проверка собственного кода перед PR
- **Peer review** — ревью коллегами, использование checklist
- **CI checks** — успешное прохождение автоматических проверок

### 4. Integration
- **Merge** — слияние в основную ветку после апрува
- **Deployment** — подготовка релиза и публикация
- **Monitoring** — отслеживание метрик и логов

## 🧪 Тестирование

### Типы тестов

#### Unit Tests
```python
from datetime import datetime

import pandas as pd

from bquant.analysis.zones.models import ZoneAnalysisResult, ZoneInfo


def create_sample_zone() -> ZoneInfo:
    """Создаёт минимальную зону для unit-тестов."""
    # NOTE: пример обновлен для использования универсальных моделей v2.1
    index = pd.date_range("2024-01-01", periods=3, freq="H")
    data = pd.DataFrame({"close": [1.0, 1.1, 1.2]}, index=index)
    return ZoneInfo(
        zone_id=0,
        type="bull",
        start_idx=0,
        end_idx=2,
        start_time=index[0].to_pydatetime(),
        end_time=index[-1].to_pydatetime(),
        duration=3,
        data=data,
        indicator_context={"detection_strategy": "demo", "detection_indicator": "close"},
    )


def test_zone_result_shape():
    zone = create_sample_zone()
    result = ZoneAnalysisResult(zones=[zone], statistics={"zones_count": 1}, hypothesis_tests={})

    assert result.zones[0].zone_id == 0
    assert result.statistics["zones_count"] == 1
```

#### Integration Tests
```python
from pathlib import Path

import pandas as pd

from bquant.analysis.zones.models import ZoneAnalysisResult, ZoneInfo


def build_result() -> ZoneAnalysisResult:
    index = pd.date_range("2024-01-01", periods=2, freq="H")
    data = pd.DataFrame({"close": [1.0, 1.2]}, index=index)
    zone = ZoneInfo(
        zone_id=1,
        type="bull",
        start_idx=0,
        end_idx=1,
        start_time=index[0].to_pydatetime(),
        end_time=index[-1].to_pydatetime(),
        duration=2,
        data=data,
        indicator_context={"detection_strategy": "demo", "detection_indicator": "close"},
    )
    return ZoneAnalysisResult(zones=[zone], statistics={"zones_count": 1}, hypothesis_tests={})


def test_full_pipeline(tmp_dir: Path = Path("results")):
    """Интеграционный тест сериализации и загрузки результатов."""
    tmp_dir.mkdir(parents=True, exist_ok=True)
    target = tmp_dir / "dev_guide_demo.pkl"
    result = build_result()
    result.save(target, format="pickle", include_data=False)

    loaded = ZoneAnalysisResult.load(target, format="pickle")
    assert isinstance(loaded, ZoneAnalysisResult)

    target.unlink(missing_ok=True)
```

#### Performance Tests
```python
import time

import pandas as pd

from bquant.analysis.zones.models import ZoneAnalysisResult


def create_large_dataset(size: int = 5000) -> pd.DataFrame:
    return pd.DataFrame({"close": pd.Series(range(size))})


def test_performance_budget():
    """Тест производительности: генерация данных укладывается в бюджет."""
    start = time.perf_counter()
    data = create_large_dataset()
    elapsed = time.perf_counter() - start

    assert not data.empty
    assert elapsed < 0.5
```

### Покрытие тестами
```bash
# Генерация отчета о покрытии
pytest --cov=bquant --cov-report=html

# Минимальное покрытие
pytest --cov=bquant --cov-fail-under=80
```

## ⚡ Производительность

### Профилирование
```python
import pandas as pd

from bquant.core.performance import performance_context, performance_monitor


@performance_monitor()
def slow_function(df: pd.DataFrame) -> float:
    """Функция с профилированием."""
    return float(df["close"].mean())


with performance_context("operation_name"):
    slow_function(pd.DataFrame({"close": [1.0, 1.1, 1.2]}))
```

### Оптимизация
- **NumPy-векторизация** — избегайте Python-циклов
- **Кэширование** — сохраняйте повторно используемые расчёты
- **Параллелизм** — используйте multiprocessing для тяжёлых задач

## 🔍 Отладка

### Логирование
```python
import logging

from bquant.core.logging_config import setup_logging

# Настройка логирования
setup_logging(level="INFO")

# Использование в коде
logger = logging.getLogger(__name__)
logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
```

### Обработка ошибок
```python
import logging

from bquant.core.exceptions import BQuantError, DataError


logger = logging.getLogger("bquant.docs.error")


class DummyAnalyzer:
    def analyze_complete(self, data):
        raise DataError("invalid data payload")


dummy_analyzer = DummyAnalyzer()

data = {"frame": "demo"}

try:
    dummy_analyzer.analyze_complete(data)
except DataError as e:
    logger.error(f"Data error: {e}")
except BQuantError as e:
    logger.error(f"BQuant error: {e}")
```

## 📦 Упаковка

### Структура пакета
```
bquant/
├── __init__.py
├── core/
├── data/
├── indicators/
├── analysis/
├── visualization/
└── ...
```

### Настройка pyproject.toml
```toml
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "bquant"
version = "0.0.0"
description = "Quantitative analysis library for financial data"
# ... остальные настройки
```

## 🔄 CI/CD

### GitHub Actions
```yaml
name: Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      - name: Install dependencies
        run: |
          pip install -e .[dev]
      - name: Run tests
        run: |
          pytest --cov=bquant
```

## 🤝 Вклад в проект

### Типы вкладов
- **Bug fixes** — исправление ошибок
- **Feature requests** — добавление функциональности
- **Documentation** — улучшение документации
- **Performance** — оптимизация производительности
- **Testing** — расширение покрытия тестами

### Процесс
1. **Fork** репозитория
2. **Create** ветку для фичи или исправления
3. **Implement** изменения с тестами
4. **Test** локально (`pytest`, `pre-commit`)
5. **Submit** Pull Request с описанием и результатами тестов

## 🔗 Связанные разделы

- **[User Guide](../user_guide/README.md)** — Руководство пользователя
- **[API Reference](../api/README.md)** — Справочник API
- **[Tutorials](../tutorials/README.md)** — Обучающие материалы
- **[Examples](../examples/README.md)** — Примеры использования

## 📞 Поддержка разработчиков

### Каналы связи
- **GitHub Issues** — для багов и проблем
- **GitHub Discussions** — для вопросов и обсуждений
- **Pull Requests** — для предложений изменений

### Ресурсы
- **[Contributing Guidelines](../../README.md)** — рекомендации по участию
- **[Code of Conduct](../../LICENSE)** — правила поведения
- **[License](../../LICENSE)** — лицензия проекта

---

**Начать изучение:** [API Pipeline](../api/analysis/pipeline.md) 🏗️
