> 🌐 **Публічне дзеркало формул** — `formulas.freyal.renderhorizon.org`. Лише визначення метрик/формул; **живих цифр і доступів тут немає** (вони звіряються на сервері за авторизацією).
> **Згенеровано:** `2026-07-28 00:55:01 IST` · rev `n/a` · оновлюється автоматично кожні 5 хв із canonical. Це завжди остання версія — використовуй її замість знімка у скачаному брифі.

# 📚 Універсальний каталог метрик і ресурсів — `reports.halleg.renderhorizon.org`

> Єдина база знань для обох брифів (`BRIEF_new_report.md`, `BRIEF_edit_report.md`).
> Тут зібрані **всі** звіти, метрики, формули, розрізи, поля provider-settings (supportzones)
> і доменні інваріанти нашого сервера. Бриф під час інтерв'ю **звіряє** побажання замовника саме
> з цим каталогом — щоб не вигадувати метрику, яка вже є, і не забути обов'язкові домовленості.
>
> Джерела істини: `web-analytics/app.py` (маршрути), `web-analytics/powerbi/docs/LEGEND*.md`,
> `report-skill-from-spec/references/report-patterns.md`, `web-analytics/trader_detailed.py`
> (маппінг supportzones), `~/projects/knowledge/financial-formulas/` (canonical фінформули).

---

## 🕐 Актуальність формул (читати ПЕРШИМ)

- **🌐 ЗАВЖДИ СВІЖЕ ДЖЕРЕЛО (для всіх, хто скачав бриф):**
  **`https://formulas.freyal.renderhorizon.org/metrics-catalog.md`**
  Перед кожним ТЗ **підтягни цей URL** (WebFetch/браузер) і бери формули **звідти** — він ребілдиться з canonical
  **кожні 5 хв**, тож формули останні навіть у зовнішнього замовника без доступу до наших репозиторіїв.
  Текст нижче в цьому файлі — лише **офлайн-фолбек** на випадок, якщо URL недоступний.
- **Знімок станом на:** `2026-07-27` · **версія каталогу:** `v3`.
- **Правило свіжості (головне).** Цей файл — **знімок**, формули з часом дрейфують (напр. CR перевели на метод
  Фінансів 2026-07-27). Тому **перед тим як вписати будь-яку формулу в ТЗ — візьми її з live-URL вище** (а на
  нашому сервері ще й перезвір із canonical-джерелом наживо, список нижче). Якщо жива версія відрізняється від
  знімка — **жива перемагає**, а знімок тут же онови (рядок формули + Changelog + дата/версія вгорі).
- **Джерело істини по кожному типу формул** (перезвіряти саме тут):

| Тип формули | Canonical (де актуальна версія) |
|---|---|
| Фінансові (CR, settlement, deposit, комісії, маржинальність, scoring) | `~/projects/knowledge/financial-formulas/` + `lab-dashboard-metrics.md` |
| Визначення метрик звітів (легенда) | `web-analytics/powerbi/docs/LEGEND*.md`, `legend_rows.txt` |
| Реально реалізована формула конкретного звіту | код `web-analytics/*.py` (модуль, що будує звіт) |
| Кінцеві цифри | live-джерела §9 (CH hermes / halleg / supportzones / dsfrogboard) |

- **Освіжити (30 сек на метрику):** `grep` формулу в canonical → порівняти зі знімком → якщо різне, оновити рядок,
  додати запис у Changelog, підняти дату/версію. `knowledge/` синкається cron'ом кожні 5 хв (hard-reset на origin) —
  тому це завжди остання версія компанії.

### 📝 Changelog формул
| Дата | Версія | Що змінилось |
|---|---|---|
| 2026-07-27 | v3 | **CR → метод Фінансів** (`success/final`, без `pending`/`processing`, не `COUNT(*)`); чисельник = `completed`+`successed_by_partner` в усіх звітах |
| 2026-07-27 | v2 | Правило точності звірки **1:1** (до копійки/пункту); онлайн-звірка (real-time) з 4 джерел §9 |
| 2026-07-22 | v1 | Первинний каталог: звіти, метрики, скоринг, розрізи, supportzones-поля, інваріанти |

---

## 0. Як користуватись каталогом (для інтерв'ю)

