# 07.4.4.1.8 — Execution Freshness & Market Quality Layer

## Статус

Этап завершён.

## Цель этапа

Добавить отдельный слой проверки качества рынка перед входом в позицию.

Этап 07.4.4.1.7 уже перевёл автоторговлю на live market runtime, websocket snapshots, REST fallback и bid/ask-aware анализ. Но после этого оставалась важная проблема: стратегия могла видеть корректный тренд и live-импульс, но сама возможность безопасного исполнения сделки ещё не оценивалась отдельно.

Этап 07.4.4.1.8 добавляет execution freshness и market quality diagnostics:

- проверку наличия market snapshot;
- проверку свежести snapshot;
- проверку возраста bid/ask данных;
- расчёт spread;
- разделение warning и blocking состояний;
- отображение качества рынка в Telegram UI;
- блокировку входа при плохих execution-условиях;
- human-readable диагностику причин, почему вход сейчас небезопасен.

---

# Что было до этапа

До внедрения этого слоя система уже умела:

- получать live bid/ask через MarketDataRunner;
- хранить snapshot в MarketPriceCache;
- использовать market snapshot в TrendStrategy;
- показывать причину HOLD;
- защищать runtime loop от падения.

Но execution layer ещё не отвечал на вопросы:

```text
А можно ли прямо сейчас безопасно открыть позицию?
```

Например, могли возникать ситуации:

```text
Сигнал готов
Рынок трендовый
Импульс подтверждён
```

но при этом:

- bid/ask snapshot устарел;
- spread стал слишком широким;
- websocket lagging;
- REST fallback дал данные, но они уже начали стареть;
- market data временно недоступны.

До этого такие ситуации были видны только косвенно или не были видны в UI совсем.

---

# Что внедрено

## 1. Execution quality layer

В runtime автоторговли добавлен отдельный слой оценки качества исполнения.

Теперь система анализирует не только торговый сигнал, но и качество рынка для входа:

```text
Strategy signal
↓
Market analysis
↓
Live impulse diagnostics
↓
Execution freshness & market quality
↓
Execution decision
```

Это отделяет две разные сущности:

- стратегия может быть права по направлению;
- рынок может быть плохим для исполнения.

---

## 2. Snapshot availability check

Добавлена проверка наличия market snapshot.

Если snapshot отсутствует, система не должна считать вход безопасным.

Диагностика:

```text
⛔ Вход · нет данных рынка
```

Это означает, что в текущий момент нет достаточных данных bid/ask для безопасной оценки цены входа.

---

## 3. Snapshot age tracking

Система начала учитывать возраст market snapshot.

`age` — это возраст последнего market snapshot в секундах.

Пример:

```text
age 0.6с
```

означает, что последние bid/ask данные были получены 0.6 секунды назад.

Это важно, потому что при автоторговле нельзя входить по данным, которые выглядят валидными, но фактически уже устарели.

---

## 4. AGING_SNAPSHOT

Добавлено промежуточное состояние:

```text
AGING_SNAPSHOT
```

Оно означает:

```text
snapshot ещё можно использовать, но он начинает стареть
```

Это warning-состояние, а не обязательно блокировка.

UI может показать:

```text
⚠️ Рынок · данные стареют (2.8с)
```

Смысл:

- market runtime жив;
- данные ещё есть;
- но задержка уже повышена;
- вход становится менее надёжным.

---

## 5. STALE_SNAPSHOT

Добавлено критическое состояние:

```text
STALE_SNAPSHOT
```

Оно означает:

```text
snapshot уже слишком старый для безопасного входа
```

В этом случае execution должен быть заблокирован.

UI:

```text
⛔ Вход · рынок неактуален
```

Смысл:

- последние bid/ask данные могли устареть;
- текущая цена могла измениться;
- риск slippage повышен;
- вход по такой цене небезопасен.

---

## 6. Spread calculation

Добавлен расчёт spread между bid и ask.

Формула:

```text
spread_percent = ((ask - bid) / mid_price) * 100
mid_price = (ask + bid) / 2
```

Теперь система понимает, насколько дорого входить в рынок прямо сейчас.

---

## 7. Spread warning layer

Добавлено warning-состояние для повышенного spread.

UI:

```text
⚠️ Рынок · spread 0.1%
```

Это означает:

- вход ещё не обязательно запрещён;
- но рынок стал менее качественным;
- bid/ask разъехались;
- скрытая стоимость входа выросла.

Для торговли это значит:

- хуже цена входа;
- выше вероятность мгновенного минуса после открытия;
- выше риск slippage;
- слабая ликвидность по текущему инструменту.

---

## 8. Spread block layer

