Skip to content

Разбор торговой сессии harvester-engine 11–14 сентября 2026 ​

Дата составления: 15.09.2026. Наблюдения относятся к UTC 14.09.2026.

Граница воспроизводимости. Отчёт составлен по живым read-only запросам, выполненным штатным scripts/analysis/forensics.sh, SQLite positions и orders, витрине ClickHouse positions_wide, экономическому ledger, stop_frames, admission_attempts, эпохам config и runs, а также по прочитанной реализации. Отдельный неизменяемый экспорт исходных ответов в этой работе не сохранён. Поэтому приведённые числа подтверждают тот прогон, но не дают полной автономной повторяемости без повторного доступа к тем же источникам.

Отчёт фиксирует исследование и дефекты аналитической поверхности. Исправление скриптов подготовлено в отдельном worktree fix/analytics-report-defects, но на момент составления не слито и не развёрнуто. Новые торговые пороги этим отчётом не назначаются.

1. Окно и деньги ​

ПоказательЗначениеИсточник
Позиций22SQLite positions / ClickHouse ledger
Первое исполнение BUY11.09 18:48:18.264 UTCзапрос исполнений входа
Последнее закрытие14.09 15:25:35.746 UTCpositions.closed_at
BUY cash$173.59025экономический ledger
Net returns$169.09061экономический ledger
Итог−$4.49964разность cash и returns

Положительный результат был у 18 позиций и составил +$8.19974. Четыре отрицательные позиции дали −$12.69938. Сумма сходится: 8.19974 − 12.69938 = −4.49964.

Финальная причина в позицииКоличествоPnL
exit_target16+$7.402139
Выходы maker-заявками по рангу2−$4.000000
resolution4−$7.901779
Итого22−$4.499640

Экономический журнал даёт дополнительное разложение того же потока:

Группа ledgerКоличествоSharesCashFeesPnL
BUY fills23 prints186.469563−$173.59025——
SELL fills26 fills−175.410000+$161.16482$0.04398−$3.045068
Settlement4−11.050790+$7.92579—−$1.446299
Итого——−$4.49964—−$4.491367

Сумма SELL cash уже указана после комиссии; повторно вычитать $0.04398 из $169.09061 нельзя. 23 записи BUY включают два частичных исполнения одного входного ордера; количество записей исполнения не равно числу позиций.

Cash-result совпадает. Разница между ledger realised −$4.491367 и суммой positions.realized_pnl_micro_usd −$4.499640 составляет $0.008273 и объясняется residual basis. Это не независимый аудит кошелька или on-chain cash-flow: отдельный неизменяемый экспорт в работе не сохранён и новая RPC сверка не выполнялась.

Финальная причина позиции скрывает часть stop-истории: частичный защитный SELL может быть записан в orders, после чего остаток доезжает до redeem и финальная строка получает resolution.

В исследованном окне встречались конфигурационные эпохи v66-r3…v72-r3. Новый max_entry_price=.75 вступил 13.09 в 09:17:52 UTC, уже после последнего входа в 06:31:58 UTC; следовательно, сравнение эффекта этого изменения по данным данного окна не доказано. В отчёте не делается причинный вывод о влиянии max_entry_price.

В проверенных эпохах также зафиксированы изменения: v66 — budget/market 5, DCA выключен; v67 — budget 10, DCA включён с inside-spread; v68 — min_probability_rank=4, max_shares=10, fill_budget=18000, reprice tolerance 50, entry_window=NULL; v70 — total_budget=990 вместо 100, circuit loss 15; v71 — reactive drift 10 вместо 20; v72 — предел цены входа .75 вместо .95 (сохранённые значения 750 и 950). Обозначения в этом абзаце сокращённые; это перечень наблюдавшихся изменений, а не готовый набор ключей и значений для записи в config.db. Единицы остальных параметров здесь не переопределяются. Одновременно менялось несколько условий, поэтому причинный эффект отдельного параметра не выделен.

Основной зафиксированный build сессии: ddefc9506e7f95090f6041c74a9fe89c7331eda9.

2. Wellington: фактическая защитная цепочка ​

Позиция:

text
CID:    0xb8212f3b1e91a749efb92941ba93606d38f7ad57d6b5130de09319284419d5dd
signal: 1789212094637-000000000733-89dbbb5c75fbb662
BUY:    10 @ 0.92, 12.09 11:24:49.948 UTC