0. **Освіжи формули ПЕРШИМ ділом** (див. «Актуальність формул» вище): перезвір кожну потрібну формулу з canonical
   наживо; застарілі в знімку — онови. У ТЗ іде **жива** формула, не заморожена.

1. Замовник називає метрику/розріз → знайди її нижче.
2. **Є в каталозі** → бери готову формулу, не переписуй. Уточни лише пороги/період, якщо відрізняються.
3. **Немає** → це нова метрика → зафіксуй точну формулу зі слів замовника + познач `⚠ нова, звірити з knowledge`.
4. **Фінансова** (комісії, settlement, deposit, scoring, конверсії) → **обов'язково** звірити з
   `~/projects/knowledge/financial-formulas/`; якщо там інше — не застосовуй мовчки, спитай.

---

## 1. Наявні звіти на сервері (щоб не дублювати)

`REPORT_LABELS` з `web-analytics/app.py`. Перед створенням нового звіту перевір — можливо, потрібне
вже є як вкладка/слайсер існуючого.

| id (URL `/…`) | Назва в UI | Про що |
|---|---|---|
| `trader-kpi` | Trader KPI | Головні KPI по трейдерах (обсяг, CR, активні, депозити) |
| `trader-operational` | Trader Operational | Оперативний зріз: зміни, наливи, on-shift, аномалії |
| `trader-detailed` | Trader Detailed | Деталізація по провайдеру: баланси/ліміти/статуси (тягне supportzones-поля) |
| `trader-hourly-calculator` | Trader Hourly Calculator | Погодинний калькулятор навантаження |
| `trader-scoreboard` | Scoreboard | Скоринг трейдерів, тири, Total score + тренди |
| `trader-weekly` | Weekly KPI | Тижневі KPI (ISO Пн–Нд), Δ тиждень-до-тижня |
| `trader-affiliate` | Affiliate Dashboard | Дашборд по афіліатах (пули трейдерів) |
| `trader-affiliate-weekly` | Affiliate Weekly | Тижневий по афіліатах: portfolio / funnel / risk / subaff-matrix |
| `trader-affiliate-tier` | Affiliate Tier | Тири на рівні афіліатів |
| `churn` | Retention & Churn | Відтік/реактивація трейдерів |
| `churn-v2` | Retention & Churn V2 | Оновлена методологія churn |
| `trader-merchant-slu` | Merchant SLU | Зріз по мерчантах / SLU-групі |
| `trader-main-dashboard` | Main Dashboard | Головний дашборд (еталон-порт PBI Main_dashboard) |
| `trader-daily-payin` | Daily Payin | Денний payin-обсяг |
| ~~`trader-capacity`~~ | Trader Capacity | ⏸ приховано (owner перебудовує на staging) |
| ~~`trader-shifts`~~ | Trader Shifts | ⏸ приховано |

Каталог у застосунку віддається endpoint-ом `GET /api/reports-list`.

---

## 2. Бібліотека метрик (переписуй формулу, не вигадуй)

### 2.1 Обсяг і активність
| Метрика | Код/алиас | Формула | Одиниця |
|---|---|---|---|
| PayIn Volume | `vol` | `SUM(amount) WHERE operation='payin'`, застосувати `vol_filter>5k` | ₹ |
| PayOut Volume | — | `SUM(ABS(amount)) WHERE operation='payout'` (в Hermes payout з мінусом → `ABS`) | ₹ |
| Volume, L (scaled) | `Volume,L` | `vol / 100 000` | — |
| Active Traders | `tru` | `COUNT(DISTINCT provider)` з `payin>0` | шт |
| AVG Active Traders | `tr` | `AVG(daily_active_count)`; завжди `tr ≤ tru` | шт |
| Active days | — | к-сть різних днів з ≥1 транзакцією у періоді | дн |
| Avg PayIn/Trader | `avg` | `vol / SUM(daily_active_count)` (знаменник — сума, не середнє) | ₹ |
| Active accounts | — | `COUNT(DISTINCT bank_account)` з ≥1 успішною трз | шт |
| New Traders | `nt` | перша payin-транзакція припадає на період | шт |

