# 11. Кореляція ЕМА подій з рухами зігзага

Пара: `BTC_USDT`.

## Ціль

Перевірити, чи повʼязані чотири експоненційні середні по ряду подій
(`клас210ема4`) з напрямком руху ціни — окремо для зігзага 2.3% і для
зігзага 0.8%. Пороги самостійні: кожен дає свої півоти по всьому ряду.

Питання, яке закривається: чи несе стан стакану, усереднений за ~12 годин,
інформацію про те, куди йде поточний рух.

## Дані

| Що | Значення |
| -- | -------- |
| Джерело | `data/datasets/BTC_USDT/class210ema4/{train,val,test}.npz` |
| Батько | `клас210х210х3` → `клас210х14х3` → `клас210х14х5` → `клас210х8` |
| Період | 2026-02-14 … 2026-08-16 UTC |
| Подій | 40 242 (train 24 150 / val 6 032 / test 10 060) |
| Подія | 210 секунд, крок 210, без перекриття |
| Період ЕМА | 200 подій ≈ 11 год 40 хв |
| Ціна для зігзага | `price_open` події (`price_avg` першої секунди) |

Усі три вибірки складаються в **один ряд за `timestamp`**: і ЕМА, і зігзаг —
наскрізні по часу, розбиття тут потрібне лише для того, щоб дані лишались
тими самими, що в інших класах.

## План роботи

1. Побудувати `клас210ема4` з `клас210х210х3` (чотири ЕМА, період 200).
2. Скласти всі вибірки в один ряд за часом.
3. Побудувати два самостійні зігзаги по `price_open`: 2.3% і 0.8%,
   кожен своїм прогоном по всьому ряду.
4. Кожній події поставити напрямок руху, у якому вона стоїть: `+1` вгору,
   `-1` вниз; події поза зігзагом (до першого півота й після останнього) —
   не рахуються.
5. Порахувати кореляцію кожної з чотирьох фіч з цим напрямком — Пірсоном
   і Спірменом.
6. Завести ціну в клас тим самим правилом, що й решту фіч, і рахувати
   ЕМА цінової фічі замість ЕМА ціни (етап 2).
7. Додати нормований зігзаг: місце події в нозі, `-1` у нижньому півоті,
   `+1` у верхньому (етап 3).
8. Будувати зігзаг на ЕМА ціни того самого періоду, що й фічі: спершу
   ЕМА, потім півоти, потім нормалізація (етап 4).
9. Нормувати ногу трьома скейлерами — мінмакс, робаст, квантиль — і тим
   самим скейлером по тій самій нозі обробляти фічу (етап 5).

## Етап 1. Кореляція з рухами зігзага 2.3% і 0.8% — підтверджено, 2026-08-24

### Метод

`клас210ема4` — чотири ЕМА на подію (`rules/01-data-and-db.md` →
Класи (події) → клас210ема4):

```
ema_price       = ЕМА(price_open)
ema_balance     = ЕМА(balance)
ema_d_balance   = ЕМА(d_balance)
ema_vol_balance = ЕМА(vol_balance)

ЕМА: alpha = 2 / (період + 1), старт із першого значення ряду, період 200
```

Зігзаг (`rules/02-markup.md`, `rules/scripts/zigzag.py`): розворот
підтверджується зміною на поріг від екстремуму, `OUTER_THRESHOLD = 0.023`,
`INNER_THRESHOLD = 0.008`. **Два самостійні зігзаги**: кожен поріг
проходить увесь ряд `price_open` окремо і має власні півоти й власні межі.
Півоти 2.3 входять і в зігзаг 0.8 (розворот на 2.3% — це й розворот на
0.8%), але зворотного звʼязку немає: рухи 0.8 не обрізані півотами 2.3
і живуть також до першого й після останнього з них.

Напрямок події = напрямок руху, у якому вона лежить. Кореляції:
Пірсон (на ряду ±1 це точково-бісеріальна) і Спірмен (Пірсон на середніх
рангах) — `scripts/correlation.py`.