Перед стопом были три rank-maker SELL: .71 в 01:14:54.857, .70 в 01:15:54.870 и .69 в 01:16:55.855 UTC; fills не было. В 01:17:07.247 сработал stop-preemption, в 01:17:07.249 был создан stop-ордер, а в 01:17:07.348 состоялось исполнение FAK-ордера с ролью sharp_stop_confirmed. Все перечисленные времена защитных продаж относятся к 14.09 UTC:

text
SELL fill: 8.33 @ 0.12
gross:     0.9996
fee:       0.04398
net:       0.95562
остаток:   1.67; settlement 14.09 12:23:00.890 UTC
redeem:    @ 1.00; финальное подтверждение 12:28:40.655 UTC
PnL:       −6.57438

Кадр стопа в 01:17:06.928 имел bid=.13, ask=.47, threshold=.35, возраст 20 ms и debounce 60 s. Это был кадр fired=1. Вокруг эпизода записано 256 кадров и четыре эпизода, из них 254 кадра с fired=1; взведение зафиксировано в 01:16:06.921 UTC. Данные покрывают только интервал 01:17:06.928…01:26:45.262 и не являются непрерывной будущей ликвидностью.

Текущий пол исполнения вычисляется как floor = threshold − margin и удерживает стоп только при bid < floor (strategy.rs:6103, runtime_config.rs:360). Для этого кадра при margin < .22 bid .13 ниже пола и стоп удерживается; при margin = .22 пол равен .13, строгое условие не выполняется; при большем отступе этот bid также проходит. Это объясняет ценовое условие, но не выбирает значение отступа и не доказывает исполнение альтернативной заявки. Формула имеет нижнее ограничение в один pip; пример выше относится к указанному диапазону цен. Gamma подтвердил итог NO=1: это объясняет выплату остатка, но один такой случай не обосновывает отключение стопа. Арифметика фактического результата: −9.20 + 0.99960 − 0.04398 + 1.67 = −6.57438.

3. Контрольный Karachi ​

СобытиеФакт
12.09, CID 0xe6d8e5f78f4e6f17e6edd63024d10c1276f1c7d720593412f7b2f0fd4b334f8aBUY 7 @ .68, фактически 3.125; остаток ордера отменён как strategy_entry_withdraw; resolution 0; loss −$2.125
13.09, CID 0x4a9bf9ca45852af7de919d5b2a1e20a8210449516c7432f7fd93a61a1bece765BUY 10 @ .95; rank SELL .70 без fill, затем .69 с fill; NO=0; сохранено 6.9 против удержания
14.09, CID 0x75bcb515d56eea1bb05e73acae0184618f97011bae8b6ae6a521483ab0241052BUY 10 @ .91; rank SELL .78 без fill, затем .77 с fill; Gamma наблюдал NO=.9995, финальный исход ещё не подтверждён; текущий loss −$1.4

Karachi показывает противоположную цену удержания: при разрешённом NO=0 позиция теряет весь остаток. Два описанных эпизода недостаточны для выбора числового stop-floor.

Положительные факторы сессии: 16 целевых выходов дали +$7.402139, один исполненный ранговый выход в Karachi 13.09 сохранил $6.9 против нулевой выплаты при удержании, а кадр Wellington был свежим (20 ms). Отрицательные факторы: четыре убыточные позиции перекрыли результат 18 прибыльных; Wellington FAK создал остаток меньше минимального размера SELL, допускаемого движком; частичные BUY-позиции ниже этого размера также не могут пройти обычный выход или стоп через ExitSizeDecision::DustStranded. Дополнительно аналитика ошибочно пометила реальные частичные покупки как entry_filled=N.

4. Дефекты аналитики ​

4.1. forensics.sh исключает реальные BUY-филлы ​

В scripts/analysis/forensics.sh:248 проверка entry_filled требует status='FILLED'. В наблюдавшихся строках позиций 251, 254 и 263 были реальные BUY-филлы, но соответствующий ордер завершился не статусом FILLED; для Karachi подтверждён статус CANCELLED с причиной strategy_entry_withdraw. Такой вход исключается из отчёта, хотя позиция существует. Это расходится с фактической моделью данных: единицей экономического анализа должен быть каждый реальный BUY-fill.

README scripts/analysis/README.md:163-171 отдельно документирует dust и отсутствие survivorship, но теперь согласовано считать в EV все фактические BUY-филлы. Исправление должно менять критерий на наличие положительного fill, сохраняя отдельную маркировку частичного и dust-входа.

4.2. cmd_positions создаёт ложный PHANTOM для REDEEMED ​