### 2.2 Якість / конверсія / швидкість
| Метрика | Формула | Примітка |
|---|---|---|
| **CR (Success Rate), %** — ⚖️ **метод фінансів (стандарт Андрія)** | `success / final` (див. callout нижче) — **НЕ** `success/COUNT(*)` | BLANK при final=0 |
| Change CR / Trend CR | абсолютна різниця CR (п.п.) поточний − попередній | лише «зрілі» трейдери (30D≥2.0міс / 14D≥0.9 / 7D≥0.5) |
| % Auto (Auto success) | `COUNT(success AND edited_by_support=false) / COUNT(success)` | payout-auto: `checking_by = AUTO_PAYOUT_CHECKER` |
| PayIn speed | середній час хв від `cp.createdAt` до успіху; 95-й перцентиль (відкид 5% викидів); лише провайдери з >3 трз і vol>5k | UX-метрика |
| PayOut speed | середній час хв від `cpo.assignedAt` до успіху payout; ті ж фільтри | |
| PI/PO median time | `MEDIAN(approved_at − source_created_at)` по completed | джерело — `payment_status_history` |
| %Payin < 5min | частка payin, оброблених <5 хв | quality-of-service |
| %Payout < 30min | частка payout, оброблених <30 хв | |

> ⚖️ **CR — метод фінансів (обов'язковий стандарт: усі звіти зводимо до того, як рахують Фінанси/lab).**
> `CR = success / final`, де:
> - **success (чисельник)** = `status IN ('completed','successed_by_partner')` — **однаково в усіх звітах**.
>   Прибрати внутрішню розбіжність: `Operational` рахував success тільки як `successed_by_partner`,
>   `Merchant-SLU` — тільки як `completed`; звести до **обох** статусів скрізь.
> - **final (знаменник)** = лише заявки, що дійшли **фінального** статусу: `success + reject + cancel + expire + fail`.
>   **Виключити `pending`/`processing`** (ще не фінальні). **НЕ `COUNT(*)`** — саме тут головне розходження.
> - **Навіщо:** щоб CR збігався з lab (Фінанси) та `eye-of-god` **1:1**. Наш старий CR (з `COUNT(*)`) систематично
>   **занижений** — незавершені заявки висять у знаменнику. Різниця максимальна протягом дня (багато `pending`).
> - **Коди статусів у hermes:** success = `completed`/`successed_by_partner`; reject = `rejected`/`rejected_by_partner`.
>   `cancel`/`expire`/`fail` у нашому коді **не використовуються** — точний перелік фінальних кодів **уточнити у Фінансів**.
> - ⚠ **Canonical:** цієї формули ще НЕ в `~/projects/knowledge/financial-formulas/` (lab-файл не має метрики конверсії).
>   Після підтвердження списку фінальних статусів — **зафіксувати через MR у `renderhorizon/knowledge`**, і лише тоді вважати остаточною.

### 2.3 Гроші / депозити / ефективність
| Метрика | Формула | Примітка |
|---|---|---|
| Deposit | `SUM(cum_dep)` на LAST_DAY періоду (snapshot; виключити archive і рахунки «Payable») | у Scoreboard — bank accounts з тегом "deposit" |
| Settlement | `SUM(expenses.cash_out) WHERE category='settlement'` (живі expenses) | fin-формула → knowledge |
| Settle/PayIn %, `stl%` | `SUM(settlement) / vol` | |
| Settle | сума розрахованих коштів за період; в UI інвертована (`×-1`) як додатне | |
| **Vol/Dep Ratio** `vd` | `(vol/active_days) / (dep_active × 93)`. `93` — константа з PBI, **не міняти** | >2.0 добре · 1.5–2.0 норма · <1.5 низько |
| Balance2dep, % | мінімальний поріг balance/deposit, щоб трейдер лишався активним | risk-mgmt |
| Statement % | частка bank_accounts з підвантаженою випискою (`bank_statement_reports`) | |

### 2.4 Порівняння / динаміка (є майже в кожному звіті)
- **Δ до попереднього періоду** (семафор good/neutral/bad) — обов'язковий патерн.
- **Change / Trend** *(volume, CR, active days, total score)* — з фільтром «зрілості» (виключає новачків <2 міс).
- **Traders change / growth %** — `count − count_prev` та `(count−count_prev)/count_prev`.
- **Hour-to-Hour ★** — «чесне порівняння»: обрізає кожен історичний період до поточної позиції всередині
  періоду (день → до поточної години IST; тиждень → до дня+години; місяць → до дня місяця).
- **TOP-N Best/Worst** — топ-7 за приростом/падінням Total score.
- **Weekly comparison** — ключові метрики поточний тиждень vs попередній.

---

## 3. Скоринг трейдерів (Scoreboard) і тири

**Total score** = зважене середнє 7 субскорів (кожен 0–100):
`Volume 30% · Success 20% · Activity 10% · Tenure 10% · VeloIn 10% · VeloOut 10% · Stability 10%`.
(Альтернативний «чистий» вигляд у report-patterns: сума субскорів − Cost, макс 700 — уточни, яку шкалу хоче замовник.)

| Субскор | Логіка (пороги фіксовані, не квантилі) |
|---|---|
| **Volume score** | ≥20M:100 · 10–20M:80 · 5–10M:60 · 2.5–5M:40 · 1–2.5M:20 · <1M: `(vol/100k)*2` |
| **Success score** | ≥50%:100 · 45–49.9:85 · 40–44.9:70 · 35–39.9:50 · 30–34.9:30 · <30%:0 |
| **Activity score** | active_days<5 → 0; інакше `(active_days/30)*100` |
| **Tenure score** | ≥12міс:100 · 6–11:70 · 3–5:50 · 1–2:30 · <1:10 |
| **VeloIn score** | ≤3хв:100 · 3.1–5:80 · 5.1–10:60 · 10.1–15:40 · >15:20 |
| **VeloOut score** | ≤15хв:100 · 15.1–20:80 · 20.1–25:60 · 25.1–30:40 · >30:20 |
| **Stability score** | від коеф. варіації (std/avg volume): менша варіація → вищий бал (max 100); якщо CV>0.8 або avg=0 → 20 |

**Тир (Tier)** з Total score: **Platinum ≥80 · Gold 65–79 · Silver 45–64 · Bronze 30–44 · Inactive <30**.
Є `Tier prev` (базлайн) і матриця міграцій `Previous Tier → Current Tier`.
**VAS-код** (Volume·Activity·Stability, напр. `1-1-1` найкращі, `3-3-3` кандидати на churn/реактивацію).

> Порог/ваги — узгоджені з PBI-еталоном. Якщо замовник хоче інші — це **зміна формули**, фіксувати окремо
> і звіряти з `knowledge/financial-formulas/` та PBI Main_dashboard.

---

## 4. Розрізи / слайсери / фільтри (стандартний набір)

| Слайсер | Значення |
|---|---|
| **Affiliate** (multi) | визначається за префіксом імені трейдера (`G[P2P] → Griffin`); підтримує Master & Sub-affiliate |
| **Manager** (multi) | provider_group (apg.name) |
| **Status** | active / archive / audit / restricted / suspicious / locked / scammer / lost / 60DaysLost / … |
| **Group** | P2P (default) · SLU · Intent · Transit · Other · ALL |
| **Trader / Name** | конкретний провайдер |
| **Tier** | Platinum / Gold / Silver / Bronze / Inactive |
| **Period / From–To** | Daily / Hourly / Weekly (ISO) / Monthly; або довільний диапазон |
| Active days / Working month / PayIn·PayOut speed | діапазонні фільтри (переважно в scoreboard/analysis) |

Кнопка **Clear all slicers** скидає всі фільтри.

---

## 5. Provider-settings (supportzones.net) → як лягає у звіти

Панель `supportzones.net/settings-provider` (Keystone/Hermes «Account Providers») — джерело
статусів і балансів провайдера. Ці поля вже споживає `trader-detailed` (і частково `operational`).
Дані доступні в ClickHouse `hermes` через таблицю `providers` (CDC-реплікa) — окремий логін у панель
для побудови звіту **не потрібен**, панель — це людський UI над тими самими полями.

| Поле в supportzones «Account Providers» | Поле в даних (CH `providers`/`bank_accounts`) | Використання у звіті |
|---|---|---|
| **Status** (бейджі Restricted / Suspicious / Locked) | `ap.status` | статус-бейдж, слайсер Status; лише 3 значення дають бейдж, `active/audit/…` — без бейджа |
| **Balance** | operational `earnings_balance` (canonical, не `provider_balance`) | колонка Balance, big-balance ≥100k |
| **Limit** | `custom_limit_to_warn_about_overflow` (fallback = deposit INR) | колонка Limit; overflow-warn |
| **%** (Balance/Limit) | `balance / limit` | напр. 229k/600k = 38.2% |
| **Restrict toggle (payin)** | `restrictToggleForPayin` / `restrict_toggle_for_payin` | antiscam-ознака (не є статусом!) |
| **Balance-threshold ban** | `is_restricted_by_balance_threshold` (`in_ban`) | risk: balance2dep поріг |
| **Working hours** | `working_hours_from` / `..._to` + `on_shift` | зміна/шифт, аномалії on-shift |
| **Deposit** | `bank_accounts.account_balance` рахунку-депозиту × exchange rate | deposit_inr |
| **Наливи (naliv)** | `bank_accounts.for_client_payin=1 AND is_paused=0 AND work_state='work'` | к-сть активних UPI |
| **Group / Manager** | `provider_group.name` | розріз Manager |

> ⚠ Для звіту цифри беремо **з ClickHouse `hermes`** (реплікa supportzones), а не скрейпимо панель.
> supportzones-панель у брифі — це спосіб для замовника **показати пальцем**, яке саме поле/статус він має на увазі.

---

## 6. Доменні інваріанти (зашиті домовленості — не перепитувати щоразу)

- Ринок **Індія**. Валюта **INR (₹)**. Час **Asia/Kolkata (IST, UTC+5:30)**.
- `day = toDate(toTimezone(ts,'Asia/Kolkata'))`. Тиждень — **ISO Пн–Нд**. Дані з **2026-01-01**.
- **`vol_filter`**: в обсяг потрапляють лише провайдери з `SUM(payin) > 5 000` у вікні (відсікає тестові), **per provider per period**.
- Службовий провайдер **`Operation provider`** завжди виключений.
- **Трейдер = provider (AccountProvider)**; PayOut зберігається з мінусом → в UI `ABS`.
- Статуси платежів: успіх = `completed` / `successed_by_partner`; відмова = `rejected_by_partner` / `Rejected`.
- Термінальні статуси провайдера (churn): `scammer, lost, 60DaysLost, locked, archive, restricted`.
- **BLANK/пусто** у клітинці = «недостатньо даних» (новачок без історії або дільник 0), а не 0.
- Мова UI — **українська**, код — англійська.

## 7. Джерела даних і оновлення

- **ClickHouse `hermes`** (live-реплікa прод-PG Hermes через PeerDB CDC, лаг сек-хв).
  Таблиці: `transactions`, `payments` (payin/payout), `expenses`, `bank_accounts`, `providers`,
  `provider_groups`, `payment_status_history`, `exchange_rates`, `bank_statement_reports`.
- Доступ до CH — через скіл `data-readonly-access` (readonly).
- **Оновлення/кеш**: легкий live — in-memory ~5 хв (кнопка Update форсить); важкий — фоновий worker
  у SQLite/JSON (`cache_worker.py`→`kpi_cache.db`; `cache_worker_weekly.py`→`mat_cache.db`;
  `scoreboard.py`→`scoreboard_cache.json`), timer 5 хв / 30 хв / 4 год за важкістю.
- **Грейн розрахунку** (щоб збігалось з еталоном): CR/Auto — на рівні `(trader×slot×hour)` потім `SUM`;
  Volume: Hourly = `SUM(ABS)` на (trader×slot), Daily/Matrix = `ABS(SUM)` на день.

## 8. Стек і стиль (успадковувати завжди)

- Backend **FastAPI** (Python) · Frontend **Vanilla JS + Chart.js 4.x** (без React/Vue) · Nginx + Let's Encrypt.
- UI-шаблон: шапка+логотип → вкладки-періоди (Daily/Hourly/Weekly/Monthly) + вкладка **Legend** →
  слайсери → **KPI-картки** → таблиця/матриця → **Δ-семафор** → картка LastRefresh + кнопка Update.
- Палітра: фон `#FFFFFF`, текст `#252423`, акцент `#118DFF`; семафор good `#1AAB40` / neutral `#D9B300` / bad `#D64554`.
- **Доступ/RLS**: JWT + bcrypt; `admin` (все + аудит), `user` (бачить лише своїх менеджерів/афіліатів).
  Кожен запит логується (user, endpoint, фільтри, timestamp).
- Деплой: `reports.halleg.renderhorizon.org` (Андрій, автодеплой push→main) та/або `reports.freyal` (наш).
