В продуктовой аналитике легко дойти до состояния, когда экспериментов много, а уверенности в решениях мало.

Типовые симптомы:

  • тест идет «пока не станет понятно»;

  • MDE (minimal detectable effect) забывают зафиксировать (или берут «как обычно»);

  • p-value проверяют каждый день и закрывают эксперимент на первом же p < 0.05;

  • ARPU и другие денежные метрики шумят так, что любой вывод спорный;

  • после релиза эффект не подтверждается, в следствие чего доверие к экспериментам падает.

Чтобы доверять своим тестам, не попадаться в эти простые ловушки, нужно не так и много: заранее фиксировать минимально значимый эффект, понимать требования к размеру выборки и выбирать метрики так, чтобы они отвечали именно на ваш продуктовый вопрос.

Я собрал небольшой практический каркас для B2C‑экспериментов: расчёты мощности и размера выборки, дизайн метрик (включая ratio и линеаризацию) и high‑level дизайн эксперимента (MDE - sample size - duration).

Репозиторий: https://github.com/Niuhych/trustworthy-experiments-core/tree/main


Что внутри репозитория

  • src/tecore/power.py — power analysis и sample size (пропорции и средние).

  • src/tecore/metrics.py — ratio‑метрики и линеаризация, вспомогательные функции для метрик.

  • src/tecore/design.py — high‑level дизайн эксперимента (MDE - sample size - duration).

Ноутбуки с примерами:

  • notebooks/01_power_analysis_arpu_cr.ipynb

  • notebooks/02_metric_design_b2c.ipynb

  • notebooks/03_experiment_design_tradeoffs.ipynb


Анализ мощности теста: сколько пользователей нужно на самом деле

Кейс: конверсия (CR)

Пусть:

  • baseline CR = 5%;

  • хотим увидеть разницу в +1% (с 5% до 6%);

  • alpha = 0.05 (two‑sided);

  • target power = 0.80;

  • равные группы.

Для разницы двух пропорций при равных группах нормальная аппроксимация даёт оценку:

n \approx \frac{2 \cdot \bar{p}(1-\bar{p}) \cdot \left(z_{1-\alpha/2} + z_{power}\right)^2}{\delta^2}\bar{p}=\frac{p_0+p_1}{2}

Где:

  • n - размер выборки на группу;

  • p0 - базовая конверсия в контроле;

  • p1 - ожидаемая конверсия в тесте;

  • \bar{p} - средняя конверсия между контролем и тестом;

  • z_{1-\alpha/2} - критическое значение стандартного нормального распределения для уровня значимости alpha (для two-sided теста);

  • z_{power} - квантиль стандартного нормального распределения, соответствующий целевой мощности теста (power = 1 − beta);

  • δ=∣p1​−p0​∣ - абсолютный MDE (например, δ=0.01 = +1%).

В коде:

from tecore.power import sample_size_proportions

p_baseline = 0.05
mde = 0.01  # +1 percentage point

res = sample_size_proportions(
    p_baseline=p_baseline,
    mde=mde,
    alpha=0.05,
    power=0.80,
    tail="two-sided",
)

print("n per group:", res.n_per_group)
print("total n:", res.n_total)

Для этих чисел получается порядка 8 159 пользователей на группу.

Дальше полезно смотреть не только оценку размера выборки, но и взглянуть на кривую мощности эксперимента: как мощность (power) растет при увеличении выборки.

 Как растёт мощность A/B-теста конверсии при увеличении выборки
Как растёт мощность A/B-теста конверсии при увеличении выборки

Практический вывод: если вы не набираете нужный размер выборки, вы не «ускоряете» эксперимент, то есть повышаете вероятность получить отрицательный результат даже там, где эффект действительно есть.


Кейс: ARPU (средняя метрика)

Для разницы средних (равные группы, общий std) используется:

n \approx \frac{2\sigma^2 \left(z_{1-\alpha/2} + z_{power}\right)^2}{\delta^2}

