Готовые рецепты формул
Каждый рецепт — задача + список нужных полей + формула + разбор + граничные случаи. Если в датасете другие имена ключей — подставьте свои.
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 ≤ 0 → null. 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 = null → null. Других режимов нет → ноль.
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 = 0 → null. 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) = 0 → null (деление на ноль в 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 = 0 → null.
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 = 0 → null. tax_rate > 1 (если пользователь ввёл «13» вместо «0.13») → доход станет отрицательным.
Частые ошибки во всех рецептах
- Спутали формат процента (
0.05vs5). Финансовые функции работают с дробями. - Не отсортировали строки перед
running_sum/lag. - Забыли про null — все арифметика с пустыми значениями возвращает
null, что отображается в виджете как «—». Защищайтеcoalesce(..., 0).