cmd_positions (scripts/analysis/forensics.sh:1275) применяет phantom-проверку к REDEEMED-позиции. Для строки 251 это даёт ложный phantom, хотя её финальный статус означает redeem-путь и не доказывает отсутствие реального выхода. Эта ошибка создаёт ложную метку PHANTOM у позиции. Глобальный предикат SCH_PHANTOM_PRED (forensics.sh:253) используется в отдельном контуре очистки stop-выборки; прямое влияние именно этой ложной метки на весь EV-отчёт в данной работе не измерено.

4.3. stops ищет финальную причину вместо stop-цепочки ​

SCH_STOP_PRED в scripts/analysis/forensics.sh:244 фильтрует только exit_reason LIKE 'stop_loss%'. Позиция Wellington в финальной строке имеет resolution, поэтому cmd_stops не показывает её защитную цепочку, несмотря на подтверждённый sharp_stop_confirmed SELL и fill 8.33 @ .12.

Роли stop-ордеров уже являются отдельными сохраняемыми значениями sharp_stop, sharp_stop_confirmed, sharp_stop_partial и sharp_stop_confirmed_partial (ports/intent_role.rs:124-135). Для анализа попыток и фактических филлов нужно читать эту колонку и связывать цепочку по token_id + signal_id, а финальную exit_reason использовать только как результат позиции.

4.4. stop-counterfactual дублирует эпохи и выбирает неправильный exit ​

В ClickHouse-ветке stop-counterfactual соединение positions_wide с stop_frames идёт только по signal_uid (forensics.sh:2080-2130). Для Wellington это даёт две строки эпох/состояний: v71/closed_at=NULL/exit=NULL и v72/resolution/exit=1. В расчёте dfact (:2264-2273) выбирается финальная цена 1 и размер кадра 10, хотя фактический stop-fill был 8.33 @ .12.

Приоритет класса fire корректен: cls сначала проверяет ep_fired=1 (:2218), поэтому Wellington не является подтверждённым no-fire. Дефект состоит в связывании фактического выхода и дублировании эпох: counterfactual строка остаётся, но её денежная интерпретация неверна.

4.5. ClickHouse-витрина обнуляет фактический остаток закрытой позиции ​

В marts.rs:165-188 ветка закрытых позиций безусловно ставит нулевой inventory, если closed_at заполнен, без проверки завершённости redeem. Для Mexico, SQLite position 263, SQLite хранит остаток 8773 micro-shares и redeem_status=FAILED, тогда как positions_wide показывает inventory 0. Поэтому статус позиции, остаток и результат погашения нельзя сводить в один признак «закрыта». Это дефект витрины/классификации, а не доказательство денежной потери.

4.6. Варианты стопа и частичного входа ​

ВариантВозможная выгодаРиск/ценаКак проверять
Существующий floor = threshold − marginОграничивает слишком дешёвое исполнение и сохраняет текущий контрактНиже пола позиция может дойти до нулевой выплатыИсправленная выборка stop-fill и контрфактов по фиксированным горизонтам
Нижний предел цены выключенПродажу не блокирует это ценовое условиеЭто условие не ограничивает цену исполнения; возможна продажа на кратком провалеПолная серия фактических цен исполнений и глубины
Адаптивный полМожет учитывать глубину, время и восстановлениеНовый контракт и сложность без достаточных данныхНепрерывная книга/очередь, latency, recovery и сравнимые эпохи

Рекомендация — сначала исследовать существующий пол. Порог и отступ не назначены. Полное отключение стоп-защиты также не обосновано: Karachi 13.09 показывает риск удержания до нулевой выплаты.

Для частичного входа остаются разные ограничения: сохранение контекста добора, оставшийся бюджет и минимальный размер заявки. Восстановление исходной закреплённой цены вместе с ограниченным DCA — исследовательское направление (strategy.rs:9851). Переход к FOK или taker-поведению требует отдельной оценки стоимости исполнения и проверки фактических fill-результатов; он не следует из этой сессии.

Вариант частичного входаВозможная выгодаОграничение и проверка
Восстановить исходный контекст цены и использовать DCA в прежних лимитахУстранить пропуск добора только из-за рестартаПроверить актуальность цены, сетку, бюджет и отсутствие повторного BUY; восстановление контекста само по себе не решает недостаток бюджета
Сохранить текущую механикуНе вводить новую торговую логикуИзмерять капитал и время в остатках; проблема пропуска DCA после рестарта остаётся
Изменить способ входа на FOK либо немедленное исполнениеПроверить возможность уменьшения частичных входовСравнить пропущенные входы, фактические исполнения, комиссии и цену; FAK сам по себе не исключает частичного исполнения

