Как посчитать synthetic control в SQL

Закрепи формулу synthetic control в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать synthetic control в Telegram

Зачем synthetic control

Когда у вас 1 treated unit (страна, регион, бренд) и много controls, обычный DiD не работает — нет «параллельной группы». Synthetic control строит взвешенную комбинацию controls, которая до intervention максимально похожа на treated. Разница после intervention — оценка эффекта.

Применение: оценка эффекта рекламной кампании в одной стране, лонч feature в одном городе, влияние policy change на регион.

Идея метода

  1. Treated unit i*, набор control units i ∈ {1, …, J}.
  2. Найти веса w_i ≥ 0, Σw_i = 1, чтобы Σ w_i × y_i(t) ≈ y_{i*}(t) в pre-period.
  3. Predicted y* в post = Σ w_i × y_i(t_post).
  4. Effect = actual y_{i*}(t_post) − predicted.

Веса обычно подбирают оптимизацией (Abadie). В SQL только грубая аппроксимация.

Synthetic control в SQL

В SQL минимально работающий вариант — равные веса по K «самым похожим» controls:

WITH series AS (
    SELECT
        region_id,
        week_date,
        metric_value,
        AVG(metric_value) FILTER (WHERE week_date < '2026-04-01') OVER (PARTITION BY region_id) AS pre_mean
    FROM weekly_metrics
    WHERE week_date BETWEEN '2025-10-01' AND '2026-05-01'
),
treated_pre AS (
    SELECT AVG(metric_value) AS treated_pre_avg
    FROM series
    WHERE region_id = 'treated_region'
      AND week_date < '2026-04-01'
),
candidates AS (
    SELECT
        region_id,
        ABS(MAX(pre_mean) - (SELECT treated_pre_avg FROM treated_pre)) AS distance
    FROM series
    WHERE region_id <> 'treated_region'
    GROUP BY region_id
    ORDER BY distance ASC
    LIMIT 5
)
SELECT
    s.week_date,
    AVG(s.metric_value) FILTER (WHERE s.region_id IN (SELECT region_id FROM candidates)) AS synthetic,
    MAX(s.metric_value) FILTER (WHERE s.region_id = 'treated_region') AS actual
FROM series s
GROUP BY s.week_date
ORDER BY s.week_date;

Это примитивный «top-5 closest» — не оптимальные веса, но даёт baseline.

Эффект treatment

После построения synthetic — разница post-period:

WITH compared AS (
    SELECT
        week_date,
        actual,
        synthetic,
        actual - synthetic AS gap
    FROM weekly_compare
)
SELECT
    week_date,
    actual,
    synthetic,
    gap
FROM compared
WHERE week_date >= '2026-04-01'
ORDER BY week_date;

Cumulative effect:

SELECT SUM(gap) AS cumulative_effect
FROM weekly_compare
WHERE week_date >= '2026-04-01';
Закрепи формулу synthetic control в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать synthetic control в Telegram

Placebo-тест

Применить тот же метод к каждому control — посмотреть, насколько часто effect такой большой случайно:

-- Псевдо-код: для каждого региона запускаем тот же расчёт, как будто он "treated"
-- Если treated даёт effect = +20%, а у placebo regions диапазон -3% до +5% —
-- эффект статистически отделён от шума.

В SQL реализуется через цикл по регионам (PL/pgSQL), в Python проще через pandas + scipy.

Если у treated эффект сильнее, чем у 95% placebo-regions — значимо. Иначе — это шум.

Частые ошибки

Ошибка 1. Bad pre-fit. Если synthetic плохо повторяет treated в pre-period, верить пост-разнице нельзя.

Ошибка 2. Использовать controls, которые сами «обработаны». Если в control regions была своя кампания, synthetic тоже выросло бы. Тщательно отбирайте donor pool.

Ошибка 3. Слишком мало donors. Минимум 10-20 controls для устойчивых весов.

Ошибка 4. Игнорировать covariates. Помимо pre-period outcome, в матчинг включают age structure, GDP, plan distribution и т.д.

Ошибка 5. Не делать placebo. Без placebo-теста — это просто наблюдение, не статистическая значимость.

Связанные темы

FAQ

Когда synthetic control?

Один treated unit, много controls, есть длинный pre-period.

Минимум pre-period?

Не меньше 10–20 точек. Лучше 30+.

Donors можно weight больше 1?

Стандартный SC — weights в [0, 1] и сумма = 1. Bias-variance trade-off через регуляризацию.

CI для эффекта?

Placebo-тест даёт permutation-based p-value.

Реализация в SQL — это норма?

Для оценки направления — да. Для production-grade — Python pysyncon / R synth.