Добавлено blocking-состояние для слишком высокого spread.

UI:

```text
⛔ Вход · высокий spread 0.17%
```

Это означает:

```text
сигнал может быть валидным, но вход сейчас запрещён из-за плохих рыночных условий
```

Такой слой особенно важен для менее ликвидных инструментов, например LTC, где spread может быстро расширяться.

---

## 9. Разделение WARNING и BLOCKED

Слой качества рынка разделён на два уровня:

```text
GOOD     — рынок нормальный
WARNING  — рынок ухудшился, но вход ещё может быть допустим
BLOCKED  — вход запрещён
```

Это важно, потому что не каждый широкий spread должен немедленно блокировать систему.

Пример:

```text
⚠️ Рынок · spread 0.1%
```

это warning.

А:

```text
⛔ Вход · высокий spread 0.17%
```

это уже block.

---

# Что изменилось в AutoTradeState

В состояние автоторговли добавлены поля execution quality diagnostics.

Они нужны, чтобы UI, execution engine и journal могли видеть одну и ту же runtime-оценку рынка.

Логически добавлены поля такого уровня:

```python
execution_quality
execution_quality_reason
execution_quality_message
spread_percent
snapshot_age_seconds
```

Их назначение:

- `execution_quality` — общий статус качества рынка;
- `execution_quality_reason` — машинный код причины;
- `execution_quality_message` — короткое human-readable сообщение;
- `spread_percent` — текущий spread в процентах;
- `snapshot_age_seconds` — возраст market snapshot.

---

# Что изменилось в AutoTradeService

## 1. Добавлена синхронизация execution quality

В AutoTradeService добавлен слой синхронизации execution quality state.

Он получает market snapshot, рассчитывает качество рынка и сохраняет результат в AutoTradeState.

Теперь state содержит не только:

```text
last_signal
market_state
entry_block_reason
```

но и:

```text
execution_quality
execution_quality_reason
spread_percent
snapshot_age_seconds
```

---

## 2. Execution quality теперь обновляется в runtime cycle

В `run_cycle()` execution quality проверяется каждый цикл автоторговли.

Это значит, что Telegram UI может показывать актуальное состояние рынка даже когда стратегия остаётся в HOLD.

---

## 3. Execution block reason получил market-quality причины

Если рынок плохой для входа, state получает execution block reason.

Например:

```text
высокий spread
нет данных рынка
рынок неактуален
```

Это не strategy diagnostics, а именно execution diagnostics.

---

# Что изменилось в Telegram UI

## 1. Добавлена строка качества рынка

В UI появилась отдельная строка:

```text
⚠️ Рынок · spread 0.1%
```

Она показывает warning по качеству рынка.

---

## 2. Добавлена строка блокировки входа

Если execution quality блокирует вход, UI показывает:

```text
⛔ Вход · высокий spread 0.17%
```

Это означает, что проблема не в стратегии, а в условиях исполнения.

---

## 3. Убрана лишняя детализация age при нормальном snapshot

Ранее строка могла выглядеть слишком длинно:

```text
⚠️ Рынок · spread повышен (spread 0.12%, age 0.8с)
```

После правки нормальный age не показывается.

Теперь:

```text
⚠️ Рынок · spread 0.12%
```

Age показывается только когда он важен:

```text
⚠️ Рынок · данные стареют (2.8с)
⛔ Вход · рынок неактуален
```

---

## 4. Терминология UI приведена к единому стилю

Используются короткие роли строк:

```text
Сигнал   — сырой сигнал стратегии
Тренд    — состояние рынка
Условие  — почему стратегия пока не дала вход
Рынок    — качество рыночных данных / spread warning
Вход     — блокировка входа в позицию
```

Это сделало UI компактнее и понятнее.

---

# Улучшения аналитики

## 1. Strategy diagnostics отделены от execution diagnostics

Теперь система различает:

```text
Условие · слабый импульс
```

и:

```text
⛔ Вход · высокий spread
```

Первое означает:

```text
стратегия пока не видит достаточного импульса
```

Второе означает:

```text
даже если сигнал появится, вход сейчас небезопасен
```

Это критично для будущей аналитики, потому что причины отсутствия сделки теперь можно классифицировать отдельно.

---

## 2. Добавлена аналитика spread как качества рынка

Spread теперь рассматривается не как техническая деталь стакана, а как полноценный market quality metric.

Это позволяет в будущем строить аналитику:

- какие активы чаще имеют высокий spread;
- в какие часы execution quality ухудшается;
- какие сигналы были заблокированы из-за плохой ликвидности;
- где стратегия была права, но рынок был плохой для входа.

---