Минимальный размер исходной maker-заявки не гарантирует такого же минимального размера фактического исполнения. Исследование DCA должно учитывать это отдельно.

5. Отдельный остаток Mexico и граница денежной сверки ​

Для Mexico (CID 0xe585ec89c7ebdba6839e836db032e86e602cdf50ba921e08bbc407ab8d52e0ae, SQLite position 263) закрытая строка содержит остаток 8773 micro-shares и redeem_status=FAILED в SQLite; ClickHouse positions_wide показывает нулевой inventory_shares. Экономический ledger даёт realised −4.491367, а positions — −4.499640; расхождение 0.008273 объясняется residual basis. По имеющимся данным это не доказанная потеря денег: для такого вывода нужен отдельный разбор redeem-транзакции, остатка и записи ledger. Причина redeem FAILED в этой работе не исследована.

Идентификатор позиции: pos-2484906-ord-directional-entry-1789236285461-000000119175-8926c09a4ed57761-1789236285461-000000119176.

Реконструкция остатка по журналу исполнений: два BUY на 3.880878 и 3.157895 доли (cost=3.659667 и 2.977894), всего 7.038773 доли и 6.637561 стоимости; SELL 7.030000 долей дал net 6.959700, basis 6.629288, realized 0.330412; остаток 0.008773 доли имеет basis 0.008273, а строка позиции отражает realized 0.322139. Это объясняет, почему ledger и позиция имеют разные realized при совпадающем cash-result.

Отдельная частичная Mexico-позиция: CID 0x04a1086fe2baea70f43270ca9ca9e204c627bf9d6e5862a78fc32cac8df315e5, BUY 1.30579 @ .81, redeem 1, PnL +$0.248101.

6. Существующие механизмы и их границы ​

Пол исполнения и план защитной продажи уже существуют. Их наблюдаемость включает pm_engine_stop_execution_floor_held_total, pm_engine_stop_exit_plan_total{kind} и pm_engine_exit_residual_stranded_total{origin}. Проверка наличия кода не доказывает, что каждый механизм был реально использован в последнем runtime. DCA-метрика присутствует в исходниках сборки 40329ef828bb4016ea515976c37429e530c9cf82, которую сообщает запись runs для запуска r76-c4ca86abf2834ff8954bd189a7f1c602 от 14.09 19:07:01.622 UTC. Включение коммита 6c19b8a2 проверено через git merge-base --is-ancestor. Это более поздний запуск, чем последнее закрытие исследуемой сессии; проверка манифеста развёртывания здесь не выполнялась. Фактическая запись метрики pm_engine_dca_skip_total{reason} в этой сессии отдельно не проверена.

Семантика этих рядов ограничивает выводы: pm_engine_dca_skip_total{reason} считает такты/оценки, а не эпизоды; pm_engine_stop_exit_plan_total{kind} растёт только после успешного emit_order для плана FAK/FOK и не включает синхронные отказы, обычные лимитные, ручные и аварийные продажи; у него семь значений kind. Отказ FloorUnreachable учитывается отдельно в pm_engine_stop_execution_floor_held_total. Ряд pm_engine_exit_residual_stranded_total{origin} считает эпизод по сигналу в памяти с origin=partial_sell или entry_shortfall; после рестарта тот же остаток может быть посчитан повторно. Эти ограничения описаны в docs/operations/alerts-and-monitoring.md.

Семь значений плана: top_absorbs, remainder_sellable, named_cap, deepened, shrunk, tail_unavoidable, book_unknown. Счётчик удержания ценовым ограничением считает оценки, поэтому его нельзя приравнивать к числу уникальных стоп-эпизодов.

Причины пропуска DCA: restore_backoff, buy_already_resting, target_price_not_pinned, pinned_price_off_grid, remaining_below_min_size, no_progress_limit, post_only_would_cross. Существуют и сообщения в логах; это не означает наличие полной единой истории решений с ценой, бюджетом, книгой и последующими исполнениями. Новая метрика не восстанавливает события прошлой версии задним числом.

В strategies/directional/strategy.rs:9851 при отсутствии контекста закреплённой цены происходит пропуск; восстановление цены после рестарта ещё не реализовано и является отдельным направлением исследования. Восстановление контекста не устраняет другой отказ — оставшийся бюджет может не покрывать минимальную заявку. Также не следует утверждать, что биржа запрещает FAK меньше 5 долей: в этой работе подтверждён только внутренний гейт движка.

7. Что нужно измерить перед выбором пола ​

