# Аудит контент-генератора — 4 августа 2026

Инвентаризация скриптов генерации контента, их источников данных и того,
что из этих данных мы получаем автоматически.

Аудит проводился на чтение; правок в код не вносилось.

---

## 1. Скрипты генерации контента

### Работают и автоматизированы (2 продукта)

| Что | Модуль | Запуск |
|---|---|---|
| Ежедневный макро-брифинг → Telegram | `content/macro_briefing.py` (1713 стр.) + `orchestrator/scheduler.py` | планировщик в tmux `cg:0`: генерация 10:00 МСК, автопубликация 19:00 |
| GCRM CM-Balance ротация → алерт | `content/russia_rotation.py`, `content/data_updater.py` | cron: `rotation-4h` каждые 4 ч, `rotation-tlt` 20:00, `rotation-oi` 20:55, `rotation-check` пт 20:55 |

### Работают, но только вручную (9 скриптов)

- `content/cot_analyzer.py` — `cot-signals`
- `content/cot_es_deepdive.py` — `cot-deepdive`
- `content/cot_gold_deepdive.py` — `cot-gold-deepdive`
- `content/rotation_engine.py` — `rotation`
- `content/rotation_state_machine.py` — `rotation-status` (вызывается и планировщиком)
- `content/moex_beta_screener.py` — `moex-beta`, `moex-rotation`, `moex-monitor`
- `content/gcrm_history.py` — `gcrm-context`
- `content/intermarket_signals.py`
- `content/segment_engine.py` — `segment-tsp`, `segment-review`

### Сломаны — команда есть, модуля нет (9 команд)

```
gas-monitor  → content.thursday_gas_monitor      ModuleNotFoundError
aeo-context  → providers.aeo2026_provider        ModuleNotFoundError
signal-scan  → content.signal_scanner            ModuleNotFoundError
daily        → content.signal_card               ModuleNotFoundError
weekend      → content.signal_card               ModuleNotFoundError
cot-radar    → content.signal_card               ModuleNotFoundError
moex         → content.russia_crypto_scanner     ModuleNotFoundError
crypto       → content.russia_crypto_scanner     ModuleNotFoundError
fomc         → content.fomc_card                 ModuleNotFoundError
```

Этих шести модулей **никогда не было в git-истории** — они не удалены, а не
написаны. `run.py` объявляет команды под ненаписанный код. Сюда попадают почти
все «карточные» форматы: дневная сигнальная карта, выходной сет-ап,
крипто-уголок, FOMC-карточка, газовый монитор.

### Мёртвый код (4 модуля, ~1800 строк, никто не вызывает)

- `content/scenario_engine.py` (406 стр.)
- `content/sector_rotation.py` (570 стр.)
- `content/m2_cot_cycle_analysis.py` (651 стр.)
- `content/regime_stepper.py` (339 стр.) — вдобавок не импортируется:
  `ImportError: cannot import name 'auto_load_csv' from 'calibrate_step_dw'`

---

## 2. Данные

### Получаем автоматически и свежо

| Источник | Состояние на 04.08.2026 |
|---|---|
| CBR | 3956 строк, вчера |
| MOEX ISS | 814 строк, 2 дня |
| FRED | 19 934 строк, 3 дня |
| Bybit BTC | ежедневно, +365 строк |
| COT (CFTC) | 23 196 строк, 34 инструмента, отчёт от 28.07 (норма — еженедельная публикация) |
| Finam gRPC 60M | 22 тикера, вчера |
| World Bank / IMF | еженедельно, годовые ряды — отставание нормально |

### Не получаем — источники блокируют

- **Investing.com** → `403 Forbidden` **каждый день без исключения**.
  `investing_calendar.json` не обновлялся 14 дней.
  Читают: `macro_briefing`, `scenario_engine`.
- **Rosstat / fedstat.ru** → `403 Forbidden`. В БД **ноль строк** с этого
  источника, при том что `collect-rosstat` стоит в еженедельном расписании.
  Российской макростатистики нет вообще.

### Получаем частично — молчаливая деградация

**13 из 27 тикеров Yahoo встали 21–22 июля** (13 дней):
`BND, COPX, DBB, FXE, FXI, FXY, GDX, LQD, UUP, VNQ, VWO, XLE, XME`.

При этом лог рапортует `Yahoo: +286 rows, 0 errors` — сборщик считает пустой
ответ успехом. Бьёт по `rotation_engine` (слой DOLLAR через UUP/FXE, CREDIT
через LQD/HYG, EM через VWO) и по `intermarket_signals`.

### Не получаем автоматически — файл читают, но никто не пишет

- **`rotation_panel.json`** — **писателя в коде нет вообще**, при 7 читателях:
  `macro_briefing`, `cot_analyzer`, `cot_es_deepdive`, `cot_gold_deepdive`,
  `intermarket_signals`, `scenario_engine`, плюс `update-segments` берёт его как
  определение вселенной US ETF. Заморожен 13 дней назад, цены трёхнедельной
  давности.
  Брифинг частично спасён: секция сегментов сначала пробует свежий
  `segment_state.json` и падает на `rotation_panel` только как на запасной
  вариант. **График сегментов и все COT-разборы читают его напрямую, без
  фолбэка.**
- **`calendar_scenarios.json`** — писателя нет; читает `scenario_engine`
  (который и так мёртвый).
- **`vol_regimes.json`** — ни читателей, ни писателей.
- **`update-segments`** (пересчёт состояний US ETF) — не в планировщике и не в
  cron, только руками.
- Кластер исследовательских артефактов заморожен на 21–22 июля:
  `cot_signals.json`, `rotation_leadlag.json`, `rotation_cot_crosscheck.json`,
  `m2_dollar_leadlag.json`, `macro_causal_chain_thesis.json`, `gold_*`,
  `fomc_*`, `*_xref.json`. Часть из них — вход для `rotation_state_machine`.
- `macro_briefing` ищет `../../../1st/config/economic_events.json` — каталога
  `1st/` не существует нигде, ветка всегда возвращает пусто.

---

## 3. Прочие находки

**Публикация ломалась на невалидном HTML.** 31 июля брифинг пять раз подряд не
ушёл:

```
Telegram API HTTP 400: can't parse entities:
Unsupported start tag "5%):</b" at byte offset 2332
```

В текст попала подстрока вида `(<5%)`, а отправка идёт в режиме HTML без
экранирования. С 1 августа публикуется нормально (2740 знаков) — то есть баг
латентный и сработает снова, когда данные дадут такую же строку.

**`gcrm-context` падает** — `AttributeError: 'NoneType' object has no attribute
'get'` в `gcrm_history.py:423`. Поломка доэтапная, воспроизводится и в
монорепной копии.

---

## Итого

Из ~20 контент-модулей реально в проде живут **два**: ежедневный брифинг и
ротационный алерт. Девять команд не запускаются, четыре модуля мертвы.

Данные для двух живых продуктов в основном есть, но с тремя дырами:

1. календарь (Investing.com) и Росстат заблокированы источниками;
2. треть Yahoo-тикеров тихо встала, сборщик рапортует успех;
3. `rotation_panel.json` — файл, от которого зависят все COT-разборы и график в
   брифинге, — не имеет автоматического обновления.

---

## Оговорка о методе

Аудит был на чтение, но чтобы отличить «сломано» от «работает», команды
запускались — а часть из них пишет результат. За время аудита в `/opt`
обновились `es_cot_deepdive.json`, `cot_signals.json` и добавилась строка в
таблицу `rotation_snapshots` (id=19). Это штатные записи этих команд, ничего не
перезаписано разрушительно.
