Skip to main content
Glama
README.md
# Echo — объяснимые аномалии во временных рядах через Matrix Profile

Единственный проект в этой серии, который меняет не только масштаб, а
**домен и математический аппарат**. Вместо дискретных символьных систем
(git, файлы, политики) — непрерывные сигналы: показания датчиков,
метрики серверов, биометрика, финансовые ряды.

## Почему Matrix Profile, а не просто "порог + z-score"

Наивное обнаружение аномалий ("если значение выше среднего на 3σ — тревога")
не объясняет *почему* что-то аномально и плохо работает с формой сигнала —
пропускает "структурные" аномалии (например, правильные значения, но не в
то время суток). Matrix Profile для каждого фрагмента сигнала находит его
**ближайшего двойника** во всей остальной истории. Нет хорошего двойника —
аномалия, и вот **её конкретное объяснение**: "вот с чем я тебя сравнивал,
и даже это не похоже".

## Демонстрация на реалистичных данных

240 часов (10 дней) почасовых показаний датчика температуры с естественным
суточным циклом. В часы 120–131 датчик "застревает" на 23°C, не падая
ночью, как во все остальные дни.

```
ANOMALIES (discords):
  Subsequence at [100:124] doesn't resemble anything else in the series
  (distance=4.77). ...
  Subsequence at [124:148] doesn't resemble anything else (distance=2.05).

RECURRING PATTERNS (motifs):
  Subsequence at [0:24] closely repeats the pattern at index 24
  (distance=0.00, near-zero means an almost exact shape match).
```

Обе найденные аномалии точно накрывают внедрённый диапазон 120–131 —
подтверждено golden-тестом. При `top_k=3` отчёт всё равно возвращает
только две: нулевые distance после дедупликации — это мотивы, не аномалии,
и `top_discords` их не подмешивает. Мотивы находят точные суточные циклы
(окна на границах дней) — корректный фон нормальности.

## Ключевая деталь алгоритма: exclusion zone

Без неё у каждого фрагмента "ближайшим соседом" тривиально оказался бы он
сам или соседнее перекрывающееся окно (расстояние ~0), и весь профиль был
бы бессмысленным. Exclusion zone (половина длины окна вокруг каждой точки)
— это не оптимизация, а требование корректности из оригинальной статьи
(Yeh et al., 2016). Проверено отдельным тестом, что при её отсутствии все
"ближайшие соседи" оказались бы тривиально рядом.

## Реальная находка в процессе разработки: дедупликация top-k

При первом запуске top-3 "самых аномальных" фрагментов оказались тремя
**соседними окнами, покрывающими одну и ту же аномалию** — технически
корректно, но бесполезно. Решение: `top_discords` пропускает кандидатов
ближе `subsequence_length` к уже выбранным и останавливается на distance≈0.

## Архитектура (Clean Architecture по Мартину)

```
src/echo/
├── entities/
│   ├── time_series.py      # z-normalize, distance, finite checks
│   ├── matrix_profile.py   # алгоритм + exclusion zone
│   └── findings.py         # Discord/Motif, top-k, preview
├── use_cases/
│   └── analyze_time_series.py
├── interfaces/
│   └── ports.py            # SeriesLoader
├── infrastructure/
│   └── csv_series_loader.py
└── presentation/
    ├── composition_root.py
    ├── formatting.py
    └── mcp_server.py
```

Алгоритм — brute-force O(n²m), осознанно: корректность важнее скорости
для типичных объёмов (сотни–тысячи точек). MASS/FFT не реализован —
задокументированное ограничение.

## Установка

```bash
pip install -e ".[dev]"
```

## Подключение к Cursor / Claude Desktop

Как у остальных серверов серии (надёжнее, чем `echo-mcp` вне PATH):

```json
{
  "mcpServers": {
    "echo": {
      "command": "C:\\Python314\\python.exe",
      "args": ["-m", "echo.presentation.mcp_server"]
    }
  }
}
```

## MCP Tools

| Tool | Назначение |
|---|---|
| `analyze_series(values, subsequence_length, top_k)` | Анализ ряда напрямую |
| `analyze_csv(file_path, column, subsequence_length, top_k)` | Числовая колонка CSV |

Вход отвергает NaN/Inf, пустой CSV, `top_k < 1` и неверную длину окна.

## Тесты

```bash
.\make.ps1
```

Стена Мартина: black, ruff, mypy, pytest --cov≥90, лимиты функций.
Golden stuck-sensor, hypothesis-свойства distance/exclusion zone,
дедупликация top-k без фейковых аномалий, MCP-tools.

## Лицензия

MIT