До числового решения требуется восстановить исправленную выборку:

  • все фактические BUY-филлы, включая CANCELLED-ордера с положительным filled_shares;
  • все попытки стопа по orders.exit_role, их нулевые, частичные и полные исполнения, связывая цепочку повторной продажи по token_id + signal_id;
  • для каждого решения — книгу, best bid/ask, глубину, возраст, latency, конфигурационную эпоху, threshold и фактически применённый floor;
  • цену и ликвидность после решения на фиксированных горизонтах и до resolution;
  • полный путь решений entry → reprice → DCA, чтобы не смешивать эпохи и действия;
  • непрерывную историю будущей книги и очереди. Текущие stop_frames покрывают отдельные кадры и не доказывают непрерывную будущую ликвидность;
  • residual/redeem reconciliation и причину redeem FAILED для Mexico.

В проверенной выборке 22 связанных со входами записи admission_attempts с возрастами книги 18…2639 ms, что укладывается в лимит 3000 ms. Это подтверждает возраст этих записей, но не доказывает непрерывность всей ленты и не заменяет историю книги и очереди. Возраст книги при входе Wellington составил 32 ms, при рассмотренном стопе — 20 ms. Эти замеры не подтверждают устаревшую книгу как причину данных двух решений.

8. Рекомендация и статус ​

Первый шаг — исправить аналитические связи и повторить ограниченный анализ. До этого нельзя надёжно сравнивать долю проигравших позиций, закрытых реальным stop-fill, среднюю фактическую цену stop-fill, качество стопов и стоимость удержания ниже пола.

После исправления следует сначала проверить существующий простой механизм floor = threshold − margin в теневом/наблюдаемом режиме. Он сохраняет maker-only rank-защиту, потому что floor применяется только к stop-пути до отмены rank-владельца (strategy.rs:6103), а rank SELL имеет отдельную maker-only валидацию. Новый адаптивный floor или новый торговый контракт следует рассматривать только после серии полных stop-контрфактов; текущих данных для такого решения нет.

Статус работы: исправление аналитических отчётов подготовлено в отдельном рабочем дереве, но не завершено — полный набор проверок не выполнен, изменения не слиты и не развёрнуты.

Пользователь согласовал одну работу класса «дефект» без новой карточки OpenSpec и включение всех реальных покупок в EV, в том числе частичных и мелких остатков. Это согласование исправления отчётов не является выбором новых торговых параметров.

9. Источники и пределы доказательности ​

Для живых результатов использованы запросы к SQLite и ClickHouse, перечисленные во введении. Команда forensics.sh positions --engine --json воспроизвела ложные entry_filled=N и PHANTOM; команда stops сообщила об отсутствии стоп-закрытий при фактической цепочке Wellington. Ограниченный запрос к positions_wide FINAL и stop_frames воспроизвёл две строки разных эпох. Полный stop-counterfactual с запросами будущих цен не запускали.

Прочитанные источники реализации и описания:

  • Штатная форензика (scripts/analysis/forensics.sh): фильтры входов и стопов, cmd_positions, соединение данных и денежная формула stop-counterfactual.
  • Контракт аналитических команд (scripts/analysis/README.md): прежнее исключение частичных входов и границы выводов об EV.
  • Проекция позиций (crates/pm-engine/src/observability/analytics/marts.rs): position_row, обнуление остатка при заполненном closed_at.
  • Реестр позиций (crates/pm-engine/src/engine/position_registry.rs): сохранение остатка после продажи и расчёт результата закрытой позиции.
  • Стратегия (crates/pm-engine/src/strategies/directional/strategy.rs): ценовой запрет до отмены существующего выхода, причины пропуска DCA.
  • Параметры исполнения (crates/pm-engine/src/strategies/directional/runtime_config.rs): расчёт нижнего предела цены.
  • Решение о размере выхода (crates/pm-engine/src/strategies/directional/exit_size_decision.rs): DustStranded для остатка ниже минимального размера.
  • Роли заявок (crates/pm-engine/src/ports/intent_role.rs): различение защитных продаж.
  • Метрики: единицы счётчиков и ограничения.

Строки исходников в тексте относятся к прочитанной версии до исправления отчётов; после изменения файлов их номера могут сместиться. Таблицы этого отчёта сохраняют результаты анализа, но не заменяют отсутствующий неизменяемый экспорт всех 22 позиций и исходных ответов. Полную построчную ведомость всех позиций здесь не восстанавливаем по памяти. Отдельный аудит кошелька и ончейн-балансов, причина redeem_status=FAILED, исполнение альтернативных заявок и прибыльность нового алгоритма остаются непроверенными. Один результат сессии не доказывает устойчивый EV.