Перейти к содержимому

Готовые рецепты формул

Каждый рецепт — задача + список нужных полей + формула + разбор + граничные случаи. Если в датасете другие имена ключей — подставьте свои.

1. Месячный денежный поток (доход − расход за период)

Задача: в каждой строке транзакции считать «вклад в чистый поток» — доход положительный, расход отрицательный.

Поля: type (Список: income/expense), amount (Деньги).

if(type == "income", amount, -amount)

Как читать: условие — тип == доход. Если правда, возвращаем amount. Иначе -amount. На дашборде sum(...) этого поля = чистый поток.

Граничные случаи: amount = null → результат null; type пуст → попадёт в ветку else (расход), что может быть нежелательно — добавьте coalesce(amount, 0) и проверку type != null, если важно.

2. Доходность портфеля за период

Задача: «начальная стоимость / конечная стоимость / годы» → среднегодовая доходность.

Поля: initial_value, current_value, years_held.

cagr(initial_value, current_value, years_held)

Как читать: среднегодовая ставка как (end / start)^(1/years) − 1. Возвращает дробь.

Граничные случаи: start ≤ 0 или years ≤ 0null. end ≤ 0−1 (полная потеря).

3. Остаток по ипотеке после N платежей

Задача: в дочернем датасете «График платежей» в каждой строке-месяце видеть остаток долга.

Поля: principal (тело кредита, Деньги, неизменно на каждой строке), annual_rate (Процент, как дробь, например 0.07), total_months (Целое), payment_index (Целое 1..N, порядковый номер платежа).

principal - running_sum(pmt(annual_rate / 12, total_months, principal) - (principal - running_sum(pmt(annual_rate / 12, total_months, principal) * 0)) * (annual_rate / 12))

⚠️ Уточнить: точная формула «остаток после N платежей» в Invest на момент написания требует комбинировать pmt + running_sum особым способом, который может быть сложен в одну строку. Если важна точная цифра — считайте остаток в отдельных колонках: «процент за период», «погашение тела», и тогда running_sum(тело) даст накопленное погашение.

Простая альтернатива (если строка — это просто номер месяца):

pmt(annual_rate / 12, total_months, principal) * payment_index

Это сумма ВСЕХ платежей до текущего — не остаток, но тоже полезно.

4. Налог на доход (УСН 6% / НДФЛ 13%)

Задача: считать налог построчно.

Поля: amount (Деньги), tax_regime (Список: usn6, ndfl13).

if(tax_regime == "usn6", amount * 0.06,
if(tax_regime == "ndfl13", amount * 0.13, 0))

Граничные случаи: amount = nullnull. Других режимов нет → ноль.

5. Средняя цена покупки крипты

Задача: в виджете KPI «Средняя цена покупки BTC».

Где считать: не в формуле-поле, а в виджете на дашборде.

  • Источник: «Сделки», фильтр ticker == "BTC", type == "buy".
  • Значение: sum(qty * price) / sum(qty) — но это формула виджета, требует кастомного выражения.

Если виджет не поддерживает кастомное выражение — добавьте поле-формулу в датасет «Сделки»:

Поля: qty (Число), price (Деньги), type (Список).

if(type == "buy", qty * price, 0)

Назовите его buy_volume. Тогда KPI «Средняя цена» = sum(buy_volume) / sum(if(type == "buy", qty, 0)) — но в виджет нужно отдавать оба числа отдельно.

⚠️ Уточнить: возможность ввести «деление двух агрегатов» прямо в виджете на момент написания не подтверждена; может потребоваться вспомогательное поле или внешний расчёт.

6. Cap rate с учётом простоя (vacancy)

Задача: реальная доходность с учётом, что объект сдан не круглый год.

Поля: monthly_rent (Деньги), occupancy_pct (Процент, как дробь 0.85 = 85%), purchase_price, annual_expenses.

cap_rate(monthly_rent * 12 * occupancy_pct - annual_expenses, purchase_price)

Как читать: годовая выручка домножается на коэффициент заполняемости, затем вычитаются расходы, делится на цену.

Граничные случаи: purchase_price = 0null. occupancy_pct > 1 или < 0 — формула посчитает буквально (никаких проверок).

7. MoM (изменение в % к прошлому месяцу) через lag

Задача: в линейном графике / таблице — изменение продаж к прошлому месяцу.

Поля: month_start (Дата, первое число месяца), revenue (Деньги). Сортируйте по дате.

roi(revenue, lag(revenue))

