# 33. Сигнал купівлі й продажу з видач мереж

| | |
| --- | --- |
| Пара | BTC_USDT + 5 монет |
| Клас | `клас210х10-1х7д/д` (вісь ряду), `клас210х14х4ц` і сім класів сітки 210 с — у самих мережах |
| Вкладка | [`/calls`](http://localhost:8080/calls) |
| Статус | етапи 1–13 підтверджені, 2026-09-18; етапи 14 і 15 підтверджені, 2026-09-29 |

## Ціль

У проєкті є мережі, які кажуть **про ногу**: «нога кінчається», «ми на
80 % ноги», «це зона розвороту». Жодна не каже того, заради чого все
робиться. Питання цього дослідження одне:

> **Чи можна з їхніх видач зібрати одне рішення — купити або продати —
> і поставити його близько до розвороту зігзага 2.3 % на ема10?**

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

## Дані

Шість монет, вісь — події `клас210х10-1х7д/д` (сітка 210 с), межа
train|val береться з самого датасету.

| | |
| --- | --- |
| Подій усього | 412 811 (шість монет) |
| Подій з основними каналами | 287 109 |
| Подій з усіма девʼятьма каналами | 254 029 |
| Розворотів зігзага 2.3 % | 718 — 607 train, 111 val |
| Навчання / відкладене / val | 184 733 / 46 187 / 23 109 подій |

Зона, в яку треба влучити, несиметрична: **50 подій до розвороту і 15
після** — та сама, що заміряна на фічах класу в дослідженні 32. Ранній
сигнал ще можна виконати, пізній — ні.

### Які мережі беруться

| Канал | Мережа | Що каже |
| ----- | ------ | ------- |
| `tooth` | `legtooth` (дослідження 32, етап 11) | зубець кінця ноги, сира видача |
| `line` | `legline` (дослідження 32, етап 11) | частка пройденої ноги, 0…1 |
| `p100` | `hazard100` (дослідження 20) | «півот у наступні 100 подій» |
| `p10`, `p40`, `p160`, `p640` | `hazard4` (дослідження 20) | чотири горизонти того самого |
| `pivot`, `correct` | `zone` (дослідження 31) | «це зона розвороту» / «це зона корекції» |

Замість `legleft` і `legtip` драбини стоять **наші** `legtooth` і
`legline` — з тією самою роботою, «де кінець ноги» і «де ми в нозі».
Причина не смакова: `legleft` іде за **фальшивим** півотом, підставленим
у канали розмітки (міра 0.776 → 5.79,
[`fake_pivot_BTC_USDT.json`](../32-loss-ladder/results/fake_pivot_BTC_USDT.json)),
тобто тримається на розмітці, якої в торгівлі немає. `legtooth` і
`legline` розмітки не бачать: у їхній рамці всі чотири канали розмітки
погашені, а «своя нога» дорівнює одиниці скрізь.

### Спільна вісь

Мережі живуть на різних розмітках, але всі — на сітці подій 210 с.
Видача кладеться на вісь **за часом події** і тільки якщо найближча
подія осі ближча за пів кроку (105 с). Чого немає — `NaN`, а не нуль.
Горизонти `hazard` живуть на коротшому ряді, ніж решта, тому подія
рахується, коли є **основні** чотири канали (`tooth`, `line`, `pivot`,
`correct`), а відсутність горизонтів іде окремою ознакою.

Замір іде на процесорі: прохід LSTM на `mps` дає різну видачу залежно
від того, чи був у процесі зворотний прохід (дослідження 32,
`val_series.py`).

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

| № | Крок | Статус |
| - | ---- | ------ |
| 1 | Вхід: видачі чотирьох мереж на спільній осі кожної монети, **і на train теж** — інакше поєднання нема на чому вчити | підтверджено, 2026-09-17 |
| 2 | Розбір: що кожен канал каже про розворот — AUC із підлогою на перемішаних мітках, верхівка з покриттям, напрямок, профіль по відстані до півота і схожість каналів між собою | підтверджено, 2026-09-17 |
| 3 | Поєднувач: три набори ознак (самі мережі, сама ціна, разом), епоха й поріг за відкладеним шматком train, замір на val проти каналів, причинного зігзага 1.2 % і монетки | підтверджено, 2026-09-17 |
| 4 | Поправка: чи знають мережі, **де** в останніх 150 подіях був розворот — сигнал зігзага посувається назад у найгучнішу подію каналу | підтверджено, 2026-09-17 |
| 5 | Памʼять замість агрегатів: GRU веде монету подія за подією на тій самій цілі й тій самій мірі — на самих миттєвих числах і поверх 47 ознак MLP | підтверджено, 2026-09-17 |
| 6 | Драбина порогів суперника від 0.4 до 3.0 % і крива випадковості за частотою — щоб кожен рядок читався проти монетки з такою самою кількістю сигналів | підтверджено, 2026-09-17 |
| 7 | Симуляція торгівлі: $1000 на val BTC, вхід наступною подією, комісія й сліпедж, перевертання позиції і той самий сигнал без шортів, проти «купив і тримав» | підтверджено, 2026-09-17 |
| 8 | Комірка памʼяті: LSTM проти GRU на тому самому вході, ході, seed і мірі — з видачею на навчанні, відкладеному шматку й val | підтверджено, 2026-09-18 |
| 9 | Зона розвороту часткою ноги: мітка ставиться не сталими 50 подіями, а часткою ноги, що впирається в півот (дослідження 32, етап 9) — та сама сітка комірок і подач на обох зонах | підтверджено, 2026-09-18 |
| 10 | Стан ноги: видача обраної мережі описується без навчання — профіль уздовж ноги, профіль навколо розвороту, перемикання знака і ціна підтвердження; ряд кожної монети на val і на всьому датасеті | підтверджено, 2026-09-18 |
| 11 | Правило ноги: драбина причинних правил на двох числах моделі з монеткою тієї самої частоти й сталим контролем, кола пошуку одне за одним | підтверджено, 2026-09-18 |
| 12 | Мережа ноги на дві голови: бік ноги окремо від зони розвороту, дві `BCEWithLogits` у втраті, збалансована точність і AUC кожної голови проти сталої відповіді й монетки | підтверджено, 2026-09-18 |
| 13 | Грід ручок двоголової мережі й драбина функцій втрат: у втраті зʼявляється ціна різкості — крок числа понад 0.2 коштує квадратично, а прокол із поверненням коштує добутком сусідніх рухів | підтверджено, 2026-09-18 |
| 15 | Перетини голови «бік ноги» з її власною емою як зони пошуку розвороту — дві моделі етапу 7 дослідження 34 шукають у зоні саму подію межі, з підлогою на випадкових подіях і драбиною розмірів зони | підтверджено, 2026-09-29 |
| 14 | Торгівля ногою: одна угода на ногу — вхід на зміні боку мережі, вихід на її ж зоні кінця; бік читається трьома сімействами (несиметричні рівні `up`/`down`, перетин двох ем видачі, пік лінії відкатом) із заміром затримки оголошення, ручки колами на відкладеному шматку train з умовою «торгує ногами», гроші на val шести монет проти холду, ема ціни тим самим механізмом, зігзага 1.2 % і монетки; угоди на ряді вкладки | підтверджено, 2026-09-29 |

## Скрипти

| Скрипт | Що робить | Вихід |
| ------ | --------- | ----- |
| [`scripts/calls_data.py`](scripts/calls_data.py) | ганяє чотири мережі по train і val кожної монети й кладе видачі на спільну вісь | `results/calls_<модель>_<PAIR>.npz`, `results/calls_input_<PAIR>.npz`, `results/calls_input.json` |
| [`scripts/calls_look.py`](scripts/calls_look.py) | розбір каналів однією лінійкою: AUC, підлога, верхівка, напрямок, профіль, Спірмен пар | `results/calls_look.json` |
| [`scripts/calls_train.py`](scripts/calls_train.py) | поєднувач на трьох наборах ознак, суперники і поправка зігзага | `results/calls_train.json`, `models/calls/model.pt`, `models/calls/norm.npz` |
| [`scripts/calls_memory.py`](scripts/calls_memory.py) | поєднувач із памʼяттю: GRU уздовж подій, два набори ознак, той самий поріг і та сама міра | `results/calls_memory.json`, `models/calls/memory.pt`, `models/calls/memory_norm.npz` |
| [`scripts/calls_rivals.py`](scripts/calls_rivals.py) | драбина порогів причинного зігзага і крива випадковості за частотою | `results/calls_rivals.json` |
| [`scripts/calls_money.py`](scripts/calls_money.py) | симуляція $1000 на val: кожен сигнал із комісією й сліпеджем, у двох режимах, проти «купив і тримав» | `results/calls_money.json` |
| [`scripts/calls_cells.py`](scripts/calls_cells.py) | дві комірки памʼяті на тому самому вході: GRU і LSTM × два набори ознак × дві зони розвороту, поріг із відкладеного шматка й міра на всіх трьох шматках | `results/calls_cells.json`, `models/calls/cell_<комірка>_<подача>_<зона>.pt`, `models/calls/cell_norm.npz` |
| [`scripts/calls_state.py`](scripts/calls_state.py) | стан ноги з видачі обраної мережі: профілі вздовж ноги й навколо розвороту, перемикання знака, ціна підтвердження, ряди всіх монет | `results/calls_state.json`, `results/calls_state_series_<PAIR>_<val\|all>.json` |
| [`scripts/calls_rules.py`](scripts/calls_rules.py) | драбина правил ноги: кола пошуку, монетка тієї самої частоти й сталий контроль, переможець кожного кола | `results/calls_rules.json`, `results/calls_proba_<PAIR>.npz` |
| [`scripts/legs_grid.py`](scripts/legs_grid.py) | грід ручок колами й драбина функцій втрат від ваг переможця, із заміром різкості видачі | `results/legs_grid.json`, `models/legs_heads/grid.pt` |
| [`scripts/legs_heads.py`](scripts/legs_heads.py) | та сама мережа на дві голови: бік ноги і зона розвороту окремо, матриці обох голів, контролі й ряди всіх монет | `results/legs_heads.json`, `results/legs_heads_series_<PAIR>_<val\|all>.json`, `models/legs_heads/model.pt` |
| [`scripts/calls_series.py`](scripts/calls_series.py) | ряд val однієї монети: ціна, сигнали трьох видів і канали під ними | `results/calls_series_<PAIR>.json` |
| [`scripts/legs_cross.py`](scripts/legs_cross.py) | перетини `p_side` з її емою як кандидати в розворот, перевірка околу двома моделями дослідження 34, драбина «як близько» і ряд val під вкладку | `results/legs_cross.json`, `results/legs_cross_series_<PAIR>.json` |
| [`scripts/legs_calls.py`](scripts/legs_calls.py) | торгівля ногою: одна угода на ногу з `p_side` і `p_zone` — два сімейства читання боку, кола ручок на відкладеному шматку, гроші на val шести монет проти ема ціни, холду, зігзага й монетки | `results/legs_calls.json`, `results/legs_calls_series_<PAIR>_<val\|all>.json` |

```bash
# 1. вхід: усі чотири мережі по всіх шести монетах, потім зшивання
python3 research/33-buy-sell-signal/scripts/calls_data.py
python3 research/33-buy-sell-signal/scripts/calls_data.py --model zone
python3 research/33-buy-sell-signal/scripts/calls_data.py --join

# 2. розбір каналів
python3 research/33-buy-sell-signal/scripts/calls_look.py

# 3. поєднувач і суперники
python3 research/33-buy-sell-signal/scripts/calls_train.py --epochs 20

# 4. памʼять замість агрегатів
python3 research/33-buy-sell-signal/scripts/calls_memory.py --epochs 20

# 5. драбина порогів суперника і крива випадковості
python3 research/33-buy-sell-signal/scripts/calls_rivals.py

# 6. симуляція $1000 на val
python3 research/33-buy-sell-signal/scripts/calls_money.py

# 7. комірки памʼяті × подачі × зони розвороту (8 прогонів)
python3 research/33-buy-sell-signal/scripts/calls_cells.py --epochs 20

# те саме тільки на одній зоні
python3 research/33-buy-sell-signal/scripts/calls_cells.py --zones частка

# 8. стан ноги: розбір видачі обраної мережі без навчання
python3 research/33-buy-sell-signal/scripts/calls_state.py

# 9. правило ноги: драбина пошуку
python3 research/33-buy-sell-signal/scripts/calls_rules.py --rounds 3

# 10. мережа ноги на дві голови
python3 research/33-buy-sell-signal/scripts/legs_heads.py

# 11. грід ручок і драбина функцій втрат
python3 research/33-buy-sell-signal/scripts/legs_grid.py

# 12. торгівля ногою: одна угода на ногу
python3 research/33-buy-sell-signal/scripts/legs_calls.py

# 13. ряд val для вкладки
python3 research/33-buy-sell-signal/scripts/calls_series.py
python3 research/33-buy-sell-signal/scripts/calls_series.py --pair ETH_USDT

# 14. перетини голови з емою і перевірка їх моделями межі дослідження 34
python3 research/33-buy-sell-signal/scripts/legs_cross.py
python3 research/33-buy-sell-signal/scripts/legs_cross.py --span 400
```

Дашборд тримає памʼять; перед прогонами його треба глушити.

## Розбір каналів

Кожен канал міряється тим самим: AUC «подія в зоні розвороту проти
решти», поруч підлога — те саме AUC на **перемішаних** мітках. Числа —
середнє по шести монетах.

| Канал | AUC train | підлога | AUC val | верхівка val | напрямок |
| ----- | --------- | ------- | ------- | ------------ | -------- |
| `tooth` | 0.7125 | 0.5002 | 0.6737 | 2.04 | 0.4713 |
| `line` | 0.4005 | 0.4987 | **0.4033** | 0.27 | 0.4533 |
| `p100` | 0.7328 | 0.5015 | 0.7220 | 2.03 | 0.3333 |
| `p10` | 0.7166 | 0.5018 | 0.7271 | 2.26 | 0.3962 |
| `p40` | 0.7170 | 0.5018 | 0.7272 | 2.26 | 0.3958 |
| `p160` | 0.7176 | 0.5017 | 0.7274 | 2.26 | 0.3957 |
| `p640` | 0.7177 | 0.5016 | 0.7274 | 2.26 | 0.3951 |
| `pivot` | 0.7189 | 0.5010 | 0.7261 | 2.35 | 0.4688 |
| `correct` | 0.7180 | 0.5010 | 0.7227 | 2.38 | 0.4569 |

«Верхівка» — у скільки разів найгучніші 5 % каналу частіше лежать у
зоні, ніж вона трапляється в ряді.

Що з цього видно:

1. **Зону бачать усі, крім лінії.** Вісім каналів тримають AUC
   0.67–0.73 при підлозі 0.50, і на val не гірше, ніж на train.
2. **`line` дивиться в інший бік.** AUC 0.40 — у зоні розвороту частка
   ноги **нижча**, ніж поза нею. Це той самий перевернутий розмах, що
   був видно на вкладці дослідження 32: лінія стоїть вище на початку
   ноги, ніж у кінці.
3. **Напрямку немає в жодному.** AUC «зона верхнього півота проти
   нижнього» — 0.33–0.47, тобто мережі кажуть «кінець ноги», а не
   «кінець ноги вгору». Бік доводиться брати з ціни.
4. **Канали кажуть майже одне й те саме.** Спірмен `p10`–`p40` = 1.00,
   `p160`–`p640` = 0.999, `pivot`–`correct` = 0.994, `pivot`–`tooth` =
   0.747. Девʼять каналів — це дві-три незалежні думки.
5. **Рівень каналу їде, порядок — ні.** На BTC у val зона тримає
   медіану `pivot` 0.16 при максимумі 0.27, а поза зоною канал доходить
   до 0.31: сталий поріг із train вибирає не ті події, хоча AUC 0.68.
   Тому в ознаки йде **ранг у хвості** останніх 600 подій, а не саме
   число.

## Поєднувач

Мережа на 64 і 32 нейрони, три виходи — `купівля`, `продаж`, `нічого`.
З кожного каналу беруться чотири числа: саме значення, середнє за 10 і
за 60 подій і ранг у хвості 600 подій. Поруч — причинні числа ціни: хід
ема10 за 10/30/100/300 подій і відкат від крайньої точки вікон 300 і
900 подій (те саме число, на якому стоїть зігзаг-суперник).

Ознаки поділені на дві групи, і навчання йде **тричі**: на самих
мережах, на самій ціні й на всьому разом. Так питання «що дають мережі
понад ціну» отримує число, а не думку.

Останні 20 % подій train відрізані й не вчаться — по них вибирається
**епоха і поріг**. Епоха вибирається не втратою, а самою ціллю:
скільки розворотів відкладеного шматка взято з точністю ±50 подій
(втрата й влучність розходяться вже з третьої епохи). Поріг ставиться
так, щоб сигналів вийшло приблизно стільки ж, скільки розворотів, і
далі працює чергування: після купівлі береться тільки продаж.

Val у виборі не бере участі взагалі.

### Числа на val — 60 розворотів, шість монет

| Сигнал | скільки | ±5 | ±15 | ±50 | ±100 | медіана \|зсуву\| | взято ходу |
| ------ | ------- | -- | --- | --- | ---- | ---------------- | ---------- |
| поєднувач: мережі | 151 | 8.3 % | 18.3 % | 40.0 % | 61.7 % | 75 | −0.99 % |
| поєднувач: ціна | 46 | 3.3 % | 6.7 % | 15.0 % | 30.0 % | 278 | −3.43 % |
| поєднувач: разом | 102 | 8.3 % | 10.0 % | 28.3 % | 46.7 % | 163 | −1.48 % |
| `tooth` | 112 | | 18.3 % | 35.0 % | | | −1.01 % |
| `p100` | 175 | | 18.3 % | 43.3 % | | | −0.97 % |
| `pivot` | 198 | | 18.3 % | 40.0 % | | | −1.60 % |
| `correct` | 187 | | 20.0 % | 41.7 % | | | −1.48 % |
| `line` | 17 | | 0.0 % | 1.7 % | | | −2.40 % |
| **зігзаг 1.2 %** | 136 | 6.7 % | **35.0 %** | **71.7 %** | **91.7 %** | **47** | **+1.20 %** |
| монетка | 151 | 8.3 % | 10.0 % | 40.0 % | 60.0 % | 122 | +1.14 % |

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

**Поєднувач не працює.** Монетка в цьому рядку — одна роздача, і вона
випадково дала ті самі 40 %; на кривій випадковості з 20 роздач
(розділ «Скільки з цього — випадок») частота 151 сигнал дає 30.3 %.
Тобто поєднувач тримає ×1.3 проти випадку на ±50 і ×1.7 на ±15 — трохи
вище за випадок, але не сигнал: причинний зігзаг 1.2 % на тій самій
ціні тримає ×2.6 і ×3.5, бере 71.7 % проти 40 % і єдиний із усіх
виходить у плюс по ходу. Ціна окремо ще гірша, разом — гірше, ніж самі
мережі.

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

## Памʼять замість агрегатів

MLP вище — мережа **на подію**. Памʼять їй підсунута руками: середнє за
10 і 60 подій та ранг у хвості 600. Форма вікон там задана, і мережа не
може ні вибрати іншу, ні згадати, що такий самий зубець уже був на цій
нозі. Тим часом канали, які вона поєднує, дивляться вперед кожен на
свою пару подій: `p10` каже «півот у межах 10 подій», `tooth` — «нога
кінчається». Ланцюжок таких відповідей — послідовність, і звʼязати її
може тільки рекурентна мережа.

GRU на 64 нейрони, один шар, три виходи. Веде монету подія за подією з
початку ряду. Навчання йде шматками по 1024 події, перші 200 подій
шматка гріють памʼять і на них не вчиться. Замір — **один прохід по
всьому ряду монети** без нарізки, тобто так, як воно працювало б живцем.
Ціль, зона, поріг за кількістю, чергування, міра і відкладений шматок
train — ті самі, що в MLP.

Набори два:

| Набір | Що на вході |
| ----- | ----------- |
| `сире` | тільки миттєві числа — девʼять каналів, ознака «є горизонти» і хід ема за 10 подій (11 ознак). Усе довге мережа має дістати з памʼяті сама |
| `разом` | ті самі 47 ознак MLP: памʼять **поверх** руками зроблених вікон |

### Числа на val — 60 розворотів, шість монет

| Сигнал | скільки | ±5 | ±15 | ±50 | ±100 | медіана \|зсуву\| | взято ходу |
| ------ | ------- | -- | --- | --- | ---- | ---------------- | ---------- |
| памʼять: `сире` | 93 | 5.0 % | 11.7 % | **46.7 %** | 66.7 % | 181.8 | −2.86 % |
| памʼять: `разом` | 120 | 5.0 % | 13.3 % | 33.3 % | 56.7 % | 112.0 | −1.72 % |
| MLP: мережі | 151 | 8.3 % | 18.3 % | 40.0 % | 61.7 % | 75 | −0.99 % |
| зігзаг 1.2 % | 136 | 6.7 % | 35.0 % | 71.7 % | 91.7 % | 47 | +1.20 % |

Числа не порівнюються стовпчик у стовпчик, бо частота різна: 93 сигнали
проти 151. Проти **кривої випадковості** (розділ нижче) на своїй частоті
виходить так:

| Сигнал | сигналів | ±15 проти випадку | ±50 проти випадку |
| ------ | -------- | ----------------- | ----------------- |
| памʼять: `сире` | 93 | 11.7 % / 5.4 % = **×2.2** | 46.7 % / 19.3 % = **×2.4** |
| памʼять: `разом` | 120 | 13.3 % / 8.8 % = ×1.5 | 33.3 % / 24.4 % = ×1.4 |
| MLP: мережі | 151 | 18.3 % / 10.8 % = ×1.7 | 40.0 % / 30.3 % = ×1.3 |
| зігзаг 1.2 % | 136 | 35.0 % / 9.9 % = **×3.5** | 71.7 % / 28.1 % = **×2.6** |

**Памʼять сильніша за MLP, але сигналу все одно не дає.** На своїй
частоті вона тримає ×2.2–2.4 проти випадку там, де MLP тримає ×1.3–1.7,
і робить це на 11 миттєвих числах замість 47 ознак. Але хід вона так
само втрачає: −2.86 % проти +1.20 % у зігзага, і зігзаг лишається
вищим за неї на обох допусках.

Три речі, які видно з цього прогону:

1. **Руками зроблені вікна памʼяті шкодять.** Набір `разом` гірший за
   `сире` на обох допусках, і найкраща епоха в нього друга з двадцяти —
   він одразу вчить відкладений шматок напамʼять. Готові середні й
   ранги забирають у GRU те, що вона мала б вибрати сама.
2. **Крива навчання стоїть на місці.** Влучання ±50 на відкладеному
   шматку гуляє між 0.117 і 0.233 без напрямку всі 20 епох, найкраща
   епоха — 17-та, і це шум, а не збіжність. Втрата при цьому падає
   рівно (1.08 → 0.36): мережа вчить фон, а не розвороти.
3. **Архітектура тут не вузьке місце.** Памʼять, яка бачить увесь ряд
   від початку, не знайшла в цих каналах напрямку, бо його там немає
   (AUC напрямку 0.33–0.47 у розділі розбору).

## Комірка памʼяті: LSTM проти GRU

GRU у розділі вище була вибрана без заміру — за швидкістю. Тут обидві
комірки вчаться **тим самим** ходом: однакові ширина памʼяті (64
нейрони, один шар), шматок 1024 події з прогрівом 200, крок 0.002,
ваги класів 1/3/3, 20 епох, `seed 17`, ціль, зона, спосіб порога,
чергування і міра. Різниця лише в комірці й подачі.

| Комірка | Ворота | Стан | Ваг на 11 ознаках |
| ------- | ------ | ---- | ----------------- |
| GRU | двоє | один вектор `h` | 14 979 |
| LSTM | троє | два вектори, `h` і `c` | 19 907 |

### Датасет

Той самий, що в усьому дослідженні: шість монет на осі подій
`class210x10m1x7dd`, канали — видачі раніше навчених мереж проєкту
(`calls_data.py`). Розбиття за датою однакове на всі монети, межа —
**2026-08-14 00:02 UTC**.

| Монета | подій | з входом | навчання | півотів | відкладене | півотів | val | півотів |
| ------ | ----- | -------- | -------- | ------- | ---------- | ------- | --- | ------- |
| BTC_USDT | 70 647 | 30 300 | 21 400 | 68 | 5 351 | 8 | 3 549 | 6 |
| ETH_USDT | 71 451 | 49 086 | 35 825 | 99 | 8 957 | 11 | 4 304 | 4 |
| SOL_USDT | 70 944 | 46 712 | 34 190 | 103 | 8 548 | 13 | 3 974 | 8 |
| XRP_USDT | 64 261 | 42 066 | 30 747 | 82 | 7 687 | 10 | 3 632 | 24 |
| BNB_USDT | 71 248 | 43 552 | 32 677 | 72 | 8 170 | 8 | 2 705 | 4 |
| DOGE_USDT | 64 260 | 42 313 | 29 894 | 96 | 7 474 | 10 | 4 945 | 14 |
| **разом** | **412 811** | — | **184 733** | **520** | **46 187** | **60** | **23 109** | **60** |

- **навчання** — події до межі, крім останніх 20 % ряду train.
- **відкладене** — ті останні 20 % train: на них обирається епоха
  й ставиться поріг.
- **val** — усе після межі; у виборі епохи й порога не бере участі.

Поріг ставиться **один раз** на відкладеному шматку — стільки сигналів,
скільки там півотів, — і тим самим порогом міряються всі три шматки.
Частота на них виходить різна (на val сигналів на подію більше, ніж на
train), тому рядки читаються кожен проти своєї частоти, а не стовпчик
у стовпчик.

### Числа на всіх трьох шматках

| Прогін | Шматок | сигналів | півотів | ±5 | ±15 | ±50 | ±100 | у зоні |
| ------ | ------ | -------- | ------- | -- | --- | --- | ---- | ------ |
| GRU · `сире` | навчання | 468 | 520 | 0.8 % | 5.0 % | 13.9 % | 28.1 % | 15.0 % |
| | відкладене | 64 | 60 | 6.7 % | 10.0 % | 23.3 % | 25.0 % | 22.8 % |
| | val | 93 | 60 | 5.0 % | 11.7 % | **46.7 %** | 66.7 % | 13.8 % |
| LSTM · `сире` | навчання | 454 | 520 | 2.7 % | 9.0 % | 18.1 % | 29.0 % | 21.4 % |
| | відкладене | 63 | 60 | 10.0 % | **23.3 %** | **30.0 %** | 33.3 % | 33.4 % |
| | val | 95 | 60 | 3.3 % | 11.7 % | 33.3 % | 61.7 % | 14.0 % |
| GRU · `разом` | навчання | 458 | 520 | 1.9 % | 8.3 % | 20.0 % | 31.7 % | 23.4 % |
| | відкладене | 61 | 60 | 5.0 % | 6.7 % | 20.0 % | 26.7 % | 22.2 % |
| | val | 120 | 60 | 5.0 % | 13.3 % | 33.3 % | 56.7 % | 11.2 % |
| LSTM · `разом` | навчання | 396 | 520 | 2.5 % | 8.9 % | 17.1 % | 26.2 % | 22.6 % |
| | відкладене | 63 | 60 | 6.7 % | 13.3 % | 21.7 % | 25.0 % | 20.3 % |
| | val | 77 | 60 | 5.0 % | 8.3 % | 20.0 % | 41.7 % | 16.3 % |

Ваги й епоха кожного прогону:

| Прогін | ваг | ознак | епоха з 20 | поріг | навчання |
| ------ | --- | ----- | ---------- | ----- | -------- |
| GRU · `сире` | 14 979 | 11 | 17 | 0.2588 | 2.0 хв |
| LSTM · `сире` | 19 907 | 11 | 14 | 0.3076 | 2.0 хв |
| GRU · `разом` | 21 891 | 47 | 2 | 0.3321 | 2.1 хв |
| LSTM · `разом` | 29 123 | 47 | 1 | 0.3165 | 2.1 хв |

### Що з цього виходить

1. **Комірка нічого не вирішує.** На відкладеному шматку виграє LSTM
   (30.0 % проти 23.3 % ±50 і 23.3 % проти 10.0 % ±15), на val —
   GRU (46.7 % проти 33.3 % ±50), а ±15 у них на val однакове
   (11.7 %). Обидва шматки — по 60 півотів, тобто різниця в 8 півотів
   перевертає порядок. Це шум, а не перевага комірки.
2. **Вибір за відкладеним шматком не переноситься.** Найкращим
   прогоном правило проєкту називає `LSTM · сире` — і саме він на val
   слабший за GRU. Ще одне свідчення, що на 60 розворотах така різниця
   нічого не означає.
3. **Подача важить більше за комірку.** Набір `разом` гірший за `сире`
   в **обох** комірках, і найкраща епоха в нього перша-друга з двадцяти:
   47 рукотворних ознак дають перевчитись одразу. Різниця між подачами
   (33.3 % проти 46.7 % у GRU) більша за різницю між комірками.
4. **Втрата падає в усіх, влучання — ні.** У всіх чотирьох прогонах
   втрата навчання йде вниз рівно, а влучання ±50 на відкладеному
   шматку гуляє без напрямку. Тому епоха й береться не за втратою.
5. **LSTM на чверть дорожча** за ті самі числа: 19 907 ваг проти
   14 979 на тих самих 11 ознаках, час навчання однаковий.

Висновок той самий, що в розділі про памʼять: вузьке місце — вхід, а не
архітектура. Міняти GRU на LSTM сенсу немає.

## Зона розвороту часткою ноги

Етапи 3–8 ставили мітку сталим вікном: 50 подій до півота й 15 після,
однаково на кожен розворот. Це суперечить тому, що вже виміряно в
**дослідженні 32, етап 9**: згасання зони перед розворотом нарізно на
коротких, середніх і довгих ногах дає 30 / 50 / 100 подій, тобто
10.0 / 9.5 / 9.2 % довжини ноги. Розмах у подіях **3.3×**, у частках —
**1.09×**. Зона стоїть у частці ноги; ті самі 50 подій — це 17 %
короткої ноги і 3.7 % довгої, тобто коротка нога діставала більше
безштрафових подій, ніж довга. Голова ноги (після півота) там же
виміряна як коротка й **у подіях** — 10…30, тому 15 подій лишаються.

Мітка тепер ставиться так (`calls_look.tails_of`):

```
хвіст(півот) = max(округл(0.10 × довжина ноги, що в нього впирається), 5)
голова       = 15 подій
```

Нога півота — відрізок від попереднього півота до нього; у першого
півота ряду береться видима частина. На шести монетах хвіст виходить
**5…310 подій, медіана 56** проти сталих 50.

Прогони — та сама сітка комірок і подач на обох зонах, усе інше
однакове (`seed 17`, 20 епох, поріг за кількістю півотів відкладеного
шматка).

### Числа на val — 60 розворотів, шість монет

| Прогін | зона | сигналів | ±5 | ±15 | ±50 | ±100 | у зоні |
| ------ | ---- | -------- | -- | --- | --- | ---- | ------ |
| GRU · `сире` | події | 93 | 5.0 % | 11.7 % | **46.7 %** | 66.7 % | 13.8 % |
| GRU · `сире` | **частка** | 73 | **10.0 %** | **20.0 %** | 35.0 % | 60.0 % | 8.5 % |
| LSTM · `сире` | події | 95 | 3.3 % | 11.7 % | 33.3 % | 61.7 % | 14.0 % |
| LSTM · `сире` | **частка** | 69 | 6.7 % | 13.3 % | 33.3 % | 45.0 % | 12.5 % |
| GRU · `разом` | події | 120 | 5.0 % | 13.3 % | 33.3 % | 56.7 % | 11.2 % |
| GRU · `разом` | частка | 40 | 3.3 % | 3.3 % | 13.3 % | 23.3 % | 11.4 % |
| LSTM · `разом` | події | 77 | 5.0 % | 8.3 % | 20.0 % | 41.7 % | 16.3 % |
| LSTM · `разом` | частка | 32 | 5.0 % | 5.0 % | 18.3 % | 21.7 % | 20.4 % |

Проти кривої випадковості на **своїй** частоті (мітка міняє й кількість
сигналів, тому інакше читати не можна):

| Прогін | сигналів | ±5 проти випадку | ±15 проти випадку |
| ------ | -------- | ---------------- | ----------------- |
| GRU · `сире`, події | 93 | 5.0 / 2.3 = ×2.2 | 11.7 / 5.4 = ×2.2 |
| GRU · `сире`, **частка** | 73 | 10.0 / 1.7 = **×5.9** | 20.0 / 4.6 = **×4.3** |
| LSTM · `сире`, події | 95 | 3.3 / 2.3 = ×1.4 | 11.7 / 5.4 = ×2.2 |
| LSTM · `сире`, **частка** | 69 | 6.7 / 1.7 = ×3.9 | 13.3 / 4.6 = ×2.9 |

### Що з цього виходить

1. **Частка ноги збирає сигнал щільніше до розвороту.** На `сире`
   близькі допуски ростуть в обох комірках: ±5 у GRU 5.0 → 10.0 %,
   ±15 11.7 → 20.0 %; у LSTM ±5 3.3 → 6.7 %. Далекий допуск ±50 при
   цьому падає (46.7 → 35.0 % у GRU) — мітка стала строгішою, і
   «влучив десь поруч» більше не зараховується так щедро.
2. **Сигналів менше на чверть** (93 → 73 і 95 → 69) при тій самій
   процедурі порога. Це і є звуження зони на коротких ногах.
3. **Проти випадковості виграш більший**, бо рідший сигнал міряється
   проти нижчої підлоги: ×5.9 на ±5 замість ×2.2.
4. **Набір `разом` частка вбиває**: 40 і 32 сигнали, ±15 3.3 і 5.0 %.
   47 рукотворних ознак і без того перевчались, а вужча мітка лишає
   їм ще менше позитивів.
5. **Гроші не зрушились.** Узятий хід на val лишається відʼємним у
   всіх восьми прогонах (−1.06 … −3.23 %). Зона в частці ноги —
   правильніша мітка, але вона так само рахує **події**, а не рух:
   подія за 30 кроків до розвороту в флеті й така сама подія всередині
   руху коштують однаково.

Тому наступний етап — мітка не в подіях і не в частках ноги, а в
**грошах**: «звідси угода до наступного півота бере ≥ 80 % ноги».

## Стан ноги: розбір видачі без навчання

Обрана мережа (`LSTM · сире · зона «частка»`) навчена казати «зона
розвороту». Тут її видача **не вчиться далі** — вона описується. Беруться
два числа на подію, рахується `продаж − купівля`, згладжене ема20, і
дивиться, як воно поводиться вздовж ноги зігзага 2.3 % і навколо самого
розвороту. Усе на **val** шести монет: 54 ноги, медіана 140 подій і
5.03 % ходу.

### Уздовж ноги

Число, повернуте в бік **своєї** ноги (для ноги вгору це «продаж», бо
вона йде до верхнього півота):

| десятина ноги | нога вгору: сер. | «продаж» зверху | нога вниз: сер. | «купівля» зверху |
| ------------- | ---------------- | --------------- | --------------- | ---------------- |
| 0–10 % | −0.212 | 19.0 % | +0.293 | 31.0 % |
| 10–20 % | +0.028 | 48.5 % | −0.145 | 78.9 % |
| 30–40 % | +0.014 | 44.1 % | −0.223 | 81.7 % |
| 50–60 % | +0.076 | 45.8 % | −0.230 | 86.6 % |
| 70–80 % | +0.235 | 70.0 % | −0.332 | 96.6 % |
| 80–90 % | +0.277 | 72.4 % | −0.308 | 95.0 % |
| **90–100 %** | **+0.578** | **93.7 %** | **−0.422** | **98.4 %** |

Число росте монотонно від початку ноги до кінця. AUC «остання десятина
ноги проти всієї решти» за самим числом — **0.7579** (1347 подій проти
11 719). Перша десятина несе протилежний знак: це стан попередньої ноги,
який ще не згас.

### Навколо розвороту

Число в бік **нової** ноги і найгучніше з двох (впевненість), по
клітинках у 10 подій:

| відстань до півота | число нової ноги | найгучніше з двох |
| ------------------ | ---------------- | ----------------- |
| −100…−90 | +0.001 | 0.653 |
| −50…−40 | −0.129 | 0.616 |
| −10…0 | −0.436 | 0.611 |
| **0…+10** | **−0.483** | 0.639 |
| +10…+20 | −0.178 | 0.537 |
| +20…+30 | −0.024 | 0.518 |
| +30…+40 | +0.054 | 0.495 |
| +60…+70 | +0.082 | 0.509 |
| +110…+120 | +0.202 | 0.558 |

1. **На самому півоті мережа найвпевненіша в старій нозі** — мінімум
   −0.483 стоїть після розвороту, а не до нього.
2. **Далі стан провалюється**: найгучніше з двох падає з 0.586 до 0.258
   у перші 60 подій, нижче 0.25 — на 70 % розворотів. Але така сама яма
   буває і всередині ноги (21 нога з 27), тому сама по собі вона
   розворот не називає.
3. **Знак перевертається з медіанною затримкою +34.5 події** після
   півота, квартилі +21.8 / +71.8; раніше за півот — 7.9 % випадків,
   у ±15 подій — 2.6 %, у ±50 — 52.6 %. Це **констатація**, не
   передбачення.
4. **Частота нормальна**: 71 перемикання на 53 розвороти, тобто 1.34 на
   розворот, медіана — одне на ногу.

### Чого коштує підтвердження

| вхід після півота | лишається ноги (медіана) |
| ----------------- | ------------------------ |
| 20 подій | 78.6 % |
| **35 подій** (медіанна затримка) | **64.2 %** |
| 60 подій | 61.4 % |

Тобто підтвердження «нова нога пішла» коштує близько третини руху. На
медіанній нозі в 5.03 % це лишає ~3.2 % проти 0.14 % витрат на угоду в
обидва боки — місце для торгівлі є, якщо вихід так само не спізнюється.

### Нога за мережею проти ноги розмітки

Стан (`знак ема20`) — це і є нога, як її бачить мережа. Подія за подією
на val, проти ноги зігзага 2.3 %:

| нога розмітки | подій | стан називає її правильно |
| ------------- | ----- | ------------------------- |
| вгору | 33 348 | **37.8 %** |
| вниз | 20 851 | **69.6 %** |

Ноги вниз мережа веде, ноги вгору — ні: там вона частіше каже «вниз»,
ніж «вгору», тобто гірше за монетку. Профіль по десятинах показує те
саме з іншого боку: на ногах вгору правильний бік зверху лише 44–48 %
подій у середині ноги й доростає до 93.7 % тільки в останній десятині,
тоді як на ногах вниз тримається 79–98 % від другої десятини.

### Що це дає

- **«Яка нога йде» — читається.** Знак каже правильний бік у 94–98 %
  подій останньої десятини й тримається одним перемиканням на ногу.
- **«Нога скінчилась» — наполовину.** Сигнал у числі є (AUC 0.758), але
  порогом по висоті його не взяти: сплеск такої ж висоти буває всередині
  ноги, а сама точка перемикання спізнюється на ~35 подій.
- Це пояснює, чому правило `argmax + поріг` дає відʼємні гроші: воно
  ловить високе число, а високе воно **всю** ногу.

## Правило ноги: драбина пошуку

Розбір стану дав опис, а торгівлі потрібен **алгоритм**. Тут із двох
чисел моделі шукається причинне правило, яке на кожній події видає стан
`+1` (йде нога вгору), `-1` (нога вниз) або `0`. Місця зміни стану — це
його розвороти.

### Як міряється

| Число | Що це |
| ----- | ----- |
| нога | частка подій, де стан збігається з ногою зігзага 2.3 % |
| ±15 / ±50 | скільки півотів мають перемикання в цій відстані |
| монетка ±50 | те саме для випадкових перемикань **тієї самої частоти**, 5 роздач |
| надлишок | `влучання ±50 − монетка` — оцінка, за якою обирається правило |
| лишилось ноги | скільки руху лишається, якщо входити на перемиканні |

Три речі, без яких ця драбина брехала б:

1. **Оцінка — надлишок, а не відношення.** Відношення нагороджує рідкі
   правила (мала підлога), саме влучання — часті (велика підлога).
2. **Вибір — на відкладеному шматку train**, val тільки показується.
3. **Контролі.** «Завжди вгору» / «завжди вниз» — бо ніг вгору в ряді
   71.8 % подій. «Зігзаг ціни X %» — те саме правило **без моделі**:
   якщо воно вище, модель у цій задачі не додає нічого.

### Коло 1: 27 правил

| Правило | надлишок: відкладене | val | нога | ±50 | монетка ±50 | перемикань |
| ------- | -------------------- | --- | ---- | --- | ----------- | ---------- |
| **зігзаг ціни 0.4 %** | **+0.267** | +0.371 | 63.7 % | 97.3 % | 60.2 % | 792 |
| зігзаг ціни 0.8 % | +0.110 | +0.332 | 67.6 % | 73.9 % | 40.7 % | 395 |
| зігзаг ціни 1.2 % | +0.017 | +0.288 | **68.8 %** | 53.1 % | 24.3 % | 233 |
| контроль: завжди вгору | 0.000 | 0.000 | **71.8 %** | — | — | 0 |
| гістерезис 0.2 на ема20 | −0.013 | +0.085 | 54.1 % | 12.6 % | 4.1 % | 46 |
| асиметрія ↑0.2 ↓0.05 | −0.023 | +0.168 | 51.0 % | 21.6 % | 4.9 % | 72 |
| гістерезис 0.1 на ема20 | −0.043 | +0.117 | 53.5 % | 15.3 % | 3.6 % | 54 |
| модель + ціна 0.4 % | −0.060 | +0.139 | 53.6 % | 18.0 % | 4.1 % | 62 |
| знак ема20 | −0.140 | +0.023 | 50.0 % | 19.8 % | 17.5 % | 176 |
| знак ема5 | −0.197 | +0.042 | 49.4 % | 28.8 % | 24.7 % | 292 |

### Кола 2 і 3: сітка навколо переможця

Переможець не зрушив: `зігзаг ціни 0.4 %` лишився найкращим на
відкладеному шматку (+0.267) у всіх трьох колах. Поруч: `0.6 %`
(+0.163 на відкладеному, +0.431 на val) і `0.2 %` (+0.197 / +0.184).

### Що з цього виходить

1. **Модель у цій задачі не додає нічого.** Кожне правило на її числах
   має на відкладеному шматку **відʼємний** надлишок (найкраще −0.013),
   тоді як звичайний причинний зігзаг на ема ціни дає +0.267. На val
   картина та сама: 97.3 % півотів проти 18.0 % у найкращого правила на
   моделі.
2. **Ногу правила на моделі не визначають.** 53.6 % збігу проти 68.8 %
   у зігзага ціни 1.2 % і 71.8 % у сталої відповіді. Ноги вниз вони
   ведуть (69 %), ноги вгору — ні (44 %).
3. **Високе `×монетка` в правил на моделі — артефакт рідкості.**
   `модель + ціна` дає ×4.35, але це 18 % узятих півотів проти 4.1 % у
   монетки; зігзаг 0.4 % має ×1.62 — і 97.3 % узятих півотів.
4. **Алгоритм, який у нас є, — це причинний зігзаг на ціні.** Поріг
   береться за відкладеним шматком: 0.4 % дає найбільший надлишок, але
   792 перемикання; 1.2 % дає найкращу ногу (68.8 %) при 233
   перемиканнях. Обидва не потребують мереж узагалі.

## Стан ноги: розбір видачі без навчання

Обрана мережа (`LSTM · сире · зона «частка»`) навчена казати «зона
розвороту». Тут її видача **не вчиться далі** — вона описується. Беруться
два числа на подію, рахується `продаж − купівля`, згладжене ема20, і
дивиться, як воно поводиться вздовж ноги зігзага 2.3 % і навколо самого
розвороту. Усе на **val** шести монет: 54 ноги, медіана 140 подій і
5.03 % ходу.

### Уздовж ноги

Число, повернуте в бік **своєї** ноги (для ноги вгору це «продаж», бо
вона йде до верхнього півота):

| десятина ноги | нога вгору: сер. | «продаж» зверху | нога вниз: сер. | «купівля» зверху |
| ------------- | ---------------- | --------------- | --------------- | ---------------- |
| 0–10 % | −0.212 | 19.0 % | +0.293 | 31.0 % |
| 10–20 % | +0.028 | 48.5 % | −0.145 | 78.9 % |
| 30–40 % | +0.014 | 44.1 % | −0.223 | 81.7 % |
| 50–60 % | +0.076 | 45.8 % | −0.230 | 86.6 % |
| 70–80 % | +0.235 | 70.0 % | −0.332 | 96.6 % |
| 80–90 % | +0.277 | 72.4 % | −0.308 | 95.0 % |
| **90–100 %** | **+0.578** | **93.7 %** | **−0.422** | **98.4 %** |

Число росте монотонно від початку ноги до кінця. AUC «остання десятина
ноги проти всієї решти» за самим числом — **0.7579** (1347 подій проти
11 719). Перша десятина несе протилежний знак: це стан попередньої ноги,
який ще не згас.

### Навколо розвороту

Число в бік **нової** ноги і найгучніше з двох (впевненість), по
клітинках у 10 подій:

| відстань до півота | число нової ноги | найгучніше з двох |
| ------------------ | ---------------- | ----------------- |
| −100…−90 | +0.001 | 0.653 |
| −50…−40 | −0.129 | 0.616 |
| −10…0 | −0.436 | 0.611 |
| **0…+10** | **−0.483** | 0.639 |
| +10…+20 | −0.178 | 0.537 |
| +20…+30 | −0.024 | 0.518 |
| +30…+40 | +0.054 | 0.495 |
| +60…+70 | +0.082 | 0.509 |
| +110…+120 | +0.202 | 0.558 |

1. **На самому півоті мережа найвпевненіша в старій нозі** — мінімум
   −0.483 стоїть після розвороту, а не до нього.
2. **Далі стан провалюється**: найгучніше з двох падає з 0.586 до 0.258
   у перші 60 подій, нижче 0.25 — на 70 % розворотів. Але така сама яма
   буває і всередині ноги (21 нога з 27), тому сама по собі вона
   розворот не називає.
3. **Знак перевертається з медіанною затримкою +34.5 події** після
   півота, квартилі +21.8 / +71.8; раніше за півот — 7.9 % випадків,
   у ±15 подій — 2.6 %, у ±50 — 52.6 %. Це **констатація**, не
   передбачення.
4. **Частота нормальна**: 71 перемикання на 53 розвороти, тобто 1.34 на
   розворот, медіана — одне на ногу.

### Чого коштує підтвердження

| вхід після півота | лишається ноги (медіана) |
| ----------------- | ------------------------ |
| 20 подій | 78.6 % |
| **35 подій** (медіанна затримка) | **64.2 %** |
| 60 подій | 61.4 % |

Тобто підтвердження «нова нога пішла» коштує близько третини руху. На
медіанній нозі в 5.03 % це лишає ~3.2 % проти 0.14 % витрат на угоду в
обидва боки — місце для торгівлі є, якщо вихід так само не спізнюється.

### Нога за мережею проти ноги розмітки

Стан (`знак ема20`) — це і є нога, як її бачить мережа. Подія за подією
на val, проти ноги зігзага 2.3 %:

| нога розмітки | подій | стан називає її правильно |
| ------------- | ----- | ------------------------- |
| вгору | 33 348 | **37.8 %** |
| вниз | 20 851 | **69.6 %** |

Ноги вниз мережа веде, ноги вгору — ні: там вона частіше каже «вниз»,
ніж «вгору», тобто гірше за монетку. Профіль по десятинах показує те
саме з іншого боку: на ногах вгору правильний бік зверху лише 44–48 %
подій у середині ноги й доростає до 93.7 % тільки в останній десятині,
тоді як на ногах вниз тримається 79–98 % від другої десятини.

### Що це дає

- **«Яка нога йде» — читається.** Знак каже правильний бік у 94–98 %
  подій останньої десятини й тримається одним перемиканням на ногу.
- **«Нога скінчилась» — наполовину.** Сигнал у числі є (AUC 0.758), але
  порогом по висоті його не взяти: сплеск такої ж висоти буває всередині
  ноги, а сама точка перемикання спізнюється на ~35 подій.
- Це пояснює, чому правило `argmax + поріг` дає відʼємні гроші: воно
  ловить високе число, а високе воно **всю** ногу.

## Правило ноги: драбина пошуку

Розбір стану дав опис, а торгівлі потрібен **алгоритм**. Тут із тих
самих двох чисел моделі шукається правило, яке причинно видає на кожній
події стан `+1` (йде нога вгору, ціль — верхній півот), `-1` (нога вниз)
або `0` (ще не знає). Місця зміни стану — його розвороти.

Міряється на val усіх шести монет, 111 розворотів:

| Число | Що це |
| ----- | ----- |
| нога | частка подій, де стан збігається з ногою зігзага 2.3 % |
| ±15 / ±50 | скільки півотів мають перемикання в цій відстані |
| монетка ±50 | те саме для випадкових перемикань **тієї самої частоти**, 5 роздач |
| ×монетка | оцінка, за якою обирається переможець кола |
| лишилось ноги | скільки руху лишається, якщо входити на перемиканні |

Два контролі обовʼязкові. **Монетка тієї самої частоти** — бо часте
правило виглядає точнішим просто тому, що його більше. **Стала
відповідь** — бо ніг вгору в ряді 71.8 % подій, і будь-який збіг нижче
цього числа гірший за «завжди вгору».

### Коло 1: сімейства

| Правило | нога | вгору | вниз | ±50 | монетка ±50 | ×монетка | перемикань |
| ------- | ---- | ----- | ---- | --- | ----------- | -------- | ---------- |
| **гістерезис 0.1 на ема20** | 53.5 % | 44.0 % | 68.6 % | 15.3 % | 3.6 % | **×4.26** | 54 |
| число ≥ 0.3 | 53.1 % | 42.2 % | 70.5 % | 22.5 % | 6.7 % | ×3.38 | 73 |
| гістерезис 0.2 на ема20 | 54.1 % | 41.1 % | 74.9 % | 12.6 % | 4.1 % | ×3.05 | 46 |
| підтвердження 15 подій | 48.2 % | 35.4 % | 68.7 % | 20.7 % | 11.0 % | ×1.89 | 118 |
| знак ема20 (те, що було) | 50.0 % | 37.8 % | 69.6 % | 19.8 % | 17.5 % | ×1.13 | 176 |
| знак ема5 | 49.4 % | 36.3 % | 70.3 % | 28.8 % | 24.7 % | ×1.17 | 292 |
| знак ема150 | 52.4 % | 40.3 % | 71.9 % | 3.6 % | 4.0 % | ×0.91 | 51 |
| контроль: завжди вгору | **71.8 %** | 100 % | 0 % | — | — | — | 0 |
| контроль: завжди вниз | 28.2 % | 0 % | 100 % | — | — | — | 0 |

### Коло 2: сітка навколо переможця

| Правило | нога | ±50 | монетка ±50 | ×монетка | перемикань |
| ------- | ---- | --- | ----------- | -------- | ---------- |
| **ема10, поріг 0.1, підтвердження 1** | 53.6 % | 18.0 % | 4.1 % | **×4.35** | 62 |
| ема20, поріг 0.1 | 53.5 % | 15.3 % | 3.6 % | ×4.26 | 54 |
| ема10, поріг 0.05 | 52.1 % | 22.5 % | 5.8 % | ×3.90 | 78 |
| ема10, поріг 0.2 | 55.2 % | 14.4 % | 4.1 % | ×3.48 | 48 |
| ема40, поріг 0.2 | 53.0 % | 6.3 % | 2.7 % | ×2.34 | 34 |

### Коло 3: дрібніша сітка

Переможець не зрушив: `ема10, поріг 0.1` лишився найкращим (×4.35).
Найближчі — `ема6, поріг 0.1` (×4.16 при 70 перемиканнях) і `ема6,
поріг 0.15` (×4.17). Тобто оптимум пологий: у вікні 6–15 подій і порозі
0.1–0.15 результат той самий.

### Що вийшло

1. **Правило знайдене, і воно вчетверо краще за випадок** у тому, що
   стосується **розворотів**: 18.0 % півотів мають перемикання в ±50
   подій проти 4.1 % у монетки тієї самої частоти — **×4.35**. Головне,
   що дав пошук, — гістерезис: перемикатись лише коли різниця відійшла
   від нуля на 0.1. Без нього (просто знак) виходить ×1.13, тобто
   нічого.
2. **Ногу правило не визначає.** 53.6 % збігу проти 71.8 % у сталої
   відповіді «завжди вгору». Ноги вниз воно веде (69 %), ноги вгору —
   ні (44 %). Як детектор напрямку це гірше за константу.
3. **Ціна залишається та сама**: медіана зсуву перемикання — сотні
   подій, у ±15 потрапляє одиниці відсотків. Правило констатує розворот
   із запізненням, а не називає його.

Правило-переможець (`win 10`, `level 0.1`) і малює ногу на графіку
вкладки.

## Дві голови: бік ноги і зона розвороту окремо

Попередні мережі дослідження казали «зона розвороту» одним числом, і
бік ноги з них не читався. Тут задача розділена на **дві незалежні відповіді** на кожній події:

| Голова | 0 | 1 |
| ------ | - | - |
| бік ноги | нога вниз | нога вгору — **нога, якій подія належить**, зона свого боку не втрачає |
| зона розвороту | тіло ноги | зона: хвіст ноги 10 % її подій плюс 15 після півота |

Мережа й вхід ті самі, що в `LSTM · сире`: 11 миттєвих чисел, 64
нейрони, один шар, шматки по 1024 події з прогрівом 200, `Adam` 0.002,
20 епох, `seed 17`. На виході два логіти замість трьох чисел, втрата —
сума двох `BCEWithLogits`, у зони позитив дорожчий утричі (її подій
приблизно ушестеро менше). Поріг обох голів 0.5. Епоха (15-та)
обирається середнім **збалансованої точності** двох голів на
відкладеному шматку.

### Голова «бік ноги» — val, 23 109 подій

| було \ сказала | нога вниз | нога вгору | повнота |
| -------------- | --------- | ---------- | ------- |
| нога вниз | **3 787** | 2 733 | 58.1 % |
| нога вгору | 3 147 | **13 442** | 81.0 % |
| точність | 54.6 % | 83.1 % | |

| На чому | точність | збалансована | AUC |
| ------- | -------- | ------------ | --- |
| мережа, val | **74.6 %** | **69.6 %** | **0.724** |
| мережа, відкладене | — | 74.9 % | 0.802 |
| контроль: завжди «нога вгору» | 71.8 % | 50.0 % | — |
| контроль: монетка за часткою | 59.4 % | 49.7 % | — |

### Голова «зона розвороту» — val

| було \ сказала | тіло ноги | зона | повнота |
| -------------- | --------- | ---- | ------- |
| тіло ноги | **14 164** | 5 528 | 71.9 % |
| зона розвороту | 1 473 | **1 944** | 56.9 % |
| точність | 90.6 % | 26.0 % | |

| На чому | точність | збалансована | AUC |
| ------- | -------- | ------------ | --- |
| мережа, val | 69.7 % | **64.4 %** | **0.717** |
| мережа, відкладене | — | 54.4 % | 0.648 |
| контроль: завжди «тіло ноги» | 85.2 % | 50.0 % | — |
| контроль: монетка за часткою | 74.7 % | 49.6 % | — |

### По монетах, val

| Монета | бік: точність | бік: збалансована | бік: AUC | зона: збалансована | зона: AUC |
| ------ | ------------- | ----------------- | -------- | ------------------ | --------- |
| BTC_USDT | 83.1 % | 86.2 % | 0.918 | 56.6 % | 0.657 |
| ETH_USDT | 78.8 % | 67.5 % | 0.677 | 69.6 % | 0.782 |
| SOL_USDT | 78.7 % | 77.3 % | 0.802 | 65.8 % | 0.735 |
| XRP_USDT | 56.8 % | 55.0 % | 0.585 | 63.3 % | 0.658 |
| BNB_USDT | 69.7 % | 58.6 % | 0.635 | 55.8 % | 0.621 |
| DOGE_USDT | 77.1 % | 71.1 % | 0.707 | 64.5 % | 0.759 |

### Що з цього виходить

1. **Бік ноги визначається.** 74.6 % точності проти 71.8 % у сталої
   відповіді й 69.6 % збалансованої проти 50 % — мережа називає
   напрямок ноги краще за константу й робить це на обох боках
   (58.1 % вниз, 81.0 % вгору).
2. **Поділ на дві голови й дав цей результат.** Кожна голова бачить усі
   події: подія зони розвороту лишає свій бік і вчить голову боку, а не
   віднімається від неї.
3. **Зона розвороту слабша, але читається**: збалансована 64.4 %, AUC
   0.717, повнота зони 56.9 % при точності 26.0 % — тобто вона вдвічі
   частіша, ніж треба.
4. **Розбіжність між монетами велика**: бік ноги від 56.8 % (XRP) до
   83.1 % (BTC), AUC від 0.585 до 0.918. Вибірка val — 111 розворотів,
   тому порядок видно, а різницю в кілька відсотків — ні.
5. **Голова боку сильніша на відкладеному шматку** (AUC 0.802 проти
   0.724 на val), голова зони — навпаки (0.648 проти 0.717). На такій
   вибірці це радше шум, ніж перевчання.

## Грід ручок і драбина функцій втрат

Ручки мережі й сама форма втрати підібрані заміром, а не на око.

### Ціна різкості у втраті

До двох `BCEWithLogits` додано штраф за те, як мережа **рухає** числа
між сусідніми подіями:

```
крок   = |p(t) − p(t−1)|
стрибок = jump · середнє( relu(крок − step)² )      step = 0.2
прокол  = spike · середнє( relu( −(p(t)−p(t−1)) · (p(t+1)−p(t)) ) )
```

Стрибок робить один рух на 0.6 дорожчим за три по 0.2 (квадрат від
перевищення), а прокол коштує тоді й тільки тоді, коли рух одразу
розвертається — тобто саме за «сіпнулась і повернулась».

### Кола гріду

Ручки перебираються колами: коло бере переможця попереднього і міняє
тільки свою групу. Оцінка — середня збалансована точність двох голів на
**відкладеному шматку** train, 12 епох на прогін, шість монет.

| Коло | Варіанти (оцінка на відкладеному) | Переможець |
| ---- | --------------------------------- | ---------- |
| ширина | 32 → 0.608 · 64 → 0.613 · **128 → 0.620** | `hid 128` |
| крок | **0.001 → 0.647** · 0.002 → 0.620 · 0.004 → 0.616 | `lr 0.001` |
| глушіння | 0.05 → 0.624 · **0.1 → 0.647** · 0.2 → 0.634 | `drop 0.1` |
| ціна зони | 2 → 0.608 · **3 → 0.647** · 5 → 0.607 | `zone 3.0` |
| різкість | без штрафу → 0.626 · **1/1 при 0.2 → 0.647** · 3/3 при 0.2 → 0.616 · 3/1 при 0.1 → 0.635 · 1/3 при 0.3 → 0.591 | `jump 1 · spike 1 · step 0.2` |

**Штраф за різкість допомагає, але помірний.** Пара 1/1 дає 0.647 проти
0.626 без штрафу; втричі дорожчий штраф гірший за його відсутність
(0.616) — мережа починає боятись рухатись узагалі.

**Проколів у цієї мережі й так мало.** Частка кроків понад 0.2 — 0.34 %
без штрафу і 0.33 % зі штрафом; помітно вона падає лише під фокальною
втратою (0.10 %). Тобто одиночні сіпання були не тією бідою, яку варто
було лікувати першою, — числа й без того рухаються повільно.

### Драбина функцій втрат

Від ваг переможця гріду, по 3 епохи на щабель; щабель лишається, якщо
оцінка на відкладеному виросла, інакше ваги відкочуються.

| Щабель | Стало | Було | Рішення |
| ------ | ----- | ---- | ------- |
| той самий штраф | 0.621 | 0.647 | вертаю |
| стрибок удвічі дорожчий | 0.613 | 0.647 | вертаю |
| прокол удвічі дорожчий | 0.611 | 0.647 | вертаю |
| безплатний крок 0.1 | 0.611 | 0.647 | вертаю |
| зона вдвічі дорожча | 0.645 | 0.647 | вертаю |
| фокальна втрата γ=2 | 0.628 | 0.647 | вертаю |
| бік важить удвічі | 0.614 | 0.647 | вертаю |

**Жоден щабель не втримався.** Донавчання трьома епохами з іншою
втратою щоразу давало гірше на відкладеному шматку, тому ваги
лишились ті, що дав грід. Найближче підійшла «зона вдвічі дорожча»
(0.645 проти 0.647), найдалі — подвоєння прокола.

Підсумкові ручки: `hid 128`, `lr 0.001`, `drop 0.1`, `zone 3.0`,
`step 0.2`, `jump 1.0`, `spike 1.0`. На них і навчена мережа розділу
вище (краща епоха — девʼята з двадцяти).

## Торгівля ногою: одна угода на ногу

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

Бік ноги можна прочитати двома способами, і обидва перебираються
нарізно:

```
рівень    ема(p_side, ema) вище up — нога вгору, нижче down — нога
          вниз, між порогами бік ТРИМАЄТЬСЯ той, що був
перетин   швидка ема(p_side, fast) вище повільної ема(p_side, slow) —
          нога вгору, нижче — вниз; рівень тут не потрібен узагалі
пік       зігзаг на самій ема-лінії: тримається її біжучий максимум, і
          коли лінія відкотилась від нього на back, пік ОГОЛОШУЄТЬСЯ —
          нога вниз; дзеркально для мінімуму

вхід      бік перемкнувся й тримається hold подій підряд
          (а якщо enter_zone > 0 — ще й зона ≥ enter_zone):
          бік угору — лонг, бік вниз — шорт
вихід     зона ≥ exit_zone і угода прожила щонайменше floor подій —
          або зміна боку, яка відкриває наступну угоду
```

Поріг тут несиметричний навмисне: `p_side` на нозі вгору стоїть біля
0.65, на нозі вниз — біля 0.30, і 0.5 посередині не обовʼязково
найкраще місце для обох боків. Саме тому `up` і `down` перебираються
окремими колами.

### Кола ручок

Оцінка — середній PnL шести монет на **відкладеному шматку train** із
комісією 0.05 % і сліпеджем 0.02 % за бік, вхід наступною подією.
Переможець шукається **тільки серед тих, хто справді торгує ногами** —
угод від 0.5 до 2.0 на ногу зігзага 2.3 % у вікні; якщо таких у колі
немає, береться найближчий до однієї угоди на ногу. Без цієї умови грід
сходиться до «майже не торгувати»: у кеші на відкладеному шматку
вигідніше, ніж у ринку.

Сімейство «рівень», кола одне за одним (угод на ногу · медіана угоди ·
PnL):

| Коло | Варіанти | Переможець |
| ---- | -------- | ---------- |
| згладження боку | 40 → 3.61 · −4.79 % · 100 → 2.94 · −4.10 % · 200 → 2.41 · −3.35 % · **400 → 1.81 · 329 под. · +1.20 %** | `ema 400` |
| поріг угору | **0.5 → 1.81 · +1.20 %** · 0.55 → 1.15 · −0.10 % · 0.6 → 0.46 · 0.65 → 0.19 · 0.7 → 0.11 (усі троє не торгують ногами) | `up 0.5` |
| поріг униз | 0.5 → 1.81 · +1.20 % · 0.45 → 1.22 · +3.15 % · **0.4 → 1.02 · 773 под. · +3.24 %** · 0.35 → 0.80 · +0.32 % · 0.3 і 0.25 — не торгують ногами | `down 0.4` |
| згладження боку ще раз | 40 → 2.83 · 100 → 2.07 (не торгують) · 200 → 1.48 · +1.60 % · **400 → 1.02 · +3.24 %** | `ema 400` |
| підтвердження входу | 1 → +3.20 % · 10 → +3.24 % · **30 → +3.42 %** · 90 → +2.63 % | `hold 30` |
| згладження зони | 1 · 10 · 40 — усі по +3.42 % | `zone_ema 1` |
| зона на вході | **0.0 → +3.42 %** · 0.3 → +1.12 % · 0.5 → −1.60 % | `enter_zone 0.0` |
| вихід по зоні | без виходу → +3.42 % · 0.5 → +4.37 % (медіана угоди 152 под.) · 0.7 → +6.05 % · **0.85 → +6.24 % (480 под.)** | `exit_zone 0.85` |
| мінімальна довжина угоди | 0 → +6.24 % · 50 → +6.76 % · **150 → +7.35 %** | `floor 150` |

Сімейство «перетин» тими самими колами дійшло до `fast 200`,
`slow 1600`, `hold 90`, `exit_zone 0.5`: **+2.04 %** при 1.41 угоди на
ногу. Сімейство «пік» — до `ema 400`, `back 0.1`, `hold 90`,
`exit_zone 0.85`, `floor 150`: **+6.64 %** при 1.31 угоди на ногу.

| Сімейство | угод | на ногу | медіана угоди | PnL | просадка |
| --------- | ---- | ------- | ------------- | --- | -------- |
| **рівень** (`ema 400`, `up 0.5`, `down 0.4`) | 54 | **1.00** | 501 под. | **+7.35 %** | 4.23 % |
| пік (`ema 400`, `back 0.1`) | 71 | 1.31 | 500 под. | +6.64 % | 5.25 % |
| перетин (`fast 200`, `slow 1600`) | 76 | 1.41 | 133 под. | +2.04 % | 3.94 % |

Кола сімейства «пік» показують, де в нього вузьке місце — у **розмірі
відкату**, а не у згладженні: на `ema 400` відкат 0.01 дає 4.19 угоди
на ногу і −5.12 %, 0.05 — 2.13 і −2.94 %, 0.1 — 1.31 і +3.85 %, 0.2 —
0.85 і +2.98 %. Дрібні відкати ловлять шум лінії, великі — ловлять
пік запізно.

Підсумкові ручки: `рівень`, `ema 400`, `up 0.5`, `down 0.4`,
`hold 30`, `zone_ema 1`, `enter_zone 0.0`, `exit_zone 0.85`,
`floor 150`.

Що з колон видно одразу:

1. **Поріг униз — не 0.5.** Зсунути його до 0.4 (тобто «у шорт лише
   тоді, коли мережа справді впевнена») дає +3.24 % проти +1.20 %, і
   саме воно приводить кількість угод до однієї на ногу. Поріг угору
   рухати не треба: 0.5 найкращий, а з 0.6 правило перестає торгувати
   взагалі.
2. **Бік треба гладити сильно.** Ема 400 подій проти 40: 1.02 угоди на
   ногу замість 3.61 і плюс замість мінуса.
3. **Плюс приносить вихід, а не вхід.** Без виходу по зоні +3.42 %, з
   виходом на 0.85 після 150 подій — +7.35 % при тій самій кількості
   угод. Голова зони справді каже, коли ногу пора закривати.
4. **Зона на вході тільки шкодить** (+3.42 → +1.12 → −1.60 %): чекати
   підтвердження зони на вході означає заходити пізно.
5. **Перетин двох ем видачі гірший за рівні** (+2.04 проти +7.35 %),
   хоча й тримає угоди коротшими.
6. **Пік лінії відкатом майже дорівнює рівням** (+6.64 проти +7.35 %) —
   але коштує затримки: оголошення приходить за ~540 подій після самої
   крайньої точки лінії. Рівні того самого не вимагають, бо не чекають
   відкату: вони перемикають бік на перетині порога.

### Чого коштує оголошення піка

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

| Монета | перемикань | до крайньої точки лінії | до півота зігзага |
| ------ | ---------- | ----------------------- | ----------------- |
| BTC_USDT | 5 | 527 под. | 141 под. |
| SOL_USDT | 1 | 1857 под. | 258 под. |
| XRP_USDT | 2 | 1493 под. | 288 под. |
| DOGE_USDT | 2 | 897 под. | 155 под. |
| ETH_USDT і BNB_USDT | 0 | — | — |
| **разом** | 10 | **542 под.** | **193 под.** |

Тобто на `ема 400` перемикання боку приходить приблизно через 540
подій після самої крайньої точки лінії й стоїть за 193 події від
півота зігзага — це і є відповідь на «як виявити пік»: відкатом, і не
безплатно. На самій ціні той самий спосіб — це вже наявний суперник
`зігзаг 1.2 %`: біжучий екстремум ема10 плюс відкат на 1.2 % (його
власна затримка — 15–43 події, етап 14 нижче по тексту дослідження 33
міряв її окремо).

### Що вийшло на val: $1000 на монету

| Монета | угод | ніг зігзага | кінець | PnL | виграшних | середня угода | просадка | шарп |
| ------ | ---- | ----------- | ------ | --- | --------- | ------------- | -------- | ---- |
| BTC_USDT | 6 | 5 | $1097.18 | +9.72 % | 50.0 % | +1.76 % | 6.39 % | 7.43 |
| ETH_USDT | 1 | 3 | $1031.38 | +3.14 % | 100 % | +3.28 % | 1.57 % | 7.00 |
| SOL_USDT | 2 | 7 | $1067.21 | +6.72 % | 100 % | +3.47 % | 1.80 % | 11.50 |
| XRP_USDT | 3 | 23 | $997.30 | −0.27 % | 33.3 % | +0.21 % | 8.19 % | 0.03 |
| BNB_USDT | 1 | 3 | $1042.40 | +4.24 % | 100 % | +4.39 % | 1.58 % | 14.75 |
| DOGE_USDT | 3 | 13 | $1138.07 | +13.81 % | 33.3 % | +4.76 % | 12.50 % | 2.95 |
| **правило, середнє** | 16 | 54 (0.30/ногу) | — | **+6.23 %** | — | — | **5.34 %** | — |
| купив і тримав | 6 | — | — | **+24.26 %** | — | — | 11.31 % | — |
| ема ціни (`fast 200` / `slow 3200`) | 16 | 0.30/ногу | — | +19.38 % | — | — | 11.31 % | — |
| монетка тієї самої частоти | 16 | 0.30/ногу | — | +7.48 % | — | — | 12.72 % | — |
| зігзаг 1.2 % | 136 | 2.52/ногу | — | +1.88 % | — | — | 21.74 % | — |

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

### Що з цього виходить

1. **Правило робить те, що просили**: вхід на початку ноги мережі,
   вихід на її кінці, одна угода на ногу — на відкладеному шматку
   рівно 1.00 угоди на ногу, і жодної розмітки всередині.
2. **Підбір порогів дав утричі більше, ніж симетричні 0.5/0.5**:
   +7.35 % проти +1.20 % на тому самому шматку, і це ефект двох чисел —
   `down 0.4` і `ema 400`.
3. **На val правило не піднялось ні над ціною, ні над випадком**:
   +6.23 % проти +19.38 % у ема ціни, +24.26 % у холду і **+7.48 % у
   монетки** тієї самої частоти. Просадка в нього найменша (5.34 %),
   але це єдина перевага.
4. **Частота на val падає втричі**: 0.30 угоди на ногу замість 1.00 на
   відкладеному шматку. Ема 400 подій, налаштована на ноги одного
   шматка, на іншому шматку тримає бік довше, ніж живуть ноги, — на
   23 ноги XRP припало 3 угоди.
5. **Головне число цього етапу — не PnL, а те, що ема самої ціни,
   підібрана тим самим гридом, утричі краща за видачу мережі.** Голова
   боку не додає до ціни нічого, що конвертувалось би в гроші на
   відкладеному в часі шматку.

## Скільки з цього — випадок

Розмітка проєкту — зігзаг **2.3 %** на ема10: його півоти є ціллю, і це
не міняється. Суперник — **інше правило**: «ема відійшла від крайньої
точки ряду на `X` %». Розмітки воно не бачить, і порогу `X` розмітка не
задає. У заміру вище `X` = 1.2 % було взято на око, «приблизно пів
ноги». Тут воно міряється драбиною, і поруч із кожним щаблем іде
монетка тієї самої частоти.

| Поріг | сигналів | ±15 | монетка ±15 | ×монетка | ±50 | монетка ±50 | медіана \|зсуву\| | взято ходу |
| ----- | -------- | --- | ----------- | -------- | --- | ----------- | ---------------- | ---------- |
| 0.4 % | 419 | 73.3 % | 18.3 % | ×4.0 | 90.0 % | 75.0 % | 12.5 | +0.20 % |
| 0.6 % | 297 | 61.7 % | 16.7 % | ×3.7 | 90.0 % | 68.3 % | 15.5 | +0.85 % |
| 0.8 % | 220 | 51.7 % | 15.0 % | ×3.4 | 83.3 % | 48.3 % | 25.0 | +0.80 % |
| **1.2 %** | 136 | 35.0 % | 3.3 % | **×10.5** | 71.7 % | 35.0 % | 47.0 | +1.20 % |
| 1.6 % | 88 | 25.0 % | 3.3 % | ×7.5 | 61.7 % | 23.3 % | 66.8 | +2.04 % |
| 2.3 % | 60 | 13.3 % | 1.7 % | ×8.0 | 40.0 % | 21.7 % | 96.5 | +2.14 % |
| 3.0 % | 48 | 10.0 % | 1.7 % | ×6.0 | 26.7 % | 11.7 % | 183.2 | +1.74 % |

Поріг 1.2 % **витримав замір**: за перевагою над монеткою тієї самої
частоти він найвищий щабель драбини (×10.5 на ±15). Видно й дві речі
поруч: чим нижчий поріг, тим ближче сигнал до півота, але тим менше
взятого ходу (0.4 % дає медіанний зсув 12.5 події і всього +0.20 %
ходу), а поріг, рівний розмітці (2.3 %), спрацьовує рівно раз на
розворот, зате запізнюється на 96.5 події.

### Крива випадковості за частотою

Монетка, якій дали задану кількість сигналів; 20 роздач на точку,
сигнали розкидані по монетах у пропорції їхніх подій.

| Сигналів | ±5 | ±15 | ±50 | ±100 | медіана \|зсуву\| |
| -------- | -- | --- | --- | ---- | ---------------- |
| 40 | 1.2 % | 3.3 % | 8.5 % | 17.5 % | 330.0 |
| 59 | 1.2 % | 3.8 % | 12.3 % | 23.8 % | 242.2 |
| 90 | 2.3 % | 5.4 % | 19.3 % | 35.1 % | 163.7 |
| 120 | 3.0 % | 8.8 % | 24.4 % | 44.1 % | 131.3 |
| 151 | 4.3 % | 10.8 % | 30.3 % | 51.4 % | 110.2 |
| 199 | 6.3 % | 13.8 % | 41.4 % | 66.8 % | 72.2 |
| 300 | 5.8 % | 18.8 % | 53.4 % | 81.1 % | 50.3 |
| 420 | 9.8 % | 25.7 % | 68.8 % | 91.2 % | 33.8 |

Крива — обовʼязкова лінійка для всієї таблиці val: 40 % влучань ±50 у
поєднувача на 151 сигналі й 40 % у зігзага 2.3 % на 60 сигналах — це
**різні** результати, бо випадок на цих частотах дає 30.3 % і 12.3 %
відповідно.

## Чи знають мережі, **де** був розворот

Зігзаг спізнюється за будовою: він чекає, поки ціна відійде від
крайньої точки на 1.2 %, і його медіанний зсув — 47 подій. Останній
замір ставить окреме питання: **чи знає котрийсь канал, де саме в
останніх 150 подіях була та крайня точка.** Сигнал зігзага посувається
назад — у найгучнішу подію каналу за ці 150 подій.

| Сигнал | ±5 | ±15 | ±50 | ±100 | медіана \|зсуву\| | взято ходу |
| ------ | -- | --- | --- | ---- | ---------------- | ---------- |
| зігзаг 1.2 % як є | 6.7 % | 35.0 % | 71.7 % | 91.7 % | 47.0 | +1.20 % |
| ↑ памʼять `сире` | **26.7 %** | 43.3 % | **78.3 %** | **93.3 %** | 27.8 | +6.59 % |
| ↑ `pivot` | 20.0 % | **45.0 %** | **78.3 %** | 91.7 % | **20.2** | +6.79 % |
| ↑ `p100` | | 40.0 % | 68.3 % | | 32.8 | +7.18 % |
| ↑ `p10`…`p640` | | 35.0 % | 68.3 % | | 28.8 | +5.24 % |
| ↑ `correct` | | 40.0 % | 66.7 % | | 30.5 | +5.34 % |
| ↑ `tooth` | | 30.0 % | 63.4 % | | 36.8 | +3.97 % |
| ↑ поєднувач | | 36.7 % | 63.3 % | | 25.0 | +5.40 % |
| ↑ `line` | | 21.7 % | 63.3 % | | 45.0 | +0.50 % |

Канал `pivot` зменшує медіанний зсув **удвічі** — з 47 подій до 20.2 —
і піднімає влучання ±15 з 35 % до 45 %, а ±5 — утричі, з 6.7 % до 20 %.
Сила поєднувача з памʼяттю кладе сигнал ще точніше **на ±5 подій**:
26.7 % проти 20 % у `pivot` і 6.7 % у самого зігзага, хоч медіана зсуву
в неї гірша (27.8 проти 20.2). Тобто там, де памʼять попадає, вона
попадає щільно, а там, де ні, — промахується дальше.

**Важливо, чим це не є.** Майбутнього в поправці немає жодного: вікно —
це `[at − 150, at]`, усі 150 подій і всі канали на них уже відомі в мить,
коли зігзаг підтвердився. Невиконуване тут інше — **точка дії лежить у
минулому**: у мить сигналу та подія вже минула, і вхід у ній не
поставиш. Плюс два справжні розриви: `argmax` по вікну відомий лише на
його правому краю (живцем на події `at − 20` видно «максимум поки що»,
а не «максимум вікна»), і сам правий край тримається на зігзагу, який
чекає 1.2 % ходу. Стовпчик «взято ходу»
для підтягнутих рядків — число **заднім числом**, не торговий
результат. Замір відповідає на питання про знання, а не про виконання:
мережі не кажуть, **коли** розвертатись, але досить точно кажуть, **де**
розворот стався, щойно він став видимим.

## Симуляція торгівлі: $1000 на val BTC

Влучання ±50 подій — не гроші. Останній замір ставить питання прямо:
що зробив би з $1000 кожен із цих сигналів на val BTC.

Умови за [`rules/04-trading.md`](../../rules/04-trading.md):

| Що | Як |
| -- | -- |
| Капітал | $1000, повністю в позиції, без плеча, складний |
| Вхід | **наступною подією** після сигналу, не тією самою |
| Витрати | комісія taker 0.05 % + сліпедж 0.02 % **за бік** |
| Позиція | `обидва` — сигнал перевертає лонг/шорт; `лонг` — продаж виводить у кеш |
| Просадка | переоцінка на **кожній** події, не на закритті угоди |
| Гроші | `Decimal`, ціни до копійки |

Комісія в правилах стоїть як `TODO`, тому взято ф'ючерсний taker і
поруч подано драбину чутливості. **Стопа немає**, тому це замір
сигналу, а не стратегія: правила не дозволяють відкривати позицію без
стопа.

Вікно: 3549 подій, 13.3 дня, ціна 63 042.82 → 77 403.99, хід ряду
416.2 % — це **тренд угору** з шістьма розворотами 2.3 %.

### Перевертання позиції

| Сигнал | угод | кінець | PnL | виграшних | просадка | шарп |
| ------ | ---- | ------ | --- | --------- | -------- | ---- |
| **купив і тримав** | 1 | **$1226.33** | **+22.63 %** | 100 % | 5.21 % | 12.08 |
| зігзаг 1.2 % | 10 | $1199.43 | +19.94 % | 50.0 % | 7.41 % | 10.84 |
| зігзаг 2.3 % | 6 | $1156.25 | +15.62 % | 50.0 % | 7.04 % | 8.75 |
| зігзаг 0.8 % | 28 | $1014.35 | +1.43 % | 42.9 % | 15.09 % | 1.07 |
| поєднувач MLP | 12 | $980.64 | −1.94 % | 41.7 % | 10.70 % | −1.05 |
| зігзаг 0.4 % | 62 | $895.61 | −10.44 % | 30.6 % | 18.48 % | −6.11 |
| монетка | 10 | $882.48 | −11.75 % | 50.0 % | 19.09 % | −6.63 |
| поєднувач із памʼяттю | 8 | $848.86 | −15.11 % | 75.0 % | 25.23 % | −7.96 |

### Той самий сигнал без шортів

| Сигнал | угод | кінець | PnL | виграшних | просадка | шарп |
| ------ | ---- | ------ | --- | --------- | -------- | ---- |
| **зігзаг 1.2 %** | 5 | **$1208.83** | **+20.88 %** | 60.0 % | **4.60 %** | **13.39** |
| зігзаг 2.3 % | 3 | $1179.97 | +18.00 % | 66.7 % | 4.33 % | 11.19 |
| зігзаг 0.8 % | 14 | $1114.19 | +11.42 % | 64.3 % | 7.08 % | 7.80 |
| монетка | 5 | $1046.13 | +4.61 % | 60.0 % | 3.74 % | 4.12 |
| поєднувач із памʼяттю | 4 | $1045.95 | +4.59 % | 100 % | 2.35 % | 6.25 |
| поєднувач MLP | 6 | $1032.31 | +3.23 % | 50.0 % | 5.35 % | 3.07 |
| зігзаг 0.4 % | 31 | $1047.47 | +4.75 % | 41.9 % | 9.33 % | 3.57 |

### Чутливість до витрат

Кінцевий капітал за різної ціни обслуговування, за бік:

| За бік | зігзаг 1.2 % | поєднувач MLP | памʼять | монетка |
| ------ | ------------ | ------------- | ------- | ------- |
| 0 % | $1216.35 | $997.26 | $858.42 | $894.93 |
| 0.02 % | $1211.49 | $992.49 | $855.68 | $891.36 |
| 0.05 % | $1204.24 | $985.37 | $851.58 | $886.02 |
| 0.10 % | $1192.25 | $973.60 | $844.79 | $877.20 |

### Що з цього виходить

1. **Нічого не побило «купив і тримав».** $1226.33 без жодної моделі
   проти $1208.83 у найкращого сигналу. На тренді угору це очікувано:
   будь-який вихід із ринку коштує частини тренду.
2. **Сигнал зігзага 1.2 % — єдиний, що тримає гроші.** Без шортів він
   дає +20.88 % при просадці 4.60 % проти 5.21 % у холду, тобто трохи
   кращий шарп (13.39 проти 12.08) при майже тому самому PnL. Це вся
   перевага, яка в дослідженні є.
3. **Обидва поєднувачі на рівні монетки.** Без шортів: $1032 і $1046
   проти $1046 у монетки. З шортами вони гірші за неї. Влучання
   «×1.3–2.4 проти випадку» в грошах не видно.
4. **Порядок тримається не на комісії.** При нульових витратах
   поєднувач усе одно $997, а монетка $895: справа не в обслуговуванні,
   а в самих сигналах.
5. **Вікно маленьке.** 13.3 дня, 6 розворотів, один напрямок тренду.
   Різниця між сусідніми рядками тут — не результат; результат — те, що
   мережі не піднялися над монеткою, а простий зігзаг піднявся.

## Перетини голови з емою: кандидати в розворот і їх перевірка

Скрипт: [`scripts/legs_cross.py`](scripts/legs_cross.py). Ряд —
**val BTC_USDT**, 9 412 подій, та сама двоголова мережа етапу 12.

### Правило кандидата

Правило причинне й читає одне число — видачу голови «бік ноги» проти
**її власної ема 200**:

| Умова | Кандидат |
| ----- | -------- |
| видача перетинає ему **зверху вниз** | продаж |
| видача перетинає ему **знизу вгору** | купівля |

Беруться не всі перетини, а ті, що пройшли **два відбори**. Обидва
причинні й читають те саме одне число:

| Відбір | Умова | Навіщо |
| ------ | ----- | ------ |
| рівень | продаж — тільки поки голова ще вище 0.5, купівля — поки ще нижче | голова, що вже перейшла на інший бік, кінця старої ноги не оголошує: там ема просто доганяє нове положення |
| тиша | перетин ближчий за 20 подій до попереднього **взятого** відкидається | вікно однієї відповіді моделі ±10 подій, тож два такі перетини питають про ті самі події |

Перші 200 подій ряду — прогрів ема, перетини там не рахуються.

Голова відповідає **не на кожній події**: там, де входу немає, немає й
числа. Тому попереднє значення береться з останньої події, **де воно
є**, а не з сусідньої — дірка в ряді перетину не ковтає. На val BTC
голова говорить на 3 549 подіях із 9 412 (відрізок 643 … 6 101), і
справжніх меж у нього потрапило **6 з 8**.

Без відборів перетинів **127**, з ними — **61**. Жодного знайденого
розвороту й жодної закритої межі при цьому не втрачено: рубається
рівно шум. Половину зняв рівень (127 → 66), решту — тиша (66 → 61).
Що саме кожен відбір дає, виміряно на тому самому ряді:

| Правило | Перетинів | Знайдено | Меж закрито |
| ------- | --------: | -------: | ----------: |
| усі перетини | 127 | 6 | 5 |
| + рівень | 66 | 6 | 5 |
| + рівень і тиша | **61** | **6** | **5** |
| + глибина відходу ≥ 0.05 | 35 | 3 | 3 |
| + попередній бік тримався ≥ 50 под. | 25 | 4 | 4 |

Два останні рядки — відбори, від яких довелось відмовитись: вони
ріжуть сильніше, але разом із шумом забирають знайдені розвороти.

### Чим перевіряється кандидат

Перетин **не називає подію** — він каже зону: «нога, схоже, кінчилась
десь тут». Далі в цій зоні працюють дві моделі **етапу 7 дослідження
34** — ті самі, що на вкладці [`/border`](http://localhost:8080/border),
навчені на подіях краю шести монет до межі val, по 7 800 подій кожна:

| Модель | Що дає | Чого чекаємо на межі |
| ------ | ------ | -------------------- |
| бік межі | P(подія належить нозі, що почалась) | до межі низько, після — високо |
| бік розвороту | P(межа поруч — вершина) | продаж — вершина, купівля — дно |

Сходинка «боку межі» шукається по **всіх** положеннях межі в зоні
±25 подій — це той самий `SNAP_SPAN`, у якому розмітка переносить
півот на екстремум ціни. Кожне положення міряється своїм вікном ±10
подій — тим, на якому модель вчилась, — і модель сама **називає
подію**, де сходинка сходиться найкраще. «Бік межі» читається в рамці
тієї ноги, яка мала б кінчатись: продаж — рамка вершини, купівля —
рамка дна.

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

Слова «підтвердили» тут немає навмисно, і це не стилістика.

### Чому моделі кажуть «півот тут» майже завжди

Питання «чи тут півот» жодна з двох моделей не бере — відповісти на
нього вона не може за побудовою:

| | |
| --- | ---: |
| навчальна вибірка обох моделей | **9 300 подій** |
| з них краї 465 справжніх меж (±10 від кожної) | **9 300** |
| з них подій середини ноги | **0** |

Модель ніколи не бачила події, яка не є краєм. Тому «бік межі»
вибирає з двох — хвіст старої ноги чи голова нової; «бік розвороту»
вибирає з двох — вершина чи дно. **Класу «тут нічого немає» в них не
існує.**

У ряді val BTC їх питають на 3 475 подіях, з яких подіями краю є
лише **124 — 3.6 %**. Решту 96.4 % питань модель бачить уперше і
все одно відповідає впевнено.

Звідси й розрив, який видно оком:

| | |
| --- | ---: |
| справжніх меж у val BTC | 8 на 9 412 подій — **одна на 1 176** |
| апріорний шанс межі у вікні ±25 (51 подія) | **4.3 %** |
| частка зон, де моделі вказали подію | **80.3 %** |

Це не шум прогону і не помилка налаштувань: модель відповідає на
інше питання, ніж те, яке їй ставить ланцюжок. Її власне дослідження
це й фіксує — замір етапу 7 дослідження 34 умовний за побудовою:
«модель питають тільки на подіях краю, а в живому ряді край ще треба
знайти».

Тому в ланцюжку в неї лишається рівно одна робота — **вказати
подію** всередині зони, знайденої першою ланкою. Знайти саму зону
вона не може, і питати її про це марно.

Моделі межі працюють у ряді **не завжди**: вони пускаються рівно там,
де стався перетин, і тільки в його зоні (плюс вікно ±10, потрібне
самій відповіді на краях зони). На val BTC це **3 475 подій з 9 412 —
36.9 % ряду**; поза зонами їхніх ліній немає. Причина проста: вони
вчились на подіях краю і поза краєм відповідають завжди й гучно, тому
пускати їх по всьому ряду — значить дивитись на шум.

Згода околу **збалансована**: половина її — частка подій до межі,
названих старою ногою, половина — частка подій після, названих новою.
Рівна лінія, хоч висока, хоч низька, дає рівно 0.5, тому поріг стоїть
саме там.

### Сирі лінії моделей у зонах не кажуть нічого

Дивитись на самі видачі двох моделей марно, і це виміряно:

| Що міряли | На val BTC у зонах |
| --------- | -----------------: |
| «бік межі» перескакує через 0.5 | 667 разів на 3 475 подій — **раз на 5.2 події** |
| стрибків у зоні зі справжньою межею | медіана 10.5 |
| стрибків у зоні **без** межі | медіана 9.0 |
| «бік розвороту» нижче 0.05 або вище 0.95 | **86.8 %** подій |
| медіана «боку розвороту» | 0.845 |

Справжня межа дала б **одну** сходинку — а лінія дає девʼять на
пʼятдесят подій, і в порожній зоні рівно стільки ж. «Бік розвороту»
ніколи не каже «не знаю»: він стоїть на рейках 0 або 1. Причина та,
яку виміряв етап 7 дослідження 34: моделі вчились **тільки на подіях
краю**, тому поза краєм бачать край скрізь.

Вирок ухвалюється **не з цих ліній**, а зі **згоди зони** — окремої
плашки ряду: «якщо межа стоїть тут, наскільки окіл ±10 із цим
згоден». У згоди пік є, і його модель обирає.

Що цей вибір не випадковий — показує окремий контроль. Справжня межа
взагалі досяжна лише в **7 зонах із 61**, і з них дістають:

| Хто називає подію | Влучань у ±10 |
| ----------------- | ------------: |
| **модель** | **6 із 7** |
| випадкова подія тієї самої зони | 2.5 (середнє з 2 000 прогонів) |
| сам перетин, без моделі | 2 |
| стеля зони (будь-яка подія) | 7 |

Отже, моделі не «нічого не кажуть» — вони нічого не кажуть про те,
**чи** тут розворот, але добре кажуть, **де** саме він, коли він у
зоні є. Це і є вказівник без фільтра.

### Що таке межа і як рахується влучання

**Межа** — це справжня точка розвороту ноги з розмітки проєкту:
зігзаг 2.3 % на ема10, півот перенесений на екстремум `price_close` у
вікні ±25 подій. На val BTC їх **8** — 4 вершини і 4 дна. Ні перетин,
ні моделі її не бачать: вона тільки для перевірки.

Розворот вважається **знайденим**, якщо межа того самого боку стоїть
не далі ніж **±10 подій від події, яку назвала модель** — а не від
самого перетину. Це не дрібниця: перетин 08-25 07:58 стоїть за 27
подій від вершини (на дві події далі за край зони), а названа моделлю
подія — за **2**. Стара міра рахувала це промахом, хоч ланцюжок
спрацював.

Окремо лишається питання «чи була межа в зоні перетину взагалі» — це
міра **першої** ланки, а не моделей.

| Термін | Що це | На val BTC |
| ------ | ----- | ---------: |
| межа | справжній розворот ноги з розмітки (правда) | 8 |
| перетин | де спрацювало правило | 61 |
| зона | ±25 подій навколо перетину, де шукають моделі | 36.9 % ряду |
| знайдений розворот | подія, яку назвала модель у зоні | 49 |

### Скільки перетинів і що з них вийшло

Зона ±25 подій, допуск вказівки ±10:

| Сигнал | Перетинів | Моделі вказали подію | Межа в зоні | Знайдено |
| ------ | --------: | ------------: | ----------: | -------: |
| продаж | 41 | 31 | 2 | 2 |
| купівля | 20 | 18 | 4 | 4 |
| **разом** | **61** | **49** | **6** | **6** |

| моделі \ правда | межа поруч із названою подією (±10) | межі там немає |
| --------------- | ----------------------------------: | -------------: |
| назвали подію | **6** | 43 |
| змовчали | 0 | **12** |

Похибка вказівки на знайдених: медіана **4 події**, найкраща — **1**.

**Підлога.** Максимум по всій зоні дається задешево, тому та сама
перевірка проганяється на **400 випадкових** подіях відрізка, де бік
береться так само, як у правила:

| На чому | Назвали подію | Знайдено |
| ------- | ------------: | -------: |
| перетини (61) | 80.3 % | **9.8 %** |
| випадкові події (400) | **85.5 %** | 3.8 % |

Після відборів перетин уперше стоїть вище підлоги там, де це важить:
знайдених розворотів на ньому 9.8 % проти 3.8 % на випадковій події —
у 2.6 раза. Підтвердження як таке підлогу так і не перебиває (80.3
проти 85.5 %): моделі кажуть «так» майже скрізь, і фільтром вони
не є — вони **вказівник**.

### Драбина розмірів зони

| Зона | Назвали подію | З них знайдено | Точність | Справжніх меж у зоні перетину | З них зловлено | Похибка вказівки |
| ---- | ------------: | -------------: | -------: | ----------------------------: | -------------: | ---------------: |
| ±10 под. | 41 | 4 | 9.8 % | 2 з 6 | 1 | 7 под. |
| **±25 под.** | **49** | **6** | **12.2 %** | **5 з 6** | **4** | **4 под.** |
| ±50 под. | 49 | 6 | 12.2 % | **6 з 6** | 4 | 4 под. |
| ±100 под. | 52 | 3 | 5.8 % | 6 з 6 | 3 | 1 под. |
| ±200 под. | 44 | 1 | 2.3 % | 6 з 6 | 1 | 0 под. |

Ширша зона не допомагає: модель дістає далі, але звідти приносить
подію, яка до межі вже не має стосунку. Найбільше **знайдених** дає
зона ±25 … ±50, і саме там похибка вказівки найменша при повному
покритті.

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

### Що ряд показує

| На графіку | Що це |
| ---------- | ----- |
| сіра смуга | зона, де питали моделі — 36.9 % ряду |
| плашка «згода зони» | число, з якого йде вирок; ромб на ній — обрана точка на висоті своєї згоди |
| точка на ціні | **перетин** — де спрацювало правило; форма каже вирок |
| ромб на ціні | **подія, яку назвала модель** усередині зони |
| сіра риска | справжня межа ноги — правда, у правилі не бере участі |

Точка і ромб — **різні ланки** ланцюжка, і стоять вони на різних
подіях. Точка є на кожному перетині; ромба немає там, де моделі
змовчали. Відстань між точкою і її ромбом — це зсув, який моделі
внесли у вказівку.

| Форма | Що означає | На val BTC |
| ----- | ---------- | ---------: |
| ● залита точка | перетин, у якому розворот знайдено | 6 |
| ○ порожнє коло | моделі назвали подію, а межі біля неї немає | 43 |
| □ квадрат | межа в зоні була, а моделі змовчали | 0 |
| · дрібна цятка | моделі змовчали, і межі не було | 12 |
| ◆ залитий ромб | названа подія, біля якої межа справді стоїть | 6 |
| ◇ контурний ромб | названа подія, біля якої межі немає | 43 |

Залитих точок і залитих ромбів завжди порівну: це той самий вирок,
показаний на двох подіях — на перетині й на вказівці.

Усі позначки розділу малюються в **екранних** координатах. Полотно
ряду тягнеться зумом тільки по X (`scale(view.k, 1)`), тому фігура,
намальована в координатах даних, на зумі пласкішає: коло стає
горизонтальним еліпсом, ромб — рискою. У екранних координатах форма й
розмір позначки однакові на будь-якому масштабі.

### Шість знайдених розворотів

| Коли, UTC | Сигнал | На перетині | Найкраща в зоні (зсув) | Бік розвороту | Перетин до межі | Похибка вказівки |
| --------- | ------ | ----------: | ---------------------: | ------------: | --------------: | ---------------: |
| 08-23 08:58 | купівля | 0.100 | 0.773 (−11) | 0.422 | −17 под. | 6 под. |
| 08-25 07:58 | продаж | 0.096 | 0.723 (−25) | 0.938 | **−27 под.** | **2 под.** |
| 08-26 14:09 | купівля | 0.400 | 0.864 (+19) | 0.001 | 15 под. | 4 под. |
| 08-26 16:01 | купівля | 0.500 | 0.864 (−13) | 0.001 | −17 под. | 4 под. |
| 08-28 02:32 | продаж | 0.500 | 0.955 (−17) | 0.995 | −18 под. | **1 под.** |
| 08-28 21:59 | купівля | 0.673 | 0.718 (+4) | 0.177 | −1 под. | 5 под. |

На пʼяти з шести згода **рівно на перетині** не дотягує до 0.5 —
питання «чи межа стоїть саме тут» відкинуло б їх усі. Працює саме
зона: у стовпці поруч та сама згода в найкращому її положенні, і там
вона від 0.72 до 0.96.

Рядок 08-25 — той, заради якого мірка й змінилась: перетин стоїть за
27 подій від вершини, тобто **поза** зоною ±25, а названа моделлю
подія — за 2. За старою міркою це був промах.

Перетин 08-22 04:14 має межу в зоні (за 7 подій), але названа подія
відстоїть від неї на 18 — понад допуск ±10, тож він чесно лишився
в «хибах». Це єдиний такий випадок: усюди, де межа в зоні була,
моделі або вказали в допуск, або промахнулись на цьому одному.

### Що з цього виходить

1. **Перетини, що лежать на самих півотах, губила не умова рівня, а
   дірка в ряді.** Голова говорить не на кожній події, і поки
   попереднє значення бралось із сусідньої події, а не з останньої,
   **де воно є**, перетин на півоті просто не помічався. Коли памʼять
   через дірки полагодили, умова рівня перестала щось коштувати: з
   нею перетинів 66 замість 127, а знайдених розворотів так само 6 і
   покриття меж так само 5 з 6. Тиша в 20 подій знімає ще пʼять
   перетинів і теж нічого не забирає — разом 61.
2. **Влучання треба міряти від названої події, а не від перетину.**
   Робота ланцюжка — знайти розворот; перетин лише каже, де шукати.
   Стара міра губила випадки, де модель вказала за 2 події від межі,
   тільки тому, що сам перетин стояв на дві події далі за край зони.
3. **Як фільтр моделі не працюють — і не можуть.** Питання «чи тут
   півот» у них не стоїть: уся навчальна вибірка обох — **9 300
   подій, і всі 9 300 — краї** справжніх меж, подій середини ноги в
   ній нуль. Класу «тут нічого немає» не існує, тому «ні» сказати
   нічим. Півот у нозі один — 8 меж на 9 412 подій, одна на 1 176, і
   апріорний шанс межі у вікні ±25 — 4.3 %; моделі кажуть «ось вона»
   у 80.3 % зон.
4. **Числа моделей цього розриву не рятують.** На випадкових подіях
   вони називають подію в **85.5 %** зон, на перетинах — 80.3 %. «Ні»
   сказано 12 разів із 61, і **жодного разу** там, де межа справді
   була (пропусків 0). Власні числа моделей теж не ділять: медіана
   згоди на «хибах» — 0.855, на знайдених — 0.818, тобто **вища** в
   помилок. Жодного порога, що відріже хиби й лишить знахідки, у цих
   числах немає. Сира лінія «боку межі» в зоні зі справжньою межею
   стрибає через 0.5 стільки ж разів, скільки в порожній (10.5 проти
   9.0), а «бік розвороту» в 86.8 % подій стоїть на рейках.
5. **Як вказівник — працюють.** Коли межа в зоні є, модель називає
   подію з медіанною похибкою **4 події**, найкраща вказівка —
   **1 подія**. Контроль це підтверджує: межа досяжна лише в 7 зонах
   із 61, і модель бере з них **6**, тоді як випадкова подія тієї
   самої зони бере 2.5, а сам перетин — 2. Це і є їхня робота: не
   «так чи ні», а «ось ця подія».
6. **Ширша зона повноти не додає.** ±25 і ±50 дають по 6 знайдених,
   ±100 і ±200 — уже 3 і 2: модель дістає далі, але приносить звідти
   подію, яка до межі стосунку не має. Зона має бути такою, як похибка
   першої ланки, і не більшою.
7. **Точність ланцюжка тримається на першій ланці.** Це видно прямо
   з відборів: 6 знайдених зі 127 — 4.7 % проти підлоги 3.8 %
   (майже нічого), 6 із 61 — **9.8 %**, у 2.6 раза вище підлоги. Той
   самий чисельник, вдвічі менший знаменник. Далі рухати точність
   треба тим самим шляхом — рідшою першою ланкою; друга на неї не
   впливає.
8. **Це не новина, а те саме, що вимірював етап 7 дослідження 34.**
   Його власний замір названий там умовним за побудовою: «модель
   питають тільки на подіях краю, а в живому ряді край ще треба
   знайти». Ряд того етапу показує те саме: зарубка лінії «бік межі»
   буває тисячі разів на чотири справжні межі. Помилка була не в
   прогоні, а в тому, що я підписав другу ланку словом
   «підтвердили» — вона нічого не підтверджує і не може.

## Результат

1. **Сигналу купівлі й продажу з поєднання видач не виходить.** MLP
   бере 40 % розворотів ±50 подій при випадку 30.3 % на тій самій
   частоті — ×1.3; причинний зігзаг 1.2 % на тій самій ціні бере
   71.7 % при випадку 28.1 % (×2.6) і єдиний виходить у плюс по ходу.
2. **Памʼять допомагає, але не вирішує.** GRU уздовж подій на 11
   миттєвих числах тримає ×2.2–2.4 проти випадку там, де MLP на 47
   ознаках тримає ×1.3–1.7, і бере 46.7 % ±50 на 93 сигналах замість
   40 % на 151. Хід вона так само втрачає (−2.86 %), а крива навчання
   на відкладеному шматку стоїть на місці всі 20 епох — вузьке місце не
   в архітектурі.
3. **Готові вікна памʼяті шкодять рекурентній мережі**: набір з усіма
   47 ознаками MLP гірший за самі миттєві числа й вчить відкладений
   шматок напамʼять уже з другої епохи.
4. **Зона розвороту — частка ноги, а не стале вікно.** Ті самі 50
   подій — це 17 % короткої ноги і 3.7 % довгої (дослідження 32,
   етап 9). На мітці «10 % ноги + 15 подій» сигнал сів щільніше до
   розвороту: ±5 у GRU · `сире` 5.0 → 10.0 %, ±15 11.7 → 20.0 % на
   чверть меншій кількості сигналів, а проти випадковості виграш
   виріс із ×2.2 до ×5.9. Узятий хід лишився відʼємним.
5. **Комірка памʼяті теж нічого не вирішує.** LSTM і GRU на тому самому
   вході, ході й seed розходяться в межах шуму: на відкладеному шматку
   вище LSTM (30.0 % проти 23.3 % ±50), на val — GRU (46.7 % проти
   33.3 %), а ±15 у них на val однакове. Обидва шматки — по 60 півотів,
   тому 8 півотів перевертають порядок. Різниця між **подачами**
   (`сире` проти `разом`) більша за різницю між комірками, і LSTM при
   цьому на чверть дорожча за вагами.
6. **Причина в самому вході.** Напрямку в каналах немає (AUC 0.33–0.47),
   канали дублюють один одного (Спірмен до 1.00), а їхній рівень їде
   між train і val.
7. **У грошах на val BTC мережі не піднялися над монеткою.** $1000 із
   комісією й сліпеджем, вхід наступною подією: холд $1226.33, зігзаг
   1.2 % без шортів $1208.83 при меншій просадці (4.60 % проти 5.21 %),
   а поєднувачі $1032 і $1046 проти $1046 у монетки.
8. **Порівнювати можна тільки на однаковій частоті.** Крива
   випадковості з 20 роздач: 151 сигнал дає 30.3 % ±50, а 60 сигналів —
   12.3 %. Без цієї лінійки частіший сигнал виглядає точнішим просто
   тому, що його більше. Поріг суперника 1.2 % витримав власну драбину
   від 0.4 до 3.0 % — він найвищий саме за перевагою над монеткою
   (×10.5 на ±15).
9. **`line` як канал шкідливий**: AUC 0.40, тобто в зоні розвороту
   частка ноги нижча, ніж поза нею.
10. **Мережі корисні не там, де їх питали.** Вони не кажуть, коли
   розвертатись, але кажуть, де був розворот: `pivot` вдвічі зменшує
   зсув сигналу зігзага (47 → 20.2 події), а сила памʼяті вчетверо
   піднімає влучання ±5 подій (6.7 % → 26.7 %). Це знання **заднім
   числом** — майбутнього у вікні немає, але точка дії в минулому — і
   саме воно є тим, що варто брати в роботу далі.

Числа міряні на **60 розворотах val** шести монет, причому 24 з них —
XRP. Це мало; порядок величин на цьому видно, але різниця в кілька
відсотків між сусідніми рядками — шум.

## Вкладка «Сигнал купівлі й продажу»

URL: [`/calls`](http://localhost:8080/calls). Сім розділів, кожен —
свій ендпоінт.

| Розділ | Що показує |
| ------ | ---------- |
| Постановка | питання вкладки, які мережі взяті й чому дві замінені; таблиця монет: подій, покриття основних і всіх каналів, розворотів усього і на val |
| Що кожна видача каже про розворот | AUC train і val із підлогою, верхівка, напрямок, пік профілю — рядок на канал, плюс тези про напрямок і про рівень, що їде |
| Поєднувач | таблиця val: три набори ознак, кожен канал окремо, зігзаг і монетка на одній лінійці; окремо таблиця поправки зігзага; хід навчання обраного набору |
| Поєднувач із памʼяттю | GRU проти MLP на тій самій мірі: два набори ознак, суперники, хід навчання і зсув зігзага в найгучнішу подію памʼяті |
| Скільки з цього — випадок | драбина порогів суперника від 0.4 до 3.0 % з монеткою тієї самої частоти на кожному щаблі й крива випадковості за частотою |
| Симуляція торгівлі | $1000 на val BTC: кожен сигнал із комісією й сліпеджем у двох режимах, проти «купив і тримав», і чутливість до витрат |
| Ряд val BTC | ціна з зігзагом і три види сигналів на ній: трикутник — поєднувач, квадрат — зігзаг, порожній трикутник — зігзаг, підтягнутий мережею; під ціною два числа поєднувача з порогом, у підвалі — канали |

Ендпоінти: `/api/calls/input`, `/api/calls/look`, `/api/calls/train`,
`/api/calls/memory`, `/api/calls/rivals`, `/api/calls/money`,
`/api/calls/series`. Кожен розділ без свого файлу показує, який скрипт
запустити, і не гасить решту вкладки.

## Вкладка «Памʼять: LSTM · сире»

URL: [`/cells`](http://localhost:8080/cells). Ендпоінт один —
`/api/cells/compare`.

Заміри вище порівняли вісім прогонів; на вкладку йде **один обраний** —
`LSTM · сире · зона «частка»` (`CALLS_CELL` у
[`dashboard/app.py`](../../dashboard/app.py)). Комірка й подача обрані
за заміром, а зона — не гіперпараметр: вона виміряна в дослідженні 32
і в подіях просто неправильна, тому «частка» стоїть незалежно від
того, що показує відкладений шматок.
Решта прогонів лишається у `results/calls_cells.json` і в таблицях цієї
статті як доказ вибору, але вкладку не займає: вона веде далі тільки ту
комірку, з якою працюємо.

| Розділ | Що показує |
| ------ | ---------- |
| Датасет | на чому вчились і на чому міряно: подій і півотів у кожному шматку кожної монети, межа розбиття за датою, рядок «разом» |
| Обрана комірка | рядок на кожен із трьох шматків на одній лінійці, два графіки — влучання ±50 на відкладеному шматку по епохах (крапка — епоха, з якої взяті ваги) і втрата навчання, — і таблиця ціни комірки: ваг, ознак, епоха, поріг, час |
| Ряд val BTC | ціна з зігзагом 2.3 % і сигналами комірки, під нею — два її числа з порогом на спільній осі X |
| Стан ноги | профіль числа вздовж ноги (таблиця + графік), профіль навколо розвороту (таблиця + графік), перемикання знака, ціна підтвердження — і ряд із двома перемикачами: **монета** (шість) × **частина** (тільки val / увесь ряд). На ціні — заливка ногою за мережею (зелене вгору, червоне вниз) і зігзаг 2.3 % лінією поверх; під ціною — нога суцільним проти ноги зігзага пунктиром, `продаж − купівля` сире й згладжене та сира видача моделі. За мишкою йде пунктирне перехрестя наскрізь по всіх плашках |

Ендпоінти: `/api/cells/compare`, `/api/cells/state` і
`/api/cells/state/<PAIR>/<val\|all>` — ряд кожної монети окремим файлом,
бо увесь ряд шести монет в одну відповідь не кладеться.

Без файлів `results/calls_cells.json` і `results/calls_state.json` кожен
розділ показує, який скрипт запустити, і не гасить решту вкладки.

## Вкладка «Нога: бік і зона розвороту»

URL: [`/legs`](http://localhost:8080/legs). Шість розділів, три пари
ендпоінтів.

| Розділ | Що показує |
| ------ | ---------- |
| Дві голови | що відповідає кожна голова, розмір зони, ціна позитиву зони, поріг і правило вибору епохи |
| Що вийшло на val | матриця кожної голови, збалансована точність і AUC проти сталої відповіді й монетки, розріз по монетах, хід навчання |
| Грід і драбина | кола перебору ручок із заміром різкості видачі, драбина функцій втрат від ваг переможця і підсумкові ручки |
| Ряд | ціна з заливкою боком ноги й жовтими смугами сказаної зони, під нею ціль зігзага, ще нижче — два числа голів зі своїм порогом; на ціні — **угоди правила**: трикутник угору — вхід у лонг, вниз — у шорт, порожній квадрат — вихід; перемикачі **монета** × **частина** (тільки val / увесь ряд), поле **ема на плашках моделі** і пунктирне перехрестя за мишкою |
| Перетини | зони пошуку з перетину видачі голови з її емою, дві моделі дослідження 34 називають подію межі всередині зони й **тільки там** — поза зонами їхніх ліній у ряді немає, а знайдений розворот стоїть ромбом на ціні; з підлогою на випадкових подіях, матрицею вироку, драбиною розмірів зони і рядом val: ціна з перетинами, під нею видача голови зі своєю емою, ще нижче — обидві моделі межі |
| Торгівля ногою | правило «одна угода на ногу» з його ручками, два сімейства читання боку поруч, кола перебору переможця й суперника «ема ціни» з умовою «торгує ногами», і $1000 на монету на val: кожна монета окремо, середнє й суперники — ема ціни, холд, зігзаг 1.2 %, монетка |

Ема плашок моделі (підтверджено, 2026-09-19) рахується у браузері
з самої видачі голови —
`alpha = 2 / (span + 1)`, причинно, зліва направо, синьою лінією
поверх сирого числа. Поле приймає ціле від 1 до 1000; `1` — без
згладження, лінія не малюється. Число ніде не зберігається: це
спосіб подивитися, а не параметр моделі. За замовчуванням стоїть
**200** — та сама ема, з якої розділ «Перетини» бере кандидатів.

Розділ «Перетини» вантажиться двома запитами: опис із вироками
приходить одразу, ряд — окремо на монету. Кольори в ньому означають
**бік межі**, а не бік угоди: зелене — вершина (там продаж), червоне —
дно (там купівля). Вирок каже **форма** точки: залита — розворот
знайдено, порожнє коло — підтвердили дарма, квадрат — межа є,
а моделі змовчали, дрібна цятка — і моделі, і правда кажуть
«нічого тут немає». Вирок точки — той самий, що в колонці таблиці,
і рахується від події, яку назвала модель, тому залитих точок рівно
стільки, скільки залитих ромбів. Знайдений розворот — **ромб** на ціні: подія, яку
назвала модель усередині зони; залитий — межа поруч, контурний —
межі там немає. Сіра смуга на всіх плашках — сама зона:
поза нею лінії моделей порожні, бо там їх не питали, а не тому, що
вони дали нуль. Компоновка за `rules/05-visualization.md`: опис
зверху, пʼять плашок на спільній осі X зі спільним зумом, легенда під
графіком.

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

Ендпоінти: `/api/legs/heads`, `/api/legs/heads/series/<PAIR>/<val\|all>`,
`/api/legs/grid`, `/api/legs/calls`,
`/api/legs/calls/series/<PAIR>/<val\|all>`, `/api/legs/cross` і
`/api/legs/cross/series/<PAIR>` (частина там завжди val: моделі межі
вчились до неї).
Без файлів `results/legs_heads.json` і `results/legs_calls.json` кожен
розділ показує, який скрипт запустити, і не гасить решту вкладки.

## Тести

[`tests/test_buy_sell_signal.py`](../../tests/test_buy_sell_signal.py) —
на скрипти:

- `TestCallsAxis` — видача кладеться на вісь за часом і тільки ближче
  ніж пів кроку; далека подія не лягає нікуди.
- `TestCallsZone` — зона несиметрична, бік зони каже «купівля» на
  нижньому півоті й «продаж» на верхньому, відстань до півота має
  правильний знак.
- `TestCallsRuler` — AUC збігається з ручним рахунком на маленькому
  прикладі, підлога на перемішаних мітках дає ≈0.5, верхівка ділиться
  на покриття.
- `TestCallsFeatures` — причинні вікна не заглядають уперед: середнє,
  максимум і ранг у хвості на події `k` не міняються від того, що
  стоїть після неї.
- `TestCallsFires` — чергування не дає двох сигналів підряд в один бік,
  поріг за кількістю знаходить приблизно потрібну частоту.
- `TestCallsShift` — поправка не посуває сигнал уперед і не міняє їх
  порядок.
- `TestCallsMoney` — перевертання позиції рахується як треба, а порожній
  список сигналів не ламає міру.
- `TestCallsMemoryBlocks` — нарізка ряду на шматки: кожна навчальна
  подія потрапляє рівно в один шматок, перед шматком стоїть прогрів,
  порожня маска не дає шматків; набір `сире` лишає тільки миттєві
  числа.
- `TestCallsMemoryWalk` — прохід памʼяті: три числа на подію сумуються
  в одиницю, відповідь події не міняється від того, що стоїть після
  неї, а подія без входу лишається порожньою.
- `TestCallsMoney1000` — симуляція: угода відкривається **наступною**
  подією після сигналу, сигнал на останній події не виконується,
  витрати беруться з обох боків, режим «лонг» сидить у кеші замість
  шорта, просадка міряється на кожній події, холд — одна угода.

- `TestCellsCell` — обидві комірки дають три числа на подію, що
  сумуються в одиницю; LSTM важить більше за GRU тієї самої ширини, але
  менш ніж у півтора раза; відповідь LSTM на події не міняється від
  того, що стоїть після неї; невідома комірка — помилка.
- `TestCellsSplit` — опис датасету: півоти рахуються всередині свого
  шматка, порожній шматок не має півотів, шматки сумуються по монетах,
  дати — UTC.
- `TestLegsCrossEma` — ема видачі: перше число лишається собою, крок
  дорівнює `2/(span+1)`, дірка в ряді тримає останнє значення, а ряд,
  що починається діркою, ще не має лінії.
- `TestLegsCrossFind` — перетини: падіння крізь лінію — продаж,
  зростання — купівля, падіння з-під 0.5 продажем не рахується, а
  підйом з-над 0.5 — купівлею, перетин ближчий за тишу до
  попереднього **взятого** відкидається, тиша міряється саме від
  взятого, прогрів ема сигналів не дає, але памʼять під час прогріву
  вже набирається, дірка в ряді перетину не ковтає, а ряд без жодної
  відповіді не дає нічого.
- `TestLegsCrossAsk` — питання до моделей: чиста сходинка дає згоду
  околу 1.0, рівна лінія — рівно 0.5 і низька, і висока, сходинка
  навпаки — 0.0, продаж хоче вершину, а купівля дно, кожен бік читає
  **свою** рамку, модель сама називає положення межі в околі й зсув
  цього положення від перетину, а згода на самому перетині лишається
  окремим числом.
- `TestLegsCrossTruth` — правда: відстань тримає знак, «своя» відстань
  дивиться тільки на межу свого боку, ширша зона зараховує те, що
  вужча відкидала, влучання несе індекс своєї межі, а ряд без меж не
  влучає нікуди.
- `TestLegsCrossOutput` — вивід ряду: поза зоною лінії порожні, зона
  несе й вікно, потрібне самій відповіді, без перетинів не питають
  ніде, дві близькі зони зливаються в одну, а смуга не вилазить за
  межі ряду.
- `TestLegsCrossZone` — зона й влучання: широка зона дає моделі
  назвати саму межу, вузька спиняє її на краю зони, влучання
  читається від названої події, а не від перетину, названа далеко
  подія влучанням не стає, драбина тримає точність окремо від
  повноти, а лінія згоди має пік рівно на справжній межі, порожня
  поза зоною і читає рамку свого сигналу.
- `TestLegsCrossVerdict` — чотири клітинки вироку («знайдено», «хиба»,
  «пропуск», «відхилено») названі кожна своїм словом, а межа без
  перетину свого боку лишається непокритою.

[`tests/test_dashboard.py`](../../tests/test_dashboard.py) — на вкладку:
`TestLegsTab` (ендпоінти вкладки, зокрема `/api/legs/cross` і ряд
перетинів, адресований самим імʼям монети — шлях у нього не проліза́є),
`TestLegsMarkup` (правило кандидата, обидві моделі дослідження 34 у
описі, питання ставиться зоною, а не точкою, підлога на випадкових
подіях, зона, якою пораховані числа, позначена в драбині, відрізок, де голова мовчить, чотири клітинки вироку, драбина з
точністю й повнотою нарізно, рядок кожного перетину, робота моделей
тільки в зонах із часткою ряду, ромб знайденого розвороту в легенді,
смуга зони на кожній плашці, колір ромба за боком межі, форма
позначки на зумі та її екранне місце, легенда
**під** графіком,
чотири плашки ряду, колір точки як бік межі й назви моделей у шапках
плашок), `TestCallsTab` (усі сім ендпоінтів віддають файли, без файлів
— 404 і вкладка не падає) і `TestCallsMarkup` (у розмітці є числа розбору, обидві
таблиці поєднувача, памʼять проти MLP, драбина суперника з розділенням
розмітки 2.3 % і порога суперника, крива випадковості, симуляція $1000 проти
холду з приміткою про відсутній стоп, і три види сигналів у легенді
ряду).

- `TestLegsHeadsTarget` — дві мітки: бік ноги лишається й усередині
  зони розвороту, поза крайніми півотами мітки немає, зона — частка
  своєї ноги.
- `TestLegsHeadsScore` — дві на дві: у сітку йдуть лише події з міткою,
  збалансована точність — середнє двох повнот, AUC ідеального поділу
  дорівнює одиниці, а рівних чисел — половині.
- `TestLegsHeadsWalk` — прохід двоголової: два числа на подію в межах
  нуля й одиниці, майбутнє на відповідь не впливає, подія без входу
  лишається порожньою.
- `TestLegsCallsEma` — ема правила причинна: розмах `1` лишає ряд як є,
  майбутнє на минулу подію не впливає, дірка тягне попереднє значення.
- `TestLegsCallsLeg` — бік ноги: рівні тримають бік між порогами й
  перемикають його на них, перетин ем читає бік без рівня взагалі,
  пік оголошується тільки після відкату (більший відкат — довше
  чекання), міра каже, на скільки подій оголошення спізнилось, а
  подія без числа лишається без боку.
- `TestLegsCallsTrades` — правило: зміна боку відкриває й закриває
  рівно одну угоду, друга угода в ту саму ногу не заходить, запас
  тримає ногу до справжнього повороту, підтвердження відсуває вхід,
  зона на вході може його затримати, зона на виході закриває угоду до
  розвороту, мінімальна довжина тримає молоду угоду відкритою, остання
  угода закривається на останній події вікна, події поза маскою не
  торгуються, майбутнє відкриту угоду не рухає, а сама угода
  розкладається на сигнал входу й сигнал виходу.
- `TestCallsStateRanks` — ранги з усередненням однакових значень: без
  них AUC на рівних числах дає нуль замість половини.
- `TestCallsStateSmooth` — згладжування знака причинне: майбутнє на
  подію не впливає, дірка тягне попереднє значення, до першого числа
  немає нічого.
- `TestCallsStateLegs` — ноги val: нижній півот починає ногу вгору,
  ноги поза відкладеною частиною не беруться, запізнення входу з'їдає
  частку ноги.
- `TestCallsStateSwitch` — перемикання знака рахується від півота, ряд
  без переходу не дає відстані, кожен перехід лишається міткою зі своїм
  боком.

Вкладка `/legs`: `TestLegsTab` (вкладка зареєстрована, ендпоінти віддають
обидві голови й сигнали, обидва ряди адресуються монетою й частиною,
чужий шлях відмовляється) і `TestLegsMarkup` (у розмітці є опис обох
голів, їхні матриці плутанини, контролі, чотири плашки ряду з
перехрестям, перемикачі й поле ема; сама ема рахується правильно,
розмах `1` не дає лінії, заголовки плашок моделі називають розмах;
розділ торгівлі описує правило обома способами читання боку, показує
два сімейства поруч, кола перебору з умовою «торгує ногами», гроші
кожної монети проти ема ціни, холду, зігзага й монетки, а без файлу
просить запустити скрипт; мітки входу й виходу доходять до плашки
ціни).

Вкладка `/cells`: `TestCellsTab` (ендпоінт лишає з файлу тільки обраний
прогін, а коли його там немає — віддає все, що є; без файлу — не готово; ряд адресується монетою й частиною, а чужий шлях
відмовляється) і `TestCellsMarkup` (у розмітці є всі три шматки прогону,
опис датасету з межею розбиття, таблиця ціни комірки, обидва полотна
кривих, плашка ряду val, профілі стану з обома полотнами, перемикачі
монети й частини, три плашки ряду стану — і підказка запустити скрипт,
коли файлу немає).

## Файл дослідження

[`research/33-buy-sell-signal/33-buy-sell-signal.md`](33-buy-sell-signal.md)
