Stage 07.4.3.2 — price polling, event bus and UI throttling

This commit is contained in:
2026-05-02 14:57:43 +03:00
parent 38c8686a9b
commit bd6b40fcb2
9 changed files with 644 additions and 31 deletions

View File

@@ -0,0 +1,328 @@
# Stage 07.4.3.2 — Price Polling + EventBus + UI Throttling
## 🎯 Цель этапа
Разделить три независимых процесса автоторговли:
- частое получение рыночной цены;
- анализ стратегии;
- обновление Telegram UI.
Главная цель — убрать постоянное обновление Telegram на каждом цикле анализа и подготовить архитектуру к реальному execution.
---
## 🧱 Что было до этапа
Ранее один runner фактически связывал всё вместе:
```text
run_cycle()
strategy.analyze()
update state
edit Telegram message
```
Из-за этого:
- Telegram мог получать слишком частые `edit_message_text`;
- появлялся риск `Flood control exceeded`;
- частота анализа зависела от UI;
- цена не была выделена в отдельный polling-процесс.
---
## ✅ Что реализовано
## 1. MarketDataRunner
Добавлен отдельный runner для быстрого обновления рыночной цены.
Файл:
```text
app/src/integrations/exchange/market_data_runner.py
```
Задача:
```text
каждую 1 секунду:
получить актуальную цену
сохранить её в MarketPriceCache
```
Runner работает отдельно от Telegram UI и отдельно от анализа стратегии.
---
## 2. MarketPriceCache
Обновлён кэш рыночных цен.
Файл:
```text
app/src/integrations/exchange/market_cache.py
```
Теперь cache хранит:
- symbol;
- price;
- bid_price;
- ask_price;
- updated_at;
- source.
Кэш становится единым источником актуальной цены для:
- экрана автоторговли;
- стратегии;
- будущего execution engine.
---
## 3. ExchangeService.refresh_price_cache()
В `ExchangeService` добавлен метод:
```python
refresh_price_cache(symbol)
```
Назначение:
- получить цену через REST;
- записать цену в `MarketPriceCache`;
- вернуть `TickerPrice`.
Это позволяет отдельно обновлять цену без прямого обновления Telegram UI.
---
## 4. Кэширование exchangeInfo
В `ExchangeService` добавлен class-level cache:
```python
_exchange_symbols_cache
```
Это нужно, чтобы быстрый price polling не вызывал `exchangeInfo` слишком часто.
Используется class-level доступ:
```python
type(self)._exchange_symbols_cache
```
---
## 5. EventBus
Добавлен простой in-memory EventBus.
Файл:
```text
app/src/core/event_bus.py
```
EventBus хранит:
- текущую версию событий;
- последний тип события;
- последний payload.
Используется для важных изменений:
```text
auto_status_changed
auto_signal_changed
auto_decision_changed
```
---
## 6. AutoTradeService emits events
`AutoTradeService` теперь отправляет события при изменениях:
### Смена статуса автоторговли
```text
OFF → OBSERVING
OBSERVING → RUNNING
RUNNING → OFF
```
Событие:
```text
auto_status_changed
```
### Смена сигнала
```text
HOLD → BUY
BUY → SELL
SELL → HOLD
```
Событие:
```text
auto_signal_changed
```
### Смена decision state
```text
WAITING → CONFIRMING
CONFIRMING → READY
READY → BLOCKED
```
Событие:
```text
auto_decision_changed
```
---
## 7. AutoTradeRunner decoupling
`AutoTradeRunner` теперь разделяет процессы:
```text
MarketDataRunner: 1 сек
Strategy analysis: 5 сек
Telegram UI: 60 сек или событие
```
### Telegram обновляется:
- сразу при важном событии;
- либо раз в 60 секунд;
- только если текст реально изменился;
- с учётом `TelegramRetryAfter`.
---
## 8. UI throttling
Добавлена защита от Telegram flood control:
- не отправлять update, если текст не изменился;
- не обновлять UI чаще заданного интервала;
- учитывать `TelegramRetryAfter`;
- снимать регистрацию, если сообщение удалено.
---
## 🧠 Итоговая архитектура
```text
MarketDataRunner
ExchangeService.refresh_price_cache()
MarketPriceCache
TrendStrategy / Auto UI
AutoTradeService
EventBus
AutoTradeRunner
Telegram UI
```
---
## 📂 Изменённые / добавленные файлы
### Добавлены
```text
app/src/core/event_bus.py
app/src/integrations/exchange/market_data_runner.py
```
### Изменены
```text
app/src/trading/auto/runner.py
app/src/trading/auto/service.py
app/src/integrations/exchange/service.py
app/src/integrations/exchange/market_cache.py
app/src/telegram/handlers/auto.py
```
---
## ✅ Проверка
Проверено:
- бот запускается без ошибок;
- цена отображается на экране автоторговли;
- `MarketDataRunner` обновляет цену отдельно;
- Telegram UI не обновляется каждую секунду;
- кнопки не ловят flood control;
- сигнал и decision state обновляются через EventBus;
- экран обновляется сразу при важных изменениях;
- `exchangeInfo` не дергается на каждом price polling.
---
## ⚠️ Ограничения текущего этапа
EventBus пока:
- in-memory;
- без подписчиков;
- без persistence;
- без приоритетов событий.
Это нормально для текущего этапа. Для будущего execution можно расширить EventBus или заменить на более полноценную event-модель.
---
## 🔜 Следующий этап
Рекомендуемый следующий этап:
```text
Stage 07.4.3.3 — Position / Execution Skeleton
```
Возможные задачи:
- модель позиции;
- entry price;
- position size;
- unrealized PnL;
- execution readiness;
- безопасный skeleton исполнения ордеров без реальной отправки.
---
## ✅ Итог
Stage 07.4.3.2 завершает важный архитектурный переход:
```text
от UI-driven автоторговли
к event-driven trading engine
```
Теперь система готова к дальнейшему развитию execution layer.