Live и walk-forward

Главное требование v42: offline replay должен идти тем же путем, что live.

Если replay использует другой press, другой MTF, другую session reset policy или другой director, результат нельзя напрямую сравнивать с live.

Live entrypoint

Текущий live runner:

store/market/tools/whaler_s300_stage_live.py

Он по умолчанию использует:

DEFAULT_BAKE   = store/market/personalities/whaler_v42_mtf_s300_short_wide_may01_20.d8p
DEFAULT_LABELS = store/market/runs/v42_mtf_s300_short_wide_may01_20/v42_mtf_s300_short_wide.tsv

Live пишет run-дир вида:

store/market/runs/live/s300_stage_BTCUSDT_YYYYMMDD_HHMMSS/

Внутри должны появляться:

frames.mtf.s300.jsonl
tape.mtf.s300.raw8.vsb
mtf.s300.html

frames.mtf.s1800.jsonl
tape.mtf.s1800.raw8.vsb
mtf.s1800.html

director.json
director.tsv
director.html

Offline live-equivalent replay

Текущий offline runner:

store/market/tools/whaler_live_replay_walkforward.py

Он делает:

historical frames
  -> closed MTF s300/s1800
  -> d8_agent_cli v42
  -> phase director
  -> optional catalog filter
  -> optional inventory journal

Это не старый research replay. Это parity runner, который должен повторять live-связку.

Откуда взялся s1800

В all-history отчете:

store/market/runs/v42_mtf_s300_short_wide_all_history_2026-01-01_2026-05-30/tf_signal_compare.html

сравнивались фазовые слои:

s300
s900
s1800
s3600

на моментах sparse s300-сигналов. Сводка отчета:

days=150
base_points=43200
signals=150
signal_days=97
s300_long_at_signals=79
s300_short_at_signals=71
s900_long_at_signals=81
s900_short_at_signals=69
s1800_long_at_signals=68
s1800_short_at_signals=82
s3600_long_at_signals=66
s3600_short_at_signals=84

Визуально и по phase-sim sweep лучшим практическим слоем стал s1800. Например phase_s1800_lb224_th0.json на том же all-history прогоне:

frames=43200
phase_frames=7200
signals=150
trades=150
return=+25.63%
win=51.33%
profit_factor=1.45
max_drawdown=13.74%

Для сравнения, s900 с тем же lb224/th0 дал отрицательный результат:

return=-11.02%
win=38.67%
profit_factor=0.83
max_drawdown=29.81%

А s3600 был положительным, но хуже s1800:

return=+10.98%
win=50.0%
profit_factor=1.19
max_drawdown=19.95%

Вывод: s1800 не является отдельным swarm в текущем live, но его роль как HTF-фазы подтверждена экспериментом.

Почему закрытые bucket важны

В live нельзя знать будущее незакрытого 5-минутного окна.

Поэтому offline тоже не должен использовать неполный bucket так, будто он был закрыт.

Правило:

Decima получает только закрытый s300 bucket
директор получает только закрытый s1800 bucket

Если это нарушить, walk-forward станет оптимистичным и перестанет быть проверкой live.

Session reset

Текущий replay использует:

--swarm-session-reset utc-day
--swarm-session-frames 288

Почему это важно:

  • Decima имеет внутреннее состояние;
  • долгий непрерывный replay без reset может отличаться от live-дней;
  • reset по UTC-day ближе к дневной торговой дисциплине;
  • 288 s300-кадров = 24 часа.

Если поменять reset policy, это уже новая проверка.

Level-v3 invariant

Для истории level-v3 должен давать:

86400 frames per day

Это было специально исправлено, потому что без этого MTF и walk-forward могут "терять" пустые секунды и давать другой слух.

Проверка ETHUSDT после исправления:

150 дней
каждый день: 86400 frames.level-v3.jsonl

Пример ETHUSDT transfer

Команда:

python3 store/market/tools/whaler_live_replay_walkforward.py \
  --frames-glob 'store/market/runs/ETHUSDT-2026-*/frames.level-v3.jsonl' \
  --start 2026-01-01 \
  --end 2026-05-30 \
  --out-dir store/market/runs/v42_transfer_ETHUSDT_levelv3_fixed_2026-01-01_2026-05-30

Результат:

raw_frames=12960000
s300 closed_frames=43200
s1800 closed_frames=7200
short signals=138
trades=68
pnl=+13.6846
return=+13.68%
win=64.7%
dd=19.22%
equity=113.6846
position=flat

Помесячно:

2026-01: trades=13 pnl=+10.0041 win=76.9%
2026-02: trades=15 pnl=-6.2165  win=46.7%
2026-03: trades=15 pnl=+2.6741  win=60.0%
2026-04: trades=16 pnl=+5.3470  win=68.8%
2026-05: trades=9  pnl=+1.8759  win=77.8%

Вывод: ETH transfer не идеален, но положительный. Это полезный стресс-тест переносимости.

Что сравнивать live vs replay

Минимальный parity checklist:

одинаковая .d8p
одинаковый labels TSV
одинаковый MTF scale
одинаковые closed bucket rules
одинаковая bootstrap policy
одинаковая session reset policy
одинаковый phase lookback
одинаковая комиссия
одинаковый same-side режим
одинаковый catalog-фильтр, если он включен
одинаковое carry/close at EOF

Сравниваемые выходы:

s300 frame count
s1800 frame count
signals count
pattern ids
director decisions
position transitions
realized pnl
mark pnl
drawdown

Почему live может временно молчать

v42 может долго не давать торговых действий:

  • s300 прогревается;
  • s1800 прогревается еще дольше;
  • phase может быть neutral;
  • боковик не проходит фильтры;
  • Decima может услышать сигнал, но директор решит skip;
  • позиция может быть уже открыта, а same-side не дает причины закрыть.

Это нормальное поведение. Молчание в боковике - часть стратегии.

Что должно быть видно в HTML

director.html должен быть мониторингом, а не просто картинкой результата.

Минимально он должен показывать:

run id
symbol
env
start time
uptime
last update time
websocket messages
trades received
frames
reconnects
s300 frames
s1800 frames
signals
position
equity
realized pnl
mark pnl
drawdown
last decision
last reason
paths to JSON/TSV/HTML

Для VPS это станет главным экраном здоровья.

Когда live "ок"

Live считается технически здоровым, если:

  • WebSocket не завис;
  • ws_messages растет;
  • trades растут;
  • frames растут;
  • reconnects не растут бесконтрольно;
  • s300 и s1800 файлы обновляются;
  • director.json/html обновляются;
  • inventory не расходится с директором;
  • нет неожиданных exceptions;
  • свободное место на диске не заканчивается.

Когда live не "ок"

Нужно вмешиваться, если:

  • WebSocket сообщений нет;
  • trades не растут при живом рынке;
  • frames не растут;
  • s300/s1800 html не обновляется;
  • director не пишет новые отчеты;
  • reconnects растут часто;
  • position в inventory отличается от биржи;
  • диск почти заполнен;
  • director.json битый или пустой;
  • live использует не ту .d8p или labels.

Правило для будущих экспериментов

Любой новый v43+ эксперимент должен отвечать:

чем он отличается от v42?
какой слой изменен?
сохраняется ли live/replay parity?
какой baseline replay?
какой transfer по ETHUSDT?
какой риск хуже, чем у v42?

Без этого v42 остается базой.