# 07.4.4.1.8.1 — Spread Hysteresis Layer

## Статус
✅ Завершено

## Цель этапа

Этап 07.4.4.1.8.1 добавляет hysteresis-механику для spread quality layer, чтобы убрать дребезг состояния рынка около пороговых значений spread.

До этого execution quality могла быстро переключаться между состояниями `GOOD`, `WARNING` и `BLOCKED`, если spread колебался рядом с границами `0.08%` и `0.15%`. Это приводило к визуальному миганию Telegram UI и нестабильному поведению execution gate.

После внедрения hysteresis состояние меняется не по одной границе, а по отдельным порогам входа и выхода.

---

## Что было сделано

### 1. Заменены одиночные spread-пороги на hysteresis-пары

Ранее использовались два порога:

```python
_warning_spread_percent = 0.08
_max_spread_percent = 0.15
```

Теперь spread quality использует четыре значения:

```python
_spread_warning_enter_percent = 0.08
_spread_warning_exit_percent = 0.06

_spread_block_enter_percent = 0.15
_spread_block_exit_percent = 0.12
```

Это позволяет системе отдельно понимать:

- когда нужно перейти из `GOOD` в `WARNING`;
- когда можно вернуться из `WARNING` в `GOOD`;
- когда нужно перейти из `WARNING`/`GOOD` в `BLOCKED`;
- когда можно выйти из `BLOCKED` обратно в `WARNING`.

---

## Новая логика spread hysteresis

### GOOD → WARNING

Если рынок был нормальным, предупреждение появляется только когда spread достигает warning enter threshold:

```text
spread >= 0.08% → WARNING
```

### WARNING → GOOD

Если рынок уже был в состоянии предупреждения, обратно в норму он возвращается только когда spread опускается ниже exit threshold:

```text
spread <= 0.06% → GOOD
```

Это защищает UI от частого переключения около `0.08%`.

---

### WARNING → BLOCKED

Execution block включается только когда spread достигает block enter threshold:

```text
spread >= 0.15% → BLOCKED
```

### BLOCKED → WARNING

После блокировки вход не разблокируется сразу при снижении spread до `0.149%`. Для выхода из BLOCKED spread должен снизиться до block exit threshold:

```text
spread <= 0.12% → WARNING
```

Это защищает execution pipeline от дребезга около `0.15%`.

---

## Добавлен helper `_spread_execution_quality`

В `AutoTradeService` добавлен отдельный метод:

```python
def _spread_execution_quality(
    self,
    *,
    state: AutoTradeState,
    spread_percent: float | None,
) -> tuple[str | None, str | None, str | None, bool]:
```

Он отвечает только за spread-based quality decision и учитывает предыдущее состояние:

- `state.execution_quality`
- `state.execution_quality_reason`

Это важно, потому что hysteresis не может работать только от текущего spread. Ему нужно знать, в каком состоянии система была до текущего цикла.

---

## Поведение helper-а

### Если предыдущий статус был `BLOCKED / HIGH_SPREAD`

Система остаётся в `BLOCKED`, пока spread выше exit-порога:

```text
spread > 0.12% → BLOCKED
```

Если spread снизился ниже block exit, но всё ещё выше warning exit:

```text
0.06% < spread <= 0.12% → WARNING
```

Если spread снизился достаточно сильно:

```text
spread <= 0.06% → GOOD
```

---

### Если предыдущий статус был `WARNING / WIDE_SPREAD`

Система переходит в `BLOCKED`, только если spread дошёл до block enter:

```text
spread >= 0.15% → BLOCKED
```

Остаётся в `WARNING`, пока spread выше warning exit:

```text
spread > 0.06% → WARNING
```

Возвращается в `GOOD`, только если spread опустился до нормального уровня:

```text
spread <= 0.06% → GOOD
```

---

### Если предыдущего spread-состояния не было

Для первого расчёта используется обычная enter-логика:

```text
spread >= 0.15% → BLOCKED
spread >= 0.08% → WARNING
spread < 0.08% → GOOD
```

---

## Обновлена `_sync_execution_quality_state`

Вместо прямой проверки:

```python
spread > _max_spread_percent
spread > _warning_spread_percent
```

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

```python
self._spread_execution_quality(
    state=state,
    spread_percent=state.spread_percent,
)
```

Это сохранило существующую архитектуру execution quality, но добавило устойчивость к рыночному шуму.

---

## Что осталось без изменений

Этап не менял:

- `AutoTradeState` структуру;
- Telegram UI layout;
- execution quality labels;
- market snapshot age logic;
- stale snapshot logic;
- execution block behavior;
- `ExecutionEngine`;
- market data runner;
- strategy logic.

Правка была локализована в `AutoTradeService`.

---

## Почему это важно для торговли

Spread — это разница между лучшей ценой покупки и лучшей ценой продажи. Чем spread выше, тем дороже входить в позицию и тем больше риск получить плохую цену.

Без hysteresis возможна ситуация:

```text
0.149% → WARNING
0.151% → BLOCKED
0.148% → WARNING
0.152% → BLOCKED
```

Для трейдинга это плохо, потому что:

- UI мигает;
- journal получает больше шумных событий;
- execution gate может часто открываться и закрываться;
- пользователь видит нестабильное состояние;
- runtime принимает решения по микроколебаниям, а не по устойчивому состоянию рынка.

После hysteresis поведение становится стабильнее:

```text
BLOCKED включился при 0.15%
BLOCKED держится до снижения spread к 0.12%
WARNING держится до снижения spread к 0.06%
```

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

---

## UI-поведение после внедрения

Telegram UI стал стабильнее:

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

не мигает туда-сюда около `0.08%`.

А состояние:

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

не исчезает сразу при минимальном откате spread ниже `0.15%`.

---

## Проверка этапа

Проверено:

- `python -m compileall src` должен проходить без ошибок;
- spread warning больше не мигает около `0.08%`;
- spread block больше не мигает около `0.15%`;
- LTC показывает более стабильное состояние рынка;
- UI стал визуально спокойнее;
- execution gate стал устойчивее;
- состояние `Вход · высокий spread` выходит из блокировки только после заметного снижения spread;
- Pylance type warning исправлен через корректный bool return type.

---

## Итог

Этап 07.4.4.1.8.1 стабилизировал spread-aware execution quality layer.

Система теперь не переключает качество исполнения при каждом микроколебании spread. Это улучшает UX, снижает шум в runtime diagnostics и делает execution gate ближе к production-grade поведению.

---

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

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

- symbol-specific spread profiles;
- volatility-aware spread thresholds;
- adaptive execution quality model;
- smart re-entry after spread normalization;
- cooldown windows после execution block;
- advanced liquidity diagnostics;
- execution quality scoring;
- risk-adjusted order execution.