Как читать: lag(revenue) — прошлый месяц. roi(this, prev) — изменение в долях (0.05 = +5%).

Граничные случаи: в первой строке lag вернёт null → результат null. lag(revenue) = 0null (деление на ноль в roi).

8. YoY (год к году)

Задача: % изменения к тому же месяцу прошлого года.

roi(revenue, lag(revenue, 12))

Граничные случаи: требует минимум 12 строк до текущей. Месячные данные строго подряд, без пропусков.

9. Накопительный P&L

Задача: баланс портфеля в каждой строке ленты сделок.

Поля: realized_pl (Деньги).

running_sum(realized_pl)

Граничные случаи: строки должны быть отсортированы по дате; иначе «накопительный» теряет смысл.

10. Ранг активов по доходности

Задача: видеть, какой актив на каком месте по годовой доходности.

Поля: annual_return (Процент).

rank(annual_return)

Граничные случаи: при равенстве двух активов оба получат одинаковый ранг (см. описание rank в Кросс-строчных).

11. Дни до события

Задача: «До окончания кредита осталось X дней».

Поля: due_date (Дата).

date_diff(today(), due_date, 'days')

Граничные случаи: если due_date в прошлом — отрицательное число. Используйте max(0, ...) если хотите 0 вместо минуса.

12. Скользящее среднее за 3 месяца

Задача: сглаженная кривая месячной выручки на графике.

Поля: month_start (Дата), revenue. Сортируйте по дате.

window_avg(revenue, 3)

Граничные случаи: в первых двух строках окно неполное, но функция считает по доступным значениям.

13. Признак «выходной»

Задача: отметка субботы/воскресенья в таблице транзакций.

Поля: date_field (Дата).

is_weekend(date_field)

Возвращает true/false. Чтобы видеть человеко-читаемое — оберните в if:

if(is_weekend(date_field), "Выходной", "Будний")

14. Условная категория «высокий/средний/низкий риск»

Задача: классифицировать активы по доходности.

Поля: expected_return (Процент).

if(expected_return >= 0.20, "Высокий",
if(expected_return >= 0.10, "Средний", "Низкий"))

Как читать: вложенные if. Возвращает строку. Используйте как ось группировки на дашборде.

Граничные случаи: expected_return = null → ни одно условие не сработает, вернётся «Низкий» (поведение if для null-условия — falsy).

15. CAGR за время владения активом

Задача: годовая доходность по фактическому сроку владения.

Поля: purchase_date (Дата), purchase_price (Деньги), current_value (Деньги).

cagr(purchase_price, current_value, date_diff(purchase_date, today(), 'years'))

Граничные случаи: объект куплен меньше года назад → years < 1, CAGR-формула вернёт null. Используйте max(1, date_diff(...)) чтобы получить «номинальную годовую» — это компромисс.

16. NPV / IRR для бизнес-проекта

Задача: оценить проект с известными вкладами и доходами по годам.

Здесь обычно в одной строке датасета — один проект, и поля cf0, cf1, …, cf5.

npv(0.10, cf0, cf1, cf2, cf3, cf4, cf5)
irr(cf0, cf1, cf2, cf3, cf4, cf5)

Граничные случаи: ставка дисконтирования (0.10) в npv — фиксированная. Если хотите разные ставки в строках — введите поле discount_rate. irr не сходится — null.

17. PMT с переменными параметрами

Задача: «калькулятор» в таблице со строками-сценариями ипотеки.

Поля: principal, annual_rate (как дробь, 0.07), years.

pmt(annual_rate / 12, years * 12, principal)

Граничные случаи: annual_rate = 0 → формула вернёт равные доли тела (principal / n). years = 0null.

18. Чистая доходность аренды с учётом налогов и расходов

Задача: «настоящая» доходность квартиры.

Поля: monthly_rent, purchase_price, annual_expenses, tax_rate (Процент, как дробь — 0.13 НДФЛ).

net_yield(monthly_rent * 12 * (1 - tax_rate) - annual_expenses, purchase_price)

Как читать: годовой доход после налога минус расходы, всё на цену.

Граничные случаи: purchase_price = 0null. tax_rate > 1 (если пользователь ввёл «13» вместо «0.13») → доход станет отрицательным.

Частые ошибки во всех рецептах

  • Спутали формат процента (0.05 vs 5). Финансовые функции работают с дробями.
  • Не отсортировали строки перед running_sum / lag.
  • Забыли про null — все арифметика с пустыми значениями возвращает null, что отображается в виджете как «—». Защищайте coalesce(..., 0).

Что дальше