Параметрів підбору немає, випадковості немає, seed не потрібен: результат
детермінований.

### Результат

40 242 події. У рухах зігзага 2.3 — 39 972 (270 поза зігзагом),
у рухах зігзага 0.8 — 40 221 (21 поза): дрібний зігзаг починається раніше
й закінчується пізніше, бо його перший і останній півоти ближчі до країв ряду.

**Зігзаг 2.3%** — вгору 19 701, вниз 20 271:

| Фіча | Пірсон | Спірмен |
| ---- | -----: | ------: |
| `ema_price` | −0.0257 | −0.0409 |
| `ema_balance` | **−0.0935** | **−0.0950** |
| `ema_d_balance` | −0.0635 | −0.0578 |
| `ema_vol_balance` | −0.0328 | −0.0165 |

**Зігзаг 0.8%** — вгору 20 135, вниз 20 086:

| Фіча | Пірсон | Спірмен |
| ---- | -----: | ------: |
| `ema_price` | −0.0233 | −0.0292 |
| `ema_balance` | **−0.1608** | **−0.1462** |
| `ema_d_balance` | **−0.1185** | **−0.1274** |
| `ema_vol_balance` | 0.0833 | 0.0789 |

Повний вивід — [`results/zigzag_correlation.json`](results/zigzag_correlation.json),
звіт побудови класу — [`results/class210ema4_report.json`](results/class210ema4_report.json).
На дашборді — вкладка «Кореляції ЕМА»,
[`/correlations`](http://localhost:8080/correlations).

### Висновки

- Звʼязок є, але слабкий. Найбільший — `ema_balance` на дрібному зігзагу:
  −0.16, тобто близько 2.6% спільної дисперсії.
- Знак відʼємний: під час руху **вгору** середній баланс стакану **нижчий**
  (підтримка сильніша за опір), під час руху вниз — вищий. Те саме
  в `ema_d_balance`.
- `ema_vol_balance` — єдина фіча з плюсом на зігзагу 0.8 (+0.08): перевага
  обʼєму покупок трохи збігається з рухом вгору.
- На великому зігзагу 2.3% усе вдвічі слабше, ніж на 0.8%: ЕМА за ~12 годин
  ближча до дрібних рухів, ніж до великих.
- Пірсон і Спірмен усюди збігаються (різниця в третьому знаку) — це не
  ефект викидів і не нелінійність, звʼязок справді слабкий і монотонний.
- Сама `ema_price` з напрямком руху майже не корелює (−0.02…−0.04) —
  рівень ціни не каже, куди йде рух, і це очікувано.

Для торгівлі одного цього замало: жодна фіча не дає ані 5% дисперсії. Але
знак стійкий на обох зігзагах і на обох метриках, тому `balance` і
`d_balance` мають сенс як **контрознака** — вони йдуть проти напрямку руху.

## Етап 2. Цінова фіча замість ціни, сітка періодів 10 … 1000 — підтверджено, 2026-08-24

### Метод

Ціна заводиться в клас **тим самим правилом, що й решта фіч** — нормованою
різницею двох сторін у блоці з 14 секунд (`rules/01-data-and-db.md` →
клас210х14х4ц):

```
price_balance = (Σ рух вгору - Σ рух вниз) / (Σ рух вгору + Σ рух вниз)
              = (кінець блоку - початок блоку) / Σ|посекундних змін|
```

Далі — той самий ланцюг, що й у решти: середнє по 15 блоках
(`клас210х210х4ц`), потім ЕМА кожної фічі (`клас210ема4ц`). У цьому етапі
**замість ЕМА ціни береться ЕМА цінової фічі**, тому всі чотири ряди
безрозмірні й в одному масштабі `[-1, 1]`.

Період ЕМА береться сіткою: **10 … 400 кроком 10 і 450 … 1000 кроком 50** —
52 періоди (0.6 … 58.3 год). На кожному рахуються кореляції з напрямком
рухів зігзага 2.3% і 0.8% і між самими фічами (шість пар), Пірсоном
і Спірменом. Зігзаг, напрямки й метрики — ті самі, що в етапі 1.

### Результат

![Хітмап кореляцій](results/ema_grid.png)

Зріз на періоді 200 (Пірсон / Спірмен),
[`results/zigzag_correlation_ema4c_price.json`](results/zigzag_correlation_ema4c_price.json):

| Фіча | Зігзаг 2.3% | Зігзаг 0.8% |
| ---- | ----------- | ----------- |
| `ema_balance` | −0.0935 / −0.0950 | **−0.1608 / −0.1462** |
| `ema_d_balance` | −0.0635 / −0.0578 | −0.1185 / −0.1274 |
| `ema_vol_balance` | −0.0328 / −0.0165 | +0.0833 / +0.0789 |
| `ema_price_balance` | −0.0045 / −0.0021 | +0.0703 / +0.0894 |

Пік кожного ряду по всій сітці (Пірсон):

| Ряд | Зігзаг 2.3% | Зігзаг 0.8% |
| --- | ----------- | ----------- |
| `ema_balance` | −0.115 на 550 | −0.215 на 10 |
| `ema_d_balance` | −0.077 на 20 | −0.231 на 10 |
| `ema_vol_balance` | −0.049 на 80 | +0.133 на 10 |
| `ema_price_balance` | −0.046 на 1000 | **+0.217 на 20** |

Кореляції між фічами (діапазон по всій сітці):

| Пара | Діапазон |
| ---- | -------- |
| `d_balance × price_balance` | **−0.926 … −0.673** |
| `balance × vol_balance` | −0.719 … −0.669 |
| `d_balance × vol_balance` | −0.628 … −0.396 |
| `balance × d_balance` | +0.586 … +0.769 |
| `balance × price_balance` | −0.570 … −0.393 |
| `vol_balance × price_balance` | +0.238 … +0.440 |

Повний вивід — [`results/ema_grid.json`](results/ema_grid.json).

### Висновки

- **Цінова фіча працює краще за саму ціну.** ЕМА ціни з дрібним зігзагом
  давала −0.023, ЕМА цінової фічі — **+0.217** на періоді 20 (1.2 год).
  Це найсильніший ряд разом з `d_balance`.
- **Знак додатний і логічний**: пряміший рух вгору — рух вгору. З великим
  зігзагом фіча майже нічого не каже (−0.046 на найдовшому періоді).
- **`d_balance` виявився майже дзеркалом ціни**: пара
  `d_balance × price_balance` тримає −0.67 … −0.93 по всій сітці. Тобто
  різниця рухів опору й підтримки — це переважно та сама інформація, що
  й напрямок ціни, тільки з протилежним знаком.
- Тому й кореляції в них дзеркальні: `d_balance` −0.231 і `price_balance`
  +0.217 з тим самим зігзагом 0.8 на коротких періодах.
- **Незалежної інформації в чотирьох фічах менше, ніж здається.** Усі
  шість пар мають |r| від 0.24 до 0.93; жодна пара не близька до нуля.
- Стеля лишається тією ж: найкраще ±0.23, тобто близько 5% дисперсії.

## Етап 3. Нормований зігзаг — підтверджено, 2026-08-24

### Метод

Замість самого напрямку руху кожна подія дістає **своє місце в нозі
зігзага** (`rules/02-markup.md` → Нормований зігзаг):

```
value = 2 * (price - low) / (high - low) - 1
```

`low` і `high` — мінімум і максимум ноги, тобто ціни двох її півотів:
у нижньому півоті рівно `-1`, у верхньому рівно `+1`, між ними
пропорційно ціні. Рахується двома однаковими алгоритмами окремо: по
півотах зігзага 2.3 і по власних півотах зігзага 0.8.

**Фіча проходить те саме перетворення по тих самих ногах.** Ціль — це
місце ціни в нозі, тому й фіча береться як місце свого значення в тій
самій нозі, а не як сирий рівень: інакше корелюються різні величини.
Це `мінмакс` з [`rules/scripts/scalers.py`](../../rules/scripts/scalers.py),
застосований по нозі (етап 5 додає до нього ще два скейлери).

Ряди кореляцій тепер чотири: напрямок 2.3, напрямок 0.8 і два нормовані.
Фічі, періоди й метрики — ті самі, що в етапі 2.

### Результат

![Хітмап кореляцій](results/ema_grid_zigzag_price.png)

Нормовані зігзаги, пік по сітці (Пірсон) і зріз на 200:

| Фіча | 2.3 нормований | 0.8 нормований |
| ---- | -------------- | -------------- |
| `ema_balance` | −0.054 на 1000 (200: +0.025) | −0.310 на 1000 (200: −0.277) |
| `ema_d_balance` | −0.042 на 1000 (200: −0.017) | **−0.338 на 450** (200: −0.320) |
| `ema_vol_balance` | **−0.162 на 240** (200: −0.161) | +0.170 на 950 (200: +0.160) |
| `ema_price_balance` | +0.077 на 200 (200: +0.077) | **+0.328 на 600** (200: +0.323) |

Повний вивід — [`results/ema_grid_zigzag_price.json`](results/ema_grid_zigzag_price.json)
і [`results/ema_grid_zigzag_price.png`](results/ema_grid_zigzag_price.png),
зріз на 200 —
[`results/zigzag_correlation_ema4c_price.json`](results/zigzag_correlation_ema4c_price.json).
Зігзаг тут будується на самій ціні події (`--zigzag price`).

### Висновки

- **Нормалізація перевертає картину на великому зігзагу.** З напрямком
  руху 2.3 найсильнішим був `balance` (−0.115), з нормованим — раптом
  `vol_balance`, і втричі сильніше за свій же напрямковий результат:
  **−0.162** проти −0.049. Знак мінус: що вище ціна в нозі, то більше
  перевага продажів.
- **На дрібному зігзагу нормалізація дає найсильніші числа етапів 2–3**:
  `price_balance` **+0.328**, `d_balance` **−0.338** — проти +0.217
  і −0.231 у напрямкових версій. Питання «де ціна в нозі» фіча тримає
  краще, ніж питання «куди йде нога».
- Довгі періоди на нормованому 0.8 працюють: піки стоять на 450–1000,
  а не на 10–20, як у напрямкових рядів.
- Нормований 2.3 і нормований 0.8 дають різні відповіді на тих самих
  фічах — це два різні питання, а не один із двома точностями.

## Етап 4. Зігзаг на ЕМА ціни — підтверджено, 2026-08-24

### Метод

Порядок побудови змінено: спершу **ЕМА ціни того самого періоду**, що
й фічі колонки, потім **зігзаг** по цій ЕМА, і тільки потім
**нормалізація** ноги за алгоритмом етапу 3.

```
ема_p(price) → півоти 2.3% і 0.8% по ема_p → напрямок руху ±1
                                          → нормована нога [-1, +1]
```

Так у кожній колонці і фічі, і зігзаг згладжені однаково: період один
на все. Пороги, метрики й сітка періодів — ті самі, що в етапах 2–3.
Перемикач — `--zigzag ema` (типово) або `--zigzag price`.

### Результат

![Хітмап кореляцій](results/ema_grid.png)

Пік кожного ряду по сітці (Пірсон / Спірмен), зріз на 200:

| Фіча | Зігзаг 2.3 | Зігзаг 0.8 | 2.3 нормований | 0.8 нормований |
| ---- | ---------- | ---------- | -------------- | -------------- |
| `ema_balance` | +0.237 на 1000 | +0.242 на 950 | +0.289 на 330 | **+0.352 на 360** |
| `ema_d_balance` | +0.234 на 650 | +0.216 на 950 | −0.248 на 1000 | +0.202 на 230 |
| `ema_vol_balance` | −0.396 на 500 | −0.401 на 950 | −0.347 на 330 | **−0.417 на 380** |
| `ema_price_balance` | −0.237 на 700 | −0.188 на 1000 | −0.159 на 550 | −0.175 на 500 |

Нормовані колонки — скейлер `мінмакс`; два інші скейлери — етап 5.

Повний вивід — [`results/ema_grid.json`](results/ema_grid.json), зріз на 200 —
[`results/zigzag_correlation_ema4c.json`](results/zigzag_correlation_ema4c.json).

### Висновки

- **Згладжений зігзаг дає втричі сильніший звʼязок.** `ema_vol_balance`
  з напрямком руху 2.3: було −0.049 на ціні події, стало **−0.396** на
  ЕМА ціни. На зігзагу 0.8 той самий ряд дає **−0.401** (період 950) —
  найкращий результат усього дослідження.
- **Довгі періоди тепер працюють.** Раніше все жило на 10–20 подіях,
  тепер піки стоять на 280–1000: коли зігзаг і фічі згладжені однаково,
  довге вікно перестає бути шумом.
- **Знаки перевернулись** у `balance` і `d_balance`: з ціною подій вони
  йшли проти руху (−0.21), з ЕМА ціни йдуть **за** рухом (+0.24). Тобто
  на дрібних коливаннях вони контрознака, а на згладженому тренді — за
  напрямком.
- `ema_vol_balance` знак зберігає скрізь: перевага покупок проти руху
  вгору, −0.30 … −0.40 на довгих періодах.
- **Два зігзаги на ЕМА ціни майже збігаються.** Півоти 2.3 усі є і в 0.8,
  а на згладженому ряді дрібний поріг майже не додає своїх: на періоді 200
  обидва зігзаги дають ті самі 39 930 подій у рухах. Різниця між ними
  зростає на коротких періодах, де ЕМА ще не згладила дрібні коливання.
- **Нормалізація найкраще працює з дрібним зігзагом**: `ema_vol_balance`
  **−0.417** на 0.8 нормованому (380 подій ≈ 22 год) — найсильніша
  клітинка всього дослідження, і `ema_balance` +0.352 поруч.
- Стеля піднялась з 0.23 до **0.42** — це вже 17% дисперсії проти 5%.

## Етап 5. Три скейлери нормування — підтверджено, 2026-08-26

### Метод

Нормування ноги — це питання «де значення стоїть у своїй нозі», і
відповісти на нього можна трьома способами
([`rules/scripts/scalers.py`](../../rules/scripts/scalers.py)). Кожен
рахується **всередині ноги**, від півота до півота:

| Скейлер | Формула | Що робить |
| ------- | ------- | --------- |
| `мінмакс` | `2·(x − min) / (max − min) − 1` | краї ноги в `-1` і `+1`, між ними пропорційно значенню |
| `робаст` | `(x − медіана) / (q75 − q25)` | центр — медіана ноги, масштаб — її IQR; краї можуть вийти за ±1 |
| `квантиль` | `2u − 1`, `u` — місце x в емпіричній CDF ноги | рангове: розподіл усередині ноги стає рівним |

**Фіча проходить той самий скейлер по тих самих ногах, що й ціль** —
інакше порівнювались би різні величини. Ряди напрямку руху скейлера не
мають: там ціль категорійна (`+1` / `-1`), фіча йде як є.

Перемикач на вкладці «Кореляції ЕМА» міняє скейлер відразу в таблиці
етапу 1, у хітмапі й у таблиці обраного періоду.

### Результат

Зігзаг **на ціні події**, ряд `0.8 нормований`, пік по сітці (Пірсон):

| Фіча | мінмакс | робаст | квантиль |
| ---- | ------- | ------ | -------- |
| `ema_balance` | −0.310 на 1000 | −0.316 на 1000 | −0.352 на 1000 |
| `ema_d_balance` | −0.338 на 450 | −0.344 на 800 | −0.356 на 1000 |
| `ema_vol_balance` | +0.170 на 950 | +0.192 на 600 | +0.211 на 1000 |
| `ema_price_balance` | +0.328 на 600 | +0.326 на 900 | **+0.359 на 650** |

Зігзаг **на ЕМА ціни**, ряд `0.8 нормований`, пік по сітці (Пірсон):

| Фіча | мінмакс | робаст | квантиль |
| ---- | ------- | ------ | -------- |
| `ema_balance` | +0.352 на 360 | +0.322 на 750 | +0.350 на 360 |
| `ema_d_balance` | +0.202 на 230 | +0.179 на 360 | +0.222 на 360 |
| `ema_vol_balance` | **−0.417 на 380** | −0.327 на 400 | −0.381 на 380 |
| `ema_price_balance` | −0.175 на 500 | −0.140 на 380 | −0.164 на 340 |

Повний вивід — [`results/ema_grid.json`](results/ema_grid.json) і
[`results/ema_grid_zigzag_price.json`](results/ema_grid_zigzag_price.json),
зрізи на 200 — три файли `zigzag_correlation*.json`.

### Висновки

- **Скейлер міняє відповідь, але не міняє знак.** Жодна клітинка не
  перевернулась: три скейлери сходяться в тому, куди дивиться фіча,
  і розходяться на 0.02 … 0.09 у величині.
- **На сирій ціні виграє квантиль.** `price_balance` +0.359 проти +0.328
  у мінмакса: нога на сирій ціні має викиди, а рангове перетворення їх
  прибирає — виграють усі чотири фічі.
- **На ЕМА ціни виграє мінмакс.** ЕМА вже прибрала викиди, і рангове
  перетворення тут лише втрачає величину: `vol_balance` −0.417 проти
  −0.381 у квантиля й −0.327 у робаста.
- **Робаст найслабший у більшості клітинок.** Він ділить на IQR ноги,
  а нога зігзага — не хмара навколо центру, а монотонний рух: медіана
  й квартилі описують її гірше, ніж краї.
- **Квантиль зрівнює Пірсона зі Спірменом** (збіг до четвертого знака):
  обидва ряди після нього рангові, а Пірсон на рангах — це і є Спірмен.
  Тому колонка «Спірмен» у квантиля не додає нічого нового.
- Стеля дослідження — **0.42** (`vol_balance`, зігзаг 0.8 нормований
  мінмакс на ЕМА ціни, період 380 ≈ 22 год).

## Відтворення

```bash
R=research/11-ema-zigzag-correlation

# етап 1: клас210ема4 з готового клас210х210х3 (період 200)
python3 rules/scripts/build_class210ema4.py --pair BTC_USDT --period 200
python3 scripts/zigzag_correlation.py --pair BTC_USDT --class class210ema4 \
    --zigzag price --out $R/results/zigzag_correlation.json

# етапи 2-3: зріз на періоді 200, зігзаг на ціні події
python3 scripts/zigzag_correlation.py --pair BTC_USDT --class class210ema4c \
    --zigzag price --out $R/results/zigzag_correlation_ema4c_price.json
python3 $R/scripts/ema_grid.py --pair BTC_USDT --zigzag price \
    --prefix ema_grid_zigzag_price

# етап 4: те саме із зігзагом на ЕМА ціни того самого періоду
python3 scripts/zigzag_correlation.py --pair BTC_USDT --class class210ema4c \
    --zigzag ema --out $R/results/zigzag_correlation_ema4c.json
python3 $R/scripts/ema_grid.py --pair BTC_USDT

# тести
python3 -m unittest discover -s tests -t tests
```

Етап 5 окремих запусків не має: три скейлери рахуються тими самими
командами, кожен прогін кладе в JSON усі три ряди на кожен зігзаг.

Сітка періодів у `ema_grid.py` типова: `10:400:10` і `450:1000:50` —
52 періоди. Класи `клас210ема4ц` і його батьки будуються скриптами
`rules/scripts/build_class210x14x4c.py`, `build_class210x210x4c.py`,
`build_class210ema4c.py` (`rules/01-data-and-db.md` → Базові скрипти).

Потрібен лише готовий датасет `data/datasets/BTC_USDT/class210x210x3/`
(як він будується — `rules/01-data-and-db.md` → Готовий датасет
клас210х210х3). Нічого зовнішнього.

## Файли

| Файл | Що |
| ---- | -- |
| [`rules/scripts/class210ema4.py`](../../rules/scripts/class210ema4.py) | клас `клас210ема4`: чотири ЕМА на подію |
| [`rules/scripts/build_class210ema4.py`](../../rules/scripts/build_class210ema4.py) | побудова train/val/test тим самим розбиттям |
| [`rules/scripts/zigzag.py`](../../rules/scripts/zigzag.py) | зігзаг за порогом і рухи між півотами |
| [`rules/scripts/scalers.py`](../../rules/scripts/scalers.py) | мінмакс, робаст і квантиль — нормування ноги й фічі |
| [`tests/test_scalers.py`](../../tests/test_scalers.py) | тести скейлерів |
| [`scripts/correlation.py`](../../scripts/correlation.py) | Пірсон і Спірмен |
| [`scripts/zigzag_correlation.py`](../../scripts/zigzag_correlation.py) | напрямки рухів і кореляції етапу 1 |
| [`results/zigzag_correlation.json`](results/zigzag_correlation.json) | вивід етапу 1 |
| [`results/class210ema4_report.json`](results/class210ema4_report.json) | звіт побудови класу |
| [`tests/test_class210ema4.py`](../../tests/test_class210ema4.py) | тести класу |
| [`tests/test_correlation.py`](../../tests/test_correlation.py) | тести кореляцій |
| [`tests/test_zigzag_correlation.py`](../../tests/test_zigzag_correlation.py) | тести напрямків і зведення |
| [`rules/scripts/class210x14x4c.py`](../../rules/scripts/class210x14x4c.py) | етап 2: цінова фіча по блоках |
| [`rules/scripts/class210x210x4c.py`](../../rules/scripts/class210x210x4c.py) | етап 2: середнє по події |
| [`rules/scripts/class210ema4c.py`](../../rules/scripts/class210ema4c.py) | етап 2: ЕМА чотирьох безрозмірних фіч |
| [`scripts/ema_grid.py`](scripts/ema_grid.py) | етап 2: сітка періодів і хітмап |
| [`results/zigzag_correlation_ema4c.json`](results/zigzag_correlation_ema4c.json) | зріз етапу 2 на періоді 200 |
| [`results/class210x14x4c_report.json`](results/class210x14x4c_report.json) | звіт побудови цінової фічі |
| [`results/class210x210x4c_report.json`](results/class210x210x4c_report.json) | звіт середніх по події |
| [`results/class210ema4c_report.json`](results/class210ema4c_report.json) | звіт побудови ЕМА-класу |
| [`tests/test_class210x14x4c.py`](../../tests/test_class210x14x4c.py) | тести цінової фічі |
| [`tests/test_class210x210x4c.py`](../../tests/test_class210x210x4c.py) | тести середніх |
| [`tests/test_class210ema4c.py`](../../tests/test_class210ema4c.py) | тести ЕМА-класу |
| [`results/ema_grid.png`](results/ema_grid.png) | хітмап етапу 4 (зігзаг на ЕМА ціни) |
| [`results/ema_grid.json`](results/ema_grid.json) | усі числа етапу 4 |
| [`results/ema_grid_zigzag_price.png`](results/ema_grid_zigzag_price.png) | хітмап етапів 2–3 (зігзаг на ціні події) |
| [`results/ema_grid_zigzag_price.json`](results/ema_grid_zigzag_price.json) | усі числа етапів 2–3 |
| [`tests/test_zigzag.py`](../../tests/test_zigzag.py) | тести зігзага й нормалізації |
| [`tests/test_ema_grid.py`](../../tests/test_ema_grid.py) | тести етапу 2 |