## 3. Добавлена аналитика freshness

Возраст snapshot теперь является отдельной метрикой.

Это позволяет отличать:

```text
рынок плохой из-за spread
```

от:

```text
рынок плохой из-за старых данных
```

Для live autotrading это разные причины риска.

---

## 4. Подготовка к slippage protection

Spread diagnostics создаёт основу для будущей защиты от slippage.

Если spread растёт, то реальная цена входа может заметно отличаться от ожидаемой.

Теперь система может заранее остановить вход до того, как execution откроет позицию по плохой цене.

---

## 5. Подготовка к instrument quality scoring

На примере LTC стало видно, что разные активы имеют разную норму spread.

Этап подготовил основу для future scoring:

```text
BTC — stricter spread thresholds
LTC — wider normal spread range
XRP — отдельная ликвидность
ETH — отдельный профиль
```

Это будет важно для adaptive thresholds и per-symbol execution profiles.

---

## 6. Подготовка к hysteresis

В ходе проверки стало видно, что spread может колебаться около порога.

Из-за этого UI может переключаться между:

```text
⚠️ Рынок · spread 0.1%
```

и:

```text
⛔ Вход · высокий spread 0.17%
```

Это не ошибка, а следствие отсутствия hysteresis.

Следующий этап:

```text
07.4.4.1.8.1 — Spread Hysteresis Layer
```

должен добавить зоны стабилизации, чтобы UI и execution state не мигали на границе порогов.

---

# Что было проверено

Проверено на live UI:

- market quality line отображается;
- spread warning отображается компактно;
- высокий spread блокирует вход;
- age не показывается при нормальном snapshot;
- snapshot age остаётся доступен для AGING / STALE сценариев;
- терминология `Исполнение` заменена на более короткое `Вход`;
- `нет market data` заменено на `нет данных рынка`;
- strategy diagnostics и execution diagnostics отображаются разными строками;
- HOLD timer продолжает работать как runtime heartbeat;
- live screen обновляется после правок runner lifecycle;
- LTC корректно показывает spread diagnostics.

---

# Примеры UI после этапа

## Spread warning

```text
Сигнал 🟡 HOLD · 8м 13с
📈 Тренд · Вверх
Условие · слабый импульс
⚠️ Рынок · spread 0.1%
```

## Spread block

```text
Сигнал 🟡 HOLD · 54с
📈 Тренд · Вверх
Условие · слабый импульс
⛔ Вход · высокий spread 0.17%
```

## Нет данных рынка

```text
⛔ Вход · нет данных рынка
```

## Устаревший рынок

```text
⛔ Вход · рынок неактуален
```

---

# Что подготовлено для следующих этапов

Этап подготовил базу для:

```text
Spread Hysteresis Layer
per-symbol spread thresholds
adaptive execution quality
slippage protection
liquidity quality scoring
instrument quality profiles
market quality analytics
execution block analytics
freshness-aware execution engine
spread-aware signal confidence
```

---

# Основные изменённые файлы

- `app/src/trading/auto/service.py`
- `app/src/trading/auto/state.py`
- `app/src/trading/market_analysis/service.py`
- `app/src/trading/market_analysis/models.py`
- `app/src/integrations/exchange/models.py`
- `app/src/telegram/handlers/auto/ui.py`
- `app/src/integrations/exchange/market_data_runner.py`
- `app/src/integrations/exchange/ws_client.py`

---

# Проверка перед commit

Рекомендуемая проверка:

```bash
python -m compileall src
python -m src.main
```

После запуска проверить:

1. Экран автоторговли обновляется автоматически.
2. HOLD timer продолжает тикать.
3. Market state отображается корректно.
4. При нормальном snapshot age не отображается.
5. При warning spread показывается строка `⚠️ Рынок · spread ...`.
6. При block spread показывается строка `⛔ Вход · высокий spread ...`.
7. Сообщение `нет market data` больше не используется.
8. Вместо него отображается `⛔ Вход · нет данных рынка`.
9. Strategy diagnostics отображаются через `Условие`.
10. Execution block diagnostics отображаются через `Вход`.

---

# Итог этапа

Этап 07.4.4.1.8 добавил важный слой между стратегией и исполнением.

Теперь автоторговля оценивает не только направление рынка и силу сигнала, но и качество текущего рынка для входа.

Система стала безопаснее:

- не входит без актуальных данных;
- видит возраст snapshot;
- оценивает spread;
- предупреждает о плохом рынке;
- блокирует вход при плохом execution quality;
- показывает пользователю понятную причину.

Это подготовило автоторговлю к следующему уровню: hysteresis, adaptive execution thresholds и per-symbol market quality profiles.
