# Канва 600: півоти ноги і корекції

Вкладка: [`/canvas600`](http://localhost:8080/canvas600) · пари: BTC_USDT + 5 монет
(ETH, SOL, XRP, BNB, DOGE) · стандарт 30 с дослідження 35.

## Промпт

> роби нову вкладку — для неї .мд все як тут — готуємо канву (останні
> кращі напрацювання звідси — користуйся там) — задача взяти для канви
> ногу (500 рядків) додати по 50 рядків — буде 600 зліва та справа — за
> межами ноги, ноги які тривають меньше 7 годин — ігноруй. тепер задача:
> в цих ногах є наші 7 фіч — там відображаються корекції в середині ноги
> та корекції в кінці ноги, працювати на практиці повинно так: заходять
> дані — перетворюються на нашу канву600 — модель визначає в цій канві чи
> є там зони півотів зігзаг 2.3 % тобто чи є там початок ноги 2.3 % або
> кінець (що одне й те саме) також вона повинна відрізняти від цього
> початку або кінця корекції що всередині канви, тобто мережа бачить
> канву — визначає чи є початок — кінець ноги, якщо є або початок або
> кінець — мережа повинна відрізнити корекції в середині ноги від її
> початку або кінця та відмітити їх, і якщо ми подамо потім більше даних
> де буде і початок і кінець ноги — мережа повинна знайти початок та
> кінець а локальні корекції помітити як локальні.

Уточнення сигналу:

> перед навчанням коли наріжеш датасет - мітки корекцій, початків та
> кінців ніг пропусти через уточнювач сигналу - в діапазоні по стандарту
> вкладки - сигнал може бути меньшим або більшим - сигнал потрібно в
> заданих зонах конкретизувати та помітити в зонах лише сигнал щоб не
> помічати те що без сигналу сигналом - це "уточнення сигналу" для
> уточнення сигналу після очищення - рахуй кореляції сигналу з усіма
> частинами датасету (приклад порівняння сигналів початок ноги - період
> до ноги - кінець ноги - корекції в середині ноги) - та обери ті
> параметри сигналу що краще всього корелюють з нашими цілями! це буде
> "уточнений сигнал" обереш найкращий по кореляції - виведеш табличку в
> плашці . та побудуєш юмипи цих сигналів (всіх які в нас є цілями)
> сигнал уточнений це вікно а не один вектор з 7 . але для навчання
> використовуй 600х7 , роби чекаю уточнених сигналів на юмапах : виводь
> початок ноги, кінець ноги корекції внутрішні , звичайні частини ніг .

Вивід результатів — як на `/edges30`.

Графік:

> тепер нанеси ці корекції на графік трейн з вибором пари - щоб
> подивистись очима де вони і повверх намалюй зігзіг з яким працював

Рівна довжина пошуку піку і плутанина:

> Прибрати артефакт розміру зони. Шукати пік у вікні однакової довжини
> для півота й корекції. Тоді видно, скільки різниці справжньої. - зроби
> це і прпиши в .мд цього дослідження в стандарт щоб так було завжди та
> перерахуй це дослідження з виправленням — штраф за «корекцію, названу
> півотом» і навпаки і більше прикладів корекцій, що стоять поруч із
> півотом у тій самій канві. - це також роби

> для цієї кореляції ти рахуеш повний півот 2.3% чи розділяєш корекції
> на початок та кінець ноги? в принципі ми маємо порахувати кореляцію між
> цілими сусідніми півотами 2.3 це і є події початку та кінця ноги

> ще одни розділ - зроби для юмап к-мінс 2

> дослідження кластер 2 - зроби для нього розділом 3дюмап

> зроби там кнопку для вибору і окремого відображення здюмап кластер1

> додай окрім к-мінс автоматичний поіл на класи — да хдбскан

> розшифруй ці 2 класа і додай результати хдбскан до 3дюмап

> вчи модель знаходити к-мінс кластер1 і виводь результати на вал

> тото ми маємо в канві 600 знайти нерозривні рядки з 7 фіч, які
> відносяться до класу1 к-мінс … роби 600 з виводом на графік щоб можна
> було рухати зону канви

> можеш додати ще одну плашку знизу де ти знаходиш саме півоти2.3% тобто
> початок та кінець ноги?

> додай ще клас2 з к-мінс аналогічно тому як робив клас 1 плашкою

> одобрюю вкладку - робимо нову . візьми це Кластери 1 і 2 на канві
> руками (val) з поточної вкладки та Подача і видача мережі на одній нозі
> val з вкладки /seq30 та Ряд: ціна, ціль і обидві голови з вкладки
> /legs та виведи їх всіх під графіком вал на новій вкладці · і додай для
> кожної видачі ема як тут ладки /legs

> виводь всі видачі моделей під головним графіком , вони всі повинні
> обчислювати те що обрано на головному графіку тобто першому там де можна
> обирати зону всі інші графіки видали

> (смуги «зона кластера 1» і «зона кластера 2») видали ці 2

> (голови «бік ноги» і «зона розвороту» лінією з емою) додай ці 2 з /legs

> а чого ти не додав повнота ноги вхід 1?

> виведи мені порівняння фіч опору та підтримки в початку ноги - кінці
> ноги - корекціях та в звичайній частині ноги - зроби графік

## Ціль

Мережа отримує **канву 600** — відрізок ряду записів 30 с у матриці
600 × 7 — і на кожному рядку каже, що там:

| Клас рядка | Що це |
| ---------- | ----- |
| **півот 2.3** | зона півота зігзага 2.3 %: початок або кінець ноги (півот один — кінець однієї ноги є початком наступної) |
| **корекція** | зона краю корекції всередині ноги: внутрішній півот зігзага 0.8 % |
| **тіло** | решта |

Мережа має робити три речі:

1. **Знайти в канві півоти 2.3, скільки б їх там не було:** жодного,
   один (є тільки початок або тільки кінець ноги) чи два і більше.
2. **Відмітити корекції всередині ноги як корекції.** Відкат усередині
   ноги не можна плутати з її початком чи кінцем.
3. **Працювати на довшому відрізку.** Коли канва захоплює і початок, і
   кінець ноги, мережа знаходить обидва півоти, а локальні корекції
   між ними відмічає як локальні.

## Дані

Беруться готові записи й ноги дослідження 35, етап 3 (стандарт 30 с).
Нічого не перераховується.

| Що | Де | Як отримано |
| -- | -- | ----------- |
| записи 30 с і 7 фіч | `research/35-leg-fullness/data/bars30/<PAIR>_<part>.npz` | [`bars30.py`](../35-leg-fullness/scripts/bars30.py): секунди робочої копії сумуються в записи 30 с на сітці UTC, фічі — хід `клас210х10-1х7д/д` (шість відношень похідних + `d_price_avg`) |
| ноги зігзага 2.3 % | `research/35-leg-fullness/data/bars30/legs.json` | зігзаг 2.3 % прямо по `price_open` записів, без ема; точка кінця ноги — екстремум `price_close` у ±25 записах (`rules/02-markup.md` → Точка кінця ноги) |
| посекундні суми для канви | робоча копія `data/<рік>/<місяць>/<PAIR>/` | `bars30.read_seconds` |

- **Частини.** train — до 14.08.2026, val — з 14.08 по 22.09.2026 (UTC).
  Межа та сама, що в дослідженні 35.
- **Ноги коротші за 7 годин (840 записів) у вибірку не йдуть.** Вони
  лишаються в розмітці: їхні півоти, що потрапили в канву довгої ноги,
  розмічаються як усі інші.

| Монета | Ніг train | З них ≥ 7 год | Ніг val | З них ≥ 7 год |
| ------ | --------: | ------------: | ------: | ------------: |
| BTC_USDT | 146 | 107 | 26 | 22 |
| ETH_USDT | 229 | 137 | 40 | 29 |
| SOL_USDT | 288 | 149 | 56 | 34 |
| XRP_USDT | 166 | 110 | 100 | 33 |
| BNB_USDT | 118 | 94 | 34 | 26 |
| DOGE_USDT | 263 | 140 | 96 | 33 |
| **усі** | **1210** | **737** | **352** | **177** |

## Канва 600

Канва будується з найкращих напрацювань дослідження 35 (етапи 3 і 8).

1. **Проміжок.** Нога — це записи `first … last`, їх `L`. Крок рядка —
   `L / 500` записів. До ноги додається по 50 рядків із кожного боку,
   тобто по `0.1 · L` записів: від `first − 0.1·L` до `last + 0.1·L`.
   Рядки 0–49 лежать до ноги, 50–549 — сама нога, 550–599 — після ноги.
2. **Нарізка.** Проміжок ділиться на 600 рівних відрізків на межах
   записів. Відрізок — сума секунд, хід той самий, що в
   `bars30.edges_of`, але на 600 рядків. Оскільки нога триває щонайменше
   840 записів, у канві завжди ≥ 1008 записів, тобто ≥ 1.68 запису на
   рядок. Канва тільки **стискається**, розтягу з секунд немає.
3. **Фічі.** На кожному відрізку — хід `клас210х10-1х7д/д` (як
   `classes30.features`): 7 фіч на рядок.
4. **Нормування тільки на саму канву**, як `bars30.normalize`: медіана
   живих рядків → `sign · log1p` → 99-й перцентиль. Мертвий рядок (без
   секунд) — нулі.
5. **Стовпця маски немає** (рішення користувача). Вхід — 600 × 7.
6. **4 скаляри**, як в етапі 8 дослідження 35: `log1p` числа записів,
   `log1p` кроку рядка в секундах, `log(close/open)` канви, частка живих
   рядків.

Приклад: нога BTC на 2000 записів (16 год 40 хв). Крок — 4 записи
(2 хв) на рядок. Канва починається за 200 записів (1 год 40 хв) до
півота початку ноги і закінчується через 200 записів після півота кінця.
Півоти стоять на рядках 50 і 549.

## Розмітка рядків

**Півоти 2.3.** Це всі півоти `legs.json`, що потрапили в канву: обидва
півоти самої ноги, а також півоти сусідніх ніг у полях, якщо поле
захопило коротку сусідню ногу.

**Корекції.** Це внутрішні півоти зігзага 0.8 % усередині кожної ноги,
що потрапила в канву. Зігзаг 0.8 % ведеться по `price_open` записів
ноги з тим самим кроком `snap` (екстремум `price_close`, ±25 записів),
що й зігзаг 2.3 %. Це стандарт розмітки для порогу будь-якого розміру:
`rules/02-markup.md` → Точка кінця ноги; етап 1 дослідження 35 — ролі
«корекція-як-кінець» і «корекція-як-початок». Корекцією вважається
кожен внутрішній півот 0.8, що стоїть далі за 25 записів від обох
півотів 2.3 ноги: ближчі — це самі краї ноги. Беруться обидва боки: де нога спинилась і де рушила далі.

**Зона.** Береться правило, підтверджене в етапі 8 дослідження 35: перетин
двох множин навколо півота.

| Що | Півот 2.3 | Корекція 0.8 |
| -- | --------- | ------------ |
| за часом | 95–105 % тривалості ноги, яку півот закінчує: `p ± 0.05 · L` записів | те саме від відрізка 0.8, який півот закінчує |
| за ціною | ближче за 10 % цінової довжини тієї ноги від ціни півота | ближче за 10 % цінової довжини того відрізка 0.8 |

Рядок належить зоні, якщо хоча б один його запис лежить у ній і за
часом, і за ціною. Мітка рядка:

- `2` — рядок у зоні півота 2.3;
- `1` — рядок у зоні корекції і не в зоні півота 2.3 (півот 2.3
  важливіший);
- `0` — тіло.

Півот, чия зона тільки частково потрапила в канву, розмічається своєю
зоною як є.

## Вікна навчання

Базова канва 600 навколо кожної ноги має обидва її півоти, тому сама
не навчить випадку «є тільки початок» чи «є тільки кінець». Тому на
кожну ногу ≥ 7 год (`plan_windows`, seed 36) береться до 14 вікон:

| Вид | Скільки | Межі у записах |
| --- | ------: | -------------- |
| `base` | 1 | `first − 0.1·L … last + 0.1·L`: нога на рядках 50 … 549 |
| `shift` | 4 | та сама ширина, зсув на `δ·L`, `δ ~ U[−1, 1]`: у канві один півот ноги, жодного або сусідні |
| `inner` | 2 | ширина `U[0.3, 0.8]·L`, не менше 600 записів, цілком усередині ноги (далі за `0.05·L` від її півотів) |
| `long1.5`, `long2`, `long3` | до 3 | від `first − 0.1·Lₜ` до середини наступної ноги, кінця наступної, кінця третьої; `Lₜ` — записи всіх узятих ніг, поле 0.1·Lₜ з кожного боку; лише коли ноги йдуть впритул |
| `near` | до 4 | корекція біля півота: на кожну корекцію ноги ближче `0.2·L` до її початку чи кінця вікно ширини `max(U[0.5, 0.8]·L, 600)` з центром посередині між корекцією і півотом, зсув центру `U[−0.1, 0.1]·L` — корекція і півот в одній канві |

Вікно обрізається краями частини і не береться, коли в ньому менше
600 записів: канва тільки стискається. Розмітка вікна — за правилами
розділу «Розмітка рядків»; зона півота чи корекції, чий півот сам поза
вікном, — мітка `−1` (рядок не вчиться).

## Уточнення сигналу

Зона — це проміжок, у якому розворот **може** бути: 95–105 % тривалості і
10 % ціни. Сам сигнал у ній займає менше рядків, а буває, що його в зоні
немає зовсім. Уточнювач лишає мітку тільки там, де сигнал є, щоб рядки
зони без сигналу не вчили мережу, що вони сигнал.

1. **Сила рядка** з параметрами `(F, h, stat)`: `a(r)` — середнє `|x|`
   фіч набору `F` (одна з семи або всі сім) у рядку `r` нормованої
   канви; `s(r)` — `mean` чи `max` від `a` у вікні `r − h … r + h`.
2. **Пік** — живий рядок **вікна пошуку** з найбільшим `s` (стандарт
   нижче). Зона має сигнал, коли `s(пік) ≥ τ_q`, де `τ_q` — `q`-й
   квантиль `s` по живих рядках тіла (мітка 0) базових канв train.
3. **Уточнений сигнал** — вікно канви `пік ± h` рядків × усі 7 фіч
   (`repr`: як є — `signed`, по модулю — `abs`). Це вікно, а не один
   рядок із 7 чисел.
4. **Частини датасету** на базових канвах: `start` — зона півота
   початку ноги, `end` — кінця, `corr` — корекції 0.8, і три контролі:
   `pre` (рядки 0 … 49), `body` (50 … 549, 3 на канву), `post`
   (550 … 599). Контроль — випадковий центр, у якого ±8 рядків поза
   зонами, далі той самий хід: пік у `центр ± P`, поріг, вікно.
5. **Кореляції** — Пірсон між векторами вікон **різних** ніг.
   `M[a, b]` — середня кореляція вікон частини `a` з вікнами частини
   `b`. **Розрив цілі** `T` = `M[T, T] − max(M[T, pre], M[T, body],
   M[T, post])`. **Бал** — середній розрив трьох цілей. На частину —
   до 600 вікон (seed 36).
6. **Грід** — `F` (8) × `h` ∈ {1, 2, 4, 7, 12} × `stat` (2) ×
   `P` ∈ {2, 4, 8} × `repr` (2) × `q` ∈ {0.5, 0.7, 0.8, 0.9} = 1920
   варіантів на train. Обирається
   найбільший бал серед варіантів, де сигнал є щонайменше в 60 % зон
   кожної цілі; val — тільки замір.
7. **Уточнені мітки** всіх вікон train і val: у кожній зоні мітку (2 —
   півот, 1 — корекція) отримує тільки суцільний відрізок рядків вікна
   пошуку навколо піку з `s ≥ τ`; рядок півота 2.3 корекція не забирає. Решта рядків зони і вся зона без сигналу —
   `−1`. Для навчання вхід лишається канвою 600 × 7.
8. **Профіль фіч** — середнє кожної з 7 фіч на зсувах −12 … +12 рядків
   від піку для початку, кінця, корекцій (зони з сигналом) і звичайної
   частини ноги (`body`), по модулю і зі знаком окремо для вершин і
   днів; train і val.
9. **Сусідні півоти однієї ноги** (`--pairs`) — на базових канвах, де є
   і початок, і кінець ноги: кореляція сигналу початку з сигналом кінця
   тієї самої ноги, з кінцем випадкової іншої ноги (перестановка, seed
   36) і кожного з тілом своєї канви; 95 % інтервал різниці «своя −
   чужа» — 2000 перевибірок ніг. Усі ноги і лише ті, де обидва півоти з
   сигналом.
10. **UMAP** уточнених сигналів обраного варіанта на базових канвах
   train і val: початок, кінець, корекції (лише зони з сигналом) і
   звичайні частини ніг (відрізки `body` без відбору; до 800 / 800 /
   1200 / 1200 точок), метрики `cosine`, `euclidean`, `manhattan`,
   `n_neighbors 15`, `min_dist 0.1`, seed 36.
11. **k-means на UMAP** (`--kmeans`) — на координатах кожної карти
    (train і val × три метрики) k-means на 2 кластери, `n_init 10`,
    seed 36; склад кластерів за частинами — початок, кінець, корекції,
    звичайна частина ноги. Нумерація однакова для всіх карт: кластер 1 —
    той, де більша частка початків і кінців ноги («півотний»), кластер 2 —
    решта («тілесний»). Там само — **HDBSCAN** на тих самих координатах:
    кількість кластерів визначає сам, `min_cluster_size 50`,
    `min_samples 10`, точки поза кластерами — шум; нумерація — за
    спаданням частки початків і кінців ноги.
12. **3D UMAP кластерів** (`--cluster3d`) — точки кожного кластера
    k-means і кожного кластера HDBSCAN кожної карти окремою 3D-картою:
    ті самі вектори уточненого сигналу, та сама метрика, 3 компоненти,
    `n_neighbors 15`, `min_dist 0.1`, seed 36.
13. **Розшифровка кластерів** (`--decode`) — кластери 1 і 2 k-means на
    карті `cosine`: рівень кожної фічі (середнє `|x|` у вікні сигналу),
    AUC «кластер 1 проти 2» на всіх точках і на корекціях окремо; і
    властивості зон — для корекції розмір (%) і довжина (записів) руху
    0.8, який вона закінчує, місце в нозі 2.3 і відстань до найближчого
    півота 2.3 в частках ноги; для початку й кінця ноги — рух і довжина
    ноги 2.3, яку закінчує півот; медіани і AUC.

### Стандарт: пік шукається у вікні однакової довжини

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

- Пік шукається у **вікні пошуку**: рядок півота (рядок канви, куди
  лягає запис півота) `± P` рядків. `P` **однаковий** для півотів 2.3,
  корекцій 0.8 і контролів.
- Зона півота чи корекції **не задає**, де шукати пік. Зона півота 2.3
  ширша за зону корекції (5 % довгої ноги проти 5 % відрізка 0.8), і
  максимум, узятий з більшої кількості рядків, був би більшим сам собою —
  різниця між класами тоді частково артефакт розміру зони.
- Контроль шукає пік тим самим ходом: випадковий центр поза зонами і
  те саме вікно `± P`.

## Мережа і міра

Етап 2, [`scripts/canvas600_net.py`](scripts/canvas600_net.py).

- **Мережа** `Finder3` — трансформер на 600 рядках, як `Finder` етапу 8
  дослідження 35: рядок + 4 скаляри → лінійно в ширину 64, вивчена
  позиція кожного рядка, 2 шари уваги по 4 голови, norm first, ff 128,
  dropout 0. На кожен рядок 3 логіти: тіло / корекція / півот 2.3.
- **Мітки** — уточнені (`data/canvas600/<part>_refined.npy`); рядок `−1`
  і мертвий рядок у втрату не йдуть.
- **Втрата** — крос-ентропія з вагами класів 1 / 3 / 3 (тіло /
  корекція / півот) плюс **штраф за плутанину** з λ = 1:
  `−log(1 − p_півот)` на рядках корекції і `−log(1 − p_корекція)` на
  рядках півота, з тією самою вагою класу. Корекція, названа півотом, і
  півот, названий корекцією, коштують дорожче, ніж та сама помилка в
  тіло.
- **Приклади плутанини** — вікна `near` (розділ «Вікна навчання»):
  корекція біля півота в одній канві.
- **Сигнал** класу — рядок, де імовірність класу ≥ порогу і найбільша
  в ±10 рядках. Сигнал **добрий**, коли рядок у зоні свого класу (зона
  розмітки до уточнення). **Повнота** — частка зон із сигналом
  уточнювача, у яких є сигнал свого класу. **Сплутано** — сигнал півота
  в зоні корекції (поза зоною півота) і сигнал корекції в зоні півота.
- **Відкладені** — 20 % ніг train, seed 0: поріг кожного класу — за
  найкращим F1, епоха — за найкращим середнім F1 двох класів; стоп
  після 3 епох без покращення, стеля 30. Adam lr 1e-3, батч 32 кусками
  по 8 з накопиченням градієнта (передбачення — батчем 16: увага
  600 × 600 на 8 ГБ машини інакше йде в своп), seed 0.
  val — тільки замір, по монетах окремо.
- Ваги класів, λ і штраф за відстань від зони підбираються грідом
  наступним кроком.

## Валідація на ряді val

Етап 3, [`scripts/canvas600_data.py`](scripts/canvas600_data.py)
`--series` і [`scripts/canvas600_net.py`](scripts/canvas600_net.py)
`--outputs`.

- **Ряд val** — ковзні вікна без розмітки по 2400 записів (20 год) з
  кроком 300 записів по всьому ряду val кожної монети (369 вікон на
  монету), кожне — канва 600 × 7 тим самим ходом.
- **Імовірність запису** кожного класу — найбільша з рядків усіх вікон,
  що його накривають.
- **Сигнал** класу — запис з імовірністю ≥ порогу класу (поріг епохи з
  відкладених), найбільшою в ±60 записах. **Добрий** — запис у зоні свого
  класу (95 … 105 % тривалості × 10 % ціни); **повнота** — частка
  півотів (корекцій) ряду, у зоні яких є сигнал свого класу;
  **сплутано** — сигнал у зоні чужого класу і поза своєю.
- Епохи — найкраща ± 2.
- **Канва руками** (`probe`) — відрізок val ≥ 600 записів, обраний на
  дашборді, тим самим ходом у канву 600 і видача обраної епохи на
  кожному рядку; правда — мітки рядків канви за зонами півотів і
  корекцій.

## Мережа кластера 1

Етап 4, [`scripts/canvas600_c1.py`](scripts/canvas600_c1.py). Мережа
вчиться знаходити на канві події кластера 1 k-means («рух без рівнів»,
результат 9).

1. **Правило кластера 1.** Кластер визначений лише на точках карти UMAP,
   тому на векторах уточненого сигналу тих самих точок train (21 число:
   `|x|` вікна `пік ± 1` рядок × 7 фіч) вчиться логістична регресія
   (C = 1, seed 36) «вектор → кластер 1»; перевірка — на точках val
   проти їхнього власного k-means.
2. **Мітки рядків** усіх вікон train і val: для кожної зони півота 2.3 і
   корекції 0.8 — пік уточнювача (стандарт: рядок півота ± P) і його
   вектор; рядки уточненого сигналу зони, яку правило відносить до
   кластера 1, — `1`; сигнал кластера 2 — `0`; тіло — `0`; решта рядків
   зон і рядки з уточненою міткою `−1` — `−1` (не вчиться).
3. **Мережа** — `Finder3` етапу 2 з двома виходами, крос-ентропія з
   вагами 1 / 3, батч 32 кусками по 8, Adam lr 1e-3, відкладені 20 %
   ніг train (seed 0): поріг і епоха — за F1 на відкладених, стоп після
   3 епох без покращення, стеля 30.
4. **Міри на вікнах**: сигнал — пік ≥ порогу в ±10 рядках; добрий — у
   зоні кластера 1; повнота — частка зон кластера 1 із сигналом; і куди
   лягають сигнали: у зону півота 2.3, корекції чи поза зонами.
5. **Ряд val** (`--outputs`) — ковзні вікна етапу 3, найкраща епоха ± 2:
   сигнал — пік ≥ порогу в ±60 записах; частка сигналів у зонах півотів
   2.3, корекцій і поза зонами; скільки півотів і корекцій знайдено.
6. **Кластер 1 на канві руками** (`rule_probe`) — точка UMAP — це 3
   сусідні рядки канви × 7 фіч (21 число), тому канва проходиться вікном
   з 3 рядків з кроком 1: кожне вікно (`|x|`) — через правило кластера 1;
   рядок у зоні кластера 1, коли його накриває хоч одне вікно з
   імовірністю > 0.5; імовірність рядка — найбільша з вікон, що його
   накривають. Правда — рядки зон півотів 2.3 і корекцій 0.8 канви.
   Кластер 2 — те саме вікно з імовірністю `1 − p` (кластерів два), зона
   кластера 2 — так само: найбільша з вікон, що накривають рядок, > 0.5.
   На тій самій канві — мережа етапу 2 (найкраща епоха 7): P(півот 2.3)
   на кожному рядку, сигнал — пік вище її порогу (0.20) в ±10 рядках.

## Алгоритм на вікні канви

Етап 5, [`scripts/canvas600_rule.py`](scripts/canvas600_rule.py).

> а чи можеш ти у вікні канви алгоритмічно виявити - по фічам півот 2.3%
> (якщо корекція і півот співпадає то це півот), корекцію , тіло ноги

1. **Вхід рядка** `r` — вікно `r − 1 … r + 1` (біля краю канви
   зсувається всередину), як уточнений сигнал обраного варіанта:
   `sum7` — рівень фічі `L[f] = (|x[r−1, f]| + |x[r, f]| + |x[r+1, f]|) / 3`,
   7 чисел; `cat21` — модулі трьох рядків підряд, 21 число.
2. **Формула** — `z_k = Σ w_k · вхід + b_k` для тіла, корекції й півота
   2.3, `p = softmax(z)`: багатокласова логістична регресія, ваги класів
   1 / 3 / 3 (як у мережі), `C = 1`, стандартизація входу, ваги
   перераховані в сирі одиниці нормованої канви.
3. **Мітки** — уточнені (`<part>_refined.npy`): рядок, де збігаються
   корекція й півот, — півот; `−1` і мертві рядки не вчаться. Навчання —
   300 000 рядків ніг train без відкладених, seed 36.
4. **Сигнал і міра** — як у мережі етапу 2 (`canvas600_net.scores`): пік
   `p` ≥ порогу в ±10 рядках, поріг кожного класу — за F1 на відкладених
   20 % ніг train (seed 0), val — тільки замір.

## Канва 1100 на записах 100 с

Етап 6, [`scripts/canvas1100.py`](scripts/canvas1100.py).

> візьми весь датасет трейн для кожної пари та збери по 200 - суму 8-ми
> фіч, а потім перетвори в датасет по правилам класу клас210х10-1х7д/д
> (саме датасет) - проведи на ньому пошук очищених півотів зігзагів
> 2.3 % (нога не меньше 7 годин), потім бери канву 1100 - в 1000 має
> поміститись 4 зігзага та + 50 подій з кінців (у відповідному масштабі)
> там далі робиш юмап подій : півот 2.3%, внутрішні корекції, робиш юмап
> з цими векторами

> по 100 секунд - опечатка

> 6. Вектори. Для кожної події беру вектор уточненого сигналу 3 × 7 за
> стандартом дослідження і будую UMAP півотів 2.3 і корекцій 0.8 на
> трьох метриках. - роби просто для події

1. **Секунди → записи по 100 с** (`bars30.bars_of_frame(bar=100)`): уся
   train-частина кожної монети (до 2026-08-14), доба за добою
   стандартним читанням; запис — суми 8 колонок `клас210х8` і
   `price_avg` на сітці UTC, кратній 100 с, і кількість секунд `n`.
2. **Датасет класу** `клас210х10-1х7д/д` на записах — хід стандарту 30 с
   дослідження 35 (`bars30.features_of`, `bar = 100`): середні запису →
   рівні на обʼєм свого запису → похідна, лише коли попередній запис
   впритул (100 с) → сім відношень похідних і `d_price_avg`; нульовий
   знаменник дає 0. `data/canvas1100/<PAIR>_train.npz`.
3. **Півоти 2.3** — зігзаг 2.3 % прямо по `open` записів і точка кінця
   ноги (`snap`, екстремум `close` у ±25 записах, `rules/02-markup.md`),
   без ема. Нога — від запису після півота до наступного півота. У канву
   йдуть лише ноги ≥ 7 год (252 записи).
4. **Корекції 0.8** — `canvas600_data.corrections_of`: зігзаг 0.8 % по
   `open` усередині кожної ноги 2.3 і `snap`; корекція — внутрішній
   півот, далі за 25 записів від обох країв ноги. Зони півотів і корекцій
   — як у канві 600.
5. **Канва 1100** — кожні 4 ноги підряд (впритул, кожна ≥ 7 год), крок —
   одна нога. Плюс **зсунуті канви** — 4 на кожні 4 ноги (seed 36): те
   саме вікно, зсунуте на `δ · L / 4` записів, `δ ~ U[−1, 1]`, `L` —
   записи чотирьох ніг; півоти в них стоять у будь-яких рядках. На них
   вчиться мережа етапу 7; події й UMAP — лише з базових канв. Частина
   val (`--part val`, 14.08 … 22.09) — тим самим ходом, без UMAP. Вікно — перший запис першої ноги мінус поле … останній
   запис четвертої плюс поле, поле = 5 % записів чотирьох ніг з кожного
   боку: 4 ноги лягають на рядки 50 … 1049, по 50 рядків — за їхніми
   межами в тому самому масштабі. 1100 відрізків на межах записів
   (`bars30.canvas_blocks`), клас `клас210х10-1х7д/д`, нормування тільки
   на канву (`bars30.normalize`). Півот перед першою ногою лягає в рядок
   49, після четвертої — у 1049.
6. **Розмітка рядків** — `canvas600_data.label_rows`.
7. **Вектор події** — сам рядок канви, куди лягає запис півота чи
   корекції: 7 фіч нормованої канви як є, без пошуку піку, без вікна і
   без порогу сигналу.
8. **Події** — півоти 2.3 і корекції 0.8 у рядках 49 … 1050 хоча б однієї
   канви; подія з кількох канв — з тієї, де вона ближче до середини.
   На карту — усі події (до 4000 на клас, seed 36).
9. **UMAP** — 2 компоненти, cosine, euclidean, manhattan,
   `n_neighbors 15`, `min_dist 0.1`, seed 36.

## Мережа на канві 1100

Етап 7, [`scripts/canvas1100_net.py`](scripts/canvas1100_net.py).

> знайди біл кожного півота можеш навчити мережу яка в межах цих 1100
> подій знаходить півоти 2.3% ?

1. **Дані** — зсунуті канви 1100 етапу 6: train (до 14.08) і val
   (14.08 … 22.09). Базові канви не беруться: у них півоти завжди в
   рядках 49 і 1049, і мережа з вивченою позицією рядка вчить позицію, а
   не півот (перший прогін на базових канвах: 131 з 136 крайніх півотів
   val знайдено, 0 з 227 внутрішніх).
2. **Мітка рядка** — `1` у зоні півота 2.3, `0` — тіло й зони корекцій;
   `−1` і мертві рядки у втрату не йдуть.
3. **Розбиття по часу** — `cut` — нога на 80 % ніг монети; навчання —
   канви, чиї 4 ноги і ще одна (зсув) цілком до `cut`; відкладені — з
   ноги `cut + 1`; спільних ніг немає. val — тільки замір.
4. **Мережа** — `Finder3` етапу 2 на 1100 рядках, 2 виходи; крос-ентропія
   1 / 3; Adam lr 1e-3, батч 8 кусками по 4, seed 0, стеля 30 епох,
   стоп після 4 епох без покращення F1 на відкладених.
5. **Сигнал і міра** — як в етапі 2: пік `P(півот)` ≥ порогу в ±10
   рядках; добрий — у зоні півота; повнота — зон півота з сигналом;
   сплутано — сигнал у зоні корекції. Поріг і епоха — за F1 на
   відкладених.
6. **Контролі**: випадкові сигнали — стільки ж на випадкових живих
   рядках кожної канви (seed 36); позиційний прогноз — частка рядків
   зони півота на кожній позиції канви в навчальних канвах, без фіч,
   поріг — на відкладених.
7. Памʼяті перед прогоном — 943 МБ вільно при межі 2400: запуск з
   `--force` свідомо (канви 1100 — ~40 МБ, мережа ~0.1 М параметрів,
   увага на батч 4 — сотні МБ); дашборд на час прогону вимкнено.
8. **Канва руками на val** (`canvas1100_net.val_marks`, `probe`):

   > зроби вал на кожну монету так щоб бачити сигнал мережі і обирати
   > розмір зони

   > тільки до вал зони додай 3 півота до

   Ряд монети — хвіст train від півота, з якого перед val стоїть 3
   півоти 2.3, і весь val, записи 100 с; зігзаг 2.3 (`canvas1100.legs_of`)
   і корекції 0.8 рахуються заново по цьому ряду. Хвіст відступає на
   півот, поки перед val не стане 3 півоти: зігзаг, запущений з півота,
   першої точки ряду півотом не ставить. Відрізок від 1100 записів
   (30.6 год) → канва 1100 тим самим ходом, що в навчанні
   (`canvas1100.canvas_of`), скаляри канви, мережа на найкращій епосі
   (CPU), сигнал — пік ≥ порогу в ±10 рядках.

## Три голови, функції втрат, довші вікна і торгівля

Етап 8, [`scripts/canvas1100_heads.py`](scripts/canvas1100_heads.py),
[`scripts/canvas1100_trade.py`](scripts/canvas1100_trade.py).

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

> третя голова каде - 1- купити -1 - продати - має попадати в півоти 2,3

> і бути прибуткова завжди в ринку

1. **Канви на 6 і 8 ніг** (`canvas1100.py --legs N`): той самий хід, що
   на 4 ноги — 1100 рядків, ноги ≥ 7 год на рядках 50 … 1049, поле 5 %,
   4 зсунуті канви на кожні `N` ніг; train і val.
2. **Три голови** — `Finder3` на 1100 рядках з трьома виходами-сигмоїдами:
   `P(півот 2.3)`, `P(корекція 0.8)` і бік `P(купити)`. Мітки: півот —
   `label = 2`, корекція — `label = 1` (де корекція збігається з півотом —
   півот); бік — нога середнього запису рядка: наступний півот 2.3 —
   вершина → купити (`1`), дно → продати (`0`); бік перемикається на
   півоті, позиція завжди в ринку.
3. **Функції втрат** голів півота й корекції: `wbce` (BCE, вага позитиву
   3), `focal` (γ 2, α 0.75), `dice` (BCE + 1 − soft dice), `swap` (`wbce`
   + штраф 3 за `P(півот)` на рядках корекції і `P(корекція)` на рядках
   півота); голова боку — завжди BCE.
4. **Розбиття** — нога-різ на 80 % ніг монети train, запас по нозі з
   обох боків, однаково для 4, 6 і 8 ніг; val — тільки замір. Adam
   lr 1e-3, батч 8 кусками по 4, seed 0, стоп після 4 епох без
   покращення; епоха — за середнім F1 півота, корекції й перемикань боку
   на відкладених; пороги голів — на відкладених.
5. **Міри** — півот і корекція як в етапі 7 проти випадкових сигналів;
   бік — частка рядків із правильним боком і перемикання: добре, коли в
   зоні півота і в бік ноги за нею.
6. **Кола** — A: 4 ноги × 4 втрати; B з найкращою втратою: з нуля на
   4 + 6 + 8 ногах (`B_mix`) і довчання `A_dice` на них же (`B_tune`).
7. **Торгівля в живому часі** (`canvas1100_trade.py`, найкращий прогін):
   кожні 18 записів (30 хв) канва 1100 з 4430 записів, що **закінчуються
   на поточному записі** — даних після нього канва не бачить; рішення —
   середнє `P(купити)` останніх 3 живих рядків, ≥ 0.5 — довга, інакше
   коротка; завжди в ринку; виконання ціною `open` наступного запису;
   `Decimal`, $1000, комісія 0.05 % + сліпедж 0.02 % за бік, перевертання
   — два боки. Проти: холд з тими самими витратами; 20 випадкових
   прогонів з тією самою кількістю перевертань (seed 36). Ряд — хвіст
   train (≥ 3 півотів і ≥ 4430 записів) і val; торгівля — з першого
   запису val.

## Голова «бік ноги» до 22.09

Етап 9, [`scripts/heads33_data.py`](scripts/heads33_data.py),
[`scripts/heads33_run.py`](scripts/heads33_run.py).

> то дорахуй заьстандартами дослідження 33, аналогічнотому як там рахували

Голова «бік ноги» дослідження 33 має видачу лише на подіях, де є всі
канали входу — `tooth`, `line` (дослідження 32), `p100` і чотири
горизонти (дослідження 20 / 32), `pivot`, `correct` (дослідження 31 /
32). Підтверджені датасети скінчуються 07.09 (`клас210х10…`) і 29.08
(`клас210х14х4ц`), тому видача на val кінчалась 25–28.08. Тут той самий
ланцюжок до 22.09, **без перенавчання жодної мережі**:

1. **Датасети** в окрему папку `data/datasets_ext/`, підтверджені
   `data/datasets/` не чіпаються:
   - `клас210х10…` — `build_class210x10x7dc.py --end 2026-09-23` (межа
     train 14.08, пропуски до 60 с заповнюються — як у підтвердженому);
   - `клас210х14х4ц` — `heads33_data.py`: `build_dataset` →
     `build_class210x14x5` → `build_class210x14x3` →
     `build_class210x14x4c` з кінцем 22.09 для `BTC_USDT_29` (без
     заповнення) і `<PAIR>_fill` (до 60 с); джерело — робоча копія
     `data/`, тож вона не копіюється і не змінюється.
2. **Кеш ніг** `legleft_blocks4_gauss_clock` — штатним `legleft_data.py`
   дослідження 29 з `--data data/datasets_ext` у
   `data/heads33/legleft/`.
3. **Видачі мереж і голова** — `heads33_run.py`: функції
   `calls_data.series_split / series_hazard / series_zone`, `join`
   дослідження 33 і `legs_heads.walked` / `series_of` зі збереженими
   `models/legs_heads/model.pt` і `norm.npz`. Шляхи до датасетів і кешу
   (`edge_profile.DATASETS`, `inleg_profile.DATASETS`,
   `leg_end_data.DATASET`, `ad_legleft.DATA`) перенаправлені в памʼяті
   процесу; вихід — `results/heads33/`.
4. **Перевірка** — на подіях, що є в ряду дослідження 33, видача голови
   має збігтися з його `legs_heads_series_<PAIR>_all.json`.
5. `/valboard` бере продовжений ряд, коли він є (`valboard.HEADS_EXT`),
   інакше — ряд дослідження 33.
6. **Виняток для вкладки `/umap600`** (дозвіл користувача 2026-09-26):

   > для виключення - для цієї вкладки - дозволяю - заповни щоб показувало на всьому вал

   Між 07.09 і 14.09 у робочій копії є діри збору (07.09 — 4.7 год,
   10.09 — три по 1.1–1.8 год, 14.09 — 1.5 год), і ноги, що їх
   накривають, за стандартом (`HOLE` = 1 год) не рахуються — каналів
   `split` і `zone` там немає, голова мовчить. `heads33_run.py --holes`:
   нога, що **закінчується в val**, рахується і з дірою — `hole_hours`
   ставиться в 0 обгорткою `edge_profile.legs_of` у памʼяті процесу;
   кеш ніг — `data/heads33/legleft_holes/`, вихід —
   `results/heads33_holes/`. «Канва руками» на `/umap600` бере цей ряд
   (`/api/valboard/<PAIR>/<від>/<до>/holes`, `valboard.HEADS_HOLES`);
   `/valboard` — стандартний. Хвіст ряду після останнього півота (кінець
   у val) додається відкритою ногою до останньої події
   (`heads33_run.tail_of`): бік — протилежний останній нозі, кінець —
   остання подія ряду; горизонти `hazard100` / `hazard4` на val беруться
   без маски `known` після останньої відомої події
   (`series_hazard_tail`, `open_known`: крива мережі й так рахується на
   кожній події, маска лише ховала хвіст); так голова говорить до кінця
   val.

   > баг чому графік нижній не до кінця

## Скільки даних у вікні канви 1100

Етап 10, [`scripts/canvas1100_window.py`](scripts/canvas1100_window.py).

> на бтс вал рухаєш вікно 1100 канва так щоб воно захоплювало півоти і дивишся при яких параметрах вікна найбільше попадання в зону півотів сигналів голови 1 потім дивишся на попадання в локальні корекції сигналів голови 2 рухаеш не одне стале а фіксуеш початок і збільшкеш його вправо до максимально близької відповіді співпадіння з півотами - коли співпадіння зникає - рухаеш ліву частину вправо на крок і потім підбираєш далі - ціль - виробити механізм знаходження оптимальної кількості даних для вікна канви 1100 щоб воно визначало півоти з максимальною точністю - роби такий широкий грід .

1. **Ряд** — val BTC (з 14.08) на записах 100 с (`canvas1100_net.val_marks`),
   півоти 2.3 і корекції 0.8 з зонами — як на «канві руками». Вікно
   `[s, e]` лежить цілком у val. Модель — прогін `B_tune` етапу 8 на його
   найкращій епосі, без довчання.
2. **Мапа вікон** — усі вікна решітки: `s` і `e` кратні 72 записам (2 год)
   від першого запису val, довжина 1152 … 16128 записів (32 год … 18.7
   доби) — 73 777 вікон. На кожному — канва 1100 (`canvas1100.canvas_of`),
   три голови, мітки рядків (`label_rows`). Сигнал — пік ≥ порогу в ±10
   рядках; добрий — у зоні свого класу; повнота — частка зон свого класу
   у вікні з сигналом; F1. Голова 1 — півоти 2.3 на порогах 0.3 … 0.8,
   голова 2 — корекції 0.8 (зона корекції, що не півот) на порогах
   0.1 … 0.4. На вікно зберігаються лічильники і номери знайдених зон.
3. **Обхід** — початок фіксується, правий край росте кроком `right`,
   найкраще за F1 вікно цього початку запамʼятовується. Коли F1 падає
   нижче найкращого на `drop` і не повертається `patience` кроків (або
   вікно дійшло до 16128 записів), найкраще вікно записується, лівий
   край зсувається на `left`, правий лишається де був (не коротше за
   `min_len`), і ріст іде далі. `drop = 1` — «співпадіння зникло»: F1 = 0.
4. **Грід** на кожну голову і поріг: `right` 72 / 144 / 288, `left`
   72 / 144 / 288 / 576, `min_len` 1152 / 2232 / 4392, `drop` 0.05 / 0.1 /
   0.2 / 0.3 / 1, `patience` 1 / 3 — 360 клітинок × 6 порогів × 2 голови.
   На клітинку: число найкращих вікон, їхня довжина (записи, години,
   півотів 2.3 у вікні), середній F1, точність усіх їхніх сигналів і
   повнота — частка зон val, знайдених хоча б одним найкращим вікном.
5. **Контроль — стале вікно**: одна довжина на весь val, початок кожні
   2 год; середній F1 за довжиною, точність і повнота обʼєднання.
6. **Чим пояснюється оптимум** — найкраще вікно кожного початку мапи:
   довжина проти числа півотів 2.3 і корекцій у вікні.

## Вершина, корекція й дно на циклі вікна

Етап 11, [`scripts/canvas1100_grow.py`](scripts/canvas1100_grow.py).

> 1. P(півот 2.3) — поріг 0.6. - хай рахуе лише півоти по ерхній ціні там де продаж верхній півот вікна 2.3%
> 2. P(корекція 0.8) — поріг 0.25.
> 3. P(півот 2.3) — поріг 0.6. - хай каже лише півоти що по нижній ціні , нижній півот вікна 2.3%
> перероби на такі 3 голови . якщо голова 1 або 3 реагують на корекцію - збільш їм штраф , якщо голова 2 співпажає з 1 або 3 - збільш штраф. навчання веди потім на змінній довжині вікна канви від 2 півотів і так постіпово до 8 півотів .... другу меду бери з кроком по 1 годині , якщо після правильного півота вийшов наступний сигнал голови меньше ніж крок2.3%-зони півотів - штраф великий. якщо в ціні зони півота є ще одна вершина що не позначена півотом а модель її відмітила - це вважається за правильну відповідь. довчи модель так.

> додай це - коли досягнеш 8 півотів - потім рухай лівий край по годині поки не досягнеш 2 півотів у вікні , потім повернись до початкового півота та рухай по кроку розміром по 2 півоти у перед з мінімальним кроком (одна подія квнви ), потім таксамо додаючи по пів півота в канву і ак до 8 потім на один пів  півота вправо вікно канви 1100 з (2 півотів матиме 1 півот у вікні канви) і далі все знову весь цикл, а потім знову на пів півота рух і так двалі!  .

1. **Ряд** — записи 100 с етапу 6, ноги зігзага 2.3, півоти й корекції
   0.8 із зонами — ті самі, що в етапах 6–8; train до 14.08, val 14.08 …
   22.09, шість монет.
2. **Сітка пів півота** `q` — півоти 2.3 і середини між сусідніми
   півотами. Розмір вікна — у пів півотах: вікно з якоря `qⱼ` розміром
   `k` півотів кінчається на `qⱼ₊₂ₖ₋₂` (з якоря-півота розмір 2 — до
   наступного півота, 2 півоти у вікні; з якоря-середини — 1 півот).
   Лівий край — якір мінус ширина в часі зони останнього півота не пізніше
   якоря, не менше години.
3. **Цикл вікна** на кожному якорі:
   - **ріст** — лівий край на місці, правий щогодини (36 записів) від
     розміру 2 до 8 півотів;
   - **стиск** — правий край на розмірі 8, лівий щогодини вправо, поки у
     вікні не лишиться 2 півоти;
   - **ковзання** — повернення на якір; вікно розміром 2, 2.5 … 8 півотів
     сунеться вправо кроком в один рядок канви (записів вікна / 1100, не
     менше запису), поки лівий край не дійде до лівого краю наступного
     якоря;
   - далі якір на пів півота правіше — той самий цикл.
   Повний цикл — 4.7 млн вікон train і 1.2 млн val (ковзання — 90 %);
   канви будуються на рівній вибірці: 60 000 вікон train і 12 000 val на
   фазу, порівну на монету, вид якоря (півот / середина) і сходинку
   (розмір), seed 0. Канва 1100 — `canvas1100.canvas_of`, float16.
4. **Підтвердження** — півот 2.3 є міткою, лише коли до правого краю
   вікна `close` відійшов від нього на 2.3 % у зворотний бік; корекція 0.8
   — на 0.8 %. Непідтверджені — поза втратою і мірою всіх голів.
5. **Три голови** на рядок: `0` — вершина 2.3 (продаж), `1` — корекція
   0.8, `2` — дно 2.3 (купівля). Код рядка на кожну голову:
   | Код | Де | Вага у втраті |
   | --- | -- | ------------- |
   | `POS` | зона свого класу: вершина / корекція, що не півот / дно | окреме середнє |
   | `SWAP` | голова вершини чи дна на зоні корекції; голова корекції на зоні півота 2.3 | 3 |
   | `REPEAT` | голова вершини після підтвердженої вершини — від кінця її зони до наступного півота (дна); так само голова дна після дна: до протилежного півота нової вершини бути не може | 6 |
   | `ALT` | інша вершина в ціні зони півота: рядок між сусідніми півотами, чий `high` (для дна `low`) у ціновій смузі зони (10 % ціни попередньої ноги) і найвищий (найнижчий) у ±10 рядках | 0, сигнал — добрий |
   | `NEG` | решта живих рядків | 1 |
   | `IGNORE` | мертвий рядок; зона непідтвердженого чи захованого за вікном півота | 0 |
   Пріоритет: `POS` > `ALT` > `SWAP` > `REPEAT` > `NEG`.
6. **Втрата** на кожну голову: BCE — середнє на рядках `POS` плюс зважене
   середнє на решті живих рядків за вагами коду (вага `POS` тут не діє),
   плюс `1 − soft dice` по канві; середнє трьох голів. Зона свого класу —
   1.4–1.8 % живих рядків, `REPEAT` — 30–37 %: у спільному зваженому
   середньому (як у `dice` етапу 8) голови вершини й дна за дві епохи
   падають у нуль.
7. **Старт** — ваги `B_tune` етапу 8: вершина і дно — з виходу півота 2.3,
   корекція — з виходу корекції; вихід боку не переноситься.
8. **Навчання за циклом** — 42 сходинки в порядку циклу: якорі-півоти
   (ріст 2 … 8, стиск, ковзання 2 … 8 з кроком пів півота), потім те саме
   на якорях-серединах; на сходинку — епоха з 2000 вікон: половина — нова
   сходинка, половина — порівну з пройдених. Далі весь цикл разом: до 10
   епох по 4000 вікон порівну з усіх сходинок, стоп після 3 без
   покращення; найкраща епоха — з цієї частини. Adam lr 1e-4, батч 8
   кусками по 4, seed 0.
9. **Розбиття по часу** — різ монети на півоті ⌊0.8 · півотів train⌋:
   навчання — вікна, що кінчаються до різу, відкладені — що починаються
   після. Між епохами — сталі 350 відкладених вікон на фазу × вид якоря:
   пороги голів (0.05 … 0.95) і епоха за середнім F1 трьох голів; val —
   сталі 250 вікон на фазу × вид якоря.
10. **Міра** на голову: сигнал — пік ≥ порогу в ±10 рядках; добрий — на
    `POS` чи `ALT`; повнота — частка підтверджених зон свого класу з
    сигналом; F1; окремо — сигнали на `SWAP` і `REPEAT`. Базовий прогноз —
    стільки ж сигналів на випадкових живих рядках. val — усі побудовані
    вікна, по монетах, фазах, видах якоря і числу півотів у вікні.

## Випадкові вікна від 1 до 8 півотів

Етап 12, [`scripts/canvas1100_random.py`](scripts/canvas1100_random.py).

> як завершиш навчання - додасиш цю модель на дашборд кнопкою для вибора - краще і ще по одній злвав та справа від кращої, потім наріжеш з трейн датасету рендомом вікна щоб вміщали від 1 до 8 півотів і будеш вчити на рендомних вікнах - тобто формувати канву 1100 на рендомних вікнах - головне бери їх для подачі з різних частин датасету щоб не разом - тіпа шафл і так бери рендомні шматки данних від 1-2 півота до 8 - це дуже великий датасет і ти його вчи , рендомом це мільйони даних і різних за довжиною вікон! - найкращі 3 - кнопками на дашборд

1. **Ряд, мітки, втрата** — етапу 11: записи 100 с, півоти 2.3 і
   корекції 0.8 етапу 6, коди рядків трьох голів `codes_of` (вершина,
   корекція, дно; `SWAP`, `REPEAT`, `ALT`, підтвердження до правого
   краю), `loss_of`.
2. **Випадкове вікно** — число півотів `N` рівно з тих 1 … 8, що
   вміщаються в шматок, початок — випадковий запис, після якого в шматку
   є ще `N` півотів, правий край — випадковий запис між `N`-м і `N + 1`-м
   півотом після початку: у вікні рівно `N` півотів. Канва 1100 з
   секунд будується щоразу нова, вікна не повторюються.
3. **Подача** — 2 процеси: процес бере випадкову монету (вага — довжина
   її частини) і випадковий шматок 12 діб, читає його секунди раз і ріже
   з нього 32 випадкові вікна, далі — новий шматок. Головний процес
   тримає буфер на 1024 вікна і бере з нього випадково: у батчі — вікна
   з десятків різних шматків різних монет.
4. **Розбиття** — навчання: train до різу монети етапу 11; відкладені —
   сталі 2100 випадкових вікон після різу; val — сталі 2100 випадкових
   вікон val (seed 12).
5. **Навчання** — з найкращої епохи `G_tune` етапу 11; епоха — 20 000
   свіжих вікон; після епохи пороги голів на відкладених, міра на
   відкладених і val; стоп після 4 епох без покращення середнього F1
   трьох голів на відкладених, стеля 30 епох. Adam lr 1e-4, батч 8
   кусками по 4, seed 12.
6. **Міра** — етапу 11; три найкращі епохи міряються ще й на всіх вікнах
   циклу val етапу 11 — поряд із `G_tune`; ці три епохи — кнопками на
   дашборді.

## Вікна з одним півотом

Етап 13, [`scripts/canvas1100_random.py`](scripts/canvas1100_random.py) `--n 1 1`.

> Спробуу будьякі вікна з одним півотом

1. Хід етапу 12, вікно — рівно з одним півотом 2.3: початок — випадковий
   запис, після якого в шматку є півот; правий край — випадковий запис
   між цим півотом і наступним. Тобто лівий край — будь-де між попереднім
   півотом і цим, правий — будь-де між цим і наступним.
2. Сталі вікна — теж з одним півотом: відкладені `held_n1-1`, val
   `val_n1-1`, по 2100 (seed 12).
3. Старт — найкраща епоха `R_tune` (епоха 1); решта — як в етапі 12.
   Три найкращі епохи міряються й на всіх вікнах циклу val етапу 11
   (там окремо — група вікон з одним півотом) і йдуть кнопками на
   дашборд.

## Вікна рівномірної довжини

Етап 14, [`scripts/canvas1100_random.py`](scripts/canvas1100_random.py) `--length`.

> Тоді довчай- роби шафл вікон різної довжини в нашому контексті головне щоб розподділ був рівномірний…. Роби

> Результат кнопокд. На графік дашборда

1. Хід етапу 12, інший вибір вікна (`pick_by_length`): довжина `L` —
   рівно з 36 записів (1 год) … довжини шматка (12 діб), початок —
   випадковий; вікно береться, коли в ньому від 1 до 8 півотів. Для тієї
   самої `L` пробується до 40 початків, лише тоді тягнеться нова довжина —
   довжини взятих вікон лишаються рівномірними там, де 1 … 8 півотів
   вміщаються. Число півотів у вікні — яке випаде.
2. Сталі вікна тим самим вибором: відкладені `held_len`, val `val_len`, по
   2100 (seed 12).
3. Старт — найкраща епоха `R_tune`; решта — як в етапі 12. Три найкращі
   епохи — на циклі val етапу 11 і кнопками на дашборді.

## Найкраща довжина вікна

Етап 15, [`scripts/canvas1100_length.py`](scripts/canvas1100_length.py).

> вибери ткремо на трейн та вал найкращу довжину вікна

> в годинах для яких канвас 1100 працює краще всього

> тільки ця мережа (`RL_tune` · e19 ★)

1. Модель — `RL_tune` е19, пороги голів — її відкладених.
2. Вікна — рівномірної довжини вибором етапу 14 (`pick_by_length`, 1 год
   … 12 діб, 1 … 8 півотів): train — 2100 нових сталих вікон зі шматків
   train до різу, на яких модель училась (`train_len`, seed 12); val —
   `val_len` етапу 14.
3. Міра етапу 11 на кожному вікні; вікна діляться за довжиною на кошики
   по 24 години; у кошику — F1 трьох голів і середній F1. Найкраща
   довжина — кошик з найбільшим середнім F1, окремо на train і на val.

## Зона півота 2.3 % у момент T

Етап 16, [`scripts/canvas1100_future.py`](scripts/canvas1100_future.py),
[`scripts/canvas1100_future_net.py`](scripts/canvas1100_future_net.py),
перевірка входу — [`scripts/side_leak.py`](scripts/side_leak.py).

**Назва моделі** (прогін `Z_base`, епоха 8): повна — «ідентифікатор
поточного півота 2.3 % канвас 600 вікна до 160 годин», скорочено —
`канва600півот2.3%ідентифікатор`.

> … беремо вікно канва 1100  по 160 годин , всі дані що в плашках під графіком (три видачі моделі моделі етапів 11–12 ) дві голови моделі етапу 8 та P(кластер 2) і голова «бік ноги». ці 7 даних подаєш в канва 1100-7-160 , ця канва подається на трансформер …

> 7 │ голова «бік ноги» │ … з ем 200

> обовьязково передивись чи нема заглядання вперед

> тоді давай хай тасама архіткуткура і дані на мережу подаються і кажуть наступне: зона півота чи ні .

> півота 2.3 % маю на увазі

1. **Перевірка голови «бік ноги» на заглядання вперед** (`side_leak.py`).
   Копія продовжених датасетів усіх монет обрізається в момент `T` (усі
   події val і test пізніше `T` прибрано, train — як є), на ній
   проганяється весь ланцюжок `heads33_run --holes` — так голова
   виглядала б наживо в `T`; на спільних подіях до `T` вона
   порівнюється з готовим рядом `results/heads33_holes/`. Чотири
   моменти BTC: 04.09 18:00 і 05.09 22:00 (середина ноги), 11.09 01:00 і
   03:00 (година й три після півота 11.09 00:00, підтвердженого ема10
   лише о 14:12).
2. **Моменти T** — щогодини на записах 100 с кожної монети, окремо train
   і val; вікно `[T − 160 год, T]`, потрібні повні 160 год до T і 40 год
   після — запас, за який зона півота біля T стає відомою.
3. **Канва 1100 × 7** — на вікні канва 1100 ходом «канви руками»
   (`canvas1100.canvas_of`), на ній сім каналів:

   | № | Канал | Звідки |
   | - | ----- | ------ |
   | 1 | P(вершина 2.3) | `RL_tune` е19 (етап 14) |
   | 2 | P(корекція 0.8) | `RL_tune` е19 |
   | 3 | P(дно 2.3) | `RL_tune` е19 |
   | 4 | P(півот 2.3) | `B_tune` (етап 8) |
   | 5 | P(корекція 0.8) | `B_tune` |
   | 6 | P(кластер 2) = 1 − p | правило кластера 1 на канві 600 того самого вікна (записи 30 с), рядок бере рядок канви 600, що закінчився не пізніше його кінця |
   | 7 | голова «бік ноги», ема 200 по подіях | ряд `results/heads33_holes/`; рядок бере останню подію з видачею не пізніше свого кінця **мінус година** |

   Мертві рядки — нулі; стовпця маски у вході немає.
4. **Мітка** (`zone_of`) — запис T (записи 100 с) у зоні півота
   зігзага 2.3 %: до півота не далі за `span` записів (5 % тривалості
   ноги) і ціна не далі за `zone` (10 % ціни ноги) за його бік — та сама
   зона, що в `canvas600_data.zone_rows`; півоти й зони —
   `canvas1100_random.series_of`.
5. **Трансформер** (`Future`) — латки по 10 рядків (110 токенів × 70
   чисел → 64), позиція навчається, токен CLS, 3 шари енкодера, 4 голови
   уваги, dropout 0.1; мертві латки закриті маскою ключів; один логіт.
6. **Навчання** — BCE, Adam 3e-4, батч 64, seed 16; train — моменти до
   80 % часу train кожної монети, відкладені — після, з проміжком 200 год
   (вікно + запас); епоха — за AUC на відкладених, терпіння 4, стеля 30;
   поріг — з найкращим F1 на відкладених.
7. **Міра на val** — AUC, точність, повнота і F1 при порозі відкладених;
   база — частота зони і F1 відповіді «завжди так».
8. **Контроль** (`controls`) — одне число з останніх 10 рядків тієї самої
   канви без навчання: найбільша P(півот) `B_tune`, найбільша з
   P(вершина) і P(дно) `RL_tune`, 1 − середня P(кластер 2); AUC на train і
   val.

## Торгівля на val за зоною півота

Етап 17, [`scripts/canvas1100_zone_trade.py`](scripts/canvas1100_zone_trade.py).

> новий розділ - без підглядання в перед - симулюєш торгівлю на вал . біткоїн - сделки гна графіку відкладаєш - намалюеш лінію і кнопку вперед - коли вона в ріалтаймі буде отримувати вал данні і показувати півот =- не півот. 
> алгоритм торгівлі - отримуеш сигнал півот2.3% - дивишся в минуле - то була нога вверх на 2.3%+ чи вниз (тобто чи був попередній півот нище чи вище поточного на 2.3% ), якщо півота нема - рахуеш просто різницю ціни що було раніше - до поточного - падіння або зростання 2.3 - в результаті вирішуєш : купити чи продати з цієї точки - малюєш на графіку лінію зєднуеш початок з закриттям сделки - закриваєш на наступному півоті якщо сигнал півота є а ціна не пройшла 2.3% - то ложний півот - ігнориш його, якщо був півот але нога продовжтлась - відмічаеш новий півот на графіку, сделку не міняеш (сделку завжди від точки покупки відображай)

1. **Сигнал** — видача мережі етапу 16 `канва600півот2.3%ідентифікатор` (`Z_base`, епоха 8) на кожен
   момент T val кожної з шести монет щогодини: P(T у зоні півота) ≥ 0.05 (поріг з
   відкладених train) — «півот», інакше «не півот». Вхід мережі в T —
   лише дані до T.
2. **Роль сигналу** (`decide`) при ціні `p` (close запису T) і
   останньому прийнятому півоті `R`:
   - `R` немає — `p` вище найменшого close від початку val на 2.3 % і
     більше — нога була вгору, вершина; нижче найбільшого на 2.3 % і
     більше — дно; інакше — хибний півот;
   - `R` — дно: `p ≥ R · 1.023` — вершина; `p < R` — нога вниз
     продовжилась, нове дно (позначка, `R` = нове дно, угода та сама);
     інакше — хибний півот, ігнор;
   - `R` — вершина: дзеркально.
3. **Угода** — на вершині продаж (коротка), на дні купівля (довга);
   півот протилежного боку закриває угоду і відкриває зворотну в той
   самий момент; продовження ноги угоди не міняє — угода завжди від
   точки входу. Стоп-лосу в алгоритмі немає.
4. **Виконання** — ціною open наступного запису 100 с після T, комісія
   0.05 % і сліпедж 0.02 % за бік, гроші — `Decimal`, старт $1000;
   відкрита угода закривається на останньому записі val. Порівняння —
   «купив і тримав» тим самим механізмом.
5. **Метрики** — гроші в кінці, PnL, угоди, частка прибуткових, середня
   угода, найбільша просадка кривої грошей, Sharpe (щогодинна крива,
   річний масштаб).

## Півот 2.3 раніше за зігзаг

Етап 18, [`scripts/canvas1100_early.py`](scripts/canvas1100_early.py),
живий ряд голови «бік ноги» — [`scripts/heads33_run.py`](scripts/heads33_run.py)
`--live`, перевірка — [`scripts/side_leak.py`](scripts/side_leak.py) `--live`.

**Назва моделі** (прогін `E_tune`, епоха 11, вікно 300 год): повна —
«виявлення півота 2.3 % канва 1100 × 9 до 300 годин», скорочено —
`виявленняпівота2.3`.

> що думаєш на рахунок навчання мережі яка має одну голову і її головна
> ціль - якумога швидше знайти півот у канві, таким чином підтвердити що
> то півот до того як алгоритм зігзаг зможе це зробити

> ти береш канву 1100 - її мережу з 3 голови там де вікно 160 - було
> оптимальне - та замвсть 3 голоів робиш одну - потім доачаеш ваги
> мережі - починаеш з вікна наприклад 40 годин і грід вікн по 10 годин до
> 300 годин , авікно просукаеш зкроком в 10 хвилин на трейн датасеті і
> воно має сказати де зона пвота 2.3% якумога швидше коли ця зона
> попадає у вікно … подвати йоск щк 2 фічі: кластер 2 та голову бік ноги
> без ема … півот заходить справа в канву 1100 і мережа починає видавати
> дані - якщо виявила швидко - штраф малий, якщо виявляла довшк- штраф
> піднімати

> прибери затримку зовсім . ну і вчи нову модель - видачу на вал -
> найкраще вікно, найкращу модель , і з механізмом де модель рахує і
> постійно просуває вікно на 10 хвилин правомуч - і відображає на плашці
> знизу одразу. … головне щоб без занлядання в перед.

1. **Голова «бік ноги» без затримки і без заглядання** — живий ряд
   `heads33_run.py --live` (`results/heads33_live/`), дві зміни проти
   `--holes`:
   - **мережа зон дослідження 31 бере ноги від 1 події**
     (`leg_common.MIN_LEG`). Затримка в годину етапу 16 була не в голові,
     а тут: ноги коротші за 20 подій у мережу не йдуть, і відкрита нога
     після останнього екстремуму, поки коротша, наживо лишалась без
     видачі;
   - **кеш ніг мережі `split` — без стелі довжини**
     (`legleft_data.LENGTH`). Стеля в 3000 подій рахується від **кінця**
     ноги: на довгій нозі з історією готовий ряд зрізав її початок і
     починав памʼять `split` з місця, яке залежить від того, де нога
     скінчиться. Наживо кінця ще немає — числа розходились (ETH 19.08:
     до 0.076);
   - **видача hazard відкрита, поки у val немає півота**
     (`heads33_run.open_known`). Крива hazard причинна на кожній події, а
     маска «відстань до півота відома» на val відкривалась лише після
     першого півота val: наживо до нього (DOGE до 20.08) голова мовчала,
     а готовий ряд видачу мав. Готовий ряд від цього не змінюється.
2. **Перевірка на заглядання вперед** (`side_leak.py --live`) — усі
   датасети обрізаються в T **повністю**, і train теж: датасети
   `клас210х14х*` мережі hazard перемішані по train / val / test за
   часом, і в заміру етапу 16 їхній train ішов цілим. На обрізаній копії
   проганяється весь ланцюжок `heads33_run --live` і порівнюється з
   готовим рядом на подіях до T. Моменти — усередині найдовшої ноги val
   кожної монети (70 % і 95 % її тривалості: там спрацьовувала стеля),
   один момент через 20 хв після півота val кожної монети, обидва моменти
   ETH 19.08, на яких знайшлась стеля, і BTC 30.08 17:18.

3. **Ряд монети** — записи 100 с train і val підряд, зігзаг 2.3
   (`canvas1100.legs_of`), півоти, зони й корекції 0.8 по всьому ряду;
   **підтвердження зігзагом** — перший запис після півота, де `close`
   відійшов на 2.3 % у зворотний бік.
4. **Момент T** — кінець запису на сітці 10 хв; вікно `[T − L, T]`, `L`
   40 … 300 год кроком 10. Канва 1100 закінчується в T. Секунди
   читаються із запасом 3 год за кінцем вікна (`seconds_of`): добові
   файли робочої копії названі за місцевою датою, файл дати D
   починається о 21:00 чи 22:00 UTC дати D − 1, і `bars30.read_seconds`,
   що бере файли за датою UTC, без запасу губить до 3 год найсвіжіших
   секунд, коли вікно кінчається пізніше 21:00 UTC. Канва бере лише
   секунди до T — запас у неї не потрапляє.
5. **Вхід 1100 × 9**: 7 фіч `клас210х10-1х7д/д` канви (нормування лише на
   канву); P(кластер 2) з канви 600 того самого вікна (записи 30 с);
   голова «бік ноги» сира, без ема — рядок бере останню подію, чия видача
   готова до кінця рядка: початок події + 315 с (подія 210 с і пів події,
   на яку дослідження 33 зводить видачі сусідніх мереж). Мертві рядки —
   нулі, стовпця маски немає.
6. **Мітка рядка** — зона півота 2.3 (`label_rows`), **підтверджений він до
   T чи ні**; зона зʼявляється, коли запис півота зайшов у вікно справа.
   Корекція 0.8 — окремий код, тіло — негатив.
7. **Штраф за пізнє виявлення** — вага рядка зони півота
   `1 + 1 · min(вік, 6 год)`, вік — години від запису півота до T: щойно
   зайшов — пропуск коштує 1, через 6 год — 7. Корекція — вага 3, тіло —
   1. Втрата — BCE (середнє на зоні плюс середнє на решті з вагами) плюс
   `1 − soft dice`.
8. **Мережа** — `Finder3` мережі `RL_tune` е19 (етап 14) на 9 каналів і
   1 вихід: стовпці нових каналів у першому шарі — нулі, вихід — середнє
   виходів вершини й дна. На старті мережа видає те саме, що `RL_tune`.
9. **Розбиття** — різ етапу 11 (півот ⌊0.8 · півотів train⌋): навчання —
   T до різу мінус 40 год (мітки біля T встигли стати відомими);
   відкладені — вікна цілком після різу, T до 14.08; val — T від 15.08
   00:00 UTC (мережа hazard під головою вчилась до 14.08 15:27, її мітки
   дивляться вперед на ~100 подій) до кінця ряду мінус 40 год. Вікно val
   може заходити в train — це лише вхід.
10. **Навчання** — потік випадкових пар (T, L) з шматків по 16 діб train
    (2 процеси, 32 вікна на шматок, буфер 1024), епоха 12 000 вікон,
    Adam lr 1e-4, батч 8 кусками по 4, seed 18, стеля 16 епох, стоп після
    3 без покращення. Епоха й поріг — за середнім F1 на сталих відкладених:
    T щогодини, вікна 80, 160 і 240 год.
11. **Міра**: сигнал — пік ≥ порогу в ±10 рядках; **свіжий** сигнал — на
    рядку, що закінчився за останню годину перед T, точність — частка
    свіжих сигналів у зоні півота; півот **виявлено** в T, коли в канві T є
    сигнал на рядку його зони; **раніше за зігзаг** — виявлено не пізніше
    за підтвердження зігзагом; F1 — з точності й частки «раніше за
    зігзаг»; затримка мережі й зігзага від запису півота, випередження в
    годинах і відкат ціни від півота в момент виявлення.
12. **Контролі** — `RL_tune` е19 без довчання (P = більша з вершини й дна,
    свій поріг на відкладених) і випадкові сигнали: стільки ж свіжих
    сигналів на випадкових свіжих рядках кожного T (seed 18).
13. **Найкраще вікно** — грід 27 вікон на відкладених, T щогодини: на
    кожному вікні і мережа, і контроль `RL_tune` беруть свій поріг з
    найбільшим F1 на відкладених; найкраще — вікно з найбільшим F1 мережі.
    val — усі вікна щогодини з порогами свого вікна і найкраще вікно кожні
    10 хв (відкладені теж) з контролями; ряд val найкращого вікна кожні
    10 хв — для вкладки, її жива канва бере поріг найкращого вікна.

## Півот на купівлю: зона дна 2.3 % лише на train BTC

Етап 19, [`scripts/canvas1100_buy.py`](scripts/canvas1100_buy.py).

> зроби мені мережу таку: навчена на тільки біткоїн трейн датасеті, 160
> годинне вікно канвас 1100, ціль — ідентифікація півота на покупку,
> датасет — вхід: канва 1100 × 8, що закінчується в момент T: 7 фіч
> клас210х10-1х7д/д; P(кластер 2); — рахуєш тільки на трейн

> кластер 2 — на трейн 80 % ці — навчання — перші 80 % часу

> мінімальна тривалість ноги 7 годин — видали всі що коротші

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

1. **Дані** — тільки BTC_USDT, тільки train (до 14.08.2026): записи 100 с,
   записи 30 с, ноги й півоти train (`canvas1100_random.series_of`). Val
   та інші монети не беруться ні в навчання, ні в замір.
2. **Моменти T** — кінець запису на сітці 10 хв з повними 160 год до T і
   40 год після (запас, за який зона біля T стає відомою).
3. **Розбиття за часом** — межа на 80 % часу між першим і останнім T
   (08.07.2026 20:24 UTC): **навчання** — T до межі мінус 200 год
   (160 год вікна + 40 год запасу), 21.02 10:00 … 30.06 12:20, 15 878 T;
   **відкладені** — T від межі, 08.07 20:30 … 12.08 05:00, 4 445 T.
   Моменти проміжку не беруться ніде: канви відкладених не лягають на
   години навчання, а мітки навчання не дивляться у відкладені.
4. **Кластер 2 — лише на навчальній частині** (`--cluster`). Канви 600
   етапу 1 тільки BTC, що закінчуються не пізніше останнього навчального
   T (1076 канв, базових 88), і на них увесь хід етапу 1 заново:
   грід уточнювача 1920 варіантів (`canvas600_signal.grid` / `pick`),
   уточнені сигнали базових канв, UMAP (cosine, `n_neighbors 15`,
   `min_dist 0.1`, seed 36), k-means на 2 кластери (`n_init 10`, seed 36;
   кластер 1 — де більша частка початків і кінців ноги), правило
   кластера 1 — логістична регресія на 21 числі `|x|` вікна `пік ± 1`
   (C = 1, seed 36). P(кластер 2) = 1 − p правила ковзним вікном з 3
   рядків канви 600 (`canvas600_c1.rule_rows` / `cover`). Правило
   лежить у `models/canvas1100_buy/assigner.json`, карта —
   `results/canvas1100_buy/cluster.json`.
5. **Канва 1100 × 8** (`--build`) — вікно рівно 160 год, що закінчується
   в T (`canvas1100.canvas_of`): 7 фіч `клас210х10-1х7д/д`, нормування
   лише на канву; 8-й канал — P(кластер 2) з канви 600 того самого
   вікна, рядок бере рядок канви 600, що закінчився не пізніше його
   кінця. Мертві рядки — нулі, стовпця маски немає. Канви — `float16`
   у `data/canvas1100_buy/x.npy`.
6. **Мітка** — запис T у зоні **дна** 2.3 % (півот на купівлю): до дна не
   далі за `span` записів (5 % тривалості ноги) і ціна не вище дна
   більше ніж на `zone` (10 % ціни ноги) — `canvas1100_future.zone_of`
   на днях **лише ніг ≥ 7 год** (`long_bottoms`: дно лишається, коли хоч
   одна з двох його ніг не коротша за 7 год). Дна коротших ніг і зони
   вершин — негатив. Ціна може вийти із зони і повернутись у межах
   `span`, тому зона дна — кілька шматків записів (`pivot_zones`); саме
   ці шматки — жовті зони на вкладках. Мітки готових канв перераховує
   `--labels`. Train: навчання — 318 T у зоні, відкладені — 45 (5 днів);
   на 63 днях 2.3 train — 210 шматків, усі 363 T з міткою лежать у них і
   жодна T у них не лишилась без мітки.
7. **Мережа** — трансформер `Future` етапу 16 на 8 каналів, з нуля (без
   чужих ваг): латки по 10 рядків (110 токенів × 80 чисел → 64), вивчена
   позиція, токен CLS, 3 шари енкодера, 4 голови, dropout 0.1, один
   логіт; мертві латки закриті маскою ключів.
8. **Навчання** — Adam 3e-4, батч 64, seed 19; епоха — усі навчальні T у
   випадковому порядку. **Функції втрат** (`--loss`, по одному прогону
   `BUY_<втрата>`): `bce` — BCE; `pos` — BCE з вагою позитиву = негативів
   / позитивів навчання; `focal` — focal loss (γ 2, α 0.25); `dice` — BCE
   + (1 − soft dice) на батчі. `far` — BCE з вагою прикладу, **чим далі хибний
   сигнал від цілі, тим дорожчий**: позитив — 1, негатив —
   `1 + 4 · min(d / 48 год, 1)`, `d` — години від T до найближчого
   шматка зони дна (`distance_of`, `far_weight`), середнє зважене
   (Σ w·ce / Σ w); `far` донавчає кращу модель (`--init BUY_bce:16`, lr
   1e-4) — стартова епоха 0 міряється тим самим ходом і може бути
   обрана, стопу до 12-ї епохи при донавчанні немає. `ladder` — драбина
   штрафу: зона дна цілком (від першого шматка до останнього) ± 2 год —
   попадання, сигнал там не штрафується (вага 0); відрізок між попередньою
   і поточною зоною (від кінця попередньої + 2 год до початку поточної −
   2 год) ділиться на 10 рівних частин від поточної: ×2, ×4, … ×20 біля
   попередньої; до першої зони й після останньої — вага 0; мітка 1 — ×1
   (`ladder_weight`). `ladder2` — те саме, але **ціль — зона дна цілком
   ± 2 год** (мітка 1 на всю цю смугу, `wide_labels`; нею ж міряються
   відкладені й val), мовчання в цілі — `--silence` (×1 … ×10), частини
   між зонами — ×2, ×5, ×7, ×9, ×11, ×12, ×14, ×16, ×18, ×20
   (частини 2–5 на +1). **Стоп донавчання** — поки мережа вчиться: 3
   епохи підряд втрата навчання не падає хоча б на 1 % від найкращої,
   стеля 30; епоха — як і раніше, за F1 на відкладених. Хід `ladder2`
   (`scripts/buy_ladder2_grid.sh`): `BUY_l2` — донавчання `BUY_bce` е16
   з мовчанням ×1; далі гріда `BUY_l2s1` … `BUY_l2s10` — донавчання з
   обраної епохи `BUY_l2` з мовчанням ×1 … ×10. **Вибір епохи** — середня влучність (AP,
   площа під кривою точність — повнота) на відкладених: AUC вибирав
   епоху, де мережа ще не вчилась (стала видача з дрібними зсувами);
   терпіння 6, до 12-ї епохи стопу немає (у BCE мережа стоїть перші ~8
   епох), стеля 30. Поріг — найкращий F1 на відкладених (0.05 … 0.95
   кроком 0.05). Кращий прогін — найбільший AP на відкладених.
9. **Val BTC** (`--val`) — канви 1100 × 8 тим самим ходом на кожен T
   кожні 10 хв від 15.08 00:00 UTC до кінця ряду мінус 40 год (5265 T):
   канва бере хвіст train як історію (`series_full`), правило кластера 2
   — те саме, з навчальних 80 %; мітка — зони днів 2.3 ніг ≥ 7 год val
   (13 днів, 39 T у зоні). Видача кожної епохи на val пишеться в
   `results/canvas1100_buy/<прогін>_val.npz`; у вибір епохи й порогу val
   не йде.
10. **Міра** — на відкладених і на val при порозі відкладених: AP, AUC,
   точність, повнота, F1; база — частота зони (це ж AP випадкової
   відповіді) і F1 відповіді «завжди так»; поруч — скільки днів 2.3 дають
   зону (незалежні одиниці).

## Сигнал купівлі сумою у вікні і торгівля лише купівлями

Етап 20, [`scripts/canvas1100_buy_signal.py`](scripts/canvas1100_buy_signal.py),
тест — [`tests/test_canvas1100_buy_signal.py`](../../tests/test_canvas1100_buy_signal.py).

> береш всі моделі та епохи і підбираеш для кожної сигнал, сигнал це
> сума (може приріст — сам обирай) сигналів моделі у ковзному вікні, вікно
> і значення підбираеш, потім обираеш найкращу по результатах торгівлі та
> позначаеш і записуеш параметри для неї. обираеш так: береш ідеальну
> торгівлю по зігзагу як за еталон для кожної сделки. сделки тільки бай,
> хто ближче до еталона той і переміг. комісії по правилам проекту. …
> коли робиш сделку — памʼятаеш тільки бай по сигналу — ставиш
> тейкпрофіт через 2 %, стоплос — підбери сам. якщо ти купив і йдуть
> сигнали бай і ціна вище покупки — то добре — то підтвердження, якщо ти
> закрив сделку а сигнали бай йдуть і між поточним сигналом і попереднім
> пікова ціна меньша ніж на 2.3 % від ціни поточного сигналу — сигнал
> фейковий — ігноруй його.

> якщо ти зайшов в сделку по сигналу а ціна продовжила падати то
> тейкпрофіт переноситься на нову позицію 2 % відносно найнижчої ціни
> після сделки

1. **Видача** — P(T у зоні дна) кожної епохи кожного прогону етапу 19 на
   5265 T val BTC кожні 10 хв (`results/canvas1100_buy/<прогін>_val.npz`):
   18 прогонів, 450 епох.
2. **Сигнал** — сума видачі в ковзному вікні з `W` останніх кроків T:
   `S[k] = P[k − W + 1] + … + P[k]`; купівля — `S[k] ≥ θ`. Сума, а не
   приріст: приріст гасне на рівній серії високих P, а дно тримається
   серією. `θ` — квантиль `q` ряду `S` своєї епохи (шкали мереж різні).
3. **Угода** — лише купівля (довга). Сигнал у T без позиції — вхід ціною
   open наступного запису 100 с після T (`rules/04-trading.md` → Бектест).
   Тейк-профіт — найнижча ціна від входу (open входу і close записів після
   нього) × 1.02: ціна після входу падає — тейк спускається за нею, росте —
   тейк стоїть; стоп-лос — ціна входу × (1 − `SL`). Перший запис, чий
   close дійшов до рівня, закриває угоду ціною open наступного запису. Поки угода відкрита, сигнали купівлі — підтвердження,
   дій немає.
4. **Фейк** — коли вже є закрита угода і позиції немає: сигнал
   ігнорується, якщо найбільший close записів між попереднім сигналом
   (будь-яким, і під час угоди теж) і поточним менший за close поточного
   × 1.023. До першої угоди фейків немає.
5. **Витрати** — комісія 0.05 % і сліпедж 0.02 % за бік (ті самі, що в
   торгівлі етапу 17; у `rules/04-trading.md` значення — `TODO`); гроші —
   `Decimal`, старт $1000, кожна угода на всі гроші; угода, відкрита в
   кінці ряду, закривається close останнього запису.
6. **Еталон** — ідеальна торгівля лише купівлями по зігзагу 2.3 % ряду
   val (`canvas1100_random.series_of`): кожна нога вгору, що йде в межах
   T моделі (вершина після першого T, дно не пізніше останнього), —
   купівля open запису після дна (дно раніше першого T — після запису
   першого T), продаж open запису після вершини, ті самі витрати.
7. **Близькість до еталона** — кожна угода моделі належить циклу своєї
   ноги еталона: від попередньої вершини до вершини цієї ноги (за записом
   входу); угоди після останньої вершини — хвіст без еталона. Результат
   циклу — `∏(1 + r) − 1` угод у ньому, розрив — `R` еталона мінус
   результат. **Частка еталона** = (Σ результатів циклів + хвіст) / Σ `R`
   — більша частка = менший сумарний розрив = ближче до еталона. Рівні —
   більший PnL, далі менше угод.
8. **Грід** на кожній епосі: `W` ∈ {1, 2, 3, 6, 12, 18, 24, 36, 48, 72}
   кроків (10 хв … 12 год) × `q` ∈ {0.5, 0.7, 0.8, 0.85, 0.9, 0.93, 0.95,
   0.97, 0.98, 0.99} × `SL` ∈ {0.5, 1, 1.5, 2, 3, 4, 5} % — 700 комбінацій;
   найкраща комбінація епохи → найкраща епоха прогону. ★ зафіксований —
   `BUY_pos` е9, `W` = 18, `q` = 0.97, стоп 2 %: переможець цього гріду з
   тейком від ціни входу; з тейком від найнижчої ціни він міряється тими
   самими параметрами. ★ з тейком від найнижчої ціни — бот для експорту
   [`bot line 7.0`](../../bots/bot-line-7.0/bot-line-7.0.md). Підбір на val — `rules/03-models.md`: гіперпараметри підбираються по val.

## Живий час

Нові записи надходять → з останнього відрізка ряду будується канва 600
тим самим ходом → мережа розмічає рядки. Відрізок береться так, щоб у
нього потрапляв попередній знайдений півот 2.3: від цього півота мінус
поле до поточного запису. Так мережа бачить початок ноги, а в міру
надходження записів — її корекції і кінець, коли він настане.

## План

| Етап | Що | Статус |
| ---- | -- | ------ |
| 1 | Канва 600 і розмітка: датасет train/val з нормованою канвою, мітками рядків 0 / 1 / 2 і зсунутими вікнами; уточнення сигналу в зонах, кореляції частин, UMAP уточнених сигналів; ціна train кожної монети з зігзагом 2.3, зігзагом 0.8 і корекціями | `підтверджено`, 2026-09-25 |
| 2 | Мережа на три класи рядка на уточнених мітках зі штрафом за плутанину корекції з півотом і вікнами «корекція біля півота»: навчання, вибір епохи на відкладених, міри на val | `підтверджено`, 2026-09-25 |
| 3 | Валідація як на `/edges30`: ряд val з кнопками епох (★ ± 2) і «канва руками» — два кліки ставлять канву, краї перетягуються, під ціною — смуги півотів і корекцій | `підтверджено`, 2026-09-25 |
| 4 | Мережа кластера 1: правило кластера 1 на векторі сигналу, мітки рядків, навчання, міри на вікнах і ряді val | `підтверджено`, 2026-09-25 |
| 5 | Алгоритм на вікні канви: формула по фічах вікна з 3 рядків каже на кожному рядку «тіло / корекція / півот 2.3» (де корекція збігається з півотом — півот); та сама міра, що в мережі етапу 2 | `підтверджено`, 2026-09-27 |
| 6 | Канва 1100 на записах 100 с: датасет `клас210х10-1х7д/д` на записах 100 с усього train кожної монети, зігзаг 2.3 % (ноги ≥ 7 год), 4 ноги на 1000 рядках і по 50 за межами, UMAP півотів 2.3 і корекцій 0.8 | `підтверджено`, 2026-09-27 |
| 7 | Мережа на канві 1100 знаходить півоти 2.3: зсунуті канви, розбиття по часу, міра етапу 2 проти випадкових сигналів і позиційного прогнозу | `підтверджено`, 2026-09-27 |
| 8 | Три голови на канві 1100 — півот 2.3, корекція 0.8, бік (купити / продати); функції втрат; довші вікна (6 і 8 ніг); жива торгівля голови боку на val проти холду й випадкових перевертань | `підтверджено`, 2026-09-27 |
| 9 | Голова «бік ноги» дослідження 33 дорахована до 22.09 тим самим ходом і на тих самих вагах: продовжені датасети, видачі чотирьох мереж, шов, голова; перевірка збігу зі збереженим рядом 33 | `підтверджено`, 2026-09-27 |
| 10 | Скільки даних у вікні канви 1100: мапа всіх вікон val BTC, обхід «ріст правого краю, крок лівого» з гридом кроків, мінімальної довжини, падіння F1 і терпіння для голови півотів і голови корекцій; контроль — стале вікно | `підтверджено`, 2026-09-27 |
| 11 | Три голови — вершина 2.3, корекція 0.8, дно 2.3 — зі штрафами за плутанину з корекцією, за повтор після підтвердженого півота і з іншою вершиною в ціні зони як доброю відповіддю; довчання `B_tune` за циклом вікна: ріст від 2 до 8 півотів щогодини, стиск лівого краю до 2 півотів, ковзання розмірів 2 … 8 кроком у рядок канви, зсув якоря на пів півота | `підтверджено`, 2026-09-27 |
| 12 | Довчання `G_tune` на випадкових вікнах від 1 до 8 півотів з train: канва 1100 на льоту, шматки різних монет і частин ряду через буфер перемішування; три найкращі епохи — кнопками на дашборді | `підтверджено`, 2026-09-27 |
| 13 | Довчання `R_tune` на випадкових вікнах рівно з одним півотом: лівий край будь-де між попереднім півотом і цим, правий — між цим і наступним; три найкращі епохи — кнопками на дашборді | `підтверджено`, 2026-09-27 |
| 14 | Довчання `R_tune` на перемішаних вікнах рівномірної довжини (1 год … 12 діб) з 1 … 8 півотами; три найкращі епохи — кнопками на дашборді | `підтверджено`, 2026-09-27 |
| 15 | Найкраща довжина вікна канви 1100 у годинах для `RL_tune` е19 — окремо на train і на val, кошики по 24 години | `підтверджено`, 2026-09-27 |
| 16 | Зона півота 2.3 % у момент T: канва 1100 × 7 × 160 год з видач моделей етапів 8 і 14, кластера 2 і голови «бік ноги» (ема 200, перевірена на заглядання вперед) → трансформер: T у зоні півота чи ні | `підтверджено`, 2026-09-27 |
| 17 | Торгівля на val шести монет за сигналом «T у зоні півота 2.3 %» без заглядання вперед: вершина / дно за попереднім півотом, продовження ноги й хибні півоти, угоди лініями на графіку і кнопка «вперед» | `підтверджено`, 2026-09-29 |
| 18 | Півот 2.3 раніше за зігзаг (вкладка `/early`): голова «бік ноги» без затримки (живий ряд, перевірка повним обрізанням у T), одна голова з ваг `RL_tune` е19 на канві 1100 × 9 до T з кластером 2 і сирою головою боку, штраф за пропуск росте з віком півота, грід вікон 40 … 300 год, T кожні 10 хв, вкладка з вікном, що сунеться на 10 хв | `підтверджено`, 2026-09-29 |
| 19 | Півот на купівлю лише на train BTC: зона дна 2.3 % у момент T на канві 1100 × 8 з вікном 160 год (7 фіч класу + P(кластер 2), кластер 2 заново на навчальних 80 % BTC), трансформер `Future` з нуля; мітка — зони днів ніг ≥ 7 год; перебір функцій втрат (BCE, вага позитиву, focal, BCE + dice), епоха за F1 і поріг на відкладених 20 %; канви val BTC тим самим ходом і видача кожної епохи на val; вкладки `/buy` і `/buyval` | `підтверджено`, 2026-09-30 |
| 20 | Сигнал купівлі з видачі мереж етапу 19: сума P у ковзному вікні, вікно, поріг і стоп-лос підбираються на всіх епохах усіх прогонів торгівлею лише купівлями на val BTC — тейк 2 % від найнижчої ціни після входу, сигнали при відкритій угоді — підтвердження, після закритої угоди сигнал без підйому 2.3 % між сигналами — фейк; найкращий — найближчий до еталона, ідеальної торгівлі купівлями по зігзагу 2.3 %; блок на вкладці `/buyval` | `підтверджено`, 2026-09-30 |

## Скрипти

| Скрипт | Що робить | Вихід |
| ------ | --------- | ----- |
| [`scripts/canvas600_data.py`](scripts/canvas600_data.py) | етап 1: вікна, канва 600 × 7, корекції 0.8, мітки рядків і перелік зон; `--marks` — півоти 2.3 і корекції ряду train для графіка; етап 3: `--series` — ковзні вікна ряду val | `data/canvas600/<part>_x.npy`, `<part>.npz`, `<part>_zones.npz`, `build.json`; `results/marks/<PAIR>_train.npz` |
| [`scripts/canvas600_signal.py`](scripts/canvas600_signal.py) | етап 1: уточнення сигналу — грід, кореляції частин, уточнені мітки, профіль фіч, UMAP | `data/canvas600/<part>_refined.npy`, `results/canvas600.json`, `results/canvas600_umap.json` |
| [`scripts/valboard.py`](scripts/valboard.py) | вкладка `/valboard`: усі видачі на відрізку val — кластери 1 і 2 і півоти 2.3, мережа повноти ноги дослідження 35, ряд голів дослідження 33 | — (рахує на запит) |
| [`scripts/canvas600_c1.py`](scripts/canvas600_c1.py) | етап 4: `--labels` — правило кластера 1 і мітки рядків; навчання; `--outputs` — ряд val | `data/canvas600/<part>_c1.npy`, `<part>_c1_owner.npy`; `models/canvas600_c1/`; `results/canvas600_c1.json`, `results/c1/series_<PAIR>_eNN.npz` |
| [`scripts/canvas1100.py`](scripts/canvas1100.py) | етап 6: записи 100 с, датасет класу, ноги 2.3 і корекції 0.8, канва 1100 на 4 ноги, уточнений сигнал подій, UMAP | `data/canvas1100/<PAIR>_train.npz`, `legs.json`, `train_x.npy`, `train.npz`; `results/canvas1100.json` |
| [`scripts/canvas1100_net.py`](scripts/canvas1100_net.py) | етап 7: мережа на зсунутих канвах 1100 — зона півота 2.3 на кожному рядку, епоха й поріг на відкладених, міри на val проти випадкових сигналів | `models/canvas1100/epoch_NN.pt`, `history.json`; `results/canvas1100_net.json` |
| [`scripts/heads33_data.py`](scripts/heads33_data.py) | етап 9: `клас210х14х4ц` до 22.09 (`BTC_USDT_29`, `<PAIR>_fill`) штатними будівниками `rules/scripts` | `data/datasets_ext/<набір>/class210x14x*` |
| [`scripts/heads33_run.py`](scripts/heads33_run.py) | етап 9: видачі мереж 20, 31, 32 і голова 33 на продовженому ряді зі збереженими вагами, шлях до даних перенаправлено в памʼяті процесу; звірка з рядом 33; етап 18: `--live` — мережа зон на ногах від 1 події | `results/heads33/`, `results/heads33_live/` |
| [`scripts/canvas1100_heads.py`](scripts/canvas1100_heads.py) | етап 8: три голови, 4 функції втрат (коло A), суміш 4 / 6 / 8 ніг з нуля і довчанням (коло B) | `models/canvas1100_heads/<прогін>/`, `results/canvas1100_heads/<прогін>.json` |
| [`scripts/canvas1100_window.py`](scripts/canvas1100_window.py) | етап 10: `--map` — мапа вікон val BTC з лічильниками обох голів; `--grid` — обхід і стале вікно | `data/canvas1100_window/BTC_USDT_map.npz`; `results/canvas1100_window_BTC_USDT.json` |
| [`scripts/canvas1100_grow.py`](scripts/canvas1100_grow.py) | етап 11: `--build` — цикл вікна і рівна вибірка канв з кодами рядків трьох голів; `--run` — довчання за циклом, міра на val | `data/canvas1100_grow/<part>_*.npy`; `models/canvas1100_grow/<прогін>/`; `results/canvas1100_grow/<прогін>.json` |
| [`scripts/canvas1100_random.py`](scripts/canvas1100_random.py) | етап 12: `--fixed` — сталі випадкові вікна відкладених і val; `--run` — довчання на потоці випадкових вікон, три найкращі епохи на циклі val етапу 11; етап 13: `--n 1 1` — вікна рівно з одним півотом; етап 14: `--length` — вікна рівномірної довжини | `data/canvas1100_random/`; `models/canvas1100_random/<прогін>/`; `results/canvas1100_random/<прогін>.json` |
| [`scripts/canvas1100_length.py`](scripts/canvas1100_length.py) | етап 15: `--fixed` — сталі вікна рівномірної довжини train до різу; `--run` — F1 голів найкращої епохи прогону в кошиках довжини по 24 години, найкраща довжина на train і на val | `data/canvas1100_random/train_len_*`; `results/canvas1100_random/<прогін>_length.json` |
| [`scripts/side_leak.py`](scripts/side_leak.py) | етап 16: голова «бік ноги» наживо в момент T (ланцюжок `heads33_run --holes` на датасетах, обрізаних у T) проти готового ряду; етап 18: `--live` — ланцюжок `--live`, обрізання всіх файлів, кілька монет | `data/side_leak/<T>/`; `results/side_leak/<T>.json`, `results/side_leak_live/<PAIR>_<T>.json` |
| [`scripts/canvas1100_future.py`](scripts/canvas1100_future.py) | етап 16: `--build` — канва 1100 × 7 × 160 год з видач моделей, `--zones` — мітка «T у зоні півота 2.3 %», train і val | `data/canvas1100_future/` |
| [`scripts/canvas1100_future_net.py`](scripts/canvas1100_future_net.py) | етап 16: трансформер на канві 1100 × 7 — T у зоні півота, вибір епохи на відкладених, міра на val; `--controls` — контроль окремими каналами в готовий результат | `models/canvas1100_future/<прогін>/`; `results/canvas1100_future/<прогін>.json`, `<прогін>_val_pred.npz` |
| [`scripts/canvas1100_zone_trade.py`](scripts/canvas1100_zone_trade.py) | етап 17: торгівля на val шести монет (`--pairs`) за сигналом зони півота — кроки T, півоти з роллю, угоди, крива грошей і метрики | `results/canvas1100_future/zone_trade_<PAIR>.json` |
| [`scripts/canvas1100_buy_signal.py`](scripts/canvas1100_buy_signal.py) | етап 20: сигнал — сума видачі у вікні, торгівля лише купівлями з тейком 2 % від найнижчої ціни після входу, стопом і фейком, еталон по зігзагу 2.3 %, грід вікна, порогу й стопу на всіх епохах усіх прогонів етапу 19 | `results/canvas1100_buy/signal_pick.json` |
| [`scripts/canvas1100_buy.py`](scripts/canvas1100_buy.py) | етап 19: `--cluster` — кластер 2 на навчальних 80 % train BTC; `--build` — канви 1100 × 8 train BTC і мітка «зона дна 2.3 %»; `--labels` — мітки готових канв заново (дна лише ніг ≥ 7 год); `--val` — канви 1100 × 8 val BTC, мітка і зони днів; `--run <прогін> --loss <втрата>` — трансформер `Future` на 8 каналів, епоха за AP і поріг на відкладених, видача кожної епохи на val; `--series <прогін>` — видача всіх епох на всіх T train для вкладки `/buy` | `models/canvas1100_buy/assigner.json`, `data/canvas1100_buy/`, `models/canvas1100_buy/<прогін>/`, `results/canvas1100_buy/` |
| [`scripts/canvas1100_early.py`](scripts/canvas1100_early.py) | етап 18: `--held` — сталі канви відкладених; `--run` — одна голова з `RL_tune` е19 на канві 1100 × 9 до T, штраф за віком півота; `--grid` — грід вікон на відкладених і val, найкраще вікно кожні 10 хв з контролями, ряд val для вкладки; `probe` — канва в момент T для вкладки | `data/canvas1100_early/held_*`; `models/canvas1100_early/<прогін>/`; `results/canvas1100_early/<прогін>.json`, `<прогін>_grid.json`, `<прогін>_val_<PAIR>.json` |
| [`scripts/canvas1100_trade.py`](scripts/canvas1100_trade.py) | етап 8: голова боку в живому часі на val, завжди в ринку, гроші з витратами проти холду й випадкових перевертань | `results/canvas1100_trade_<прогін>.json` |
| [`scripts/canvas600_rule.py`](scripts/canvas600_rule.py) | етап 5: формула на вікні з 3 рядків — логістична регресія на 7 рівнях або 21 числі, пороги на відкладених, міри мережі етапу 2 | `results/canvas600_rule.json` |
| [`scripts/canvas200.py`](scripts/canvas200.py) | вкладка `/umap600`: канва 200 — блоки по 3 рядки, сума модулів і 7 \| 7 \| 7, клас блоку, UMAP; перевірка блоків сітки проти поточної карти | `results/canvas200_umap.json` |
| [`scripts/canvas600_net.py`](scripts/canvas600_net.py) | етап 2: мережа на три класи рядка; етап 3: `--outputs` — ряд val на найкращій епосі ± 2, `probe` — канва руками | `models/canvas600/epoch_NN.pt`, `history.json`; `results/canvas600_val.json`, `results/val/series_<PAIR>_eNN.npz` |

```bash
python3 research/36-canvas600-pivots/scripts/canvas600_data.py
python3 research/36-canvas600-pivots/scripts/canvas600_data.py --marks
python3 research/36-canvas600-pivots/scripts/canvas600_signal.py
python3 research/36-canvas600-pivots/scripts/canvas600_signal.py --pairs
python3 research/36-canvas600-pivots/scripts/canvas600_signal.py --kmeans
python3 research/36-canvas600-pivots/scripts/canvas600_signal.py --cluster3d
python3 research/36-canvas600-pivots/scripts/canvas600_signal.py --decode
python3 research/36-canvas600-pivots/scripts/canvas200.py
python3 research/36-canvas600-pivots/scripts/canvas600_rule.py
python3 research/36-canvas600-pivots/scripts/canvas1100.py
python3 research/36-canvas600-pivots/scripts/canvas1100.py --part val
python3 research/36-canvas600-pivots/scripts/canvas1100_net.py --force
python3 research/36-canvas600-pivots/scripts/canvas1100.py --legs 6
python3 research/36-canvas600-pivots/scripts/canvas1100.py --legs 6 --part val
python3 research/36-canvas600-pivots/scripts/canvas1100.py --legs 8
python3 research/36-canvas600-pivots/scripts/canvas1100.py --legs 8 --part val
python3 research/36-canvas600-pivots/scripts/canvas1100_heads.py --run A_wbce --loss wbce --legs 4 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_heads.py --run A_focal --loss focal --legs 4 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_heads.py --run A_dice --loss dice --legs 4 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_heads.py --run A_swap --loss swap --legs 4 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_heads.py --run B_mix --loss dice --legs 4 6 8 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_heads.py --run B_tune --loss dice --legs 4 6 8 --init A_dice --force
python3 research/36-canvas600-pivots/scripts/canvas1100_trade.py --run B_tune
python3 research/36-canvas600-pivots/scripts/canvas1100_window.py --map
python3 research/36-canvas600-pivots/scripts/canvas1100_window.py --grid
python3 research/36-canvas600-pivots/scripts/canvas1100_grow.py --build
python3 research/36-canvas600-pivots/scripts/canvas1100_grow.py --run G_tune --init B_tune --force
python3 research/36-canvas600-pivots/scripts/canvas1100_random.py --fixed
python3 research/36-canvas600-pivots/scripts/canvas1100_random.py --run R_tune --init G_tune --force
python3 research/36-canvas600-pivots/scripts/canvas1100_random.py --fixed --n 1 1
python3 research/36-canvas600-pivots/scripts/canvas1100_random.py --run R1_tune --init R_tune --n 1 1 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_random.py --fixed --length
python3 research/36-canvas600-pivots/scripts/canvas1100_random.py --run RL_tune --init R_tune --length --force
python3 research/36-canvas600-pivots/scripts/canvas1100_length.py --fixed --run RL_tune
python3 research/36-canvas600-pivots/scripts/side_leak.py --at 2026-09-04T18:00 2026-09-05T22:00 2026-09-11T01:00 2026-09-11T03:00
python3 research/36-canvas600-pivots/scripts/canvas1100_future.py --build --zones
python3 research/36-canvas600-pivots/scripts/canvas1100_future_net.py --run Z_base --force
python3 research/36-canvas600-pivots/scripts/canvas1100_future_net.py --run Z_base --controls
python3 research/36-canvas600-pivots/scripts/canvas1100_zone_trade.py
python3 research/36-canvas600-pivots/scripts/heads33_run.py --live
python3 research/36-canvas600-pivots/scripts/side_leak.py --live --pairs BTC_USDT --at 2026-08-19T21:19 2026-08-21T18:38 2026-08-25T03:01 2026-08-30T17:18
python3 research/36-canvas600-pivots/scripts/side_leak.py --live --pairs ETH_USDT --at 2026-08-19T18:20 2026-08-21T14:35 2026-08-19T22:06 2026-08-19T22:46
python3 research/36-canvas600-pivots/scripts/side_leak.py --live --pairs SOL_USDT --at 2026-08-15T14:54 2026-08-16T17:29 2026-08-30T14:18
python3 research/36-canvas600-pivots/scripts/side_leak.py --live --pairs XRP_USDT --at 2026-08-15T13:06 2026-08-16T18:44 2026-08-28T01:53
python3 research/36-canvas600-pivots/scripts/side_leak.py --live --pairs BNB_USDT --at 2026-08-16T14:58 2026-08-18T05:50 2026-08-22T05:26
python3 research/36-canvas600-pivots/scripts/side_leak.py --live --pairs DOGE_USDT --at 2026-08-18T21:16 2026-08-20T10:29 2026-09-05T18:20
python3 research/36-canvas600-pivots/scripts/canvas1100_early.py --held
python3 research/36-canvas600-pivots/scripts/canvas1100_early.py --run E_tune --force
python3 research/36-canvas600-pivots/scripts/canvas1100_early.py --grid E_tune
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --cluster
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --build
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --labels
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --val
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --run BUY_bce --loss bce --force
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --run BUY_pos --loss pos --force
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --run BUY_focal --loss focal --force
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --run BUY_dice --loss dice --force
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --run BUY_far --loss far --init BUY_bce:16 --lr 1e-4 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --run BUY_ladder --loss ladder --init BUY_bce:16 --lr 1e-4 --force
research/36-canvas600-pivots/scripts/buy_ladder2_grid.sh
python3 research/36-canvas600-pivots/scripts/canvas1100_buy.py --run BUY_l3 --loss ladder2 --init BUY_l2s7:1 --lr 1e-4 --silence 7 --steps 2,6,10,14,18,21,25,29,33,37 --force
python3 research/36-canvas600-pivots/scripts/canvas1100_buy_signal.py
python3 rules/scripts/build_class210x10x7dc.py --end 2026-09-23 --out data/datasets_ext
python3 research/36-canvas600-pivots/scripts/heads33_data.py
python3 research/29-class7dd-legs/scripts/legleft_data.py --blocks --history 4 --norm gauss --clock --data data/datasets_ext --out research/36-canvas600-pivots/data/heads33/legleft
python3 research/36-canvas600-pivots/scripts/heads33_run.py
python3 research/36-canvas600-pivots/scripts/canvas600_net.py
python3 research/36-canvas600-pivots/scripts/canvas600_data.py --series
python3 research/36-canvas600-pivots/scripts/canvas600_net.py --outputs
python3 research/36-canvas600-pivots/scripts/canvas600_c1.py --labels
python3 research/36-canvas600-pivots/scripts/canvas600_c1.py
python3 research/36-canvas600-pivots/scripts/canvas600_c1.py --outputs
python3 -m unittest discover -s tests -t tests -p "test_canvas600.py"
```

Готові функції дослідження 35 імпортуються, а не копіюються:

| Функція | Файл | Навіщо |
| ------- | ---- | ------ |
| `read_seconds`, `edges_of` | [`bars30.py`](../35-leg-fullness/scripts/bars30.py) | секунди → відрізки канви |
| `window_canvas` | [`windows30.py`](../35-leg-fullness/scripts/windows30.py) | 600 відрізків → 7 фіч → нормування на канву |
| `pivots_of`, `row_records` | [`edges30_data.py`](../35-leg-fullness/scripts/edges30_data.py) | півоти 2.3 і їхні зони, записи рядків |
| `zigzag`, `snap` | [`rules/scripts/zigzag.py`](../../rules/scripts/zigzag.py) | зігзаг 0.8 усередині ноги і точка півота |
| `Finder`, `peaks`, `score`, `record_zones`, `probe` | [`edges30_net.py`](../35-leg-fullness/scripts/edges30_net.py) | мережа, сигнали, міра, канва руками (етапи 2–3) |

## Вкладка `/canvas600`

| Блок | Що показує | Ендпоінт |
| ---- | ---------- | -------- |
| опис | ціль, канва 600, розмітка трьох класів рядка; без даних — команда, якою вони робляться | `/api/canvas600` |
| ціна train | кнопки монети; ціна train (на піксель — від найменшого до найбільшого `close`), вісь Y — межі видимого відрізка; зігзаг 2.3 (нога вгору — зелена, вниз — червона, квадрат — півот), корекції 0.8 — фіолетові точки, пунктир — зігзаг 0.8 через півоти 2.3 і корекції; зони півотів і корекцій (95 … 105 % тривалості × 10 % ціни); перемикачі «зони» і «зігзаг 0.8»; колесо — масштаб, перетягування — зсув, подвійний клік — увесь ряд | `/api/canvas600/price/<PAIR>` |
| датасет канви 600 | train і val: ніг, вікон, зон початку, кінця, інших півотів 2.3 і корекцій | `/api/canvas600` (`build`) |
| фічі опору й підтримки | чотири графіки — `d_resist_buy`, `d_bal_resist_buy`, `d_support_sell`, `d_bal_support_sell`: середнє фічі на зсувах −12 … +12 рядків від піку, лінія на частину — початок, кінець, корекція, звичайна частина ноги; перемикачі train / val і «по модулю» / «вершини, зі знаком» / «дна, зі знаком» | `/api/canvas600` (`profile`) |
| мережа | кнопки епох (★ — найкраща за F1 на відкладених); таблиця: відкладені train, val усіх монет і кожної — точність, повнота, F1, добрих / сигналів і сплутано для півота 2.3 і для корекції; хід навчання по епохах | `/api/canvas600` (`net`) |
| видача на val | кнопки епох (★ і по дві до і після); таблиця по монетах — для півота і для корекції окремо на вікнах val і на ряді val: точність, повнота, F1, добрих / сигналів, сплутано; кнопки монети; ціна val з півотами 2.3 і корекціями 0.8 та їхніми зонами (зелений — вершина, червоний — дно, фіолетовий — корекція), сигнали (синій — півот у зоні півота, фіолетовий — корекція в зоні корекції, сірий — хибний); під нею на спільній осі часу — P(півот) і P(корекція) з порогами пунктиром; зум і зсув | `/api/canvas600` (`shown`), `/api/canvas600/series/<PAIR>/<епоха>` |
| канва руками | кнопки монети й епохи; ціна val — два кліки ставлять початок і кінець канви, край виділення перетягується мишею, канва рахується заново, коли відпустили; сервер будує канву 600 з відрізка (≥ 600 записів) і проганяє мережу (`canvas600_net.probe`); під ціною — відрізок крупно: ціна, півоти й корекції із зонами, сигнали, дві смуги 600 рядків — P(півот) і P(корекція) з порогом; кольорове під смугою — рядки в зоні свого класу, риски — сигнали | `/api/canvas600/valprice/<PAIR>`, `/api/canvas600/probe/<PAIR>/<від>/<до>/<епоха>` |
| мережа кластера 1 | правило кластера 1 і його збіг із k-means; кнопки епох (★); таблиця вікон val — відкладені train, усі монети й кожна: точність, повнота, F1, добрих / сигналів, скільки сигналів у зоні півота 2.3, у зоні корекції, поза зонами; таблиця ряду val по монетах — сигналів, частки в зонах, півотів і корекцій знайдено; хід навчання; кнопки монети — ціна val з зонами і сигналами (синій — у півоті, фіолетовий — у корекції, сірий — поза зонами) і під нею P(подія кластера 1) з порогом | `/api/canvas600` (`c1_net`, `c1`), `/api/canvas600/c1series/<PAIR>/<епоха>` |
| кластери 1 і 2 на канві руками | кнопки монети; ціна val — два кліки ставлять канву, край перетягується, канва рахується заново, коли відпустили; сервер будує канву 600 і проходить її вікном з 3 рядків через правило кластера 1 (`canvas600_c1.rule_probe`); рядок підсумку — скільки рядків у зоні кластера 1 і скільки з них у зонах півота й корекції, яка частка рядків півота й корекції — кластер 1; під ціною — смуга P(кластер 1) по рядках з 0.5 пунктиром і справжніми рядками півота під нею, і смуга зон кластера 1 з рядками корекції під нею; нижче — плашка «кластер 2»: смуга P(кластер 2) з рядками півота під нею і смуга зон кластера 2 з рядками корекції під нею, частка рядків півота й корекції з підписом кластера 2; нижче — плашка «півоти 2.3»: смуга P(півот) мережі етапу 2 на тій самій канві з порогом, сигнали рисками (синя — у зоні півота, сіра — хибна) і справжніми рядками півота під нею; ті самі сигнали — на ціні | `/api/canvas600/valprice/<PAIR>`, `/api/canvas600/c1probe/<PAIR>/<від>/<до>` |
| плашка «Уточнення сигналу» | метод; сусідні півоти 2.3 однієї ноги — таблиця «своя / чужа / тіло» з інтервалом різниці; обраний варіант ★; 30 найкращих варіантів гріду за балом — набір фіч, вікно, `stat`, пошук піку `±P`, `repr`, `q`, `τ`, частка зон із сигналом, розриви трьох цілей і бал; матриця кореляцій шести частин обраного варіанта на train і на val; уточнені мітки — зон із сигналом і рядків до / після | `/api/canvas600` |
| UMAP уточнених сигналів | train / val, три метрики, розфарбування за частиною або вершина / дно; велика карта всіх чотирьох частин і чотири малі — кожна частина поверх сірих решти; підказка на точці — частина, вершина / дно, нога, вікно, рядок піку, сила | `/api/canvas600/umap` |
| UMAP · кластери | перемикач «k-means 2» / «HDBSCAN», train / val, три метрики; карта уточнених сигналів, колір — кластер (сірий — шум HDBSCAN); таблиця кластер × частина з рядком шуму: скільки точок і яка частка всіх точок частини; підказка на точці — кластер, частина, вершина / дно, нога | `/api/canvas600/umap` (`kmeans`) |
| розшифровка кластерів 1 і 2 | train і val: рівень кожної з 7 фіч у кластері 1 і 2, AUC на всіх точках і на корекціях; властивості корекцій і країв ноги в кожному кластері з AUC | `/api/canvas600` (`decode`) |
| Кластери · 3D UMAP | перемикач «k-means 2» / «HDBSCAN»; кнопки кластерів (k-means: «кластер 1» — «півотний», «кластер 2» — «тілесний», за замовчуванням; HDBSCAN — стільки, скільки знайдено), train / val, три метрики; точки обраного кластера окремою 3D-картою, колір — частина або вершина / дно; колесо — масштаб, перетягування — поворот; підказка на точці — частина, вершина / дно, нога, вікно, рядок піку | `/api/canvas600/umap` (`cluster3d`) |

Вкладка доповнюється блоками тим самим кроком, що й етапи. Вивід етапів
2–3 будується як на `/edges30`.

## Вкладка «Ряд val: кластери, нога і голови» — `підтверджено`, 2026-09-25

Вкладка [`/valboard`](http://localhost:8080/valboard):
[`scripts/valboard.py`](scripts/valboard.py), ендпоінт
`/api/valboard/<PAIR>/<від>/<до>`.

**Один головний графік** — ціна val монети з півотами 2.3 і корекціями
0.8 та їхніми зонами. Клік — початок відрізка, другий клік — кінець, край
перетягується мишею. Відпустили — сервер рахує на **цьому відрізку** всі
видачі, і вони лягають під графіком на спільну вісь часу відрізка. Інших
графіків ціни на вкладці немає.

| Смуга | Модель | Як рахується на відрізку | Правда під смугою |
| ----- | ------ | ------------------------ | ----------------- |
| P(кластер 1) | правило кластера 1 (етап 4) | канва 600 з відрізка, вікно з 3 рядків з кроком 1, імовірність рядка — найбільша з вікон, що його накривають | рядки зони півота 2.3 |
| P(кластер 2) | те саме | `1 − p` того самого вікна | рядки зони півота 2.3 |
| P(півот 2.3) | мережа етапу 2, найкраща епоха | та сама канва 600; сигнал — пік вище порогу в ±10 рядках (риски: синя — у зоні півота, сіра — хибна) | рядки зони півота |
| повнота ноги, вихід 2 | мережа дослідження 35, прогін `g12`, епоха 5 (як на `/seq30`) | канва 500 з відрізка (`windows30.window_canvas`), вхід 500 × 7 і 4 скаляри; P(рядок уже належить наступній нозі) по рядках; під смугою — **вихід 1** окремим графіком: сходинки P(q ≥ c) стовпчиками з порогом 0.5, одна відповідь на все вікно, як на `/seq30` | рядки від першої секунди наступної ноги — нога та, в якій відрізок починається |
| голова «бік ноги» | двоголова мережа дослідження 33 | події її ряду val всередині відрізка: P(нога вгору) лінією, як на `/legs` (зелена), ема 200 за замовчуванням, поріг 0.5 пунктиром, шкала −0.03 … 1.03; лінія рветься на проміжку між подіями понад 10 хв | — |
| голова «зона розвороту» | те саме | P(зона) лінією (помаранчева), ема 200, поріг 0.5 | — |

- Над кожною видачею — **своє поле ема** (у рядках канви або в подіях
  ряду голів; 1 — без ема): синя лінія поверх смуги.
- Над смугами — підсумок відрізка: частка рядків кластера 1 і 2, рядки
  півота й корекції і скільки з них кластер 1, сигнали півота 2.3.
- Ряд голів дослідження 33 покриває val лише до 07.09.2026; на відрізку
  пізніше смуги голів порожні, і вкладка пише, який проміжок покрито.
- Кнопки монети — над головним графіком.

## Вкладка «K-means: кластери 1 і 2» — `підтверджено`, 2026-09-27

> http://localhost:8080/canvas600 створи вкладку на основі цієї - пропиши
> там як ми створювали UMAP уточнених сигналів, UMAP · кластери,
> Розшифровка кластерів 1 і 2 до цього включно

> будемо далі працювати з к-мінс кластер1 та кластер2 все інше - видали

Вкладка [`/umap600`](http://localhost:8080/umap600). Нових скриптів і
ендпоінтів немає: вкладка читає ті самі `/api/canvas600` і
`/api/canvas600/umap`, що й `/canvas600`, і малює блоки тими самими
функціями з префіксом `umap600`.

| Блок | Що показує | Ендпоінт |
| ---- | ---------- | -------- |
| плашка «Метод, кластери k-means, канва 200, алгоритм на вікні, канва 1100, мережі етапів 7 і 8» | згорнута за замовчуванням; у ній — усі блоки нижче до «мережа 1100 на ряді val: канва руками»; полотна в ній перемальовуються, коли плашку відкрили | — |
| як це побудовано | метод по кроках — розділ «Уточнення сигналу», пункти 1–7, 10, 11 (лише k-means), 13: канва 600 і зони, сила рядка, пік у вікні `± P`, уточнений сигнал, частини датасету й контролі, кореляції і бал, грід 1920 варіантів, UMAP, k-means на 2 кластери, розшифровка; команди `canvas600_signal.py`, `--kmeans`, `--decode` | — |
| UMAP · кластери | лише k-means 2 (перемикача HDBSCAN немає), train / val, три метрики; карта уточнених сигналів, колір — кластер; таблиця кластер × частина; підказка на точці — кластер, частина, вершина / дно, нога | `/api/canvas600/umap` (`kmeans`) |
| розшифровка кластерів 1 і 2 | train і val: рівень кожної з 7 фіч у кластері 1 і 2, AUC на всіх точках і на корекціях; властивості корекцій і країв ноги в кожному кластері з AUC (Результат 9) | `/api/canvas600` (`decode`) |
| канва 200: UMAP блоків по 3 рядки | train / val; «сума модулів · 7» / «7 \| 7 \| 7 · 21»; три метрики; колір — клас блоку (півот 2.3, корекція 0.8, зона без сигналу, тіло ноги, поза ногою) або нога вгору / вниз; велика карта і пʼять малих — кожен клас поверх сірих решти; підказка на точці — клас, нога, вікно, блок і його рядки; під картою — таблиці «Блоки 7 \| 7 \| 7 проти поточного UMAP» (Результат 11) | `/api/canvas600/umap200` |
| алгоритм на вікні канви | перемикач «рівні 7 фіч» / «3 рядки · 21 число»; метод і пороги; таблиця — відкладені train, val усіх монет і кожної: для півота 2.3 і корекції точність, повнота, F1, добрих / сигналів, сплутано — рядок «формула» і під ним «мережа» етапу 2 на найкращій епосі; у плашці — ваги формули в сирих одиницях (Результат 12) | `/api/canvas600/rule` |
| канва 1100: записи 100 с, 4 ноги, UMAP подій | хід етапу 6 пунктами з параметрами з файлу; таблиця по монетах — записів, розривів, без похідної, ніг, ніг ≥ 7 год, медіана ноги, півотів, корекцій, канв; UMAP подій (точка — рядок події, 7 фіч) — перемикачі метрики і «півот / корекція» / «вершина / дно», велика карта і дві малі — кожен клас поверх сірих решти; підказка — клас, вершина / дно, монета, канва, рядок (Результат 13) | `/api/canvas600/canvas1100` |
| мережа: півоти 2.3 на канві 1100 | метод, розбиття, епоха ★ і поріг; таблиця — відкладені train, val усіх монет і кожної: точність, повнота, F1, добрих / сигналів, зон знайдено, сплутано — рядок «мережа» і під ним «випадкові сигнали»; у плашці — хід навчання (Результат 14) | `/api/canvas600/canvas1100net` |
| три голови: півот, корекція, бік (етап 8) | метод; таблиця прогонів — втрата, ноги, довчання, епоха, середній F1 на відкладених, на val F1 півота й корекції проти випадкових, бік правильний, F1 перемикань, F1 півота й корекції на канвах 4 / 6 / 8 ніг; таблиця торгівлі голови боку в живому часі по монетах — рішень, перевертань, гроші моделі, холд, випадкові (медіана / найкращий), перевертань у зоні півота, півотів з перевертанням (Результат 15) | `/api/canvas600/heads` |
| мережа 1100 на ряді val: канва руками | кнопки монети; ряд — записи 100 с: 3 півоти 2.3 перед val (хвіст train) і весь val, півоти 2.3 і корекції 0.8 із зонами; кнопки «вільне вікно» / «вікно 160 год» і «→ 1 год»: у вільному два кліки ставлять відрізок будь-якого розміру від 1100 записів, край перетягується — канва рахується заново, коли відпустили (`canvas1100_net.probe`); у режимі 160 год клік ставить початок, кінець — через 160 год (найкраща довжина val етапу 15), «→ 1 год» зсуває вікно на годину вправо і рахує канву заново; підсумок — записів, крок рядка, епоха, поріг, зон півота знайдено, сигналів і добрих; під ціною — відрізок крупно з сигналами мережі етапу 7 (зелений — у зоні півота, сірий — поза нею); усі видачі під ним — у згорнутій плашці (розкривається кліком, стан тримається між перерахунками канви): **моделі етапів 11–12** (`canvas1100_grow.buttons` / `models_on`): кнопки «прогін · епоха» — етап 11: найкраща епоха ★ і по одній зліва й справа, етапи 12–14: три найкращі епохи кожного прогону; прогони — у порядку появи; за замовчуванням — найкраща епоха найсвіжішого прогону (`RL_tune` е19); три смуги обраної моделі — P(вершина 2.3), P(корекція 0.8), P(дно 2.3) з порогом своєї епохи, сигналами (добрий — на рядку зони свого класу чи на іншій вершині в ціні зони півота, `POS` / `ALT`) і рядками зони свого класу під смугою; нижче — **плашки моделей етапу 8**: кнопки прогонів (A_wbce … B_tune, за замовчуванням B_tune; сервер рахує всі прогони на тій самій канві, перемикання без нового запиту) і дві смуги обраного прогону — P(півот 2.3) з порогом, сигналами і рядками зони півота під смугою, P(корекція 0.8) з порогом, сигналами і рядками зони корекції; під ними — дві видачі `/valboard` на тому самому відрізку (`/api/valboard/<PAIR>/<від>/<до>`, частина відрізка в val): P(кластер 2) = 1 − p правила кластера 1 на канві 600 без ема і рядками зони півота під смугою, і голова «бік ноги» дослідження 33 лінією з двома емами — синя (за замовчуванням 200) і фіолетова «ема 2» (за замовчуванням 50), пунктир — 0.5; на всіх графіках відрізка — вертикальні лінії півотів 2.3 (зелена — вершина, червона — дно) і перехрестя під мишею (`chartGroup` / `chartOverlay`): вертикальний пунктир через усі графіки, горизонтальний — на графіку під мишею, з його значенням на шкалі Y і часом UTC на осі X | `/api/canvas600/c1100price/<PAIR>`, `/api/canvas600/c1100probe/<PAIR>/<від>/<до>` |
| зона півота 2.3 % у момент T (етап 16) | відкрита плашка під канвою руками (`c1100ZoneRender`, `/api/canvas600/futurezone`), останній прогін: питання, вхід і лічильники зони; перевірка голови «бік ноги» на заглядання вперед (`results/side_leak/`: момент T, подій до T, найбільша різниця p_side і ема 200, видач в останню годину готовий / наживо); міри на відкладених і val (AUC, точність, повнота, F1, F1 «завжди так», частка зони); контроль окремими каналами (AUC train і val) поряд із трансформером; монети (AUC, точність / повнота, F1, частка зони); хід навчання по епохах (втрата, AUC відкладені й val, ★ — обрана); кнопки монети і ряд val: ціна в момент T і P(T у зоні) з порогом, зелена смужка внизу — T справді в зоні | `/api/canvas600/futurezone` |
| торгівля на val за зоною півота (етап 17) | відкрита плашка під зоною півота (`c1100TradeRender`, `/api/canvas600/zonetrade/<PAIR>`): кнопки шести монет (за замовчуванням BTC); алгоритм і метрики на весь val обраної монети; за замовчуванням показано весь val з усіма угодами, кнопки «з початку» (покроковий перегляд), «вперед» (година), «+24 год», «до кінця»; рядок стану — час, ціна, P, «півот» з роллю або «не півот», позиція від ціни входу, гроші, закриті угоди; ціна до поточного T (перед першим T — сірим 160 год історії, що є на першій канві) з півотами (▼ вершина, ▲ дно; великий — зі зміною боку, малий — продовження; ✕ — хибний) і угодами лініями від входу до виходу (зелена — у плюсі, червона — у мінусі, пунктир — відкрита); під нею P(T у зоні) з порогом, зелена смужка — T справді в зоні, лише для T старших за 40 год | `/api/canvas600/zonetrade/<PAIR>` |

Без даних вкладка показує метод і команду, якою дані робляться.

### Канва 200 — `підтверджено`, 2026-09-27

> 1. зроби розділ - юамп суми по модулю 3 векторів відміть до чого вони
> відносяться (півот, корекція) - виведи юмап для канва 200
> 2. потвм дай відповідб на це питання : можемо зробити 200 з таких
> стовпчиків 7 - 7 -7 ? це буде 1х21 сот акі вектори - вони збережуть
> поточний юмап ? це ж тесаме?

[`scripts/canvas200.py`](scripts/canvas200.py) →
`results/canvas200_umap.json`.

1. **Блоки.** Базова канва 600 × 7 (нормована, `data/canvas600/<part>_x.npy`)
   ріжеться на 200 блоків без перекриття: блок `b` — рядки `3b … 3b + 2`.
   Блок з мертвим рядком не береться, блок з `NaN` не проєктується.
2. **Два вигляди блоку**: `sum7` — `S[f] = |x[3b, f]| + |x[3b + 1, f]| +
   |x[3b + 2, f]|`, 7 чисел; `cat21` — модулі трьох рядків підряд,
   7 | 7 | 7 = 21 число.
3. **Клас блоку** — з уточнених міток рядків (`<part>_refined.npy`):
   `півот` — є рядок сигналу півота 2.3 (мітка 2); `корекція` — є рядок
   сигналу корекції 0.8 (мітка 1), півота немає; `зона без сигналу` — є
   рядок мітки −1, сигналу немає; `тіло ноги` — решта блоків у рядках
   50 … 549; `поза ногою` — решта.
4. **Вибірка** — до 1000 / 1200 / 600 / 1200 / 600 блоків на клас (півот,
   корекція, зона, тіло, поза ногою), seed 36; той самий набір для `sum7`
   і `cat21`.
5. **UMAP** — 2 компоненти, cosine, euclidean, manhattan, `n_neighbors
   15`, `min_dist 0.1`, seed 36; train і val окремо.
6. **Перевірка проти поточного UMAP** — на точках карти уточнених
   сигналів: `V` — вектор точки (вікно пік ± 1), `T` — `cat21` блоку
   сітки, у який падає рядок піку (`b = пік // 3`). Частка `T = V`;
   косинус `V` і `T`; збіг правила кластера 1 (етап 4) на `V` і на `T`
   і кожного з k-means (карта cosine); більшість кластерів k-means серед
   15 найближчих за cosine векторів `V` — для `V` (без себе) і для `T`.

```bash
python3 research/36-canvas600-pivots/scripts/canvas200.py
python3 -m unittest discover -s tests -t tests -p "test_canvas600.py"
```

## Вкладка «Півот раніше за зігзаг» — `підтверджено`, 2026-09-29

Вкладка [`/early`](http://localhost:8080/early) — етап 18 окремо від
важкої `/umap600`, модель `виявленняпівота2.3`. Завантажувач `LOADERS.early`, розмітка
`id="tab-early"` → `early-body`, малює `c1100EarlyRender`.

| Блок | Що показує | Ендпоінт |
| ---- | ---------- | -------- |
| метод і міра | вхід 1100 × 9, одна голова з `RL_tune` е19, штраф за віком півота; свіжий сигнал, «раніше за зігзаг», F1 | `/api/canvas600/early` |
| перевірка голови «бік ноги» | `results/side_leak_live/`: монета, T, подій до T, видач за останню годину готовий / наживо, найбільша різниця | `/api/canvas600/early` (`leak`) |
| хід навчання | епоха, втрата, поріг, F1 відкладених, точність / раніше за зігзаг за вікнами 80, 160, 240 год, ★ — обрана | `/api/canvas600/early` |
| грід вікон | на кожному вікні 40 … 300 год: поріг мережі й `RL_tune`, F1 відкладені й val проти `RL_tune`, точність, раніше за зігзаг, випередження; ★ — найкраще вікно | `/api/canvas600/early` (`grid`) |
| найкраще вікно кожні 10 хв | відкладені й val: мережа, `RL_tune` е19, випадкові сигнали; val по монетах | `/api/canvas600/early` (`grid.fine`) |
| канва, що сунеться на 10 хв | вибір довжини вікна 40 … 300 год (★ — найкраще з гріду, за замовчуванням), поріг — свій для вікна з гріду відкладених; кнопки монети і «з початку», «▶ пуск / ⏸ пауза», «→ 10 хв», «→ 1 год», «+24 год», «до кінця»; кожен крок — сервер будує канву, що закінчується в T, тим самим ходом, що в навчанні (`canvas1100_early.probe`, секунди й модель кешуються на процес), і мережа розмічає рядки; ціна канви (close на кінці рядка), блакитна смуга — свіжа година; ▼ / ▲ — півоти, заповнені — зігзаг уже підтвердив до T, контур — ще ні, ○ — мережа вже виявила до T; під ціною — P(зона півота) рядків канви з порогом і сигналами (сині — у зоні, сірі — поза), помаранчева смужка — правда готового зігзага (відома лише пізніше); нижче — видача наживо: на кожен T до поточного найбільша P на свіжих рядках, риски — свіжі сигнали; порахована лише для найкращого вікна, на інших вікнах смуга порожня з підписом. Поки гріду немає — вікно 160 год і поріг навчання, кроки T від `val_from` до кінця ряду мінус запас, видачі наживо немає | `/api/canvas600/early/<PAIR>`, `/api/canvas600/early/<PAIR>/<T>[/<вікно, год>]` |

Без даних вкладка показує команду, якою дані робляться.

## Вкладка «Торгівля» — `підтверджено`, 2026-09-30

> робиш вкладку торгівля — береш ці 2 моделі: виявленняпівота2.3 та
> канва600півот2.3%ідентифікатор. робиш графік як на картинці [вкладка
> `/early`] в одній плашці знизу одна мережа в другій — друга. додай
> можливість змінювати висоту вікон просто мишкою та зберігай її на
> наступні сесії. під видачею кожної моделі ще по плашці — для них
> настройки — довжина вікна в якому рахується сума сигналів моделі — вони
> рахуються почергово для вікон довжини що я вкажу один раз і зсуваються
> синхронно.

Вкладка [`/trade`](http://localhost:8080/trade). Завантажувач
`LOADERS.trade`, розмітка `id="tab-trade"` → `trade-body`, малює
`tradeRender`. Нових моделей і прогонів немає: вкладка читає готові
видачі двох моделей на val.

| Модель | Прогін | Що видає | Звідки |
| ------ | ------ | -------- | ------ |
| `виявленняпівота2.3` (етап 18) | `E_tune` е11, поріг 0.85 з гріду, вікно канви 40 … 300 год (★ 300) | P(зона півота 2.3) на кожному рядку канви 1100 × 9, що закінчується в T — рахується на льоту | `/api/canvas600/early/<PAIR>/<T>/<год>` |
| `канва600півот2.3%ідентифікатор` (етап 16) | `Z_base` е8, поріг 0.05 | одне число P(T у зоні півота 2.3 %) на кожен свій T, раз на годину | `results/canvas1100_future/Z_base_val_pred.npz` через `/api/trade/<PAIR>` |

Полотна зверху вниз на спільній осі часу `[T − L, T]`:

1. ціна close на кінці рядка канви до T, півоти, які зігзаг підтвердив до T;
2. `виявленняпівота2.3` — P на рядках канви T, пунктир — поріг, риски —
   сигнали (сині — у зоні півота, сірі — поза), помаранчева смужка — зона
   півота готового зігзага;
3. сума видачі `виявленняпівота2.3` за останні `W` хв у кожному T;
4. `канва600півот2.3%ідентифікатор` — P на кожен його T ≤ поточного T,
   стовпчик від `T − 1 год` до `T`, шкала 0 … max(2 · поріг, найбільша P
   монети), пунктир — поріг; ряд моделі починається з 2026-08-20 13:00
   UTC (раніше в канві 160 год не вистачає історії val);
5. сума видачі `канва600півот2.3%ідентифікатор` за останні `W` хв у кожному T.

**Сума у вікні.** Довжина `W` у хвилинах задається один раз на модель
(поле над її полотном суми, крок 10, 10 … 1440; за замовчуванням 60 хв
для `виявленняпівота2.3` і 180 хв для `канва600півот2.3%ідентифікатор`).
На кожному кроці T ряду val (кожні 10 хв) рахується одне число — сума
видачі моделі за останні `W` хвилин до T, **такої, якою модель бачила її
саме в T**, — і ставиться стовпчиком `(T − 10 хв, T]`. Далі це число не
міняється: наступні T додають свої стовпчики праворуч.

- `виявленняпівота2.3`: сума P рядків канви, що закінчується в T, з
  `T − W < row_end ≤ T` (живі рядки). Канва кожного T своя — видача на тих
  самих годинах у пізнішій канві інша, тому сума береться лише з канви
  свого T. Хвости канв (рядки за останню добу) рахує сервер пачками по 144
  кроки T (`/api/trade/<PAIR>/<год>/<від>/<до>`), вкладка тримає їх у
  памʼяті сторінки і дораховує кроки, яких на полотні ще немає; поки
  рахується — у заголовку «рахується ще N кроків T».
- `канва600півот2.3%ідентифікатор`: сума його P з `T − W < t ≤ T` — видача
  на кожен його T не залежить від пізніших даних.

Зміна `W` перераховує стовпчики з тих самих хвостів, без нового запиту.

**Кнопки** — як на `/early`: монета, вікно канви, «з початку», «▶ пуск /
⏸ пауза», «→ 10 хв», «→ 1 год», «+24 год», «до кінця»; кроки T — ряд val
`E_tune` кожні 10 хв. Колесо — масштаб усіх полотен разом, подвійний
клік — скинути.

**Висота полотен.** Під кожним полотном — смужка: тягнеш мишкою вниз чи
вгору — висота міняється (50 … 1200 px), відпустив — збережено. Висоти й
довжини вікон суми лежать у `localStorage` під ключем `trade.settings`
(`{"heights": {price, detect, detectSum, zone, zoneSum}, "sum": {detect,
zone}}`) і відновлюються в наступних сесіях браузера.

| Ендпоінт | Що віддає |
| -------- | --------- |
| `/api/trade` | монети з рядом val; для кожної моделі назва, прогін, епоха, поріг; вікна канви й найкраще — для `виявленняпівота2.3` |
| `/api/trade/<PAIR>` | кроки T і півоти ряду val `E_tune`, видача `Z_base` монети (`zone.t`, `zone.p`) за часом |
| `/api/trade/<PAIR>/<год>/<від>/<до>` | хвости канв `виявленняпівота2.3` на кроках T ряду val від `від` до `до` (до 144 кроків): `row_end` і P рядків за останню добу до T |
| `/api/canvas600/early/<PAIR>/<T>/<год>` | канва в момент T і видача `виявленняпівота2.3` на рядках (той самий, що в `/early`) |

Без прогонів вкладка показує команди, якими вони робляться. Тест —
`tests/test_dashboard.py` → `test_trade_payloads_and_markup`.

## Вкладка «Півот на купівлю: train BTC» — `підтверджено`, 2026-09-30

> на якій вкладці виклав і зроби графік і прогін під ним — в окрему
> вкладку — і навчання туди скопіюй

> прибери червоне і трикутники — відміть просто зони півота по правилам
> що в цьому чаті

Вкладка [`/buy`](http://localhost:8080/buy) — етап 19, кращий прогін
`BUY_bce` на train BTC. Завантажувач `LOADERS.buy`, розмітка
`id="tab-buy"` → `buy-body`, малює `buyRender`. Видачу рахує
`canvas1100_buy.py --series BUY_bce`: кожна збережена епоха на всіх T
train BTC (навчання і відкладені) →
`results/canvas1100_buy/BUY_bce_series.npz` (`epochs`, `prob` — епоха ×
T, `t`, `close`, `labels`, `side`, дна 2.3 ніг ≥ 7 год, шматки їхніх зон
`zone_from` / `zone_to`).

| Блок | Що показує | Ендпоінт |
| ---- | ---------- | -------- |
| мережа | архітектура, вхід 1100 × 8, мітка «зона дна 2.3 %», втрата, вибір епохи й порогу | `/api/buy` (`config`) |
| дані | лише train BTC; навчання, проміжок 200 год, відкладені — дати, число T, T у зоні дна, днів 2.3 у відкладених | `/api/buy` (`split`, `counts`) |
| кластер 2 (згорнуто) | канв 600 до межі навчання, обраний варіант уточнювача, правило кластера 1 і склад кластерів k-means (з `models/canvas1100_buy/assigner.json`) | `/api/buy` (`cluster`) |
| хід навчання | епоха, втрата, AUC, F1, поріг на відкладених, секунди; ★ — обрана; під таблицею — міри обраної епохи і база | `/api/buy` (`history`, `held`) |
| кнопки епох | усі епохи прогону, за замовчуванням ★ | — |
| рядок стану | днів 2.3 і шматків їхніх зон, поріг епохи, скільки T з P ≥ порогу і скільки з них у зоні дна, окремо у відкладених, найбільша P | `/api/buy/<епоха>` |
| ціна | close BTC у кожен T train (крок 10 хв; лінія рветься лише на дірці довшій за годину); жовті смуги — зони півота: дна 2.3 ніг ≥ 7 год, записи, де до дна не далі за 5 % тривалості ноги і ціна не вище дна більше ніж на 10 % ціни ноги (`pivot_zones` — ті самі записи, що в мітці); сіра смуга — проміжок 200 год, блакитна — відкладені | `/api/buy/<епоха>` (`zones`) |
| видача під ціною | P(T у зоні дна) обраної епохи в кожен T на спільній осі, шкала 0 … найбільша P, пунктир — поріг епохи з відкладених; жовта смужка знизу — мітка «T у зоні дна»; риски зверху — T з P ≥ порогу (сині — у зоні, сірі — поза) | `/api/buy/<епоха>` |

Колесо — масштаб обох полотен разом, перетягування — зсув, подвійний
клік — скинути. Без прогону вкладка показує команди, якими він робиться.
Тест — `tests/test_dashboard.py` → `test_buy_payloads_and_markup`.

## Вкладка «Півот на купівлю: val BTC» — `підтверджено`, 2026-09-30

> вчи мережу знаходити ці жовті зони, там канва 1100 — вона повинна
> вікном як у попередній вкладці проходити по вал видачі, але тільки
> біткоїн … роби вкладку

Вкладка [`/buyval`](http://localhost:8080/buyval) — етап 19 на val BTC.
Завантажувач `LOADERS.buyval`, розмітка `id="tab-buyval"` → `buyval-body`,
малює `buyvalRender`. Нових розрахунків вкладка не робить: видача кожної
епохи кожного прогону на всіх T val — `results/canvas1100_buy/<прогін>_val.npz`
(пише `--run`), зони днів val — `data/canvas1100_buy/val_meta.npz`.

| Блок | Що показує | Ендпоінт |
| ---- | ---------- | -------- |
| опис | навчання лише на train BTC, відкладені, val BTC (дати, T, T у зоні дна, днів 2.3), вхід, мітка, мережа, вибір епохи | `/api/buyval` (`split`, `counts`) |
| функції втрат і таблиця прогонів | для кожної втрати: епоха, F1 / AP / AUC / поріг на відкладених, на val при тому самому порозі — AP, AUC, точність, повнота, F1, сигналів; ★ — найбільший F1 на відкладених (рівний — AP); база val | `/api/buyval` (`runs`, `best`) |
| кнопки прогону й епохи, хід навчання (згорнуто) | за замовчуванням ★ і його обрана епоха | `/api/buyval` |
| кнопки T | «з початку», «▶ пуск / ⏸ пауза», «→ 10 хв», «→ 1 год», «+24 год», «до кінця» — T ходить по val кроком 10 хв | — |
| рядок стану | T, P у T і чи він ≥ порогу (сигнал купівлі), чи T у зоні дна; на всьому val — сигналів, з них у зоні дна, скільки шматків зон мали сигнал усередині чи до години після | `/api/buyval/<прогін>/<епоха>` |
| вікно 160 год до T | ціна close у кожен T вікна з жовтими зонами півота (правда, відома пізніше); під нею — P у кожен T до поточного (кожне число — з канви 1100 × 8, що закінчується в тому T), пунктир — поріг, жовта смужка — мітка, риски — сигнали | `/api/buyval/<прогін>/<епоха>` |
| увесь val | та сама пара полотен на всьому val, сіра риска — поточний T | `/api/buyval/<прогін>/<епоха>` |

**Висота полотен.** Під кожним із чотирьох полотен — смужка: тягнеш
мишкою вниз чи вгору — висота міняється (50 … 1200 px), відпустив —
збережено. Висоти лежать у `localStorage` під ключем `buyval.settings`
(`{"heights": {price, prob, allprice, allprob}}`, за замовчуванням 300,
150, 220, 120 px) і відновлюються в наступних сесіях браузера.

**Кнопки переможця торгівлі** — окремий рядок під кнопками прогонів, дві
кнопки ★ `BUY_pos` е9 етапу 20 (з `/api/buyval-signal`): «тейк 2 % від
найнижчої ціни» (`star`, `detail`) і «тейк 2 % від ціни входу» (`entry`) —
для порівняння на око; на кнопці — прогін, епоха, вікно суми, θ, тейк,
стоп і гроші на кінець val. Натиснув — обираються прогін і епоха ★, і обидві
пари полотен показують торгівлю: під ціною замість P — сума P у вікні ★
кожен T, пунктир — θ, риски — кроки з сигналом; на ціні — угоди ★:
квадрат — вхід, відрізок до виходу (зелений — у плюс, червоний — у мінус).
На вікні 160 год до T — лише те, що відомо в T: угода, відкрита в T, —
пунктир до ціни в T, тейк сходинкою за найнижчою ціною після входу
(`trades[].take` — [час, рівень] на кожній зміні) і стоп від ціни входу; на всьому val — усі угоди.
Рядок стану — сума і сигнал у T, позиція (вхід, тейк, стоп, зміна ціни),
закриті до T угоди і гроші, підсумок ★ на всьому val. Кнопка прогону чи
епохи вимикає режим переможця.

**Сигнал купівлі і торгівля (етап 20)** — блок під полотнами, свій
ендпоінт `/api/buyval-signal` (`results/canvas1100_buy/signal_pick.json`),
вантажиться незалежно від решти вкладки: правила угоди й еталона,
параметри ★, таблиця: перший рядок — зафіксований ★, далі найкраща
комбінація гріду кожного прогону, ціна val із ногами вгору еталона (жовті смуги) і угодами ★
(відрізок від входу до виходу: зелений — у плюс, червоний — у мінус),
під нею — сума P у вікні ★ з пунктиром θ; згорнуто — цикли еталона з
розривом і угоди ★. Висоти двох полотен — смужками, ключі `sigprice` і
`sigsum` у тому самому `buyval.settings` (за замовчуванням 300 і 140 px).
Без файлу блок показує команду.

Без прогонів вкладка показує команду, якою вони робляться. Тест —
`tests/test_dashboard.py` → `test_buyval_payloads_and_markup`.

## Результат і висновки

### Результат 1: датасет канви 600

| Частина | Ніг | Вікон | Зон початку | Зон кінця | Інших півотів 2.3 | Зон корекцій |
| ------- | --: | ----: | ----------: | --------: | ----------------: | -----------: |
| train | 1210 | 9068 | 5373 | 5434 | 6098 | 93 382 |
| val | 352 | 2250 | 1304 | 1339 | 1759 | 30 887 |

Зони рахуються по всіх вікнах: один півот потрапляє в кілька вікон
своєї ноги. Вікна `near` додали 1722 вікна train і 496 val.

### Результат 2: уточнений сигнал

Обрано (★): усі 7 фіч, вікно 3 рядки (`h = 1`), `mean`, пошук піку —
рядок півота ± 2 рядки (`P = 2`), `abs`, `q = 0.7`, `τ = 0.265`. Сигнал
є в 76 % зон початку, 75 % зон кінця і 64 % зон корекцій, у контролях —
у 51–58 %.

Кореляції частин на базових канвах (Пірсон між вікнами різних ніг):

| train | початок | кінець | корекція | до ноги | тіло | після ноги |
| ----- | ------: | -----: | -------: | ------: | ---: | ---------: |
| початок | **0.487** | 0.468 | 0.293 | −0.001 | −0.193 | −0.007 |
| кінець | 0.468 | **0.450** | 0.284 | 0.004 | −0.180 | −0.003 |
| корекція | 0.293 | 0.284 | **0.199** | 0.031 | −0.074 | 0.030 |
| до ноги | −0.001 | 0.004 | 0.031 | 0.043 | 0.060 | 0.047 |
| тіло | −0.193 | −0.180 | −0.074 | 0.060 | 0.157 | 0.066 |
| після ноги | −0.007 | −0.003 | 0.030 | 0.047 | 0.066 | 0.050 |

Розрив: початок 0.488, кінець 0.445, корекція 0.168, бал 0.367 (train);
на val — 0.515, 0.520, 0.175, бал 0.404.

- Сигнал півота 2.3 стійкий: вікна півотів різних ніг корелюють між
  собою на 0.45–0.49, з тілом ноги — від'ємно (−0.18 … −0.19), і на val
  так само.
- Початок і кінець ноги — один сигнал (0.468 між ними).
- Корекція — слабша версія того самого підпису: 0.28–0.29 з півотами,
  0.20 сама з собою, від тіла відходить на 0.17.
- Контролі між собою майже не корелюють (0.04–0.16): пік, узятий у вікні
  тієї самої довжини, сам по собі схожості не дає.
- Варіанти з `q = 0.9` дають більший бал (до 0.550), але сигнал
  лишається лише в 38–53 % зон півота і 23–37 % зон корекцій, і не
  проходять умову 60 %.

Уточнені мітки:

| Частина | Зон півота з сигналом | Зон корекції з сигналом | Рядків півота до → після | Рядків корекції до → після | Рядків −1 після |
| ------- | --------------------: | ----------------------: | -----------------------: | -------------------------: | --------------: |
| train | 12 665 з 16 896 | 58 740 з 93 099 | 248 249 → 41 267 | 265 666 → 145 344 | 416 968 |
| val | 3482 з 4371 | 19 749 з 30 481 | 54 926 → 11 819 | 75 515 → 46 954 | 103 038 |

### Результат 3: фічі опору й підтримки біля півота, корекції й у тілі

Середнє `|x|` фічі на зсувах −12 … −3 і +3 … +12 рядків від піку
(train; сам пік не береться — його обирає сила сигналу):

| Фіча | Початок | Кінець | Корекція | Тіло ноги |
| ---- | ------: | -----: | -------: | --------: |
| `d_resist_buy` | 0.14 / 0.12 | 0.15 / 0.13 | 0.19 / 0.18 | 0.26 / 0.27 |
| `d_bal_resist_buy` | 0.16 / 0.15 | 0.16 / 0.16 | 0.20 / 0.20 | 0.24 / 0.24 |
| `d_support_sell` | 0.15 / 0.12 | 0.16 / 0.13 | 0.18 / 0.18 | 0.26 / 0.26 |
| `d_bal_support_sell` | 0.16 / 0.16 | 0.17 / 0.16 | 0.19 / 0.20 | 0.24 / 0.23 |
| `d_up` | 0.36 / 0.36 | 0.34 / 0.35 | 0.29 / 0.29 | 0.18 / 0.19 |
| `d_down` | 0.35 / 0.35 | 0.34 / 0.35 | 0.30 / 0.29 | 0.18 / 0.19 |

(до піку / після піку)

- Біля півота 2.3 фічі опору й підтримки найслабші, у корекції —
  сильніші, у тілі ноги — найсильніші. `d_up` і `d_down` ідуть навпаки.
- Корекція лежить між півотом і тілом на всіх шести фічах: це той самий
  підпис меншої сили.

### Результат 4: сусідні півоти однієї ноги

| | train, усі (737) | train, обидва з сигналом (410) | val, усі (177) | val, обидва з сигналом (92) |
| --- | --: | --: | --: | --: |
| **початок ↔ кінець своєї ноги** | 0.384 | 0.431 | 0.398 | 0.448 |
| початок ↔ кінець чужої ноги | 0.412 | 0.443 | 0.421 | 0.460 |
| початок ↔ тіло своєї канви | −0.103 | −0.121 | −0.067 | −0.083 |
| кінець ↔ тіло своєї канви | −0.080 | −0.107 | −0.049 | −0.027 |
| різниця «своя − чужа», 95 % | −0.028 [−0.066 … 0.008] | −0.012 [−0.062 … 0.038] | −0.023 [−0.093 … 0.048] | −0.012 [−0.114 … 0.092] |

- Сусідні півоти 2.3 однієї ноги схожі між собою (0.38–0.45) і
  відрізняються від тіла своєї ж канви.
- Своя пара не схожіша за чужу: інтервал різниці всюди перетинає 0.
  Підпис півота 2.3 — спільний для всіх ніг, а не свій для кожної пари
  початок / кінець.

### Результат 5: мережа на три класи, перший прогін

Ваги класів 1 / 3 / 3, λ = 1, батч 32 (кусками по 8), MPS, ~47 с на
епоху. Стоп після епохи 10, найкраща — **7** (середнє F1 на відкладених
0.334), пороги: півот 0.20, корекція 0.40.
`models/canvas600/epoch_NN.pt`, `history.json`.

| Вибірка | Півот: точність | повнота | F1 | сплутано з корекцією | Корекція: точність | повнота | F1 | сплутано з півотом |
| ------- | --: | --: | --: | --: | --: | --: | --: | --: |
| відкладені train | 0.400 | 0.426 | **0.413** | 305 з 2782 | 0.215 | 0.310 | **0.254** | 1007 з 10 405 |
| val, усі монети | 0.383 | 0.380 | **0.381** | 415 з 3291 | 0.230 | 0.257 | **0.243** | 1228 з 12 229 |
| val BTC | 0.454 | 0.434 | 0.443 | 40 з 388 | 0.226 | 0.257 | 0.241 | 115 з 1001 |
| val ETH | 0.370 | 0.438 | 0.401 | 94 з 640 | 0.237 | 0.305 | 0.266 | 220 з 2076 |
| val SOL | 0.354 | 0.345 | 0.350 | 97 з 632 | 0.239 | 0.225 | 0.232 | 230 з 2461 |
| val XRP | 0.373 | 0.336 | 0.353 | 78 з 611 | 0.231 | 0.235 | 0.233 | 289 з 2628 |
| val BNB | 0.435 | 0.383 | 0.407 | 32 з 384 | 0.218 | 0.273 | 0.242 | 151 з 1502 |
| val DOGE | 0.360 | 0.378 | 0.369 | 74 з 636 | 0.226 | 0.278 | 0.250 | 223 з 2561 |

- Мережа знаходить 38 % зон півота 2.3 на val, і 38 % її сигналів
  півота влучають у зону півота. Корекцію вона знаходить гірше: F1 0.24.
- Сплутування: сигнал півота в зоні корекції — 13 % сигналів півота
  (val); сигнал корекції в зоні півота — 10 % сигналів корекції.
- val тримається на рівні відкладених train (0.381 проти 0.413 для
  півота, 0.243 проти 0.254 для корекції): перенавчання немає.

### Результат 6: ряд val, епоха 7

Ковзні вікна по 2400 записів з кроком 300, пороги: півот 0.20,
корекція 0.40. `results/canvas600_val.json`,
`results/val/series_<PAIR>_e07.npz`.

| Монета | Півот: точність | повнота | F1 | добрих / сигналів | сплутано | Корекція: точність | повнота | F1 | добрих / сигналів | сплутано |
| ------ | --: | --: | --: | --: | --: | --: | --: | --: | --: | --: |
| **усі** | 0.055 | 0.181 | 0.084 | 74 / 1354 | 108 | 0.099 | 0.063 | 0.077 | 146 / 1477 | 114 |
| BTC_USDT | 0.045 | 0.222 | 0.075 | 7 / 154 | 15 | 0.062 | 0.035 | 0.045 | 6 / 96 | 11 |
| ETH_USDT | 0.050 | 0.195 | 0.080 | 11 / 219 | 26 | 0.097 | 0.088 | 0.092 | 25 / 258 | 16 |
| SOL_USDT | 0.044 | 0.175 | 0.071 | 10 / 226 | 17 | 0.102 | 0.056 | 0.072 | 27 / 266 | 20 |
| XRP_USDT | 0.059 | 0.147 | 0.084 | 17 / 290 | 19 | 0.110 | 0.062 | 0.080 | 39 / 353 | 26 |
| BNB_USDT | 0.066 | 0.286 | 0.107 | 12 / 183 | 15 | 0.127 | 0.102 | 0.113 | 20 / 158 | 14 |
| DOGE_USDT | 0.060 | 0.165 | 0.088 | 17 / 282 | 16 | 0.084 | 0.054 | 0.065 | 29 / 346 | 27 |

- На ряді мережа працює набагато гірше, ніж на вікнах val: точність
  сигналу півота — 4–7 % проти 38 % на вікнах. Повнота півота — 15–29 %.
- Ймовірна причина, не перевірена: вікна навчання будуються навколо
  ноги і масштабуються під її довжину, а ковзне вікно ряду має сталу
  довжину (20 год) і не прив'язане до ніг.

### Результат 7: k-means на 2 кластери на картах UMAP

Склад кластерів (метрика `cosine`; `euclidean` і `manhattan` дають той
самий поділ):

| Вибірка | Кластер | Початок | Кінець | Корекція | Тіло ноги |
| ------- | ------- | ------: | -----: | -------: | --------: |
| train | 1, «півотний» | 440 (79 %) | 411 (74 %) | 652 (54 %) | 187 (16 %) |
| train | 2, «тілесний» | 120 (21 %) | 145 (26 %) | 548 (46 %) | 1013 (84 %) |
| val | 1, «півотний» | 105 (82 %) | 109 (82 %) | 676 (56 %) | 80 (15 %) |
| val | 2, «тілесний» | 23 (18 %) | 24 (18 %) | 524 (44 %) | 451 (85 %) |

- Карта сама ділиться на «півотний» кластер (≈ 80 % початків і кінців,
  ≈ 15 % тіла) і «тілесний» (≈ 85 % тіла) — і на val так само.
- Корекції розходяться майже навпіл (54–56 % проти 44–46 %): частина
  корекцій має підпис півота, частина — підпис тіла.

### Результат 8: HDBSCAN на картах UMAP

| Вибірка | Метрика | Кластерів | Кластер 1: початок / кінець / корекція / тіло | Шум, точок |
| ------- | ------- | --------: | -------------------------------------------- | ---------: |
| train | cosine | 2 | 420 / 380 / 600 / 145 | 125 |
| train | euclidean | 7 | 397 / 365 / 520 / 76 | 683 |
| train | manhattan | 3 | 418 / 377 / 557 / 81 | 176 |
| val | cosine | 2 | 104 / 110 / 656 / 82 | 77 |
| val | euclidean | 5 | 79 / 85 / 487 / 28 | 536 |
| val | manhattan | 3 | 98 / 107 / 624 / 58 | 82 |

- На `cosine` HDBSCAN сам знаходить ті самі 2 кластери, що й k-means:
  «півотний» і «тілесний».
- На `euclidean` і `manhattan` «півотний» кластер лишається цілим, а
  «тілесний» розпадається на кілька дрібних; шуму на `euclidean`
  найбільше (683 точки train).

### Результат 9: що таке кластери 1 і 2

Рівень фічі — середнє `|x|` у вікні сигналу; AUC — «кластер 1 більше за
кластер 2» (карта `cosine`).

| Фіча | train: кластер 1 | кластер 2 | AUC | AUC на корекціях | val: кластер 1 | кластер 2 | AUC |
| ---- | --: | --: | --: | --: | --: | --: | --: |
| `d_up` | 0.69 | 0.14 | **0.97** | 0.97 | 0.67 | 0.15 | 0.97 |
| `d_down` | 0.69 | 0.15 | **0.97** | 0.97 | 0.65 | 0.15 | 0.96 |
| `d_resist_buy` | 0.03 | 0.36 | **0.02** | 0.03 | 0.04 | 0.35 | 0.03 |
| `d_bal_resist_buy` | 0.07 | 0.36 | **0.06** | 0.07 | 0.08 | 0.35 | 0.08 |
| `d_support_sell` | 0.03 | 0.36 | **0.03** | 0.04 | 0.04 | 0.36 | 0.04 |
| `d_bal_support_sell` | 0.07 | 0.35 | **0.08** | 0.08 | 0.09 | 0.36 | 0.08 |
| `d_price_avg` | 0.72 | 0.41 | **0.88** | 0.83 | 0.75 | 0.41 | 0.90 |

- **Кластер 1 — «рух без рівнів»**: у вікні сигналу різко змінюються
  `d_up`, `d_down` і ціна, а чотири фічі опору й підтримки майже
  стоять (0.03–0.07).
- **Кластер 2 — «рівні без руху»**: фічі опору й підтримки міняються
  (≈ 0.35), а `d_up` / `d_down` — слабо (0.14–0.15), ціна — помірно.
- Кластери розділені майже без перетину (AUC 0.97 і 0.02–0.08) і
  однаково на train і val. Корекції діляться тією самою ознакою.

Властивості зон (медіани, train; AUC «кластер 1 більше»):

| Властивість | Кластер 1 | Кластер 2 | AUC train | AUC val |
| ----------- | --: | --: | --: | --: |
| корекція: рух 0.8, який вона закінчує, % | 1.52 | 1.19 | 0.64 | 0.63 |
| корекція: довжина цього руху, записів | 124 | 190 | 0.41 | 0.34 |
| корекція: місце в нозі 2.3, частка | 0.49 | 0.51 | 0.49 | 0.57 |
| корекція: до найближчого півота 2.3, частка ноги | 0.17 | 0.25 | 0.41 | 0.40 |
| початок / кінець ноги: рух ноги, % | 4.30 / 4.75 | 3.69 / 4.56 | 0.57 | 0.58 |
| початок / кінець ноги: довжина ноги, записів | 1902 / 2384 | 1583 / 2299 | 0.51 | 0.45 |

- Корекції кластера 1 — більші (1.5 % проти 1.2 %), швидші (124 записи
  проти 190) і ближчі до краю ноги (0.17 проти 0.25 ноги): вони схожі на
  півот і за підписом, і за розміром.
- Корекції кластера 2 — менші, повільніші і ближчі до середини ноги.
- Півоти 2.3 у кластері 2 (≈ 20 % усіх) закінчують трохи менші ноги
  (AUC 0.57–0.58); за довжиною ноги різниці немає.

### Результат 10: мережа кластера 1

**Правило кластера 1** збігається з k-means на 97.6 % точок train і на
95.9 % точок val (AUC 0.998 / 0.994). Мітки: train — 34 379 зон кластера
1 з 54 810 зон із сигналом (67 310 рядків `1`), val — 10 808 з 17 100
(19 183 рядки). `models/canvas600_c1/assigner.json`.

**Навчання**: стоп після епохи 7, найкраща — **4**, поріг 0.50, ~50 с на
епоху. `models/canvas600_c1/`.

Вікна val (сигнал — пік у ±10 рядках; добрий — у зоні кластера 1):

| Вибірка | Точність | Повнота | F1 | Добрих / сигналів | У зоні півота 2.3 | У зоні корекції | Поза зонами |
| ------- | --: | --: | --: | --: | --: | --: | --: |
| відкладені train | 0.297 | 0.302 | 0.299 | 2094 / 7061 | 1500 | 1447 | 4114 |
| val, усі | 0.343 | 0.244 | 0.285 | 2638 / 7682 | 1818 | 1718 | 4146 |
| val BTC | 0.349 | 0.273 | 0.306 | 307 / 880 | 222 | 177 | 481 |
| val ETH | 0.362 | 0.282 | 0.317 | 504 / 1391 | 342 | 320 | 729 |
| val SOL | 0.357 | 0.212 | 0.266 | 497 / 1391 | 325 | 341 | 725 |
| val XRP | 0.358 | 0.223 | 0.275 | 500 / 1396 | 359 | 298 | 739 |
| val BNB | 0.333 | 0.264 | 0.294 | 349 / 1049 | 246 | 228 | 575 |
| val DOGE | 0.305 | 0.241 | 0.269 | 481 / 1575 | 324 | 354 | 897 |

Ряд val (ковзні вікна етапу 3, пік у ±60 записах), епоха 4:

| Монета | Сигналів | У зоні півота 2.3 | У зоні корекції | Поза зонами | Півотів знайдено | Корекцій знайдено |
| ------ | --: | --: | --: | --: | --: | --: |
| **усі** | 1401 | 114 (8 %) | 138 (10 %) | 1149 (82 %) | 98 з 359 (27 %) | 138 з 2295 (6 %) |
| BTC | 183 | 14 | 17 | 152 | 12 з 27 | 17 з 173 |
| ETH | 246 | 18 | 27 | 201 | 14 з 41 | 26 з 285 |
| SOL | 233 | 21 | 24 | 188 | 18 з 57 | 25 з 480 |
| XRP | 260 | 22 | 26 | 212 | 20 з 102 | 27 з 628 |
| BNB | 184 | 17 | 19 | 148 | 13 з 35 | 18 з 187 |
| DOGE | 295 | 22 | 25 | 248 | 21 з 97 | 25 з 542 |

- На вікнах val мережа знаходить чверть зон кластера 1 і третина її
  сигналів влучає в такі зони; val не гірший за відкладені train.
- Сигнали на вікнах лягають у зону півота 2.3 і в зону корекції приблизно
  порівну (1818 і 1718), більшість — поза зонами (4146).
- На ряді val поза зонами — 82 % сигналів; знайдено 27 % півотів 2.3
  (у мережі етапу 2 на тому самому ряді — 18 %).

### Результат 11: канва 200 — блоки 7 | 7 | 7 проти поточного UMAP

Блоків на базових канвах: train — півот 2201, корекція 6066, зона без
сигналу 16 724, тіло 105 480, поза ногою 16 180; val — 574, 1908, 4030,
24 874, 3837.

| Міра | train | val |
| ---- | --: | --: |
| точок поточної карти | 3516 | 1992 |
| `T = V` — пік у середньому рядку свого блоку | 33.6 % | 36.5 % |
| косинус `V` і `T`, медіана | 0.891 | 0.898 |
| косинус `V` і `T`, 10-й перцентиль | 0.654 | 0.635 |
| правило кластера 1: те саме рішення на `V` і на `T` | 94.3 % | 94.7 % |
| правило на `V` = k-means | 97.6 % | 95.9 % |
| правило на `T` = k-means | 93.6 % | 92.3 % |
| 15 сусідів `V` (без себе) — кластер самої точки | 98.9 % | 98.3 % |
| 15 сусідів `T` серед точок карти — кластер самої точки | 93.7 % | 92.8 % |

| Частина | train: точок | `T = V` | косинус | правило те саме | val: точок | `T = V` | косинус | правило те саме |
| ------- | --: | --: | --: | --: | --: | --: | --: | --: |
| початок ноги | 560 | 20.9 % | 0.894 | 95.4 % | 128 | 20.3 % | 0.890 | 93.0 % |
| кінець ноги | 556 | 47.3 % | 0.959 | 93.2 % | 133 | 49.6 % | 0.993 | 95.5 % |
| корекція | 1200 | 34.8 % | 0.899 | 93.8 % | 1200 | 36.1 % | 0.904 | 93.9 % |
| тіло ноги | 1200 | 32.0 % | 0.837 | 94.9 % | 531 | 38.0 % | 0.856 | 96.6 % |

- Блок сітки 7 | 7 | 7 збігається з вектором точки тільки тоді, коли пік
  стоїть у середньому рядку блоку, — це третина точок. В інших двох
  третинах блок зсунутий на рядок; косинус падає до 0.65 у кожної десятої
  точки.
- Кластер при цьому здебільшого той самий: правило кластера 1 дає те саме
  рішення на 94–95 % точок, а блок лягає серед сусідів свого кластера на
  93 % проти 98–99 % у самого вектора. Приблизно 6–7 % точок блок сітки
  переносить в інший кластер.

### Результат 12: алгоритм на вікні канви проти мережі

Формула `sum7` (ваги в сирих одиницях, `results/canvas600_rule.json`):

| Вхід | тіло | корекція | півот 2.3 |
| ---- | --: | --: | --: |
| `d_up` | −2.82 | 0.93 | 1.88 |
| `d_down` | −2.85 | 0.86 | 1.99 |
| `d_resist_buy` | −0.36 | 0.40 | −0.04 |
| `d_bal_resist_buy` | −2.89 | 1.34 | 1.55 |
| `d_support_sell` | −1.04 | −0.10 | 1.14 |
| `d_bal_support_sell` | −2.38 | 1.80 | 0.59 |
| `d_price_avg` | −4.50 | 2.01 | 2.49 |
| `b` | 7.41 | −2.40 | −5.01 |

Пороги: `sum7` — півот 0.25, корекція 0.45; `cat21` — півот 0.20,
корекція 0.45.

| Вибірка | Хто | Півот: точність | повнота | F1 | добрих / сигналів | сплутано | Корекція: точність | повнота | F1 | добрих / сигналів | сплутано |
| ------- | --- | --: | --: | --: | --: | --: | --: | --: | --: | --: | --: |
| відкладені train | формула `sum7` | 0.184 | 0.442 | 0.260 | 814 / 4427 | 940 | 0.141 | 0.278 | 0.187 | 1357 / 9644 | 1032 |
| | формула `cat21` | 0.173 | 0.497 | 0.256 | 987 / 5717 | 1100 | 0.141 | 0.278 | 0.187 | 1360 / 9642 | 1051 |
| | мережа, епоха 7 | 0.400 | 0.426 | **0.413** | 1114 / 2782 | 305 | 0.215 | 0.310 | **0.254** | 2240 / 10 405 | 1007 |
| val, усі монети | формула `sum7` | 0.219 | 0.451 | 0.295 | 1087 / 4958 | 1185 | 0.155 | 0.239 | 0.188 | 1862 / 11 992 | 1330 |
| | формула `cat21` | 0.195 | 0.502 | 0.281 | 1287 / 6591 | 1441 | 0.155 | 0.239 | 0.188 | 1865 / 12 053 | 1335 |
| | мережа, епоха 7 | 0.383 | 0.380 | **0.381** | 1261 / 3291 | 415 | 0.230 | 0.257 | **0.243** | 2817 / 12 229 | 1228 |

- Формула по вікну з 3 рядків знаходить зони півота не гірше за мережу
  (повнота 0.45–0.50 проти 0.38 на val), але її сигнал півота влучає в
  зону півота вдвічі рідше: точність 0.20–0.22 проти 0.38.
- Півот від корекції формула розрізняє погано: 24 % її сигналів півота
  (1185 з 4958) стоять у зоні корекції, у мережі — 13 %.
- Корекцію формула знаходить гірше за мережу: F1 0.19 проти 0.24.
- 21 число замість 7 рівнів нічого не дає: F1 півота 0.28 проти 0.30,
  корекції — однаково.
- У формулі півот і корекція мають ті самі знаки ваг (плюс на
  `d_up`, `d_down`, `d_price_avg` і парах балансу) — вікно з 3 рядків
  бачить «рух без рівнів» і на ньому не відділяє півот від корекції.
  Мережа бачить усі 600 рядків; чи її перевага в точності йде саме з
  контексту ноги — не перевірено.

### Результат 13: канва 1100 на записах 100 с

| Монета | Записів | Розривів | Без похідної | Ніг | Ніг ≥ 7 год | Медіана ноги, год | Півотів | Корекцій | Канв |
| ------ | --: | --: | --: | --: | --: | --: | --: | --: | --: |
| BTC_USDT | 132 609 | 2695 | 2.0 % | 134 | 102 | 21.0 | 135 | 682 | 60 |
| ETH_USDT | 134 287 | 2690 | 2.0 % | 205 | 132 | 12.9 | 206 | 1011 | 58 |
| SOL_USDT | 133 226 | 2681 | 2.0 % | 266 | 155 | 9.8 | 267 | 1200 | 57 |
| XRP_USDT | 119 069 | 2641 | 2.2 % | 168 | 108 | 13.9 | 169 | 785 | 56 |
| BNB_USDT | 133 852 | 2684 | 2.0 % | 113 | 92 | 25.3 | 114 | 640 | 61 |
| DOGE_USDT | 119 070 | 2643 | 2.2 % | 247 | 141 | 10.9 | 248 | 954 | 42 |

Разом 334 канви, рядок канви — у середньому 438 с. Подій у канвах:
півотів 2.3 — 574, корекцій 0.8 — 3269; на карті — усі.

Частка півотів серед 15 найближчих точок на карті (півотів на карті
14.9 %):

| Метрика | у півота | у корекції |
| ------- | --: | --: |
| cosine | 0.188 | 0.141 |
| euclidean | 0.197 | 0.145 |
| manhattan | 0.194 | 0.142 |

- Півоти 2.3 і корекції 0.8 на карті майже перемішані: у сусідах півота
  півотів 19–20 % проти 14.9 % при повному змішуванні. Окремого гурту
  півотів рядок події на канві 1100 не дає.

### Результат 14: мережа на канві 1100

Канв: навчання 940, відкладені 374, val 268. Найкраща епоха — **4**
(стоп після 8, ~20 с на епоху), поріг 0.30. `models/canvas1100/`,
`results/canvas1100_net.json`.

| Вибірка | Хто | Точність | Повнота | F1 | Добрих / сигналів | Зон знайдено | Сплутано |
| ------- | --- | --: | --: | --: | --: | --: | --: |
| відкладені train | мережа | 0.125 | 0.417 | **0.192** | 782 / 6265 | 732 / 1757 | 958 |
| | випадкові сигнали | 0.043 | 0.134 | 0.065 | 267 / 6265 | 235 / 1757 | 370 |
| val, усі монети | мережа | 0.146 | 0.410 | **0.215** | 566 / 3875 | 529 / 1291 | 713 |
| | випадкові сигнали | 0.036 | 0.101 | 0.053 | 138 / 3875 | 130 / 1291 | 276 |
| | позиційний прогноз | 0.040 | 0.290 | 0.071 | — / 10 451 | — | — |
| val BTC | мережа | 0.168 | 0.492 | 0.250 | 145 / 865 | 129 / 262 | 99 |
| val ETH | мережа | 0.132 | 0.401 | 0.199 | 109 / 825 | 109 / 272 | 161 |
| val SOL | мережа | 0.137 | 0.364 | 0.199 | 68 / 495 | 68 / 187 | 124 |
| val XRP | мережа | 0.190 | 0.454 | 0.268 | 89 / 469 | 79 / 174 | 97 |
| val BNB | мережа | 0.129 | 0.382 | 0.193 | 106 / 823 | 102 / 267 | 174 |
| val DOGE | мережа | 0.123 | 0.326 | 0.179 | 49 / 398 | 42 / 129 | 58 |

- Мережа знаходить 41 % зон півота 2.3 на val, і 15 % її сигналів
  влучають у зону півота — учетверо частіше за випадкові сигнали тієї
  самої кількості (3.6 %) і за позиційний прогноз (4.0 %).
- val не гірший за відкладені train (F1 0.215 проти 0.192).
- Сплутано: 18 % сигналів стоять у зоні корекції 0.8.
- Зони рахуються по канвах, а канви перекриваються (крок — одна нога,
  4 зсуви): незалежних одиниць — ноги val, їх менше за 1291 зону.

### Результат 15: три голови, втрати, довші вікна і торгівля

Коло A — 4 ноги, val усіх монет (у дужках — випадкові сигнали):

| Прогін | Епоха | Середній F1 відкладені | Півот F1 | Корекція F1 | Бік правильний | Перемикання F1 |
| ------ | --: | --: | --: | --: | --: | --: |
| `A_wbce` | 2 | 0.141 | 0.222 (0.057) | 0.179 (0.069) | 0.588 | 0.055 |
| `A_focal` | 6 | 0.135 | 0.185 (0.053) | 0.166 (0.066) | 0.561 | 0.069 |
| `A_dice` | 6 | 0.143 | 0.224 (0.051) | 0.178 (0.067) | 0.579 | 0.064 |
| `A_swap` | 2 | 0.139 | 0.219 (0.055) | 0.175 (0.070) | 0.586 | 0.054 |

Коло B — `dice`, val на канвах 4 / 6 / 8 ніг:

| Прогін | Епоха | Середній F1 відкладені | Півот F1 4 / 6 / 8 | Корекція F1 4 / 6 / 8 | Бік, усі | Перемикання F1, усі |
| ------ | --: | --: | --- | --- | --: | --: |
| `A_dice` (лише 4 ноги) | 6 | 0.143 | 0.225 / 0.237 / 0.204 | 0.173 / 0.178 / 0.188 | 0.579 | 0.064 |
| `B_mix` (4 + 6 + 8, з нуля) | 1 | 0.143 | 0.213 / 0.229 / 0.189 | 0.185 / 0.196 / 0.214 | 0.587 | 0.057 |
| `B_tune` (4 + 6 + 8, з `A_dice`) | 1 | **0.146** | 0.220 / 0.240 / 0.185 | 0.180 / 0.188 / 0.206 | 0.586 | 0.063 |

Торгівля `B_tune` у живому часі на val, $1000, 1888 рішень на монету:

| Монета | Перевертань | З витратами | Холд | Випадкові: медіана / найкращий | Без витрат | Випадкові без витрат: медіана / найкращий | Перевертань у зоні півота | Півотів val з перевертанням |
| ------ | --: | --: | --: | --- | --: | --- | --: | --: |
| BTC | 584 | $502.73 | $1358.62 | $415.65 / $537.98 | $1144.27 | $943.05 / $1220.61 | 32 | 18 з 25 |
| ETH | 549 | $498.44 | $1456.31 | $478.63 / $622.22 | $1071.09 | $1034.01 / $1344.21 | 27 | 17 з 37 |
| SOL | 433 | $812.37 | $1545.32 | $516.11 / $710.70 | $1491.84 | $947.80 / $1305.14 | 26 | 13 з 48 |
| XRP | 481 | $668.82 | $1555.46 | $444.12 / $706.55 | $1295.22 | $872.30 / $1387.74 | 22 | 15 з 91 |
| BNB | 517 | $455.68 | $1283.93 | $486.72 / $609.06 | $941.29 | $1005.41 / $1258.11 | 22 | 16 з 33 |
| DOGE | 445 | $683.42 | $1424.34 | $483.17 / $699.96 | $1276.31 | $902.33 / $1307.20 | 30 | 18 з 88 |

- Функція втрат майже нічого не міняє: середній F1 чотирьох втрат на
  відкладених — 0.135 … 0.143, різниця в межах шуму.
- Довші вікна трохи піднімають корекцію (F1 0.18 → 0.19–0.20 на val),
  півот — ні; на 8 ногах півот гірший (0.19–0.20 проти 0.22–0.24 на 4 і
  6).
- Друга голова знаходить корекції 0.8 утричі частіше за випадкові
  сигнали (F1 0.19 проти 0.07).
- Голова боку правильна на 58–59 % рядків і в канві, яка бачить дані
  після рядка; перемикання влучають у зону півота рідко (F1 0.06).
- **Торгівля збиткова на всіх шести монетах**: $456 … $812 проти холду
  $1284 … $1555. Причина — частота: 433 … 584 перевертань за 40 діб
  (кожні 2–3 години), кожне коштує 0.14 % витрат. Без витрат голова на
  5 монетах з 6 краща за медіану випадкових перевертань тієї самої
  частоти, на SOL — краща за всі 20 (найкращий $1305 проти $1492); на
  BNB — гірша за медіану. Тобто в боці є слабкий сигнал, але не
  настільки сильний, щоб пережити витрати при такій частоті.
- Вимога «прибуткова завжди в ринку» не виконана.

### Результат 16: голова «бік ноги» до 22.09

Продовжені датасети збігаються з підтвердженими побітово на всіх
спільних подіях: `клас210х10-1х7д/д` BTC і DOGE — train однаковий, 9412
і 9408 старих подій val однакові; `BTC_USDT_29 / клас210х14х4ц` — 43 859
старих подій однакові. Кеш ніг: train — ті самі 451 нога й канали, val —
143 ноги замість 103.

| Монета | Подій з видачею: було (33) | стало | Спільних, різниця видачі | Видача на val | Подій val з видачею |
| ------ | --: | --: | --: | --- | --: |
| BTC | 30 300 | 32 028 | 30 300, **0.0** | 15.08 … 14.09 | 5277 з 15 944 |
| ETH | 49 086 | 56 114 | 49 086, **0.0** | 15.08 … 21.09 | 11 332 з 15 929 |
| SOL | 46 712 | 53 141 | 46 712, **0.0** | 16.08 … 22.09 | 10 403 з 15 922 |
| XRP | 42 066 | 48 492 | 42 066, **0.0** | 17.08 … 22.09 | 10 058 з 15 920 |
| BNB | 43 552 | 50 904 | 43 552, **0.0** | 19.08 … 22.09 | 10 057 з 15 920 |
| DOGE | 42 313 | 49 556 | 42 313, **0.0** | 14.08 … 22.09 | 12 188 з 15 918 |

- Ланцюжок відтворює дослідження 33 точно: на всіх спільних подіях
  видача голови однакова до останнього знака.
- Видача на val тепер іде до 21–22.09; на BTC — до 14.09. Канали
  `split` і `zone` існують лише всередині ніг зігзага 2.3 — після
  останнього півота ряду (BTC — 14.09) ноги ще немає, як і в дослідженні
  33, де ці канали кінчались 01–04.09.

Виняток `/umap600` (`results/heads33_holes/`):

| Монета | Подій val з видачею: стандарт → виняток | Спільні з рядом 33: макс. / медіана різниці | Лишились проміжки > 3 год |
| ------ | --- | --- | --- |
| BTC | 5277 → 9453 | 0.0 / 0.0 | 14.08 … 15.08 14:08; 09.09 20:16 … 23:23; 11.09 19:20 … 12.09 05:21; 12.09 09:19 … 13:08; 12.09 14:35 … 17:45 |
| ETH | 11 332 → 15 364 | 0.0 / 0.0 | 14.08 … 15.08 09:35 |
| SOL | 10 403 → 14 721 | 0.0 / 0.0 | 14.08 … 16.08 22:48 |
| XRP | 10 058 → 14 676 | 0.366 / 0.0007 | 14.08 … 17.08 00:40 |
| BNB | 10 057 → 14 056 | 0.514 / 0.0005 | 14.08 … 18.08 13:36 |
| DOGE | 12 188 → 15 661 | 0.0 / 0.0 | 14.08 … 14.08 15:25 |

- Діри 07–14.09 заповнені на всіх монетах.
- У XRP і BNB нога, що перетинає 14.08, мала діру понад годину; з
  винятком вона заходить своїм шматком train у статистики на train, тож
  старі числа цих двох монет зсунулись (медіана 0.0005–0.0007, максимум
  0.37 і 0.51). Решта монет збігаються з рядом 33 точно.
- Хвіст після останнього півота ряду — відкрита нога (`tail_of`,
  `open_known`): видача на всіх монетах до кінця val, 22.09 20:53.
- Що лишилось порожнім і чому: початок val до першої ноги, що має всі
  канали (15–18.08);
  на BTC 9–12.09 — горизонти hazard: `BTC_USDT_29` зібраний без
  заповнення пропусків, і в цих годинах подій `клас210х14х4ц` немає.


### Результат 17: скільки даних у вікні канви 1100

Етап 10, `results/canvas1100_window_BTC_USDT.json`; мапа —
`data/canvas1100_window/BTC_USDT_map.npz` (73 777 вікон, 22 хв на CPU).
val BTC: 33 984 записи, 25 півотів 2.3, 146 корекцій 0.8. Модель
`B_tune`.

**Голова 1 — півоти 2.3.** Найкраща клітинка обходу на кожному порозі
проти сталого вікна (найкраща довжина) і проти найкращого вікна кожного
початку мапи:

| поріг | обхід: F1 / точн. / повн. | довжина обходу, год | стале: довжина, год | стале: F1 / точн. / повн. | найкраще на початок: F1, довжина год (q25–q75), півотів |
| ----- | ------------------------- | ------------------: | ------------------: | ------------------------- | ------------------------------------------------------- |
| 0.3 | 0.340 / 0.235 / 0.84 | 436 | 400 | 0.282 / 0.189 / 0.88 | 0.375, 278 (172–364), 8 |
| 0.4 | 0.395 / 0.270 / 0.92 | 315 | 300 | 0.306 / 0.210 / 0.84 | 0.421, 224 (122–318), 7 |
| 0.5 | 0.423 / 0.302 / 0.92 | 262 | 330 | 0.318 / 0.242 / 0.88 | 0.470, 154 (100–250), 5 |
| 0.6 | 0.449 / 0.344 / 0.80 | 204 | 220 | 0.343 / 0.267 / 0.64 | 0.554, 118 (46–174), 3 |
| 0.7 | **0.538** / 0.430 / 0.76 | 65 | 176 | 0.350 / 0.328 / 0.68 | 0.726, 68 (40–142), 2 |
| 0.8 | **0.541** / 0.655 / 0.48 | 79 | 150 | 0.248 / 0.398 / 0.44 | 0.700, 98 (60–151), 2 |

Найкращий обхід: `right` 72 (2 год), `left` 576 (16 год), `min_len` 1152,
`drop` 0.2–0.3, `patience` 1. Повнота 1.0 (усі 25 півотів) — на порозі
0.4 з довгими вікнами (~444 год), точність там 0.22.

Обхід вибирає вікно за збігом із розміткою, тобто бачить відповідь: його
F1 — стеля методу, а не число, яке вийде в живому часі. Чесне число
без розмітки — стале вікно.

**F1 усіх вікон мапи за числом півотів 2.3 у вікні** (поріг 0.7):

| півотів у вікні | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 14 |
| --------------- | - | - | - | - | - | - | - | -- | -- | -- |
| F1 | 0.18 | 0.22 | 0.26 | **0.31** | 0.28 | 0.29 | 0.28 | 0.26 | 0.25 | 0.22 |
| медіана довжини, год | 54 | 70 | 104 | 132 | 166 | 192 | 260 | 316 | 374 | 420 |

На порозі 0.6 F1 росте до 4 півотів (0.30) і далі стоїть на 0.28–0.31.
Довжина найкращого вікна початку корелює з числом півотів у ньому
(r = 0.80–0.94), з F1 — слабо або навпаки (r від 0.46 до −0.52): оптимум
задає кількість ніг, а не години.

**Голова 2 — корекції 0.8.** Найкраща клітинка обходу: поріг 0.3, `right`
72, `left` 576, `min_len` 4392, `drop` 0.05, `patience` 3 — F1 0.262,
точність 0.232, повнота 0.555 (81 з 146), довжина 142 год (5 півотів).
Стале вікно — 140 год, F1 0.191, точність 0.165, повнота 0.623. За числом
півотів у вікні F1 майже рівний: 0.15–0.18 від 0 до 8 півотів, пік на
4–5, далі падає до 0.12.

**Висновки.**
- Голова півотів найточніша, коли у вікні **4 півоти 2.3** (3–4 ноги,
  медіана ~130 год на BTC val) — як канви навчання на 4 ноги; коротше
  вікно втрачає F1 швидко, довше — повільно.
- Стале вікно: краще F1 0.35 на 176 год і порозі 0.7. Обхід із
  розміткою дає 0.54 на 65–80 год — різниця є ціною того, що в живому
  часі кращий край невідомий.
- Механізм для живого часу, що випливає з мапи: лівий край вікна — на
  4-му з кінця підтвердженому півоті 2.3 мінус поле, правий — поточний
  запис; поріг голови півотів 0.6–0.7. На ряді val цим правилом він ще
  не перевірений.
- Голова корекцій від довжини вікна майже не залежить (F1 ≤ 0.26 навіть
  з розміткою).

### Результат 18: вершина, корекція й дно на циклі вікна

Етап 11, прогін `G_tune` (з `B_tune`), `results/canvas1100_grow/G_tune.json`.

- Вибірка циклу: 174 тис. канв train (навчання 129 057, відкладені
  40 519) і 34 743 val з 4.7 млн і 1.2 млн вікон повного циклу.
- 42 сходинки циклу + 6 епох усього циклу; найкраща — **епоха 45**,
  пороги вершина 0.9, корекція 0.65, дно 0.9. Середній F1 на відкладених
  зріс з 0.12 (епоха 1) до 0.194.
- Перша спроба зі спільним зваженим середнім втрати (як `dice` етапу 8)
  за дві епохи звела голови вершини й дна в нуль: зона свого класу —
  1.4–1.8 % живих рядків, `REPEAT` — 30–37 % з вагою 6. Втрату поділено
  на середнє по `POS` і зважене середнє по решті (розділ етапу 11, п. 6).

val, усі 34 743 вікна (у дужках — випадкові сигнали тієї самої кількості):

| голова | F1 | точність | повнота | сигналів | на `SWAP` | на `REPEAT` |
| ------ | -- | -------- | ------- | -------- | --------- | ----------- |
| вершина 2.3 | **0.212** (0.037) | 0.152 | 0.352 | 207 785 | 32 573 | 22 044 |
| корекція 0.8 | **0.167** (0.059) | 0.162 | 0.173 | 919 806 | 71 140 | — |
| дно 2.3 | **0.192** (0.023) | 0.149 | 0.268 | 146 510 | 25 598 | 13 815 |

За фазою циклу F1 вершина / корекція / дно: ріст 0.214 / 0.169 / 0.213,
стиск 0.215 / 0.173 / 0.183, ковзання 0.208 / 0.160 / 0.179; якорі-півоти
0.213 / 0.169 / 0.199, якорі-середини 0.211 / 0.166 / 0.185.

За числом півотів у вікні (вершина / корекція / дно):

| півотів | вікон | F1 |
| ------- | ----- | -- |
| 1 | 1 363 | 0.079 / 0.136 / 0.100 |
| 2 | 5 602 | 0.175 / 0.147 / 0.143 |
| 3 | 5 390 | 0.190 / 0.159 / 0.171 |
| 4 | 5 499 | 0.208 / 0.167 / 0.187 |
| 5 | 5 264 | 0.232 / 0.177 / 0.212 |
| 6 | 5 577 | 0.238 / 0.176 / 0.220 |
| 7 | 4 353 | 0.239 / 0.177 / 0.224 |
| 8 | 984 | 0.214 / 0.167 / 0.203 |

По монетах F1 вершина / дно: BTC 0.142 / 0.262, ETH 0.239 / 0.249, SOL
0.241 / 0.203, XRP 0.220 / 0.144, BNB 0.210 / 0.131, DOGE 0.208 / 0.165.

Висновки:
- Голови вершини й дна в 6–8 разів краще за випадкові сигнали, але
  точність ~0.15: на кожен добрий сигнал — 5–6 хибних; частина хибних —
  на корекціях (`SWAP`, 12–17 % сигналів) і повтори після свого півота
  (`REPEAT`, 9–11 %).
- Чим більше півотів у вікні, тим краще до 6–7 півотів; вікно з одним
  півотом майже не працює (F1 0.08–0.10).
- Корекція лишилась на рівні етапу 8 (0.167 проти 0.180 у `B_tune` на
  своїх канвах) і дає найбільше сигналів.

### Результат 19: випадкові вікна від 1 до 8 півотів

Етап 12, прогін `R_tune` (з `G_tune` епохи 45),
`results/canvas1100_random/R_tune.json`.

- Сталі вікна: відкладені — 2100, N 1…8: 306 / 335 / 311 / 278 / 287 /
  214 / 197 / 172 (у хвості train довгі вікна вміщаються рідше); val —
  2100, 231 … 285 на кожне N.
- 5 епох по 20 000 свіжих вікон (100 000 канв, 13–16 хв на епоху —
  темп задає збирання канв із секунд); стоп — 4 епохи без покращення
  середнього F1 відкладених після епохи 1 (0.2038; епохи 4 і 5 —
  0.2036 і 0.2033).
- Три найкращі епохи — **1, 4, 5** (кнопки на дашборді разом із `G_tune`
  е44 / е45 ★ / е46).

F1 (точність / повнота), у дужках — випадкові сигнали:

| модель | вибірка | вершина 2.3 | корекція 0.8 | дно 2.3 |
| ------ | ------- | ----------- | ------------ | ------- |
| `G_tune` е45 | цикл val, 34 743 | 0.212 (0.037) | 0.167 (0.059) | 0.192 (0.023) |
| `R_tune` е1 | цикл val | 0.219 (0.032) · 0.172 / 0.302 | 0.167 (0.058) | 0.208 (0.020) · 0.185 / 0.239 |
| `R_tune` е4 | цикл val | **0.224** (0.036) · 0.164 / 0.351 | 0.158 (0.054) | **0.209** (0.022) · 0.168 / 0.278 |
| `R_tune` е5 | цикл val | **0.225** (0.036) · 0.169 / 0.336 | 0.159 (0.059) | 0.207 (0.023) · 0.170 / 0.264 |
| `R_tune` е1 | випадкові val, 2100 | 0.211 | 0.170 | 0.210 |
| `R_tune` е4 | випадкові val | 0.217 | 0.163 | 0.214 |
| `R_tune` е5 | випадкові val | 0.220 | 0.164 | 0.209 |

`R_tune` е4 на циклі val за числом півотів (вершина / дно): 1 — 0.103 /
0.165, 2 — 0.189 / 0.206, 4 — 0.224 / 0.196, 6 — 0.249 / 0.224, 8 —
0.226 / 0.215; по монетах: BTC 0.168 / 0.272, ETH 0.245 / 0.271, SOL
0.266 / 0.213, XRP 0.240 / 0.142, BNB 0.210 / 0.158, DOGE 0.199 / 0.184.

Висновки:
- Випадкові вікна підняли вершину і дно на циклі val з 0.212 / 0.192
  (`G_tune`) до 0.224 / 0.209 (+0.012 / +0.017); корекція трохи впала
  (0.167 → 0.158).
- Найбільше виграли короткі вікна: з 1 півотом дно 0.100 → 0.165, з 2 —
  0.143 → 0.206.
- Приріст за перші 5 епох (100 тис. вікон) — плато: середній F1
  відкладених 0.2018 … 0.2038 між епохами; точність голів лишається
  0.16–0.19.

### Результат 20: вікна з одним півотом

Етап 13, прогін `R1_tune` (з `R_tune` епохи 1),
`results/canvas1100_random/R1_tune.json`.

- 6 епох по 20 000 вікон з одним півотом (~11 хв на епоху); найкраща за
  середнім F1 відкладених — епоха 2 (0.204), далі падіння до 0.165–0.169
  при спаді втрати train 1.86 → 1.61 — перенавчання на цій формі вікна.
- Три найкращі епохи — **2, 3, 1** (кнопки на дашборді).

F1, у дужках — випадкові сигнали:

| модель | вибірка | вершина 2.3 | корекція 0.8 | дно 2.3 |
| ------ | ------- | ----------- | ------------ | ------- |
| `R1_tune` е2 | val, 2100 вікон з одним півотом | 0.151 (0.033) | 0.143 (0.046) | 0.231 (0.027) |
| `R1_tune` е1 | те саме | 0.128 | 0.139 | **0.253** |
| `R1_tune` е3 | те саме | 0.150 | 0.138 | 0.209 |
| `R_tune` е5 | цикл val, вікна з одним півотом (1 363) | 0.122 | 0.137 | 0.175 |
| `R1_tune` е1 | те саме | 0.119 | 0.138 | **0.209** |
| `R1_tune` е3 | те саме | **0.146** | 0.132 | 0.165 |
| `R_tune` е4 | цикл val, усі 34 743 | **0.224** | **0.158** | **0.209** |
| `R1_tune` е1 | те саме | 0.166 | 0.153 | 0.125 |
| `R1_tune` е2 | те саме | 0.101 | 0.143 | 0.076 |
| `R1_tune` е3 | те саме | 0.113 | 0.144 | 0.087 |

Висновки:
- На вікнах з одним півотом довчання дає мало: дно 0.175 → 0.209
  (епоха 1), вершина 0.122 → 0.146 (епоха 3) — у різних епохах, а не в
  одній.
- На всьому циклі val мережа різко гіршає (вершина 0.224 → 0.101–0.166,
  дно 0.209 → 0.076–0.125): вікна з одним півотом вчать форму «один
  розворот на канву», і на вікнах з 2–8 півотами вона мовчить або
  плутає. Для ряду з кількома півотами лишається `R_tune`.

### Результат 21: вікна рівномірної довжини

Етап 14, прогін `RL_tune` (з `R_tune` епохи 1),
`results/canvas1100_random/RL_tune.json`.

- Сталі вікна: відкладені — 2100, довжина 1.3 … 288 год (квартилі 66 /
  125 / 197 год), N 1…8: 492 / 300 / 269 / 281 / 197 / 194 / 159 / 208;
  val — 2100, 1.0 … 288 год (55 / 109 / 178 год), N 346 / 250 / 246 /
  222 / 216 / 245 / 256 / 319.
- 23 епохи по 20 000 вікон (460 тис. канв, ~12.5 хв на епоху). Середній
  F1 відкладених ріс майже без зупинок: 0.199 (епоха 1) → 0.284
  (епоха 19), далі 4 епохи без покращення. Три найкращі — **19, 18, 22**
  (кнопки на дашборді, за замовчуванням — е19).

F1 · точність / повнота, у дужках — випадкові сигнали:

| модель | вибірка | вершина 2.3 | корекція 0.8 | дно 2.3 |
| ------ | ------- | ----------- | ------------ | ------- |
| `R_tune` е4 | цикл val, 34 743 | 0.224 · 0.164 / 0.351 | 0.158 | 0.209 · 0.168 / 0.278 |
| `RL_tune` е19 | цикл val | **0.330** (0.025) · 0.313 / 0.350 | 0.150 (0.054) | **0.279** (0.018) · 0.302 / 0.259 |
| `RL_tune` е18 | цикл val | 0.324 · 0.293 / 0.363 | 0.153 | 0.263 · 0.296 / 0.237 |
| `RL_tune` е22 | цикл val | **0.352** · 0.315 / 0.399 | 0.156 | **0.289** · 0.271 / 0.310 |
| `RL_tune` е19 | val рівномірної довжини, 2100 | 0.347 · 0.333 / 0.363 | 0.164 | 0.266 · 0.287 / 0.248 |
| `RL_tune` е22 | те саме | 0.368 · 0.335 / 0.408 | 0.171 | 0.298 · 0.263 / 0.345 |

`RL_tune` е19 на циклі val за числом півотів (вершина / дно): 1 — 0.260 /
0.257, 2 — 0.347 / 0.322, 4 — 0.350 / 0.300, 6 — 0.340 / 0.282, 8 —
0.272 / 0.194; по монетах: BTC 0.267 / 0.384, ETH 0.340 / 0.319, SOL
0.343 / 0.286, XRP 0.330 / 0.186, BNB 0.388 / 0.258, DOGE 0.303 / 0.223.

Висновки:
- Рівномірна довжина вікна — найсильніший крок етапів 11–14: вершина
  0.224 → 0.330, дно 0.209 → 0.279 на тих самих вікнах циклу val;
  точність голів вершини й дна вперше ~0.30 (у `R_tune` — 0.16–0.17),
  тобто на добрий сигнал — два хибних замість п'яти.
- Виграли всі довжини: вікна з одним півотом 0.10 / 0.17 → 0.26 / 0.26
  (краще за `R1_tune`, навченого лише на них), з 2–6 півотами — 0.28 …
  0.35; найслабші — 8 півотів (0.27 / 0.19).
- Сигнали вершини на корекціях і повтори після своєї вершини — 10 % і
  13 % сигналів (у `G_tune` — 16 % і 11 %).
- Корекція лишилась на 0.15–0.17 у всіх прогонах.

### Результат 22: найкраща довжина вікна

Етап 15, `RL_tune` е19, пороги 0.95 / 0.65 / 0.95,
`results/canvas1100_random/RL_tune_length.json`. Train — 2100 вікон
`train_len`, val — 2100 вікон `val_len`. F1 вершина / корекція / дно,
середній; база (випадкові сигнали) — 0.01–0.07.

| годин | train, вікон | train F1 | train середній | val, вікон | val F1 | val середній |
| ----- | -----------: | -------- | -------------: | ---------: | ------ | -----------: |
| 0–24 | 260 | 0.341 / 0.128 / 0.325 | 0.265 | 237 | 0.316 / 0.118 / 0.257 | 0.231 |
| 24–48 | 288 | 0.335 / 0.141 / 0.344 | 0.274 | 218 | 0.312 / 0.132 / 0.243 | 0.229 |
| 48–72 | 278 | 0.325 / 0.160 / 0.336 | 0.274 | 232 | 0.275 / 0.141 / 0.245 | 0.220 |
| 72–96 | 257 | 0.346 / 0.164 / 0.367 | 0.292 | 233 | 0.303 / 0.159 / 0.264 | 0.242 |
| 96–120 | 255 | 0.361 / 0.178 / 0.341 | 0.293 | 229 | 0.368 / 0.166 / 0.279 | 0.271 |
| 120–144 | 214 | 0.399 / 0.189 / 0.378 | 0.322 | 186 | 0.352 / 0.177 / 0.249 | 0.259 |
| 144–168 | 178 | 0.424 / 0.180 / 0.362 | 0.322 | 174 | 0.386 / 0.167 / 0.309 | **0.287** |
| 168–192 | 133 | 0.426 / 0.191 / 0.334 | 0.317 | 145 | 0.376 / 0.175 / 0.279 | 0.277 |
| 192–216 | 92 | 0.469 / 0.185 / 0.378 | **0.344** | 144 | 0.369 / 0.165 / 0.286 | 0.273 |
| 216–240 | 58 | 0.400 / 0.194 / 0.408 | 0.334 | 134 | 0.370 / 0.170 / 0.240 | 0.260 |
| 240–264 | 58 | 0.447 / 0.196 / 0.345 | 0.329 | 95 | 0.390 / 0.172 / 0.239 | 0.267 |
| 264–288 | 29 | 0.340 / 0.197 / 0.341 | 0.293 | 73 | 0.291 / 0.180 / 0.252 | 0.252 |

Висновки:
- Найкраща довжина: train — 192–216 год (8–9 діб), середній F1 0.344;
  val — 144–168 год (6–7 діб), 0.287.
- На обох частинах F1 росте з довжиною до ~6–9 діб і падає на найдовших;
  найслабші — вікна до 3 діб (train 0.265–0.274, val 0.220–0.231).
- На train вікон понад 8 діб мало (92, 58, 58, 29): вікно з 1 … 8
  півотами train рідко буває таким довгим.

### Результат 23: зона півота 2.3 % у момент T

Етап 16, модель `канва600півот2.3%ідентифікатор`. Перевірка входу — `results/side_leak/`; прогін `Z_base` —
`results/canvas1100_future/Z_base.json`, `Z_base_val_pred.npz`.

**Голова «бік ноги» наживо проти готового ряду** (BTC, весь ланцюжок на
датасетах, обрізаних у T):

| T | спільних подій до T (увесь ряд) | різниця p_side, макс. | різниця ема 200, макс. | видач в останню годину: готовий / живий |
| - | ---------: | --------------------: | ---------------------: | --------------------------------------- |
| 04.09 18:00 | 70 138 | 0.0 | 0.0 | 16 / 16 |
| 05.09 22:00 | 70 611 | 0.0 | 0.0 | 0 / 0 |
| 11.09 01:00 | 72 523 | 0.0 | 0.0 | 12 / 1 |
| 11.09 03:00 | 72 558 | 0.0 | 0.0 | 15 / 14 |

- Значення голови до T від майбутнього не залежать: зігзаг ставить
  останнім півотом поточний екстремум (`rules/scripts/zigzag.py`), мережі
  йдуть по подіях уперед. Півот 11.09 00:00 підтверджено ема10 лише о
  14:12, а наживо о 01:00 голова вже рахувала ногу від нього — так само,
  як готовий ряд.
- Відрізняється лише наявність видачі в останню годину перед T: канал
  `zone` (`zone_lstm.blocks_of`) відкидає хвостовий блок подій, коротший
  за чверть блока. Тому канал 7 бере голову із затримкою на годину — на
  годинах 1 … 160 до T живий і готовий ряди збігаються повністю.

**Канви:** train — 23 706 моментів T, val — 4 536 (6 монет). У зоні
півота: train 980 (0.041), val 142 (0.031).

**Прогін `Z_base`**: train 17 742, відкладені 4 766; найкраща епоха 8 з
12 (стоп за терпінням), поріг 0.05.

| | AUC | точність | повнота | F1 | F1 «завжди так» |
| - | --: | -------: | ------: | -: | --------------: |
| відкладені | 0.691 | 0.082 | 0.282 | 0.127 | 0.063 |
| val | **0.720** | 0.082 | 0.394 | **0.136** | 0.061 |

AUC val по монетах: BTC 0.756, ETH 0.630, SOL 0.748, XRP 0.715, BNB
0.706, DOGE 0.766.

Контроль — одне число з останніх 10 рядків тієї самої канви (AUC train /
val): P(півот) `B_tune` 0.693 / 0.672; найбільша P(вершина), P(дно)
`RL_tune` 0.618 / 0.588; 1 − середня P(кластер 2) 0.678 / 0.679.

Висновки:
- Зону півота мережа бачить: AUC val 0.72 і на всіх шести монетах вище
  0.6 (0.63 … 0.77).
- Точність — 8 % сигналів у зоні проти 3 % частки зони: у 2.6 раза
  краще за випадкові, але 11 хибних на 1 добрий; повнота 39 %.
- Над найкращим окремим каналом виграш малий: `B_tune` P(півот) сам дає
  0.67, 1 − P(кластер 2) — 0.68; трансформер додає 0.04 AUC.

### Результат 24: торгівля на val за зоною півота

Етап 17, `results/canvas1100_future/zone_trade_<PAIR>.json`; val кожної
монети — 756 моментів T щогодини, 20.08 13:00 … 21.09 05:00; остання
угода закривається на останньому записі val (22.09 20:58).

| монета | гроші в кінці | купив і тримав | угод | прибуткових | середня угода | найбільша просадка | Sharpe | сигналів: зі зміною боку / продовжень / хибних |
| ------ | ------------: | -------------: | ---: | ----------: | ------------: | -----------------: | -----: | ----------------------------------------------- |
| BTC | $981.25 | $1197.44 | 11 | 73 % | 0.05 % | 7.5 % | 1.67 | 98: 11 / 30 / 57 |
| ETH | $1099.64 | $1200.83 | 15 | 73 % | 0.81 % | 8.9 % | 3.13 | 93: 15 / 36 / 42 |
| SOL | $1168.52 | $1352.78 | 19 | 74 % | 1.05 % | 13.2 % | 4.06 | 88: 19 / 32 / 37 |
| XRP | $887.31 | $1318.05 | 29 | 69 % | -0.09 % | 21.9 % | 0.71 | 157: 29 / 62 / 66 |
| BNB | $841.72 | $1218.84 | 11 | 45 % | -1.35 % | 20.7 % | -3.96 | 128: 11 / 58 / 59 |
| DOGE | $1109.01 | $1292.64 | 25 | 68 % | 0.67 % | 14.8 % | 3.90 | 119: 25 / 46 / 48 |

Дві найгірші угоди кожної монети — обидві короткі: BTC −10.8 % і −4.0 %,
ETH −5.2 % і −4.4 %, SOL −9.5 % і −7.1 %, XRP −21.6 % і −9.5 %, BNB
−8.0 % і −7.7 %, DOGE −13.0 % і −11.2 %.

Висновки:
- Жодна монета не обігнала «купив і тримав»: val — місяць росту всіх
  шести (холд +20 … +35 %). У плюсі три — SOL +16.9 %, DOGE +10.9 %, ETH
  +10.0 %; у мінусі BTC −1.9 %, XRP −11.3 %, BNB −15.8 %.
- Прибуткових угод 68–74 % на всіх, крім BNB (45 %); найбільші збитки
  на кожній монеті — короткі угоди проти росту.
- До угоди доходить 11–29 сигналів з 88–157: решта — хибні (37–66) і
  продовження ноги (30–62).


### Результат 25: півот 2.3 раніше за зігзаг

Етап 18, модель `виявленняпівота2.3`. Прогін `E_tune`: `results/canvas1100_early/E_tune.json`, грід —
`E_tune_grid.json`, ряд val — `E_tune_val_<PAIR>.json`; ваги —
`models/canvas1100_early/E_tune/`.

**Голова «бік ноги» наживо проти готового ряду** (`results/side_leak_live/`,
20 моментів T на шести монетах: усередині найдовшої ноги val, через 20 хв
після півота, ETH 19.08 і BTC 30.08): на подіях до T найбільша різниця
p_side — 0.0; видач за останню годину готовий / наживо однаково, крім
трьох випадків: BTC 30.08 17:18 — 12 / 11 (подія, що почалась за 36 с до
T, наживо ще без видачі; етап її не бере — готовність через 315 с); SOL,
XRP, BNB 15–18.08 — у готовому ряду 0 видач, наживо 17 (нога через межу
14.08 у мережу зон готового ряду не йде; числа на спільних подіях — до
0.0001). Наживо канал має не менше, ніж готовий ряд.

**Навчання** — з `RL_tune` е19 (старт F1 відкладених 0.281), 14 епох,
стоп за терпінням; F1 відкладених за епохами: 0.263, 0.337, 0.307, 0.339,
0.396, 0.333, 0.437, 0.387, 0.443, 0.387, **0.476** (е11), 0.461, 0.415,
0.406.

**Грід вікон** (T щогодини, поріг кожної моделі — свій на кожному вікні
з відкладених), F1:

| вікно, год | відкладені: мережа | відкладені: RL_tune | val: мережа | val: RL_tune |
| ---------: | --: | --: | --: | --: |
| 40 | 0.432 | 0.470 | 0.283 | 0.228 |
| 80 | 0.521 | 0.402 | 0.235 | 0.267 |
| 120 | 0.542 | 0.277 | 0.246 | 0.226 |
| 160 | 0.401 | 0.329 | 0.221 | 0.262 |
| 200 | 0.544 | 0.540 | 0.260 | 0.226 |
| 240 | 0.521 | 0.275 | 0.310 | 0.229 |
| 280 | 0.621 | 0.265 | 0.276 | 0.307 |
| **300** ★ | **0.656** | 0.459 | 0.247 | 0.250 |

Усі 27 вікон — у `E_tune_grid.json` і на вкладці. Найкраще на
відкладених — 300 год, поріг мережі 0.85, контролю 0.65.

**Вікно 300 год, T кожні 10 хв:**

| | F1 | точність свіжих | раніше за зігзаг | півотів раніше / усіх | затримка мережі, год | затримка зігзага, год | випередження, год | відкат у момент сигналу, % | свіжих сигналів на добу |
| - | --: | --: | --: | --: | --: | --: | --: | --: | --: |
| відкладені: мережа | **0.569** | 0.562 | 0.576 | 72 / 125 | 3.5 | 12.5 | 5.4 | 1.33 | 0.08 |
| відкладені: RL_tune | 0.398 | 0.296 | 0.608 | 76 / 125 | 4.9 | 17.3 | 10.2 | 1.22 | 0.12 |
| відкладені: випадкові | 0.030 | 0.250 | 0.016 | 2 / 125 | — | — | — | — | 0.08 |
| val: мережа | **0.333** | 0.400 | 0.285 | 81 / 284 | 2.0 | 5.8 | 2.4 | 1.62 | 0.76 |
| val: RL_tune | 0.314 | 0.339 | 0.292 | 83 / 284 | 3.0 | 8.7 | 3.6 | 1.31 | 1.34 |
| val: випадкові | 0.084 | 0.200 | 0.053 | 15 / 284 | — | — | — | — | 0.76 |

Затримки й випередження — медіани по півотах, виявлених не пізніше за
зігзаг.

val по монетах (мережа): BTC 0.364 (раніше за зігзаг 12 з 22, випередження
6.0 год), ETH 0.365 (15 з 34, 2.1 год), SOL 0.427 (18 з 45, 1.7 год), XRP
0.148 (8 з 84, 3.2 год), BNB 0.343 (12 з 28, 5.4 год), DOGE 0.335 (16 з
71, 1.2 год).

Висновки:
- Мережа ловить частину півотів раніше за зігзаг: на val — 81 з 284
  (29 %), медіанно за 2.4 год до підтвердження зігзагом, коли ціна відійшла
  від півота на 1.6 % з 2.3 %. Випадкові сигнали тієї самої частоти — 15
  з 284.
- Точність свіжих сигналів на val — 40 % проти 34 % у `RL_tune` без
  довчання і 20 % у випадкових; сигналів на добу вдвічі менше, ніж у
  `RL_tune`. F1 val — 0.333 проти 0.314: над `RL_tune` виграш малий.
- На відкладених F1 0.569 проти 0.333 на val. Відкладені брали участь у
  виборі епохи, порогу й вікна; голова «бік ноги» на них — у періоді свого
  навчання; val — інший ринок (місяць росту всіх монет). Чесна оцінка —
  val.
- Найкраще вікно на відкладених — 300 год, але на val вікна між собою
  близькі (0.14 … 0.31) і не йдуть за відкладеними: вибір вікна на val не
  переноситься.
- Слабко на XRP (8 з 84 півотів раніше за зігзаг): там найбільше коротких
  ніг.

### Результат 26: півот на купівлю лише на train BTC

Етап 19. Кластер — `models/canvas1100_buy/assigner.json`,
`results/canvas1100_buy/cluster.json`; прогони — `results/canvas1100_buy/BUY_<втрата>.json`,
`BUY_<втрата>_val.npz`, `BUY_bce_series.npz`; ваги — `models/canvas1100_buy/BUY_<втрата>/`;
логи — `logs/buy_{cluster,build,val,bce,pos,focal,dice}.log`.

**Кластер 2 на навчальних 80 %** — 1076 канв 600 BTC (88 базових ніг),
кінець ≤ 30.06 12:20 UTC. Грід уточнювача вибрав той самий варіант, що
на шести монетах: 7 фіч, `h` 1, `mean`, `P` 2, `abs`, `q` 0.7 (поріг сили
0.265, бал 0.376). UMAP 875 точок; k-means: кластер 1 — 59 початків,
54 кінці, 332 корекції, 63 тіла; кластер 2 — 5 / 10 / 151 / 201. Правило
кластера 1 на тих самих точках — точність 0.975, AUC 0.998.

**Дані** — навчання 15878 T, у зоні дна 318; відкладені 4445 T,
у зоні дна 45 — 5 днів 2.3; val 5265 T, у зоні дна 39 — 13 днів 2.3.
База: відкладені — частота 0.010, F1 «завжди так» 0.020; val — 0.007 і 0.015
(AP випадкової відповіді дорівнює частоті).

**Перебір функцій втрат** (епоха — F1 на відкладених, поріг — з відкладених,
val — при тому самому порозі):

| прогін | втрата | епоха / усіх | F1 відкл. | AP відкл. | AUC відкл. | поріг | сигналів val | точність val | повнота val | F1 val | AP val | AUC val |
| ------ | ------ | -----------: | --------: | --------: | ---------: | ----: | -----------: | -----------: | ----------: | -----: | -----: | ------: |
| `BUY_bce` ★ | bce | 16 / 22 | 0.159 | 0.052 | 0.761 | 0.10 | 101 | 0.020 | 0.051 | 0.029 | 0.015 | 0.657 |
| `BUY_pos` | pos | 9 / 15 | 0.115 | 0.049 | 0.787 | 0.90 | 46 | 0.043 | 0.051 | 0.047 | 0.017 | 0.576 |
| `BUY_focal` | focal | 12 / 18 | 0.112 | 0.043 | 0.716 | 0.30 | 85 | 0.012 | 0.026 | 0.016 | 0.009 | 0.495 |
| `BUY_dice` | dice | 24 / 30 | 0.000 | 0.039 | 0.688 | 0.05 | 0 | — | 0.000 | 0.000 | 0.022 | 0.617 |

Хід `BUY_bce` на відкладених:

| епоха | втрата | F1 | AP | AUC | поріг |
| ----: | -----: | -: | -: | --: | ----: |
| 1 | 0.1074 | 0.000 | 0.017 | 0.654 | 0.05 |
| 2 | 0.0984 | 0.000 | 0.018 | 0.612 | 0.05 |
| 3 | 0.0983 | 0.000 | 0.016 | 0.594 | 0.05 |
| 4 | 0.0984 | 0.000 | 0.024 | 0.653 | 0.05 |
| 5 | 0.0983 | 0.000 | 0.026 | 0.700 | 0.05 |
| 6 | 0.0981 | 0.000 | 0.052 | 0.712 | 0.05 |
| 7 | 0.0982 | 0.000 | 0.069 | 0.731 | 0.05 |
| 8 | 0.0979 | 0.000 | 0.034 | 0.693 | 0.05 |
| 9 | 0.0951 | 0.082 | 0.033 | 0.682 | 0.05 |
| 10 | 0.0868 | 0.086 | 0.036 | 0.709 | 0.05 |
| 11 | 0.0763 | 0.095 | 0.037 | 0.737 | 0.15 |
| 12 | 0.0689 | 0.136 | 0.045 | 0.753 | 0.15 |
| 13 | 0.0638 | 0.127 | 0.051 | 0.739 | 0.05 |
| 14 | 0.0509 | 0.102 | 0.049 | 0.766 | 0.05 |
| 15 | 0.0437 | 0.108 | 0.046 | 0.754 | 0.10 |
| 16 ★ | 0.0410 | 0.159 | 0.052 | 0.761 | 0.10 |
| 17 | 0.0368 | 0.099 | 0.043 | 0.736 | 0.20 |
| 18 | 0.0311 | 0.127 | 0.051 | 0.771 | 0.25 |
| 19 | 0.0282 | 0.066 | 0.031 | 0.687 | 0.05 |
| 20 | 0.0229 | 0.107 | 0.035 | 0.702 | 0.05 |
| 21 | 0.0199 | 0.086 | 0.042 | 0.726 | 0.15 |
| 22 | 0.0204 | 0.102 | 0.041 | 0.698 | 0.05 |

- Перші ~8 епох BCE мережа не вчиться: втрата стоїть на рівні частоти
  зони (0.098), видача майже стала, жодна T не доходить до порогу 0.05.
  AUC і AP на відкладених (5 днів) обирали саме такі епохи (7) — тому
  епоха вибирається за F1 і не раніше 12-ї.
- Кращий на відкладених — BCE (F1 0.159 при базі 0.020, епоха 16). На val
  той самий поріг дає 101 сигнал, 2 з них у зоні дна: точність 0.020,
  повнота 0.051, F1 0.029 при базі 0.015, AP 0.015 при частоті 0.007, AUC
  0.657. Сигнал купівлі на val майже не відрізняється від випадкового.
- Вага позитиву і focal на val не кращі (AUC 0.576 і 0.495); dice на
  відкладених жодного разу не перейшла поріг (F1 0), на val — теж.
- Відкладені — 5 днів, val — 13: похибка частки `0.5 / √5 ≈ 0.22` і
  `0.5 / √13 ≈ 0.14`; різниці між прогонами на відкладених цим не
  розрізняються.

**Донавчання втратою «далі від цілі — дорожче»** (`BUY_far`: з `BUY_bce` е16,
lr 1e-4, `far` — хибний сигнал важить `1 + 4 · min(d / 48 год, 1)`):

| епоха | втрата | F1 відкл. | AP відкл. | AUC відкл. | поріг | сигналів val | з них у зоні дна | F1 val | AUC val |
| ----: | -----: | --------: | --------: | ---------: | ----: | -----------: | ---------------: | -----: | ------: |
| **0** ★ (старт — `BUY_bce` е16) | — | 0.159 | 0.052 | 0.761 | 0.10 | 101 | 2 | 0.029 | 0.657 |
| 1 | 0.0152 | 0.073 | 0.047 | 0.739 | 0.05 | 35 | 0 | 0.000 | 0.621 |
| 2 | 0.0124 | 0.077 | 0.042 | 0.744 | 0.05 | 60 | 3 | 0.061 | 0.613 |
| 3 | 0.0114 | 0.077 | 0.041 | 0.735 | 0.05 | 53 | 1 | 0.022 | 0.616 |
| 4 | 0.0101 | 0.101 | 0.038 | 0.711 | 0.05 | 83 | 4 | 0.066 | 0.614 |
| 5 | 0.0098 | 0.075 | 0.039 | 0.719 | 0.05 | 66 | 2 | 0.038 | 0.614 |
| 6 | 0.0092 | 0.057 | 0.037 | 0.691 | 0.05 | 16 | 0 | 0.000 | 0.605 |

- На відкладених донавчання F1 не підняло: з першої ж епохи 0.159 → 0.06 …
  0.10, AUC і AP теж нижчі; стоп за терпінням 6 на епосі 6, обрана — старт.
- Штраф за далекі сигнали стискає видачу: поріг падає до 0.05, сигналів на
  val менше (16 … 83 проти 101), але в зоні дна їх 0 … 4 — на 13 днях val
  різниця зі стартом не розрізняється (`0.5 / √13 ≈ 0.14`).


**Драбина штрафу `ladder2`: ціль — зона дна ± 2 год, гріда мовчання**
(мітка і міри — зона дна цілком ± 2 год; база F1: відкладені 0.073, val
0.120, частка зони на val 0.064; стоп — втрата навчання не падає 3 епохи
на 1 %, стеля 30; епоха — F1 на відкладених):

| прогін | мовчання | старт | епоха / останньої | F1 відкл. | сигналів val | точність val | повнота val | F1 val | AUC val |
| ------ | -------: | ----- | ----------------: | --------: | -----------: | -----------: | ----------: | -----: | ------: |
| `BUY_l2` | ×1 | BUY_bce:16 | 25 / 30 | 0.205 | 333 | 0.159 | 0.158 | 0.158 | 0.662 |
| `BUY_l2s1` | ×1 | BUY_l2:25 | 0 / 9 | 0.205 | 333 | 0.159 | 0.158 | 0.158 | 0.662 |
| `BUY_l2s2` | ×2 | BUY_l2:25 | 5 / 30 | 0.210 | 436 | 0.161 | 0.208 | 0.181 | 0.676 |
| `BUY_l2s3` | ×3 | BUY_l2:25 | 1 / 30 | 0.219 | 393 | 0.173 | 0.202 | 0.187 | 0.679 |
| `BUY_l2s4` | ×4 | BUY_l2:25 | 30 / 30 | 0.216 | 277 | 0.173 | 0.143 | 0.157 | 0.676 |
| `BUY_l2s5` | ×5 | BUY_l2:25 | 28 / 30 | 0.213 | 282 | 0.163 | 0.137 | 0.149 | 0.669 |
| `BUY_l2s6` | ×6 | BUY_l2:25 | 28 / 30 | 0.222 | 195 | 0.190 | 0.110 | 0.139 | 0.670 |
| `BUY_l2s7` ★ | ×7 | BUY_l2:25 | 1 / 30 | 0.223 | 371 | 0.173 | 0.190 | 0.181 | 0.680 |
| `BUY_l2s8` | ×8 | BUY_l2:25 | 28 / 30 | 0.217 | 243 | 0.173 | 0.125 | 0.145 | 0.667 |
| `BUY_l2s9` | ×9 | BUY_l2:25 | 28 / 30 | 0.215 | 252 | 0.167 | 0.125 | 0.143 | 0.665 |
| `BUY_l2s10` | ×10 | BUY_l2:25 | 2 / 30 | 0.213 | 354 | 0.175 | 0.185 | 0.180 | 0.675 |

- `BUY_l2` донавчався до стелі 30 епох (втрата падала до кінця), обрана
  епоха 25; з неї — гріда мовчання ×1 … ×10.
- Кращий на відкладених — мовчання ×7 (`BUY_l2s7` е1, F1 0.223), але F1
  усієї гріди ×2 … ×10 лежить у 0.210 … 0.223 — на 5 днях відкладених це
  не розрізняється (`0.5 / √5 ≈ 0.22`).
- На val точність сигналу 0.16 … 0.19 при частці зони 0.064 — у 2.5 … 3
  рази вище за випадкову; повнота 0.11 … 0.21 — більшість моментів зони
  мережа пропускає. Великий штраф за мовчання не піднімає повноту на val:
  прогони, що дотягнули до 28–30-ї епохи, стають обережнішими (поріг
  0.20 … 0.65, сигналів менше).
- Мітка тут ширша (± 2 год), тому з `BUY_bce` / `BUY_far` / `BUY_ladder`
  числа напряму не порівнюються.


**Драбина з добавкою, що росте** (`BUY_l3`: донавчання `BUY_l2s7` е1, мовчання
×7, частини між зонами ×2, ×6, ×10, ×14, ×18, ×21, ×25, ×29, ×33, ×37 — частина
2 +1, 3 +3, 4 +5, 5 +7 і далі на +2 до ladder2; `--steps`):

| епоха | F1 відкл. | поріг | сигналів val | точність val | повнота val | F1 val | AUC val |
| ----: | --------: | ----: | -----------: | -----------: | ----------: | -----: | ------: |
| 0 ★ (старт — `BUY_l2s7` е1) | 0.223 | 0.10 | 371 | 0.173 | 0.190 | 0.181 | 0.680 |
| 1 | 0.203 | 0.05 | 451 | 0.180 | 0.241 | 0.206 | 0.680 |
| 2 | 0.177 | 0.05 | 456 | 0.173 | 0.235 | 0.199 | 0.683 |
| 3 | 0.156 | 0.05 | 378 | 0.196 | 0.220 | 0.207 | 0.685 |
| 4 | 0.186 | 0.10 | 300 | 0.190 | 0.170 | 0.179 | 0.684 |
| 5 | 0.189 | 0.15 | 345 | 0.174 | 0.179 | 0.176 | 0.678 |
| 6 | 0.171 | 0.05 | 404 | 0.171 | 0.205 | 0.186 | 0.682 |
| 7 | 0.198 | 0.20 | 238 | 0.160 | 0.113 | 0.132 | 0.680 |
| 8 | 0.193 | 0.15 | 365 | 0.178 | 0.193 | 0.185 | 0.675 |
| 9 | 0.180 | 0.05 | 526 | 0.165 | 0.259 | 0.202 | 0.675 |
| 10 | 0.192 | 0.20 | 246 | 0.163 | 0.119 | 0.137 | 0.679 |
| 11 | 0.196 | 0.10 | 412 | 0.160 | 0.196 | 0.176 | 0.678 |
| 12 | 0.188 | 0.10 | 488 | 0.160 | 0.232 | 0.189 | 0.674 |
| 13 | 0.181 | 0.55 | 181 | 0.193 | 0.104 | 0.135 | 0.675 |
| 14 | 0.174 | 0.10 | 390 | 0.172 | 0.199 | 0.185 | 0.675 |
| 15 | 0.182 | 0.50 | 197 | 0.203 | 0.119 | 0.150 | 0.680 |
| 16 | 0.166 | 0.35 | 149 | 0.215 | 0.095 | 0.132 | 0.673 |
| 17 | 0.204 | 0.10 | 199 | 0.161 | 0.095 | 0.120 | 0.683 |
| 18 | 0.178 | 0.10 | 252 | 0.187 | 0.140 | 0.160 | 0.683 |
| 19 | 0.189 | 0.45 | 230 | 0.174 | 0.119 | 0.141 | 0.677 |
| 20 | 0.212 | 0.30 | 313 | 0.169 | 0.158 | 0.163 | 0.674 |
| 21 | 0.199 | 0.15 | 191 | 0.188 | 0.107 | 0.137 | 0.683 |
| 22 | 0.162 | 0.35 | 155 | 0.219 | 0.101 | 0.138 | 0.672 |
| 23 | 0.157 | 0.60 | 159 | 0.195 | 0.092 | 0.125 | 0.672 |
| 24 | 0.195 | 0.15 | 259 | 0.174 | 0.134 | 0.151 | 0.678 |
| 25 | 0.183 | 0.70 | 131 | 0.191 | 0.074 | 0.107 | 0.674 |
| 26 | 0.197 | 0.35 | 211 | 0.171 | 0.107 | 0.132 | 0.678 |
| 27 | 0.199 | 0.20 | 321 | 0.171 | 0.164 | 0.167 | 0.677 |
| 28 | 0.212 | 0.30 | 235 | 0.166 | 0.116 | 0.137 | 0.672 |
| 29 | 0.152 | 0.10 | 264 | 0.186 | 0.146 | 0.163 | 0.671 |
| 30 | 0.205 | 0.25 | 232 | 0.172 | 0.119 | 0.141 | 0.679 |

- Донавчання дійшло до стелі 30 епох — втрата падала до кінця (0.0768 →
  0.05 …); жодна епоха не перевищила старт на відкладених (F1 0.223),
  обрана — старт, тобто `BUY_l2s7` е1 без змін.
- На val епохи 1 … 3 дають більше влучань (повнота 0.22 … 0.24, F1 0.20 …
  0.21 проти 0.181 старту), але на відкладених вони гірші — у вибір val не
  йде; на 13 днях val різниця від старту не розрізняється.

### Результат 27: сигнал купівлі сумою у вікні і торгівля лише купівлями

Еталон на val BTC (15.08 … 21.09): 12 ніг вгору зігзага 2.3 %, Σ 81.0 %,
$1000 → $2140.27; «купив і тримав» — $1366.30. 450 епох × 700
комбінацій.

**★ `BUY_pos` епоха 9** — зафіксований (`STAR`): переможець підбору з
тейком від ціни входу (частка 19.6 %, $1170.19). Сума P за `W` = 18 кроків
(180 хв), купівля при `S ≥ θ` = 11.7406 (квантиль 0.97 ряду суми), тейк
2 % від найнижчої ціни після входу, стоп 2 % від ціни входу · частка
еталона 12.2 % · $1103.17 (PnL +103.17) · 8 угод, усі тейком, стопів 0 ·
фейків 32 · кроків із сигналом 158.

Найкраща комбінація гріду кожного прогону з тейком від найнижчої ціни (для порівняння):

| прогін | епоха | W | q | θ | стоп | частка еталона | PnL $ | угод | тейк | стоп | фейків |
| ------ | ----: | - | -: | -: | ---: | -------------: | ----: | ---: | ---: | ---: | -----: |
| `BUY_l2s4` | 23 | 3 (30 хв) | 0.99 | 1.976 | 0.5 % | 13.4 % | 113.95 | 9 | 7 | 2 | 13 |
| `BUY_l2s7` | 23 | 3 (30 хв) | 0.98 | 1.706 | 2.0 % | 13.4 % | 113.81 | 8 | 8 | 0 | 35 |
| `BUY_l2s8` | 23 | 3 (30 хв) | 0.98 | 1.762 | 2.0 % | 13.4 % | 113.81 | 8 | 8 | 0 | 35 |
| `BUY_pos` | 7 | 3 (30 хв) | 0.95 | 1.513 | 1.5 % | 13.3 % | 113.08 | 7 | 7 | 0 | 206 |
| `BUY_l2s3` | 27 | 2 (20 хв) | 0.99 | 1.720 | 2.0 % | 13.2 % | 111.94 | 7 | 7 | 0 | 19 |
| `BUY_l2s5` | 23 | 3 (30 хв) | 0.99 | 1.999 | 2.0 % | 13.2 % | 111.87 | 8 | 8 | 0 | 15 |
| `BUY_l2s2` | 14 | 3 (30 хв) | 0.98 | 1.231 | 1.5 % | 13.1 % | 111.23 | 7 | 7 | 0 | 32 |
| `BUY_l2s6` | 14 | 3 (30 хв) | 0.98 | 1.817 | 1.5 % | 13.1 % | 111.23 | 7 | 7 | 0 | 25 |
| `BUY_l3` | 14 | 3 (30 хв) | 0.98 | 1.698 | 1.5 % | 13.1 % | 111.23 | 7 | 7 | 0 | 25 |
| `BUY_l2s10` | 6 | 3 (30 хв) | 0.98 | 1.338 | 1.5 % | 13.1 % | 111.22 | 7 | 7 | 0 | 28 |
| `BUY_l2s9` | 7 | 2 (20 хв) | 0.99 | 1.541 | 2.0 % | 12.8 % | 108.15 | 8 | 8 | 0 | 2 |
| `BUY_l2` | 11 | 6 (60 хв) | 0.85 | 0.085 | 1.5 % | 11.1 % | 93.45 | 6 | 6 | 0 | 590 |
| `BUY_focal` | 17 | 12 (120 хв) | 0.98 | 1.581 | 2.0 % | 11.0 % | 92.62 | 7 | 7 | 0 | 4 |
| `BUY_bce` | 13 | 18 (180 хв) | 0.98 | 0.841 | 2.0 % | 11.0 % | 92.13 | 7 | 7 | 0 | 0 |
| `BUY_l2s1` | 9 | 12 (120 хв) | 0.95 | 1.348 | 1.5 % | 10.6 % | 89.22 | 6 | 6 | 0 | 83 |
| `BUY_far` | 0 | 6 (60 хв) | 0.90 | 0.125 | 3.0 % | 10.6 % | 88.75 | 7 | 7 | 0 | 331 |
| `BUY_ladder` | 0 | 6 (60 хв) | 0.90 | 0.125 | 3.0 % | 10.6 % | 88.75 | 7 | 7 | 0 | 331 |
| `BUY_dice` | 30 | 72 (720 хв) | 0.50 | 0.062 | 0.5 % | 10.4 % | 87.25 | 5 | 5 | 0 | 2120 |

Цикли еталона ★:

| дно | вершина | еталон | угод ★ | ★ |
| --- | ------- | -----: | -----: | -: |
| 14.08 23:58 | 21.08 08:58 | 25.58 % | 1 | 1.45 % |
| 21.08 11:33 | 22.08 04:40 | 2.85 % | 0 | 0.00 % |
| 23.08 05:16 | 25.08 02:40 | 6.96 % | 1 | 1.70 % |
| 26.08 15:03 | 28.08 01:31 | 4.61 % | 0 | 0.00 % |
| 28.08 16:25 | 30.08 16:56 | 2.79 % | 1 | 1.22 % |
| 30.08 23:46 | 31.08 19:08 | 2.43 % | 0 | 0.00 % |
| 02.09 10:50 | 03.09 21:33 | 7.44 % | 1 | 1.48 % |
| 04.09 14:48 | 06.09 23:45 | 2.19 % | 1 | 1.86 % |
| 08.09 13:51 | 09.09 08:53 | 2.46 % | 0 | 0.00 % |
| 10.09 23:13 | 11.09 14:03 | 3.74 % | 1 | 0.88 % |
| 14.09 00:28 | 14.09 20:23 | 3.72 % | 1 | 1.20 % |
| 15.09 18:48 | 21.09 20:26 | 16.20 % | 1 | 0.09 % |

Угоди ★ (час UTC; тейк — рівень на момент виходу):

| сигнал і вхід | ціна входу | вихід | ціна виходу | чому | результат | тейк |
| ------------- | ---------: | ----- | ----------: | ---- | --------: | ---: |
| 16.08 02:10 | 63046.36 | 17.08 15:30 | 64049.68 | тейк | 1.45 % | 63971.15 |
| 24.08 04:50 | 76950.75 | 24.08 11:36 | 78367.42 | тейк | 1.70 % | 78252.43 |
| 28.08 17:00 | 77788.46 | 30.08 12:33 | 78850.00 | тейк | 1.22 % | 78842.85 |
| 02.09 16:00 | 77292.01 | 03.09 12:55 | 78548.72 | тейк | 1.48 % | 78521.63 |
| 04.09 14:50 | 78692.03 | 06.09 23:36 | 80269.61 | тейк | 1.86 % | 80265.87 |
| 10.09 14:40 | 77251.00 | 11.09 12:51 | 78041.22 | тейк | 0.88 % | 78044.07 |
| 11.09 18:10 | 77072.65 | 14.09 09:51 | 78106.01 | тейк | 1.20 % | 78006.23 |
| 15.09 16:10 | 76325.79 | 16.09 18:08 | 76503.78 | тейк | 0.09 % | 76503.86 |

- Той самий ★ з тейком від ціни входу (`entry`, кнопка на вкладці) —
  частка 18.8 %, $1162.73, 8 угод тейком. Від $1170.19 першого підбору
  відрізняється базою тейку: зараз тейк і стоп рахуються від ціни, за
  якою угода куплена (open запису після T), і вихід шукається з close
  цього самого запису; у першому підборі база була close запису T, а
  пошук — з наступного запису.
- ★ заходить у ті самі 8 з 12 ніг, що й з тейком від ціни входу, по одній
  угоді на ногу, стопів 0.
- Тейк від найнижчої ціни закриває кожну угоду, після входу в яку ціна
  ще падала, раніше і нижче: результати 0.09 … 1.86 % проти 1.76 … 2.42 %
  з тейком від входу; найбільша втрата — вхід 15.09 16:10 за 2.5 год до дна
  15.09 18:48: тейк спустився до 76503.86, угода закрилась у +0.09 %.
- Найкраща комбінація гріду з цим тейком (`BUY_l2s4` е23, стоп 0.5 %) —
  частка 13.4 %, $1113.95; ★ — 12.2 %, $1103.17.
- ★ PnL +$103.17 нижче «купив і тримав» (+$366.30).
- Підбір і міра — на тому самому val (12 ніг): окремого відрізка для
  перевірки обраних параметрів немає.
