07.4.4.1.8 Execution Freshness and Market Quality Layer
This commit is contained in:
@@ -0,0 +1,663 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user