Тема
Incident 2026-07-13/14 — live-потери −$12.65: отказ стоп-контура + adverse selection
Статус: расследование ЗАВЕРШЕНО (2026-07-14, workflow wf_29526636 + wf_da6befa6, все центральные выводы прошли адверсариальную проверку по первичным источникам). Фиксы — см. §Исправления (дополняется по мере merge).
Итог в деньгах (сверено бит-в-бит с on-chain pUSD)
Старт continuous live 2026-07-13 10:38 UTC: бюджет $20.315 (cash $15.380220 + NY-позиция $4.934780). На 2026-07-14 13:40 UTC: cash $7.003709 + рыночная стоимость открытых позиций $0.662 → total economic loss −$12.649. Учётных дыр нет: мост сходится до микро-доллара. Декомпозиция: −$3.289 realized день-1 (2 стопа Warsaw/Cape Town) − $0.608 realized день-2 (стоп London −$1.748, виннер Karachi +$1.14) − $8.751 unrealized на двух позициях, где стоп-защита не отработала (Qingdao NO 0.74→0.0005; Jeddah NO 0.83→~0.05).
Первопричины (RC), все подтверждены кодом + рыночными данными
| RC | Суть | Цена |
|---|---|---|
| RC-1 | Confirm-гейт стопа слеп к комплементарному потоку: погодные NO-книги обваливаются агрессивными BUY Yes (единая книга CLOB), а trade_confirms_stop видит только SELL-принты на NO-asset_id. Jeddah был «стреляем» 65 секунд (bid 0.54–0.60 ≥ пола) — ноль стоп-попыток. Тот же класс нотационной ошибки, что fill-price баг 9952b0d9. | ≈$2.6 |
| RC-2 | HoldOnGap: при best_bid < пола (entry − max_loss) стоп молча держит позицию НАВСЕГДА; кэп убытка действует только при факте филла. Qingdao: 2 FOK-kill в единственный отскок, дальше 5+ часов тишины до нуля. При пустых bids стоп-путь пропускается до оценки. | ≈$2–3 сверх кэпа |
| RC-3 | Dust-фильтр confirm ($2/5sh) съел исполнимое окно Qingdao: ранние принты каскада не квалифицировались, первый confirm пришёл когда bid уже < пола. | входит в RC-2 |
| RC-4 | Kill-канал FOK расходится sim/live: sim = Ok+async Cancelled → cooldown ставится; live = sync Err → нет. Паритетный дефект. | поведенческий |
| RC-5 | Ненаблюдаемость: HoldOnGap/empty-bids — debug-only; счётчики не смаплены в SSE; алярмов нет. Оператор не мог видеть умирание позиций. | операционный |
| RC-6 | Sim-оптимизмы: fee=0; displayed-глубина = исполнимая с нулевой латентностью; нет balance-settling; maker fill-rate = optimistic upper bound. Dry-run базлайн уничтожен Reset'ами — сравнение шло по памяти. | завышенный dry-run winrate |
| RC-7 | Рынок: июльский zero-edge (2 research-линии ДО запуска) + вход в окно реализации температуры. Winrate live 1/6 при w* 0.71–0.84. | стратегический |
| RC-8 | Нет circuit-breaker в движке (был только в probe-supervisor скрипте). | операционный |
| RC-9 | «Мало входов»: 7 in-band кандидатов за день (потолок предиката) × бюджет $17/3 слота (92% сигналов убиты TotalBudget с 09:08; слоты держали умирающие позиции). | ёмкость |
| RC-10 | Adverse selection пассивного maker ПОДТВЕРЖДЁН: 3 незашедших кандидата выиграли бы 3/3, из 4 филлов выиграл 1. Филл = маркер токсичного момента; reactive-reprice гонит бид вниз за падающим ask. Ранжирования «безопасные сначала» в коде нет (memoryless tick-race). | ядро −EV |
| RC-11 | LDI нейтрализован (тавтологичные пороги, ратифицировано 2026-07-04) И не персистится никуда — «решить на данных» невыполнимо, статистика невозможна ретроспективно. | instrumentation gap |
Ответ «симулятор или рынок»
Оба, слоями: рынок сделал то, что июльский research предсказал (джамп-коллапсы при реализации, токсичность пассивных филлов); исполнение превратило кэпнутые −$2.40 в полные −$4.4 (RC-1..RC-3); симулятор системно оптимистичен (RC-6) и не может видеть adverse selection live-филлов. Важно: sim pm-engine ЧИТАЕТ ленту и моделирует FOK/confirm/post-only — память «SimFillEngine не читает tape» относится к pm-bot.
Решения оператора (2026-07-14)
- Авто-капитуляция сразу: при trade-confirmed обвале продавать FAK по best_bid без пола;
max_loss_milliудаляется (RULE-NEW-01). - Продолжение live-тестирования после фиксов (баланс пополнен до $22.00): деплой, снятие drain, форвард-замер r/s_eff на исправленном стоп-контуре. Формула-контролёр:
w* = (p_e − r·s_eff)/(exit − r·s_eff)— рычаги стопов снижают w* с ~0.84 (r=0) к ~0.51 (r=1, s_eff≈0.6).
Хронология ключевых событий (UTC, 2026-07-14)
05:15 Qingdao BUY 6 NO @ 0.74 филл → 05:21 обвал (toxic fill) → 05:42 первый confirm (поздно, RC-3) → 07:45 два FOK-kill @ 0.34 (RC-2) → тишина до нуля. 09:58 Jeddah partial филл 5.99 @ 0.83 → 12:00-12:01 обвал через BUY Yes (RC-1) → ноль стоп-попыток. 11:12 London BUY 6 @ 0.83 → 13:03 стоп FAK-семантики сработал @ 0.5386 (контраст-кейс: прямые SELL-No принты). 13:25 operator drain.
Исправления
План: ~/.claude/plans/live-peppy-goblet.md (одобрен оператором 2026-07-14).
Волна 1 (стоп-контур) — MERGED в main f510f599, ЗАДЕПЛОЕНА 2026-07-14 19:44 UTC (bin sha256 331c9b07…), drain снят 19:48 UTC, live возобновлён на $22.00: F1 комплемент-aware confirm (ad116d9a + RTDS-слив c12cead2 + replay-регистрация пар 4bc3f8ce + LDI-изоляция синтетики b1f94b84), F2 капитуляция FAK по best_bid без пола + удаление max_loss_milli + ресайз primary exit при partial-капитуляции (ca513623 + 844e98f6), F3 фазовые dust-гейты confirm (2868d858), F4 паритет kill-каналов + cooldown по ФИЛЛУ стопа через released-order recovery (fa16fc3b + 6ae81bda), F5a INFO-throttled переходы стоп-машины (cf46afbf). Реальные фикстуры обвалов: crates/pm-engine/tests/fixtures/trades_2026-07-14. Миграция config.db применена (max_loss_milli удалён, бюджет re-anchored 32.02558 → remaining = on-chain кэш бит-в-бит; бэкап config.db.bak-stopcontour-*). Адверсариальный review: 2 blocker + 4 major исправлены с дисконфирмацией на production-ordering.
Волна 2 (наблюдаемость + LDI) — MERGED b6c4c4de: F5b SSE-счётчики стоп-контура в EntryFunnelTick + воронка SPA (73733cc7), F5c throttled TG-алярмы 4 классов (f46993cd), F9 LDI в signals.context_json ровно как видел гейт (c1f63c17), F10 veto-трасса selection + часовая funnel-сводка (49fc6d72) + 4 repair-фикса (46c04b71, f5cbdddf, 8c2a5281, 86ec15cf).
Волна 3 (circuit-breaker + sim-fee) — MERGED d0297766: F6 авто-drain при N подряд убыточных стопов / rolling-24h убытке, стартовая оценка, стопы работают под drain (f0a8efb7, d9fa0ce6, 25ba172a, repair e24c8280), F7 опциональная sim taker-fee (SSOT fees.rs, 6fe81024). Аддендум форвард-теста §9 (фильтр veto_distance) — 791e9afb.
Отложено с обоснованием (tech-debt, требует sign-off):
- Shared-allocation release: терминал exit-ордера может снять snapshot in-flight стоп-FAK (узкий interleaving → повторный SELL; live-исход — reject по балансу, не потеря). Нужен редизайн release-семантики шаренных exit-аллокаций.
- Re-fire guard стопа без staleness-таймаута: потерянное терминальное событие (класс PM-ENGINE-28 stale-«open») подавляет стоп до реконсиляции. Развилка: staleness-knob vs переиспользование probe-cancel машинерии.
- Deploy-grace на stale max_loss_milli ключ: снять после live-верификации (ключ уже удалён из config.db).
- Seed metrics.total_usd отдаёт значение realized (display-quirk, remaining корректен).
Уроки
- Стоп-лосс на джамп-процессе обязан иметь политику терминального коллапса; «пол» без гарантии исполнения = полная потеря вместо кэпа.
- Нотация единой книги (Yes/No комплемент) — повторяющийся класс ошибок: fill-price (день-1), теперь confirm-гейт. Любой потребитель ленты обязан отвечать на вопрос «вижу ли я комплементарную сторону».
- Пассивный maker в окне реализации исхода = adverse selection: рынок наливает худшие филлы. Подтверждено данными (3/3 vs 1/4).
- Наблюдаемость отказов защиты — это тоже защита: debug-only ветки на money-путях недопустимы.
- Dry-run метрики без зафиксированного базлайна (и с wipe'ами БД) несравнимы с live — «казалось лучше» не является данными.