Где:

  • σ - стандартное отклонение метрики в популяции (в единицах ARPU);

  • δ = |μ1 − μ0| - MDE, абсолютная разница средних (например, +0.30 ARPU);

  • z_{1-α/2} и z_{power} - как и с конверсией (критическое значение и квантиль для целевой мощности).

В коде:

from tecore.power import sample_size_means

std = 5.0
mde = 0.30  # +0.30 ARPU units

res = sample_size_means(
    std=std,
    mde=mde,
    alpha=0.05,
    power=0.80,
    tail="two-sided",
)

print("n per group:", res.n_per_group)
print("total n:", res.n_total)

Смысл здесь простой: при большом разбросе метрики даже умеренный MDE в единицах ARPU быстро превращается в тысячи пользователей на группу.


Метрики в B2C: почему ARPU часто отвечает на другой вопрос

ARPU выглядит естественной метрикой про деньги, но она часто смешивает два механизма:

  • пользователи стали чаще пользоваться продуктом;

  • каждая сессия стала приносить больше денег.

Если гипотеза именно про деньги на сессию, то метрика ARPU может быть зашумленной: активность пользователей неоднородна, распределения тяжелые, а вклад редких пользователей с большими значениями увеличивает дисперсию.

В таких случаях полезно смотреть ratio‑метрику выручка на сессию. На уровне групп она определяется так:

R = \frac{\sum_i x_i}{\sum_i y_i}

Где:

  • x_i — выручка i‑го пользователя за период;

  • y_i — количество сессий i‑го пользователя за период.

Важно: ratio‑метрика часто ближе к продуктовой гипотезе, чем ARPU, которая в реальности часто становится гибридом деньги × активность.


Линеаризация ratio‑метрик: как сделать user‑level тестирование удобным

Тестировать ratio бывает напрямую неудобно, если вы привыкли к user‑level фрейму. Один из практичных приемов - линеаризация.

Сначала оцениваем базовое значение ratio в контроле:

R_0 = \frac{\sum_{i \in control} x_i}{\sum_{i \in control} y_i}

Дальше для каждого пользователя строим линеаризованную величину:

z_i = x_i - R_0 \cdot y_i

После этого сравниваем среднее z между группами обычным t‑test по пользователям.

Интерпретация:

  • если эффект в основном в деньгах на сессию, линеаризация усиливает этот сигнал;

  • если эффект в основном в количестве сессий, его лучше отдельно смотреть по y.

 ARPU vs линеаризованная ratio-метрика: как меняется форма распределения и читаемость эффекта
ARPU vs линеаризованная ratio-метрика: как меняется форма распределения и читаемость эффекта

Trade‑offs: MDE, размер выборки и длительность эксперимента

Один из самых полезных разговоров с продуктом начинается с вопроса:

  • какой эффект мы хотим видеть;

  • сколько пользователей у нас реально будет в тесте;

  • сколько дней мы готовы ждать.

Если у вас есть оценка дневного трафика, длительность эксперимента можно быстро прикинуть:

days \approx \left\lceil \frac{n}{users_{per\_group\_per\_day}} \right\rceil

Идея простая: вы либо выбираете MDE и смотрите, сколько дней нужно, либо выбираете срок и получаете какой эффект вообще детектируем при вашем трафике.

 Зависимость длительности эксперимента от MDE при фиксированном трафике (CR)
Зависимость длительности эксперимента от MDE при фиксированном трафике (CR)

Что дальше

Если коротко, мой подход такой:

  • фиксируем MDE до запуска;

  • обязательно делаем анализ мощности теста (ничего не принимаем на веру или не выбираем на глаз);

  • выбираем метрику так, чтобы она соответствовала продуктовой гипотезе;

  • где нужно используем ratio и линеаризацию, чтобы стабилизировать сигнал;

  • заранее обсуждаем trade‑offs между MDE, длительностью и трафиком.

Если интересно, могу следующим постом разобрать:

  • как аккуратно выбирать MDE (через бизнес‑эффект, экономику и ожидаемую вариативность);

  • как не убить эксперимент «подглядыванием» (и когда имеет смысл sequential‑подход).