Формулы метрик
Версия: 0.3 Дата: 2026-09-28 Аудитория: внутренний документ команды (продукт + разработка). Не предназначен для пользователя.
Этот документ — единая точка входа в логику расчётов Lumo. Сами формулы живут в screens/ рядом со своими экранами; здесь — рамка, которая их связывает: какие данные у нас уже есть, что требует персонального baseline, а что работает с первого дня, и откуда взяты веса.
1. Главный принцип — ярусы персонализации
Заголовок раздела «1. Главный принцип — ярусы персонализации»В wearable-алгоритмах нет «правильного абсолютного значения HRV». RMSSD у разных людей отличается в 10 раз (20–200 мс — обе нормы), и интерпретация без личного baseline бессмысленна. Поэтому каждая метрика принадлежит к одному из трёх ярусов:
| Ярус | Когда работает | Что туда попадает | Что показываем до |
|---|---|---|---|
| 0. Абсолютные нормы | День 1 | HR-зоны (220 − возраст), SpO2 < 90% тревожно, сон 7–9ч adult, цель 8000 шагов | Работает сразу |
| 1. Персональный baseline | 14 дней ношения | HRV (RMSSD), RHR, кожная температура (отклонение), фоновый стресс, время отхода ко сну (хронотип) | Плашка «Накапливаем данные» + абсолютная норма как fallback (см. §3) |
| 2. Долгосрочный тренд | 30–90 дней | Здоровье, Lumo Age, кардио-тренды | Скрыто полностью |
Правило: каждая метрика в screens/ должна явно указывать свой ярус. Если ярус 1 или 2, обязателен cold-start UX — что показываем, пока baseline не сформирован.
2. Baseline — как формируется
Заголовок раздела «2. Baseline — как формируется»Окна:
- Recent window — 7 дней (свежее состояние)
- Baseline window — 14 дней (личная норма)
- Long-term window — 60 дней (для медленных метрик: Здоровье, Lumo Age)
Большинство «балансовых» метрик (HRV Balance, RHR vs baseline) сравнивают recent с baseline.
Минимум данных для запуска:
- Ярус 1 (Energy, Stress, Battery): 14 ночей ношения с покрытием ≥ 70% времени сна
- Ярус 2 (Здоровье): 10 полных дней для индикатора, 30 дней для Lumo Age
Что делаем при перерывах ношения:
- < 3 дня без данных — продолжаем считать на старом baseline
- ≥ 3 дня без данных — фризим обновление baseline до накопления свежих 7 дней
- Полный сброс кольца / новый пользователь — пересчёт с нуля, плашка «Накапливаем данные, точность улучшится через N дней»
Fallback на ярус 0 для ярусов 1/2 в cold-start: используем популяционные нормы по возрасту/полу. Например, RHR ожидаемый = 60–80 для 25–45 лет; HRV-нормы по age-band. Это прокси-baseline на первые 14 дней — точность ниже, но лучше пустого экрана.
3. Данные кольца → статус интеграции
Заголовок раздела «3. Данные кольца → статус интеграции»Что кольцо отдаёт и где это в продукте — product-spec §5. Здесь — что из этого уже читает наш код. Источник реальности — LinktopDataService в iOS-приложении.
| Данные | Источник SR28D | В коде |
|---|---|---|
| Пульс, HRV (RMSSD), межударный интервал, дыхание, SpO2, температура, движение, надето, заряд | История, фид 2 | ✅ |
| На зарядке | История, фид 1 | ✅ |
| Стресс кольца | История (поле устаревшее с прошивки V0.9.4), живой замер | ⚠️ только в лог — для сверки «кольцо или свой» |
| Засыпание / пробуждение / время в постели | События сна | ✅ |
| Температура во сне поминутно | Отдельный фид | ✅ |
| Фазы сна, латентность, пульс покоя | SleepV4 на телефоне | ✅ |
| Шаги, дистанция, калории, интенсивность за 5 мин | Активность | ✅ читается, в формулы не подключено |
| Автоопределение активности, VO2max | Активность | ❌ |
| Тренировки | Режим тренировки | ❌ |
| Живой пульс + HRV + IBI, живой SpO2 | Живой замер | ✅ |
| Разовая температура | Команда | ✅ |
| Сырой PPG + акселерометр | Поток при подключении | ❌ |
Следствие для v1: Activity-компоненты в Energy / Battery и «вы много сидите» упираются в интенсивность за 5 минут — данные уже читаются, но в формулы не подключены. Пока компонент недоступен, в доке метрики стоит ⚠️ компонент недоступен — пересчитываем веса оставшихся к 1.0.
4. Композитные метрики — индекс
Заголовок раздела «4. Композитные метрики — индекс»Все формулы держим у соответствующих экранов, чтобы не было двух источников правды. Здесь — обзор: ярус, источник весов, ссылка.
| Метрика | Где формула | Ярус | Базовая модель |
|---|---|---|---|
| Sleep Score | 06-sleep-detail.md | 0 + 1 (timing — 1) | Oura Sleep Score (см. §8) |
| Energy | 07-energy-detail.md | 1 (требует HRV/RHR baseline) | Oura Readiness contributors |
| Stress (фоновый) | 08-stress-detail.md | 1 | Garmin Body Battery / Polar Stress — или метрика кольца, решаем по данным |
| Stress (замер «сейчас») | 08-stress-detail.md | 1 или 0 | Та же шкала, что фон (ярус 1), либо Baevsky SI (ярус 0) — после валидации A4 |
| Battery (Lumo) | 04-battery-detail.md | 1 (через Energy + Stress) | Garmin Body Battery |
| Здоровье | 05-health-detail.md | 2 | Oura Resilience |
| Lumo Age | 05-health-detail.md | 2 | Композит, см. §8 |
5. Raw-метрики и пороги
Заголовок раздела «5. Raw-метрики и пороги»Что отдаём на экране 11-raw-metrics.md и какие пороги используем для алертов / окрашивания.
| Метрика | Ярус | Абсолютный порог (ярус 0) | Персональный baseline (ярус 1) |
|---|---|---|---|
| HR (день) | 0 | < 40 brady, > 100 покой — алерт | — |
| HR (тренировка) | 0 | HR-зоны от max HR = 220 − возраст | Уточняем измеренным max за 60 дней |
| RHR (ночной) | 0 + 1 | < 40 / > 90 — алерт | Δ vs personal baseline (±5 bpm заметно) |
| HRV (RMSSD) | 1 | — (нет универсального порога) | Δ vs personal 14-day baseline в % |
| SpO2 | 0 | < 90% тревожно, < 95% во сне — насторожиться | Δ vs personal ночной baseline |
| Температура (кожа) | 1 | — (кожная температура на пальце 33–36°C, абсолютного порога нет) | Δ ночного среднего vs personal night baseline (±0.5°C — паттерн) |
Правило подачи raw: для ярус-0 показываем абсолютное значение + цвет по порогу. Для ярус-1 показываем абсолютное значение, но интерпретация («норма / выше / ниже») — только после baseline.
Исключение — температура. Абсолютное значение не показываем вообще: только отклонение ночного среднего от личной нормы (+0.3°C), как Oura, и статус «в вашем диапазоне / выше / ниже», как Whoop. До 14 ночей — без числа.
6. Ручные измерения — куда заходят
Заголовок раздела «6. Ручные измерения — куда заходят»Пользователь может вручную измерить через детальные экраны. Вопрос: использовать ли эти точки в композитных формулах или они только для самоощущения?
| Измерение | Источник | Использование в формулах | Использование в UI |
|---|---|---|---|
| Живой пульс | Живой замер пульса | ❌ нет (формулы используют расписание и ночь) | Точечный snapshot |
| Живой SpO2 | Живой замер SpO2 | ❌ нет (Sleep Score использует ночной) | Snapshot + история ручных замеров |
| «Стресс сейчас» | Живой замер пульса: RMSSD, IBI, стресс кольца | ❌ не входит в фоновый Stress score | Отдельный snapshot на экране Стресса, сравнение с последним часом — если шкала та же |
| HRV живого замера | Живой замер пульса | ⚠️ кандидат: заменить им дневную HRV этого дня | Snapshot |
| Разовая температура | Команда кольцу | ❌ нет | ❌ не показываем: дневная кожная температура несравнима с ночной нормой |
Решение для v1: ручные измерения — отдельный канал, не вмешиваются в композитные скоры. Иначе один невозможный замер посреди дня сломает Energy/Battery.
Открыто: HRV живого замера — единственный кандидат на интеграцию в формулы: минута неподвижного замера точнее 15-секундного по расписанию. Решаем после валидации A4 и первых пользователей.
7. Cold-start таймлайн
Заголовок раздела «7. Cold-start таймлайн»Что видит пользователь на разных стадиях накопления данных:
| День | Что доступно | Что скрыто / fallback |
|---|---|---|
| 1 | Sleep Score (если поспал в кольце), HR, SpO2 с абсолютными порогами | Energy / Stress / Battery / Здоровье — плашка «Накапливаем данные». Температура — без числа до 14 ночей |
| 3 | + первые тренды HR / SpO2 / Sleep | Те же |
| 7 | + ранний Sleep Score уверенный, ранний proxy Energy на population baseline | Stress / Battery — всё ещё плашка |
| 14 | ✅ Полный набор: Energy, Stress, Battery, baseline-зависимые raw | Здоровье — ещё нет |
| 30 | ✅ Здоровье | Lumo Age — ещё нет |
| 90 | ✅ Lumo Age | — |
Это в т.ч. ответ на вопрос продаж: «А когда уже будет польза от кольца?» — конкретные ответы по дням.
8. Веса формул — обоснование на референсах
Заголовок раздела «8. Веса формул — обоснование на референсах»Текущие веса в формулах (Energy, Sleep Score, Здоровье, Lumo Age) — округлённые, требуют валидации на ≥100 пользователях после запуска. Базируются на следующих публичных решениях:
Sleep Score (наша формула — 7 компонентов). Опирается на Oura Sleep Score: те же 7 компонентов (Total / Efficiency / REM / Deep / Restfulness / Latency / Timing). Точные веса Oura не публикует, но в их whitepaper и help-центре указано, что Total Sleep и Efficiency — доминирующие. Наши 0.25 / 0.15 для них консистентны. WASO выделили отдельным компонентом (0.10) — клинический маркер фрагментации, отсутствует у Oura, но есть у медицинских стандартов (AASM).
Energy (наша формула — 5 компонентов: Sleep / HRV / RHR / Temp / Activity). Аналог Oura Readiness. Oura использует 8 contributors, мы свернули в 5 (объединили sleep score / sleep balance, выкинули recovery index, требующий ночных RR). Наш вес Sleep 0.40 близок к доминирующему вкладу сна у Oura (по их breakdown — крупнейший контрибьютор). HRV 0.30 + RHR 0.15 = 0.45 на сердечные сигналы — близко к Whoop Recovery, где HRV — основной фактор (~50%+).
Stress (фоновый). Путь Garmin Body Battery / Polar Stress: эвристика на HRV vs personal baseline + HR + исключение активного движения. Точные формулы Garmin/Polar закрыты (Firstbeat — проприетарный алгоритм), но принцип «HRV ниже baseline → стресс выше» документирован в их whitepapers. Наша реализация = тот же принцип.
Stress on-demand (Baevsky SI) — кандидат. Академическая формула из российской/советской космической медицины (Баевский Р.М., 1979–2000е). Используется в Polar OwnRelax, упоминается в современных исследованиях по HRV. Норма 80–150, рост ×1.5–10 при стрессе. Главное отличие от фонового: даёт точечный snapshot за 2–3 минуты, а не балансное значение. Требует ряда интервалов по каждому удару — возможен, только если живой замер SR28D его отдаёт (валидация A4). Иначе замер считаем той же формулой, что фон.
Battery (Lumo). Аналог Garmin Body Battery: стартовое значение = утренний Energy, в течение дня drain от стресса/нагрузки, charge от отдыха. Наша формула проще (нет Firstbeat-математики), но архитектура совпадает.
Тренировку считаем по модели Welltory: она тратит заряд как нагрузка, но снимает накопленный сидячий стресс и даёт буфер от следующего. У Garmin похоже: заряд уходит в активности, стресс меряется только в покое. Два канала не пересекаются: нагрузка считается только на активных отрезках, стресс — только на сидячих.
Здоровье (14 дней). Аналог Oura Resilience, Whoop Recovery Trend, Polar Sleep Plus 7-day trend. Все строятся на 14–28-дневной агрегации тех же базовых сигналов. Наши веса (0.40 / 0.30 / 0.20 / 0.10) — приоритет Восстановления (HRV+RHR) > Стресса > Сна > Активности — соответствует логике Oura: устойчивость = в первую очередь автономная нервная система.
Lumo Age. Композит без прямого аналога. Reverse-fit к паспортному возрасту по 5 сигналам (см. 05-health-detail.md). Веса доминируют RHR (0.40) — научно обоснованно: RHR — самый сильный одиночный предиктор сердечно-сосудистого возраста (см. Cooper Clinic Longitudinal Study). HRV-trend (0.20) — второй валидированный сигнал. Остальные веса — рабочие, требуют калибровки на референсной когорте.
9. Stress: вход и score — однозначный data flow
Заголовок раздела «9. Stress: вход и score — однозначный data flow»Батарейку тратят два канала: drain_стресс на сидячих отрезках и drain_нагрузка на активных. Чтобы избежать рекурсии, фиксируем направление потока:
Вариант А — свой расчёт: Вариант Б — метрика кольца:RMSSD истории (раз в 5 мин) stress кольца 0–1 (история) vs личная база 14 дней × 100+ пульс+ интенсивность активности (активные отрезки исключаются) + интенсивность активности ↓ ↓ Stress score (0–100, карточка) — только сидячие отрезки ↓ Накопленный сидячий стресс S (2 часа, Stress > 50) − обнуление тренировкой − буфер после неё ↓ drain_стресс ─────┐ ├──→ Battery (0–100) drain_нагрузка ───┘ ↑ Интенсивность кольца за 5 минут или зона пульса в тренировке — только активные отрезкиАктивный это отрезок или сидячий — решает интенсивность кольца за 5 минут, режим тренировки кольца и тренировки из Apple Здоровья. Механика S и буфера — в 08-stress-detail.md, стартовые значения нагрузки — в 04-battery-detail.md.
Какой вариант — решаем по сверке на сэмпле (валидация A4: кольцо, свой, Oura daily_stress). Вход в Батарейку в обоих случаях — готовый Stress score. Stress score не использует Battery — петли нет.
Порог накопления S — Stress score > 50 (граница «Повышенный» из 08-stress-detail.md).
10. Открытые вопросы
Заголовок раздела «10. Открытые вопросы»Сводка TBD из всех экранов, чтобы не искать по 7 файлам:
- Веса формул — все текущие веса (0.40 / 0.30 / …) требуют калибровки на ≥100 пользователях после запуска. До этого — round-numbers по аналогии с Oura/Whoop.
- Перевод значений в 0–100 перед взвешиванием — итог каждой метрики (Энергия, Sleep Score, Activity Score) — взвешенное среднее её составляющих, веса заданы. Не задано, как сырое значение превращается в балл 0–100 до умножения на вес: «HRV +5% к норме», «пульс покоя −1», «температура −0,1°» в одних единицах не складываются. Стартуем с линейных функций вокруг личной нормы и калибруем на данных в процессе использования (решение 2026-09-27).
- Cold-start fallback на популяционные нормы — нужна таблица RHR/HRV ожидаемых по возрасту/полу. Источник: NHANES / Garmin user data tables / академические работы. Не сделано.
- Пульс покоя — берём у SleepV4 (пульс покоя за ночь). Сверить с Oura
lowest_heart_rateна сэмпле; если расходится — свой расчёт по минимуму устойчивого окна. - HRV живого замера → замена дневной HRV — оставлено на v1.1 после первых пользователей.
- Стресс: кольцо или свой — см. §9, решаем по данным.
PPG sample rate— закрыто: у SR28D сырой PPG 25 / 50 / 100 Гц, только при подключении. Cardio Age возможен только как ручной замер, v2.- Dynamic порог «высокого стресса» для Battery — сейчас
Sкопится выше фиксированных 50 (граница «Повышенный»). Возможно стоит делать персональным (75-й перцентиль личного распределения за 14 дней). - Коэффициенты Батарейки — все каналы (бодрствование, нагрузка, накопленный стресс, сидение, отдых) в таблице 04, снятие стресса и буфер — в 08. Стартовые значения, калибруем на сэмпле против Garmin Body Battery и Welltory. Сама модель решена 2026-09-28: тренировка тратит заряд и снимает накопленный стресс. Моки приложения считаются этой же формулой (
BatteryModel).
Версия: 0.3 Последнее обновление: 2026-09-28