# Дослідження 30 — події в межах ноги

| | |
| --- | --- |
| Пара | BTC_USDT |
| Клас | `клас210х10-1х7д/д` — шість відношень похідних сусідніх рівнів плюс похідна ціни |
| Ряд подій | `train` + `val` разом, сітка `t_start`, 70 647 подій |
| Розмітка | зігзаг 2.3 % на ема10 `price_open`, нога ділиться на 10 десятин |
| Статус | етапи 1–10 підтверджені, 2026-09-13 |
| Вкладка | [`/inleg`](http://localhost:8080/inleg) |
| Правила | [`01-data-and-db.md`](../../rules/01-data-and-db.md), [`02-markup.md`](../../rules/02-markup.md), [`05-visualization.md`](../../rules/05-visualization.md) |

## Ціль

Навчитись відрізняти події **всередині однієї ноги**: де в нозі стоїть
подія і з якого місця ряду вона вже належить іншій нозі.

Дослідження 29 (етап 1) міряло той самий клас уздовж ноги **однією
згорткою** — середнім по девʼяти блоках події. Тут питання ставиться
подія за подією і **по кожному параметру події**:

1. **Де в нозі сидить параметр** — профіль по десятинах, краї проти
   середини, розріз за напрямком ноги.
2. **Чи видно це всередині однієї ноги** — та сама різниця, порахована
   в межах кожної ноги окремо, без пулу по всіх ногах.
3. **Подія за рухом ноги проти зустрічної** — чим відрізняється подія,
   чий власний рух ціни йде в напрямку ноги, від події, чий рух іде
   проти, і як ця різниця міняється по десятинах.
4. **Де починається інша нога** — вікно подій навколо півота: з якого
   зсуву подія нової ноги відрізняється від події старої.
5. **Справжній півот проти корекції** — у нозі повно місць, де ціна
   розвернулась проти неї на 0.5–1.5 % і нога пішла далі. Чи відрізняє
   клас справжній кінець ноги від такої корекції.
6. **Чи можна відрізнити окрему подію** — те саме питання про боки
   півота, поставлене на самих числах класу й на одній події.
7. **Коли вже можна сказати, що почалась нова нога** — пачка від півота,
   що росте: 1 подія, 2, 3 … 40, на сирих числах класу; і чи схожі
   початки ніг різних напрямків між собою.
8. **Чи схожі пачки однієї ноги між собою більше, ніж із пачкою
   сусідньої** — пара пачок через півот проти пари того самого краю
   ноги, на однаковій відстані.
9. **Чи належить пачка цій нозі** — кожна пачка проти **всіх** пачок
   своєї ноги, потім проти пачок наступної, і модель, яка на це
   відповідає.
10. **Чи корелюють початок і кінець ноги** — і чи можна, порівнявши
    голову ноги з поточним вікном, сказати, що це її кінець.

## Дані

| | |
| --- | --- |
| Датасет | `data/datasets/BTC_USDT/class210x10m1x7dd/{train,val}.npz` |
| Побудова | `python3 rules/scripts/build_class210x10x7dc.py` |
| Подія | `(9, 7)` — девʼять блоків по 21 с, сім фіч |
| Фічі | `d_up`, `d_down`, `d_resist_buy`, `d_bal_resist_buy`, `d_support_sell`, `d_bal_support_sell`, `d_price_avg` |
| Період | 2026-02-14 … 2026-09-07 (`t_start` від 1771091656 до 1788738832) |
| Ноги | 70 (відкинуто з дірами понад годину — 23), 51 391 подія в ногах |
| Довжина ноги | медіана 562 події, від 80 до 3099 |

Інші пари підключаються тим самим скриптом ключем `--pair`.

## Метод

Хід розмітки той самий, що в дослідженнях 28 і 29, і береться з їхнього
скрипта `edge_profile.py`:

    ряд подій монети -> ема10(price_open) -> півоти зігзага 2.3 % -> ноги
    -> 42 величини на подію -> ранги по монеті -> чотири заміри

### Параметри події

Подія класу — це `(9, 7)`. Кожна фіча згортається в шість чисел:

| параметр | що це |
| -------- | ----- |
| `mean` | середнє по девʼяти блоках |
| `first` | перший блок події |
| `last` | останній блок події |
| `peak` | блок з найбільшим модулем, зі своїм знаком |
| `spread` | розкид по блоках (стандартне відхилення) |
| `slope` | нахил МНК по номеру блока — хід величини всередині події |

7 фіч × 6 параметрів = **42 величини на подію**, і кожна міряється
окремо.

### Ранги замість величин

Відношення похідних не мають скінченного розкиду: ділення на майже нуль
дає хвости до `1e12` (`rules/01-data-and-db.md` → `клас210х10-1х7д/д`).
Тому кожна величина переводиться **в ранги серед подій ніг цієї монети**:

| крива | що це | рівень ряду |
| ----- | ----- | ----------- |
| `ранг` | ранг самої величини, 0…1 | 0.5 |
| `амплітуда` | ранг `\|величини\|` | 0.5 |
| `сплеск` | подія в топ-5 % `\|величини\|` монети | 0.05 |

Напрямок ноги в ранг **не вноситься** (на відміну від дослідження 29):
серед параметрів є невідʼємні (`spread`), і множення на напрямок робило
б їхній ранг просто міткою напрямку. Напрямок іде окремим розрізом —
ноги вгору й ноги вниз рахуються нарізно.

### Чотири заміри

| # | Замір | Як саме |
| - | ----- | ------- |
| 1 | **Профіль по десятинах** | нога ділиться на 10 рівних за подіями частин; середнє кривої по десятині рахується **в кожній нозі**, потім усереднюється по ногах. Краї — десятини 1 і 10, середина — 4–7; різниця в похибках середнього (`t`) |
| 2 | **Всередині однієї ноги** | Спірмен кривої з номером події в її нозі і AUC «подія краю проти події середини» — обидві міри рахуються **в межах однієї ноги** і усереднюються по ногах. Нога коротша за 20 подій у ці міри не йде. Профіль пулом може бути наслідком того, що довгі ноги стоять в іншому місці ряду — всередині ноги такої лазівки немає |
| 3 | **Подія за рухом ноги** | подія віднесена до руху ноги, якщо знак її власного `ln(close / open)` збігається зі знаком ноги. Різниця «за рухом мінус зустрічна» береться **парою всередині ноги** і усереднюється по ногах; та сама різниця рахується окремо в кожній десятині |
| 4 | **Через півот** | для кожного півота беруться 40 подій до нього (хвіст старої ноги) і 40 після (голова нової). Профіль на кожному зсуві й AUC «подія нової ноги проти події старої» на вікнах 1, 2, 3, 5, 8, 13, 21, 34 події з боку. Краще вікно вибирається за `z`, а не за AUC: вікно в одну подію має лише 63 події з боку |

Фільтр дір: нога з розривами в ряді понад годину сумарно не рахується —
як у дослідженнях 28 і 29.

## Скрипти

Частина ряду вибирається на вкладці перемикачем **«частина ряду»** —
усі розділи читають ту саму частину; ендпоінти — `/api/inleg[/<розділ>]`
та `/api/inleg[/<розділ>]/train|/val`.

| Файл | Що робить |
| ---- | --------- |
| [`scripts/inleg_profile.py`](scripts/inleg_profile.py) | етапи 1–4: профіль, міри всередині ноги, розріз за рухом, вікно навколо півота |
| [`scripts/pivot_vs_correction.py`](scripts/pivot_vs_correction.py) | етап 5: справжній півот проти корекції, з контролем перемішуванням |
| [`scripts/pivot_sides.py`](scripts/pivot_sides.py) | етап 6: боки півота на сирих числах події і модель на всіх 63 одразу |
| [`scripts/leg_start_packs.py`](scripts/leg_start_packs.py) | етап 7: пачка від півота, що росте, і початки ніг між собою |
| [`scripts/pack_similarity.py`](scripts/pack_similarity.py) | етап 8: відстань між парами пачок — через півот, край ноги і середина |
| [`scripts/pack_belongs.py`](scripts/pack_belongs.py) | етап 9: пачка проти всіх пачок ноги, контроль часом і модель «чи пачка звідси» |
| [`scripts/leg_head_tail.py`](scripts/leg_head_tail.py) | етап 10: голова ноги проти її хвоста — кореляція, детектор кінця й перевірка «хвіст проти голови» |
| [`scripts/tip_series.py`](scripts/tip_series.py) | ряд val із видачею детектора: модель учиться на train, відповідає на кожній події val |
| [`../28-leg-edge-profile/scripts/edge_profile.py`](../28-leg-edge-profile/scripts/edge_profile.py) | розмітка ноги: `load`, `legs_of`, пороги `THRESHOLD`, `PERIOD`, `DECILES`, `EDGES`, `MIDDLE`, `HOLE` |
| [`../../tests/test_inleg_profile.py`](../../tests/test_inleg_profile.py) | тести кроків на синтетичному ряді |
| [`../../tests/test_dashboard.py`](../../tests/test_dashboard.py) | `TestInleg`, `TestInlegMarkup` — ендпоінт і розмітка вкладки |

Запуск:

Кожен скрипт має ключ `--part`: `all` (train + val разом, за
замовчуванням), `train` або `val`. Межа береться з самого датасету —
перший час у `val.npz`, для BTC_USDT це **2026-08-14 00:02 UTC**. На
`val` заміри рахуються тільки на подіях після межі, а **моделі вчаться
на train і відповідають на val**. Файл результату отримує суфікс:
`..._val.json`.

```bash
python3 research/30-inleg-events/scripts/inleg_profile.py
python3 research/30-inleg-events/scripts/pivot_vs_correction.py
python3 research/30-inleg-events/scripts/pivot_sides.py
python3 research/30-inleg-events/scripts/leg_start_packs.py
python3 research/30-inleg-events/scripts/pack_similarity.py
python3 research/30-inleg-events/scripts/pack_belongs.py
python3 research/30-inleg-events/scripts/leg_head_tail.py --part train
python3 research/30-inleg-events/scripts/tip_series.py
python3 research/30-inleg-events/scripts/inleg_profile.py --pair ETH_USDT
python3 -m unittest discover -s tests -t tests -k inleg
```

Прохід по BTC_USDT — 5 секунд на кожен із перших двох скриптів,
7 секунд на третій, 2 хвилини на четвертий.

Параметри (у скрипті, без ключів): `THRESHOLD = 0.023`, `PERIOD = 10`,
`DECILES = 10`, `EDGES = (1, 10)`, `MIDDLE = (4, 5, 6, 7)`,
`HOLE = 3600`, `MIN_LEG = 20`, `HOT = 0.95`, `OFFSETS = 40`,
`WINDOWS = (1, 2, 3, 5, 8, 13, 21, 34)`. Випадковості в замірах немає,
seed не потрібен.

Етап 5: `SMALLS = (0.005, 0.008, 0.010, 0.015)`, `WINDOWS = (5, 13, 21,
34)`, `GAP = 40`, `SHUFFLES = 500`, `SEED = 17`. Етап 6: `SIDES = (5, 10,
20, 40)`, `TRAIN_SHARE = 0.7`, `SEED = 17`,
`HistGradientBoostingClassifier` з `max_iter` 300, `learning_rate` 0.05,
`max_leaf_nodes` 7, `min_samples_leaf` 20, `l2` 1.0. Етап 7:
`PACKS = (1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 26, 33, 40)`,
`CLEAR = 60`, `STRIDE = 10`, `SHUFFLES = 300`, `TRAIN_SHARE = 0.7`,
`SEED = 17`, та сама модель з `max_iter` 200 і вагами боків. Етап 8:
`PACKS = (3, 5, 8, 10, 15, 20, 30, 40)`,
`SEPARATIONS = (1, 2, 3, 5, 8)`, метрики `cosine`, `euclidean`,
`manhattan`, числа сирі й рангові, `SHUFFLES = 300`, `SEED = 17`. Етап 9:
`PACKS = (10, 20, 30)`, `AGGREGATES = (median, min, q25, mean)`,
`FAR_LEGS = 2`, `MIN_PACKS = 4`, `REFERENCE = 5`, `TRAIN_SHARE = 0.7`,
`SHUFFLES = 300`, `SEED = 17`, та сама модель із `max_iter` 200.
Етап 10: `SIZES = (5, 10, 20, 40)`, `KITS = (head, plain, both)`,
`TRAIN_SHARE = 0.7`, `SHUFFLES = 300`, `SEED = 17`, та сама модель;
за замовчуванням `--part train`.

Вихід:

```
results/inleg_profile_BTC_USDT_class210x10m1x7dd.json        — етапи 1-4
results/pivot_vs_correction_BTC_USDT_class210x10m1x7dd.json  — етап 5
results/pivot_sides_BTC_USDT_class210x10m1x7dd.json          — етап 6
results/leg_start_packs_BTC_USDT_class210x10m1x7dd.json      — етап 7
results/pack_similarity_BTC_USDT_class210x10m1x7dd.json      — етап 8
results/pack_belongs_BTC_USDT_class210x10m1x7dd.json         — етап 9
results/leg_head_tail_BTC_USDT_class210x10m1x7dd_train.json  — етап 10
```

Поруч із кожним лежить `.meta.json` — те саме без найважчих блоків.

## Приклад

Вхід — подія класу, `(9, 7)`. Параметри однієї фічі:

```python
>>> block = np.array([[0., 1., 2., 3., 4., 5., 6., 7., -9.]])
>>> [round(float(reduce_blocks(block, how)[0]), 3) for how in REDUCERS]
[2.111, 0.0, -9.0, -9.0, 4.483, -0.133]  # mean first last peak spread slope
```

Вихід — рядок звіту на одну величину події:

```
d_up·mean, крива «амплітуда», усі ноги:
  десятини  0.586 0.539 0.537 0.528 0.511 0.512 0.538 0.517 0.554 0.645
  краї 0.615, середина 0.522, t +5.1
  AUC край/середина всередині ноги 0.606 (t +7.2, знак той самий у 81 % ніг)
```

## Етап 1. Величина події по десятинах ноги

Статус: **підтверджено**, 2026-09-13.

Профіль U-подібний **на всіх семи фічах і на всіх шести параметрах**:
подія краю ноги відрізняється від події середини, і відрізняється в обидва
краї однаково за формою. Амплітуда (крива «амплітуда», усі ноги, 70 ніг):

| фіча | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | краї | середина | t |
| ---- | - | - | - | - | - | - | - | - | - | -- | ---- | -------- | - |
| `d_up` | 0.586 | 0.539 | 0.537 | 0.528 | 0.511 | 0.512 | 0.538 | 0.517 | 0.554 | 0.645 | 0.615 | 0.522 | +5.1 |
| `d_down` | 0.589 | 0.535 | 0.533 | 0.544 | 0.534 | 0.514 | 0.536 | 0.528 | 0.551 | 0.631 | 0.610 | 0.532 | +4.2 |
| `d_price_avg` | 0.579 | 0.547 | 0.541 | 0.535 | 0.524 | 0.524 | 0.532 | 0.518 | 0.531 | 0.599 | 0.589 | 0.529 | +4.2 |
| `d_resist_buy` | 0.388 | 0.450 | 0.449 | 0.468 | 0.474 | 0.480 | 0.455 | 0.470 | 0.440 | 0.329 | 0.359 | 0.469 | −4.8 |
| `d_support_sell` | 0.386 | 0.445 | 0.446 | 0.446 | 0.455 | 0.477 | 0.465 | 0.467 | 0.431 | 0.344 | 0.365 | 0.461 | −4.2 |
| `d_bal_resist_buy` | 0.430 | 0.467 | 0.467 | 0.488 | 0.502 | 0.504 | 0.475 | 0.481 | 0.463 | 0.375 | 0.403 | 0.492 | −5.2 |
| `d_bal_support_sell` | 0.429 | 0.475 | 0.475 | 0.465 | 0.476 | 0.492 | 0.478 | 0.474 | 0.453 | 0.379 | 0.404 | 0.478 | −4.3 |

(параметр `mean`; решта пʼяти параметрів дають ту саму форму, найсильніші
з них — `spread` і `peak`)

Знак ділить фічі рівно на дві групи:

- **обʼєм на свій рівень** (`d_up`, `d_down`) і похідна ціни — на краях
  ноги **вищі**;
- **рівень на свій обʼєм** (`d_resist_buy`, `d_support_sell` та обидві
  балансові) — на краях ноги **нижчі**.

Це те саме твердження, прочитане з двох боків відношення: на краю ноги
обʼємний бік товстий відносно рівневого, у середині ноги — навпаки.

Розріз за напрямком: ефект є і на ногах угору, і на ногах униз, з тим
самим знаком (`d_resist_buy·spread`: t −3.4 вгору, −3.7 вниз). Ноги росту
й падіння тут не різняться.

Найсильніші величини — не `mean`, а `spread` і `peak`: рекорд
`d_resist_buy·spread` (крива «ранг»), краї 0.394 проти середини 0.490,
t −5.3.

## Етап 2. Всередині однієї ноги

Статус: **підтверджено**, 2026-09-13.

Профіль пулом міг би бути наслідком розкладки ніг у часі, тому та сама
різниця порахована в межах кожної ноги окремо.

| величина | крива | AUC край / середина | t | ніг зі знаком |
| -------- | ----- | ------------------- | - | ------------- |
| `d_resist_buy·spread` | ранг | 0.360 | −6.9 | 20 % |
| `d_resist_buy·peak` | амплітуда | 0.361 | −6.9 | 17 % |
| `d_resist_buy·mean` | ранг | 0.612 | +6.9 | 81 % |
| `d_support_sell·spread` | ранг | 0.380 | −6.3 | 26 % |
| `d_up·mean` | амплітуда | 0.606 | +7.2 | 81 % |
| `d_price_avg·spread` | ранг | 0.610 | +5.8 | 70 % |

AUC читається як «наскільки подія краю відрізняється від події середини
**всередині тієї самої ноги**»: 0.5 — не відрізняється. Різниця тримається
на 0.10–0.14 від монетки і має той самий знак у 80 % ніг. Хвіст ноги
сильніший за голову: `d_resist_buy·peak` дає 0.323 на останній десятині
проти 0.398 на першій.

Спірмен з позицією при цьому **нульовий** — найбільший за модулем
`d_bal_support_sell·slope`, ρ +0.020 (t +3.5). Це не суперечність, а
наслідок форми: профіль U-подібний, величина росте на обох кінцях ноги,
і монотонного ходу від півота до півота немає. Позиція події читається як
**відстань до найближчого півота**, а не як пройдена частка ноги.

## Етап 3. Подія за рухом ноги проти зустрічної

Статус: **підтверджено**, 2026-09-13.

Подія віднесена до руху ноги, якщо знак її власного `ln(close / open)`
збігається зі знаком ноги. Різниця береться парою всередині ноги.

| величина | крива | за рухом | проти | різниця | t |
| -------- | ----- | -------- | ----- | ------- | - |
| `d_price_avg·mean` | амплітуда | 0.553 | 0.534 | +0.0193 | +6.5 |
| `d_price_avg·mean` | сплеск | 0.076 | 0.055 | +0.0205 | +6.0 |
| `d_price_avg·spread` | ранг | 0.577 | 0.565 | +0.0124 | +4.6 |
| `d_up·slope` | ранг | 0.494 | 0.512 | −0.0179 | −3.9 |
| `d_up·mean` | амплітуда | 0.556 | 0.537 | +0.0195 | +1.5 |
| `d_resist_buy·mean` | амплітуда | 0.436 | 0.445 | −0.0090 | −0.9 |

Єдина величина, яка стабільно ділить події за напрямком їхнього руху, —
**похідна ціни** (`d_price_avg`), і ділить майже тавтологічно: подія, що
йде за ногою, має більший рух, ніж зустрічна. Рівневі та обʼємні фічі
класу різниці не показують: `d_up·mean` дає ту саму за розміром різницю
(+0.0195), але з t +1.5 — вона не тримається від ноги до ноги.

**Належність події до руху в напрямку ноги в класі не написана.** Те, що
клас справді бачить, — це не напрямок події, а її відстань до півота
(етапи 1 і 2).

Частка подій, що йдуть за ногою, по десятинах:

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| - | - | - | - | - | - | - | - | - | -- |
| 0.538 | 0.522 | 0.527 | 0.513 | 0.507 | 0.510 | 0.520 | 0.522 | 0.519 | 0.534 |

Тобто й сам рух ноги складається не рівно: на краях ноги подій у її
напрямку помітно більше, ніж у середині, — той самий U, що й у фічах.

## Етап 4. Де починається інша нога

Статус: **підтверджено**, 2026-09-13.

Вікно навколо півота, 63 півоти, до 40 подій з кожного боку. AUC «подія
нової ноги проти події старої» для `d_up·mean` (крива «амплітуда»):

| вікно, подій | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 |
| ------------ | - | - | - | - | - | -- | -- | -- |
| AUC | 0.457 | 0.457 | 0.452 | 0.411 | 0.410 | 0.409 | 0.421 | 0.431 |
| z | −0.8 | −1.2 | −1.6 | −3.9 | −5.0 | −6.4 | −7.0 | −7.8 |

Найсильніші величини на своєму кращому вікні:

| величина | крива | вікно | AUC | z |
| -------- | ----- | ----- | --- | - |
| `d_up·mean` | амплітуда | 34 | 0.431 | −7.8 |
| `d_up·spread` | ранг | 34 | 0.433 | −7.6 |
| `d_down·last` | амплітуда | 21 | 0.418 | −7.3 |
| `d_support_sell·last` | амплітуда | 21 | 0.582 | +7.3 |
| `d_resist_buy·mean` | амплітуда | 34 | 0.564 | +7.2 |
| `d_price_avg·mean` | амплітуда | 1 | 0.263 | −4.6 |

Читається так:

1. **На одній події півот не видно.** Вікна 1–3 події дають z менший за 2
   на всіх величинах класу, крім похідної ціни: AUC 0.263 на першій події
   після півота — це сам півот ема10, момент, де ціна стоїть.
2. **Різниця зʼявляється з пʼятої події** (z −3.9) і росте до вікон
   21–34 подій, тобто до 1.2–2 годин після півота.
3. **Напрямок різниці той самий, що в етапі 1**: після півота обʼємні
   відношення (`d_up`, `d_down`) **нижчі**, ніж перед ним, а рівневі
   (`d_resist_buy`, `d_support_sell`) — **вищі**.

Профіль `d_up·mean` (амплітуда) вздовж вікна: перед півотом крива
піднімається з 0.60 на зсуві −40 до 0.70 на останніх подіях старої ноги,
після півота падає з 0.675 на першій події нової ноги до 0.558 на
сороковій. Криві не дзеркальні: на однаковій відстані від півота **бік
старої ноги вищий за бік нової**, і саме ця асиметрія дає AUC нижче 0.5.

## Етап 5. Справжній півот проти корекції

Статус: **підтверджено**, 2026-09-13.

Етап 4 порівнював хвіст ноги з головою наступної — тобто **при вже
відомому півоті**. Тут питання причинне: у нозі повно місць, де ціна
розвернулась проти неї і нога пішла далі. Чи відрізняється справжній
кінець ноги від такої корекції?

Кандидати — точки розвороту проти ноги: **півот** зігзага 2.3 % (нога
справді скінчилась) проти **корекції** — півота вкладеного зігзага того
самого боку всередині ноги, не ближче за 40 подій до її країв. Навколо
кожного беруться два вікна по `W` подій: `before` (причинне — ці події
вже є), `after` і `step` = різниця.

| вкладений зігзаг | корекцій | на ногу | медіана глибини | найбільший \|z\| | шум: медіана / 95 % | p |
| ---------------- | -------- | ------- | --------------- | ---------------- | ------------------- | - |
| 0.5 % | 191 | 2.73 | 0.78 % | 4.0 | 3.0 / 3.8 | **0.008** |
| 0.8 % | 82 | 1.17 | 1.12 % | 2.9 | 3.0 / 3.7 | 0.594 |
| 1.0 % | 49 | 0.70 | 1.34 % | 3.0 | 3.0 / 3.7 | 0.424 |
| 1.5 % | 17 | 0.24 | 1.86 % | 2.9 | 3.0 / 3.8 | 0.560 |

Півотів у кожному рядку 63, рух після справжнього півота — 4.02 %
медіаною.

Контроль обовʼязковий: перебір іде по 1512 комбінаціях (42 величини × 3
криві × 4 вікна × 3 міри), і при такій кількості |z| близько 3
зʼявляється сам собою. Мітку «півот / корекція» перемішано 500 разів,
щоразу взято найбільший |z| усього перебору — це й є колонка «шум».

- **Проти корекції 0.8–1.5 % клас не бачить нічого.** Найбільший |z|
  усього перебору не відрізняється від того, що дає перемішана мітка
  (p = 0.42–0.59).
- **Проти дрібної корекції 0.5 % різниця є**: `d_support_sell·last`,
  крива «ранг», вікно 5 подій **до** кандидата — AUC 0.669, z +4.0
  проти шумових 3.0 (p = 0.008).

Та сама величина по глибині корекції (вікно 21 подія, 63 півоти в
кожному рядку):

| глибина корекції | корекцій | AUC | z |
| ---------------- | -------- | --- | - |
| 0.5–1.0 % | 140 | 0.653 | +3.5 |
| 1.0–1.5 % | 39 | 0.627 | +2.2 |
| 1.5 % і більше | 12 | 0.544 | +0.5 |

Чим глибша корекція, тим менше клас відрізняє її від справжнього кінця
ноги. На 1 % різниці вже практично немає, на 1.5 % — немає зовсім.

## Етап 6. Чи можна відрізнити окрему подію

Статус: **підтверджено**, 2026-09-13.

Етапи 1–5 міряли згортки й ранги пулом. Тут питання поставлене на самих
числах класу й на одній події: **вхід — сирі 9 блоків × 7 фіч = 63 числа
події**, мітка — бік півота (1 — подія нової ноги, 0 — подія старої),
по `K` подій з кожного боку.

Стара й нова ноги дивляться в різні боки, тому все міряється тричі: на
всіх півотах разом і на півотах `high` та `low` нарізно. Ознака **місця**
дає однаковий знак на обох, ознака **напрямку** — протилежний.

Найсильніші числа події, `K` = 20 (2520 подій, 63 півоти):

| число події | усі | high | low | z |
| ----------- | --- | ---- | --- | - |
| `d_support_sell·блок9` | 0.425 | 0.438 | 0.412 | −6.5 |
| `d_resist_buy·блок4` | 0.426 | 0.388 | 0.463 | −6.4 |
| `d_resist_buy·блок7` | 0.431 | 0.402 | 0.459 | −6.0 |
| `d_resist_buy·блок5` | 0.431 | 0.413 | 0.448 | −6.0 |
| `d_support_sell·блок6` | 0.437 | 0.438 | 0.437 | −5.4 |
| `d_down·блок9` | 0.561 | 0.555 | 0.565 | +5.3 |

Контроль: перебір 63 чисел, найбільший |z| 6.5 проти шумових 2.4
(95 % — 3.3), p = 0.000 на `K` = 10, 20 і 40. Знак однаковий на `high` і
`low` — це ознака **місця**, не напрямку.

Модель `HistGradientBoostingClassifier` на всіх 63 числах події, чесне
розбиття за часом (перші 70 % півотів учать, останні 19 відповідають):

| подій з боку | подій усього | усі | high | low | тест |
| ------------ | ------------ | --- | ---- | --- | ---- |
| 5 | 630 | 0.543 (53.2 %) | 0.494 (47.0 %) | 0.568 (54.4 %) | 190 подій |
| 10 | 1 260 | 0.506 (51.6 %) | 0.574 (55.0 %) | 0.547 (55.6 %) | 380 подій |
| 20 | 2 520 | 0.495 (49.2 %) | 0.526 (49.8 %) | 0.582 (55.8 %) | 760 подій |
| 40 | 5 040 | 0.507 (50.5 %) | 0.500 (50.5 %) | 0.574 (55.7 %) | 1 520 подій |

У дужках — влучність проти 50 % базових (боки рівні за побудовою).

- **Різниця між боками півота в самих фічах є** і вона не з випадковості:
  `d_resist_buy` на блоках 4–7 і `d_support_sell` на блоках 6–9 після
  півота **нижчі**, `d_down` на блоках 8–9 — **вищі**, з тим самим знаком
  на обох типах півотів.
- **Відрізнити окрему подію цим не можна.** Модель на всіх 63 числах дає
  на невидимих півотах AUC 0.495–0.543 і влучність 49–53 % проти 50 %
  базових. Виняток — тільки півоти `low` (нога вниз → нога вгору): там
  0.57–0.58 і 55.7 %, стійко на всіх `K`.
- Межа заміру — **19 півотів у тесті**. Це стеля того, що дає одна
  монета: далі потрібні решта пʼять.

## Етап 7. Коли вже можна сказати, що почалась нова нога

Статус: **підтверджено**, 2026-09-13.

Питання причинне: після півота пройшла одна подія, дві, три… Скільки їх
треба, щоб відрізнити **початок нової ноги** від будь-якого іншого місця
тієї самої ноги?

- Пачка — `N` подій підряд **з першої події після півота**, мітка 1.
- Проти неї — пачка тієї самої довжини з середини ноги: не ближче за
  60 подій до її початку, кроком 10 подій по ряду, мітка 0.
- Вхід — сирі числа класу: `N × 9 блоків × 7 фіч`, кожне окремою
  колонкою, і колонка знає номер своєї події в пачці
  (`d_up·блок3·подія1`).
- Модель — `HistGradientBoostingClassifier` на всіх числах пачки,
  розбиття **за часом**: перші 70 % ряду вчать, останні відповідають.
  Боки зважені: середин у 75 разів більше за початки.

63 початки ніг проти 4481–4751 середин; у тесті 11 початків із 1426 пачок
(базова частка 0.8 %).

| пачка | колонок | AUC | точність верхівки | верхня десятина | перший | \|z\| чисел | шум 95 % | p |
| ----- | ------- | --- | ----------------- | --------------- | ------ | ----------- | -------- | - |
| 1 | 63 | 0.655 | 0.0 % | 18 % | 76 | 6.5 | 3.2 | 0.000 |
| 2 | 126 | 0.677 | 0.0 % | 18 % | 24 | 6.5 | 3.5 | 0.000 |
| 3 | 189 | 0.693 | 0.0 % | 36 % | **12** | 6.5 | 3.6 | 0.000 |
| 4 | 252 | 0.709 | 0.0 % | 27 % | 26 | 6.5 | 3.8 | 0.000 |
| 5 | 315 | 0.703 | 0.0 % | 27 % | 26 | 6.5 | 3.7 | 0.000 |
| 6 | 378 | 0.718 | 0.0 % | 36 % | 34 | 6.5 | 3.7 | 0.000 |
| 8 | 504 | 0.723 | 0.0 % | 36 % | 39 | 6.5 | 3.8 | 0.000 |
| 10 | 630 | **0.727** | 0.0 % | 36 % | 34 | 6.5 | 3.9 | 0.000 |
| 13 | 819 | 0.714 | 0.0 % | 18 % | 32 | 6.6 | 3.9 | 0.000 |
| 16 | 1008 | 0.697 | 0.0 % | 18 % | 70 | 6.6 | 4.0 | 0.000 |
| 20 | 1260 | 0.706 | 0.0 % | 9 % | 104 | 6.6 | 3.9 | 0.000 |
| 26 | 1638 | 0.750 | 0.0 % | 9 % | 102 | 6.7 | 4.2 | 0.000 |
| 33 | 2079 | 0.727 | 0.0 % | 0 % | 200 | 6.7 | 4.1 | 0.000 |
| 40 | 2520 | 0.759 | 0.0 % | 9 % | 89 | 6.7 | 4.2 | 0.000 |

**Точність верхівки** — скільки справжніх початків серед верхніх `P`
пачок видачі, де `P` — скільки їх у тесті (11). **Верхня десятина** —
скільки початків зібралось у верхніх 10 % видачі. **Перший** — місце
найвищого справжнього початку у видачі.

Найсильніші числа пачки на 10 подіях:

| число події | AUC | z |
| ----------- | --- | - |
| `d_up·блок3·подія1` | 0.261 | −6.5 |
| `d_up·блок5·подія2` | 0.259 | −6.5 |
| `d_down·блок3·подія3` | 0.290 | −5.7 |
| `d_up·блок2·подія1` | 0.290 | −5.7 |
| `d_resist_buy·блок6·подія2` | 0.699 | +5.4 |

Читається так:

1. **Різниця є вже на першій події після півота** і вона не з шуму:
   найбільший |z| перебору 6.5 проти шумових 3.2 (p = 0.000). Окремі
   числа дають AUC 0.26 — це сильніше за будь-яку згортку з етапів 1–4.
2. **Пачка допомагає, але мало**: AUC моделі росте з 0.655 на одній
   події до 0.72–0.73 на 6–10 подіях і далі не росте — 0.70–0.76 при
   довжині від 13 до 40 подій, уже без ладу.
3. **Сказати «півот був» не можна на жодній довжині.** Точність верхівки
   нульова скрізь: серед 11 найгучніших пачок видачі немає жодного
   справжнього початку. Найкраща верхівка — пачка 3 події, де перший
   справжній початок стоїть 12-м у видачі; на довгих пачках він
   провалюється на 90–200-те місце.
4. **Найкраща довжина за ранжуванням — 3–10 подій** (верхня десятина
   збирає 36 % початків). Це 10–35 хвилин після півота.
5. Ноги нарізно: `вгору` AUC 0.779, `вниз` 0.661 на пачці 10 подій —
   початок ноги вгору видніший, але точність верхівки нульова в обох.

### Початки ніг між собою

Та сама пачка, питання інше: **початок ноги вгору проти початку ноги
вниз** (31 проти 32).

| пачка | найбільший \|z\| | шум 95 % | p | AUC моделі |
| ----- | --------------- | -------- | - | ---------- |
| 1 | 3.6 | 3.2 | 0.007 | 0.544 |
| 3 | 3.6 | 3.5 | 0.033 | 0.583 |
| 5 | 3.6 | 3.6 | 0.060 | 0.544 |
| 10 | 3.6 | 3.8 | 0.090 | 0.417 |
| 20 | 3.8 | 3.9 | 0.063 | 0.467 |
| 40 | 3.8 | 4.0 | 0.127 | 0.500 |

Початки ніг різних напрямків **однакові**: найбільший |z| іде врівень із
шумом, модель на невидимих початках дає 0.42–0.58. Клас не каже, куди
пішла нова нога.

## Етап 8. Пачки між собою: своя нога проти сусідньої

Статус: **підтверджено**, 2026-09-13.

Гіпотеза: пачки однієї ноги схожі між собою більше, ніж пачка цієї ноги
й пачка сусідньої. Якщо так — межу ноги видно по тому, що схожість
рветься.

Ряд кожної ноги ріжеться на пачки по `N` подій підряд, без перекриття;
пачка через півот не переходить. Пачка — сирі числа класу
(`N × 9 блоків × 7 фіч`) або ті самі числа в рангах події, зсунуті на
−0.5. Пара пачок міряється відстанню: `cosine`, `euclidean`,
`manhattan`.

**Два контролі, а не один:**

| вид пари | що це |
| -------- | ----- |
| `через півот` | дві пачки сусідніх ніг, між ними `s` пачок і півот |
| `край ноги` | пара однієї ноги на тій самій відстані, яка так само впирається в півот (починається першою пачкою ноги або закінчується останньою), але його не переходить |
| `середина` | будь-яка інша пара тієї самої ноги на тій самій відстані |

Перший контроль тримає **відстань у парі**: сусідні пачки схожі вже тому,
що сусідні. Другий тримає **місце в нозі**: пара через півот завжди
стоїть на краях, а краї в цьому класі мають свій рівень (етап 1). Тому
головне порівняння — `через півот` проти `край ноги`.

AUC «пара через півот далі одна від одної, ніж пара краю ноги», сирі
числа, `cosine` (69 пар через півот проти 140 пар краю):

| пачка, подій | пачок | s = 1 | s = 2 | s = 3 | s = 5 | s = 8 |
| ------------ | ----- | ----- | ----- | ----- | ----- | ----- |
| 3 | 17 106 | 0.477 | 0.494 | 0.503 | 0.477 | 0.523 |
| 5 | 10 253 | 0.471 | 0.498 | 0.509 | 0.497 | 0.504 |
| 8 | 6 392 | 0.523 | 0.570 | 0.481 | 0.502 | 0.512 |
| 10 | 5 110 | 0.570 | 0.469 | 0.488 | 0.508 | 0.456 |
| 15 | 3 392 | 0.536 | 0.536 | 0.488 | 0.478 | 0.473 |
| 20 | 2 540 | **0.580** | 0.469 | 0.575 | 0.536 | 0.496 |
| 30 | 1 680 | 0.533 | 0.537 | 0.509 | 0.530 | 0.525 |
| 40 | 1 255 | 0.463 | 0.541 | 0.508 | 0.503 | 0.528 |

Найкраще, що знайшлось у всьому переборі (8 довжин × 2 варіанти чисел ×
3 метрики × 5 відстаней): пачка **20 подій**, сирі числа, `cosine` —
AUC 0.580, z +1.9. Контроль перемішуванням на цій пачці: найбільший |z|
1.9, на перемішаній мітці медіана 1.3 і 95 % 2.3 → **p = 0.183**.

Рангові числа дають ще менше: 0.44–0.57 на всьому переборі, |z| ніде не
доходить до 2.4.

Другий контроль показує, звідки береться враження різниці. Та сама пара
через півот проти **середини** ноги:

| пачка, подій | проти краю | проти середини |
| ------------ | ---------- | -------------- |
| 3 | 0.477 (z −0.5) | 0.509 (z +0.2) |
| 5 | 0.471 (z −0.7) | 0.500 (z +0.0) |
| 8 | 0.523 (z +0.5) | 0.536 (z +1.0) |
| 10 | 0.570 (z +1.6) | 0.594 (z +2.7) |
| 15 | 0.536 (z +0.8) | 0.581 (z +2.3) |
| 20 | 0.580 (z +1.9) | 0.605 (z +3.0) |
| 30 | 0.533 (z +0.8) | 0.554 (z +1.5) |
| 40 | 0.463 (z −0.9) | 0.510 (z +0.3) |

Проти середини різниця на пачках 10–20 подій виглядає (z 2.3–3.0), проти
краю — гасне. Значить це **край ноги**, знайдений ще в етапі 1, а не
півот: пара, що впирається в півот, уже не схожа сама на себе, і байдуже,
перейшла вона його чи ні.

**Гіпотеза не підтвердилась.** На однаковій відстані й у тому самому
місці ноги пара пачок через півот схожа рівно так само, як пара пачок
однієї ноги. Оптимальної довжини пачки, на якій межа ноги проступала б,
у переборі немає: найкраще — 20 подій із p = 0.183, тобто нічого.

## Етап 9. Чи належить пачка цій нозі

Статус: **підтверджено**, 2026-09-13.

Питання поставлене так, як його ставить ряд: є нога й усі її пачки,
береться ще одна пачка — вона з цієї ноги?

1. Ряд ноги ріжеться на пачки по `N` подій підряд, без перекриття.
2. Усередині ноги рахуються **всі пари пачок** — кожна з кожною.
3. Пачка порівнюється з ногою **без самої себе**: її відстані до кожної
   пачки ноги згортаються в чотири числа — медіана, найближча, чверть і
   середня.
4. Ті самі числа рахуються для пачок **наступної ноги** і — контролем —
   для пачок **далекої** (несусідньої) ноги.

AUC «своя пачка далі від ноги, ніж чужа»; **нижче 0.5 означає, що своя
пачка ближча**, тобто нога тримається купи. Ранги, пачка 10 подій
(5110 пачок, 70 ніг):

| згортка | проти наступної | проти далекої | наступна проти далекої |
| ------- | --------------- | ------------- | ---------------------- |
| `manhattan · q25` | 0.399 (z −17.7) | 0.322 | 0.421 |
| `cosine · q25` | 0.406 (z −16.5) | 0.312 | 0.410 |
| `manhattan · min` | 0.408 (z −16.1) | 0.343 | 0.432 |
| `euclidean · min` | 0.414 (z −15.0) | 0.359 | 0.441 |

Контроль перемішуванням: найбільший |z| 17.7 проти шумових 1.8
(95 % — 2.8), p = 0.000.

**Своя пачка справді ближча до своєї ноги, ніж пачка наступної.** Але
далека нога ще далі (0.31–0.36), а наступна проти далекої — 0.40–0.45.
Це рівна драбина: чим далі в часі, тим менш схожа пачка. Тобто відстань
міряє передусім **час**, а не межу ноги.

Модель «чи пачка з цієї ноги» — `HistGradientBoostingClassifier` на всіх
24 відстанях пачки до ноги, розбиття за часом (перші 70 % ніг учать):

| пачка, подій | AUC | влучність | база | тест |
| ------------ | --- | --------- | ---- | ---- |
| 10 | **0.616** (z +11.1) | 58.2 % | 51.8 % | 1574 своїх / 1466 чужих |
| 20 | 0.605 (z +7.1) | 56.7 % | 51.8 % | 783 / 729 |
| 30 | 0.558 (z +3.1) | 55.6 % | 51.8 % | 485 / 452 |

### Контроль часом

Щоб прибрати з відповіді час, той самий замір робиться з **рівною
часовою відстанню**: опора — 5 пачок підряд, кандидат — **наступна
пачка одразу за опорою**; питання лише в тому, чи лежить між ними півот.

Пачка 20 подій, 66 кандидатів через півот проти 2192 усередині ноги:

| числа · метрика | median | min | q25 | mean |
| --------------- | ------ | --- | --- | ---- |
| сирі · `cosine` | 0.599 (z +2.8) | 0.570 | 0.573 | 0.557 |
| сирі · `euclidean` | 0.311 (z −5.2) | 0.317 | 0.315 | 0.314 |
| сирі · `manhattan` | 0.292 (z −5.8) | 0.291 | 0.299 | 0.299 |
| ранги · `cosine` | 0.515 (z +0.4) | 0.468 | 0.492 | 0.496 |
| ранги · `euclidean` | 0.430 (z −1.9) | 0.385 | 0.409 | 0.414 |
| ранги · `manhattan` | 0.466 (z −0.9) | 0.419 | 0.455 | 0.452 |

**Метрики сперечаються між собою, і це вирішує питання.** `euclidean` і
`manhattan` на сирих числах кажуть, що кандидат через півот **ближчий**
(0.29–0.32) — вони читають розмір, а розмір біля півота падає (етап 1).
`cosine`, який розміру не бачить і міряє тільки форму, каже протилежне й
слабко (0.60, z +2.8). Ранги стоять посередині, на 0.42–0.52. Коли
знак ефекту міняється від метрики до метрики, це не межа ноги, а
магнітуда.

Модель на тих самих відстанях при рівному часі: пачка 10 — точність
верхівки 0.0 % проти 0.8 % базових, пачка 20 — 0.0 % проти 1.8 %,
пачка 30 — 9.1 % проти 2.7 % (2 пачки з 22 верхніх).

**Висновок етапу.** Пачку наступної ноги від пачки цієї відрізнити
можна — AUC 0.616, влучність 58.2 % проти 51.8 % базових на невидимих
ногах. Але при рівній часовій відстані все, що лишається, — це падіння
розміру чисел біля півота; форма пачки межі ноги не знає.

## Етап 10. Голова ноги і її хвіст

Статус: **підтверджено**, 2026-09-13. Замір на **train** BTC_USDT: 61 нога.

У кожної ноги береться **голова** — перші `K` подій після півота,
**хвіст** — останні `K` подій перед наступним півотом, і **середини** —
решта вікон тієї самої ноги кроком `K`. Пачка описується сімома
числами: рівень кожної фічі — середнє по її подіях і блоках у рангах
серед подій ніг монети.

### Чи корелює голова з хвостом

Спірмен по 61 нозі між рівнем фічі в голові й тим самим рівнем у хвості,
вікно 20 подій:

| фіча | своя нога | своя середина | чужий хвіст |
| ---- | --------- | ------------- | ----------- |
| `d_up` | −0.056 | +0.288 | **+0.809** |
| `d_down` | −0.098 | +0.166 | +0.799 |
| `d_resist_buy` | +0.002 | +0.295 | +0.814 |
| `d_bal_resist_buy` | +0.052 | +0.022 | +0.361 |
| `d_support_sell` | −0.022 | +0.235 | +0.750 |
| `d_bal_support_sell` | −0.078 | −0.198 | +0.374 |
| `d_price_avg` | **+0.525** | +0.078 | −0.526 |

**Голова й хвіст однієї ноги не повʼязані.** Кореляція нульова на шести
фічах із семи. Виняток — `d_price_avg`: +0.53 (вікно 20) і +0.58
(вікно 40), тобто рух ціни на обох кінцях ноги справді парний — це та
сама U-форма з етапу 1.

Контроль **чужий хвіст** (хвіст сусідньої ноги, що стоїть поруч у часі)
дає +0.75…+0.81. Тобто корелює те, що **поруч у ряді**, а не те, що в
одній нозі. Це видно й у відстанях: хвіст стоїть **далі** від своєї
голови (0.088), ніж від чужої (0.053) — AUC 0.287, z −4.1.

### Детектор «це хвіст ноги»

61 хвіст проти 2017 середин (вікно 20), модель на ногах, яких не бачила:

| вхід моделі | вікно 5 | вікно 10 | вікно 20 | вікно 40 |
| ----------- | ------- | -------- | -------- | -------- |
| `head` — різниці до голови й відстані | 0.765 | 0.760 | 0.706 | 0.721 |
| `plain` — тільки рівні кандидата | **0.818** | **0.785** | **0.742** | **0.774** |
| `both` | 0.818 | 0.772 | 0.745 | 0.727 |

Точність верхівки (скільки справжніх хвостів серед верхніх `P` вікон
видачі, `P` — скільки їх у тесті) проти базової частки:

| вікно | `plain` | база | приріст |
| ----- | ------- | ---- | ------- |
| 5 | 5.6 % | 0.6 % | ×9 |
| 10 | 22.2 % | 1.2 % | ×19 |
| 20 | 16.7 % | 2.3 % | ×7 |
| 40 | 23.5 % | 4.2 % | ×6 |

Найсильніші колонки (вікно 20): `рівень·d_resist_buy` AUC 0.813,
`рівень·d_up` 0.182, `рівень·d_support_sell` 0.802,
`різниця·d_resist_buy` 0.742. Контроль перемішуванням: найбільший |z|
8.5 проти шумових 1.8 (95 % — 2.8), p = 0.000.

**Голова як опора нічого не додає.** Набір `plain` — рівні самого
кандидата, без жодної згадки про початок ноги — б'є набір `head` на
всіх чотирьох вікнах. Тобто «це край ноги» написано в самій пачці, а
порівняння з головою тільки додає шуму.

### Хвіст проти голови

Профіль ноги U-подібний, тому детектор може ловити **будь-який** край.
Пряма перевірка — хвіст проти голови, 61 проти 61, тільки рівні фіч:

| вікно | найкраща фіча | AUC | найбільший \|z\| | шум 95 % | p | модель |
| ----- | ------------- | --- | ---------------- | -------- | - | ------ |
| 5 | `d_bal_support_sell` | 0.593 | 1.8 | 2.8 | 0.297 | 0.523 |
| 10 | `d_bal_support_sell` | 0.608 | 2.1 | 2.7 | 0.160 | 0.673 |
| 20 | `d_resist_buy` | 0.610 | 2.1 | 2.6 | 0.143 | 0.594 |
| 40 | `d_bal_resist_buy` | 0.612 | 2.0 | 2.5 | 0.187 | 0.689 |

**Кінець від початку не відрізняється.** На жодному вікні |z| не виходить
за шум (p = 0.14–0.30), модель на невидимих ногах дає 0.52–0.69 при
z ≤ 1.9. Те, що ловить детектор, — це **край ноги**, а не її кінець.

### Ряд val із видачею детектора

Той самий детектор показаний рядом — компоновка за
[`rules/05-visualization.md`](../../rules/05-visualization.md): опис
зверху, графік ціни з зігзагом, видача моделі **в підвалі на спільній
осі X** зі спільним зумом і зсувом, легенда під графіком.

| | |
| --- | --- |
| Вікно | val, 14.08 … 07.09: 9412 подій по 210 с |
| Модель | учена **тільки на train**: 42 246 вікон, 60 хвостів |
| Вхід | рівні семи фіч класу у вікні з 20 подій |
| Ранги | зняті **з train**: val-подія міряється тією самою лінійкою і про майбутнє не знає |
| Видача | на **кожній події** val: 7815 вікон, 10 справжніх хвостів |
| На val | AUC **0.648**, точність верхівки 10.0 % проти 0.13 % базових, поріг верхівки 0.771 |

У підвалі показані зони хвоста — останні 20 подій кожної ноги — і поріг,
вище якого стоїть рівно стільки вікон, скільки в ряді справжніх хвостів.
Розрив у лінії видачі — подія, для якої вікно не вміщається в свою ногу.

Скрипт: [`scripts/tip_series.py`](scripts/tip_series.py), вихід —
`results/tip_series_BTC_USDT_class210x10m1x7dd.json`, вкладка читає його
ендпоінтом `/api/inleg/series`.

**Що видно на ряді.** З 10 хвостів у верхівці видачі стоїть один: AUC
0.648 проти 0.74–0.82 на train — детектор переносить за час частину
сили, але на десяти ногах val це одне влучання. Число базової частки
(0.13 %) робить приріст великим у разах і нікчемним у штуках — саме тому
val тут показаний рядом, а не однією цифрою.

## Видача на val

Val-вікно BTC_USDT: **14.08 … 07.09**, 9412 подій, **9 ніг** і **8
півотів** усередині. Це й є межа заміру: все, що спирається на півоти,
там не міряється, а все, що спирається на пачки, — міряється.

| етап | на val | висновок |
| ---- | ------ | -------- |
| 1–2, профіль по нозі | 9 ніг; `d_up·mean` краї 0.574 проти середини 0.510, t +1.5, AUC край/середина 0.572 (t +1.8) | той самий знак, що на всьому ряді (0.615 / 0.522, t +5.1), але на 9 ногах різниця не витягує на значущу |
| 5, півот проти корекції | 8 півотів проти 31 / 14 / 6 корекцій | p = 0.29 / 0.59 / 0.64 — не міряється |
| 6, боки півота | 8 півотів; найбільший \|z\| чисел 2.2–3.3 при шумі 2.4–3.3 (p 0.09–0.73); модель, учена на train: AUC 0.46–0.61 | не міряється |
| 7, пачка від півота | 8 початків ніг проти ~740 середин; модель, учена на train: AUC 0.66–0.75, **точність верхівки 0 %** на всіх довжинах, p чисел 0.24–0.99 | не міряється |
| 8, пачки між собою | 18 пар через півот; найкраще AUC 0.728 при p = 0.077 | не міряється |
| 9, чи належить пачка нозі | 945 своїх проти 771 наступної (пачка 10) | **міряється і тримається** |

Етап 9 на val, модель учена на train-подіях і відповідає на val:

| пачка | своїх / наступних | краща згортка | AUC | z | p | модель AUC | точність верхівки |
| ----- | ----------------- | ------------- | --- | - | - | ---------- | ----------------- |
| 10 | 945 / 771 | `rank·manhattan·q25` | **0.330** | −12.1 | 0.000 | **0.617** | 54.0 % проти 44.9 % |
| 20 | 470 / 383 | `rank·manhattan·q25` | 0.320 | −9.1 | 0.000 | 0.573 | 49.9 % проти 44.9 % |
| 30 | 312 / 254 | `rank·manhattan·q25` | 0.313 | −7.7 | 0.000 | 0.594 | 49.2 % проти 44.9 % |

Замір з рівною часовою відстанню на val має лише **9 кандидатів через
півот**: найбільший |z| 2.4–2.7 при шумі 2.6–2.8, p = 0.04–0.10 —
підтвердити чи спростувати висновок етапу 9 на val неможливо, він
лишається з усього ряду.

**Що val показує.** Єдине, що переживає перенесення поза час навчання, —
це етап 9: своя пачка ближча до своєї ноги, ніж пачка наступної
(AUC 0.330, p = 0.000), і модель, яка бачила тільки train, дає на val
AUC 0.617 і точність верхівки 54.0 % проти 44.9 % базових. Усе, що
спирається на окремі півоти, на val не міряється: їх там вісім.

## Результат

1. **Місце події в нозі в класі написане.** Кожна з семи фіч має
   U-подібний профіль уздовж ноги; різниця «край проти середини» тримається
   всередині окремої ноги (AUC 0.36–0.61, t до 7.2) і має той самий знак
   у 80 % ніг.
2. **Читається відстань до півота, а не пройдена частка ноги.** Монотонного
   ходу від півота до півота немає: Спірмен із позицією не перевищує 0.04.
3. **Знак ефекту залежить від боку відношення.** На краях ноги обʼємні
   відношення (`d_up`, `d_down`) і рух ціни вищі, рівневі
   (`d_resist_buy`, `d_support_sell`, балансові) — нижчі.
4. **Напрямок руху окремої події клас не бачить.** Різницю «за рухом ноги
   проти зустрічної» дає лише похідна ціни (t +6.5); решта фіч — у межах
   шуму (|t| < 4). Натомість подій у напрямку ноги більше на її краях
   (0.538 проти 0.507 у середині).
5. **Подія іншої ноги відрізняється, але не одразу.** На 1–3 подіях після
   півота клас мовчить; різниця зʼявляється з 5 подій і найнадійніша на
   вікні 21–34 події (AUC 0.43 / 0.58, |z| до 7.8). Бік старої ноги на
   однаковій відстані від півота сильніший за бік нової.
6. **Справжній кінець ноги від корекції 1 % клас не відрізняє.** Проти
   дрібної корекції 0.5 % різниця є (AUC 0.669, p = 0.008 проти
   перемішаної мітки), і вона гасне з глибиною: 0.653 на корекціях
   0.5–1 %, 0.627 на 1–1.5 %, 0.544 на глибших.
7. **Коли можна сказати, що почалась нова нога — ні на якій довжині
   пачки.** Різниця в сирих числах є вже на першій події (AUC 0.26,
   z −6.5, p = 0.000 проти перемішаної мітки), модель росте до 0.727 на
   6–10 подіях і далі не росте, але точність верхівки нульова на всіх
   довжинах: серед 11 найгучніших пачок видачі немає жодного справжнього
   початку ноги. Найкраще ранжування — пачка 3–10 подій.
8. **Початки ніг вгору й униз однакові**: |z| врівень із шумом, модель
   0.42–0.58. Куди пішла нова нога, клас не каже.
9. **Пачки однієї ноги не схожіші між собою, ніж пачка цієї ноги й
   пачка сусідньої.** На однаковій відстані в парі й у тому самому місці
   ноги AUC не відходить від 0.5: найкраще в усьому переборі — 0.580
   (пачка 20 подій, сирі числа, `cosine`) при p = 0.183 проти
   перемішаної мітки. Те, що здавалось різницею при порівнянні з
   серединою ноги (0.59–0.605), — це край ноги з етапу 1, а не півот.
10. **Голова й хвіст однієї ноги не повʼязані** (Спірмен ≈ 0 на шести
   фічах із семи; виняток `d_price_avg` +0.53). Корелює те, що поруч у
   ряді: хвіст сусідньої ноги дає +0.75…+0.81, і хвіст стоїть далі від
   своєї голови, ніж від чужої.
11. **Край ноги видно, кінець — ні.** Детектор «це хвіст» на самих
   рівнях фіч дає AUC 0.74–0.82 і точність верхівки 5.6–23.5 % проти
   0.6–4.2 % базових (приріст ×6…×19). Порівняння з головою його тільки
   псує. Але хвіст від голови той самий детектор не відрізняє: AUC
   0.59–0.61, p = 0.14–0.30 — ловиться будь-який край ноги, а не її
   кінець.
12. **Пачка наступної ноги відрізняється від пачок цієї — але за часом,
   не за півотом.** Своя пачка ближча до своєї ноги (AUC 0.399,
   z −17.7), модель дає 0.616 і 58.2 % влучності проти 51.8 % базових.
   Далека нога при цьому ще далі (0.31–0.36): відстань читає час. При
   рівній часовій відстані лишається тільки падіння розміру чисел біля
   півота — метрики розміру й форми дають протилежні знаки.
13. **Різниця між боками півота є в самих фічах, але на одній події її не
   вистачає.** По 63 сирих числах події AUC доходить до 0.425 (z −6.5,
   p = 0.000 проти шуму) і знак однаковий на півотах `high` і `low` —
   тобто це справді місце, а не напрямок. Модель на всіх 63 числах із
   чесним розбиттям за часом дає 49–53 % влучності проти 50 % базових;
   стійко вище тільки на півотах `low` — 55.7 %.

## Вкладка

[`/inleg`](http://localhost:8080/inleg) — «Події в межах ноги». Чотири
розділи, по одному на етап:

| Розділ | Що показує |
| ------ | ---------- |
| Величина події по десятинах ноги | таблиця 42 × 10, перемикачі кривої і напрямку ноги, краї / середина / `t` |
| Всередині однієї ноги | ρ з позицією і три AUC, кожна з `t` і часткою ніг зі знаком |
| Подія за рухом ноги проти зустрічної | рівні обох боків, різниця з `t`, різниця по десятинах, частка подій за рухом |
| Де починається інша нога | профіль навколо півота на полотні (хвіст старої ноги і голова нової) та таблиця AUC по вікнах |
| Ряд val і видача детектора | ціна з зігзагом 2.3 % і видача детектора «це хвіст» у підвалі на спільній осі X, зони хвоста й поріг верхівки |
| Голова ноги і її хвіст | кореляція голови з хвостом і два контролі, детектор «це хвіст» на трьох наборах входів, перевірка «хвіст проти голови» |
| Чи належить пачка цій нозі | AUC «своя пачка проти чужої» на кожній згортці, перемикачі довжини пачки й контролю (наступна / далека нога), модель і замір з рівною часовою відстанню |
| Пачки між собою | AUC «пара через півот проти пари краю ноги» на кожній довжині пачки й відстані в парі, перемикачі чисел, метрики й контролю, контроль перемішуванням |
| Пачка від півота | таблиця довжин пачки: AUC моделі, точність верхівки, верхня десятина, місце першого справжнього початку, контроль перемішуванням; найсильніші числа вибраної пачки й початки ніг між собою |
| Боки півота на самих фічах | AUC кожного з 63 чисел події × блок, перемикач high / low, контроль перемішуванням і модель на всіх числах |
| Півот проти корекції | AUC «півот проти корекції» по вікнах, контроль перемішуванням і та сама величина по глибині корекції |

Дані вкладки — `/api/inleg` (етапи 1–4), `/api/inleg/series` (ряд val),
`/api/inleg/headtail` (етап 10), `/api/inleg/belongs` (етап 9),
`/api/inleg/similarity` (етап 8), `/api/inleg/starts` (етап 7),
`/api/inleg/sides` (етап 6) і `/api/inleg/correction` (етап 5): ті самі JSON, що пишуть скрипти.
Кожен розділ читає свій ендпоінт і малюється окремо — збій одного не
гасить решту.
