Skip to content
Reliable Data Engineering
Practice problem hard recursive-ctemoving-averagetime-series
Solve it in the browser (SQL editor)

Exponential Moving Average with a Recursive CTE

Difficulty: Hard · Topics: recursive-cte, moving-average, time-series · Asked at: Two Sigma, Citadel, Robinhood, Bloomberg

Problem

Compute the exponential moving average of price with smoothing factor α = 0.5: ema_1 = price_1 and ema_t = α·price_t + (1−α)·ema_{t−1}. Return day, price, ema (2 decimals) ordered by day.

Schema and sample data

CREATE TABLE prices (day TEXT, price REAL);
INSERT INTO prices VALUES ('2026-01-01',10),('2026-01-02',12),('2026-01-05',11),('2026-01-06',15),('2026-01-07',14),('2026-01-08',8);

Expected output

daypriceema
2026-01-0110.010.0
2026-01-0212.011.0
2026-01-0511.011.0
2026-01-0615.013.0
2026-01-0714.013.5
2026-01-088.010.75

Hints

Hint 1

A window function can’t reference its own previous output, which is why recursion is needed.

Hint 2

Number the rows first, then recurse on row number n → n+1.

Solution

WITH RECURSIVE numbered AS (
  SELECT day, price, ROW_NUMBER() OVER (ORDER BY day) AS n FROM prices
), ema(n, day, price, ema) AS (
  SELECT n, day, price, price FROM numbered WHERE n = 1
  UNION ALL
  SELECT p.n, p.day, p.price, 0.5 * p.price + 0.5 * e.ema
  FROM ema e JOIN numbered p ON p.n = e.n + 1
)
SELECT day, price, ROUND(ema, 2) AS ema FROM ema ORDER BY day;

Explanation

EMA is stateful: each output depends on the previous output, not just previous inputs, so a plain window aggregate can’t express it (though it can be approximated with weighted sums over a long finite window). Recursive CTEs process one row per iteration, so they’re slow on large data. In practice compute EMA in pandas (ewm(alpha=0.5, adjust=False)), Spark applyInPandas per key, or a streaming job with state.