/* Serving mart: KC=F Coffee C futures prices, analytics-ready. */ /* Adds moving averages (20-day, 50-day SMA) and 52-week high/low range. */ /* Filtered to trading days only (NULL close rows excluded upstream). */ /* Grain: one row per trade_date. */ MODEL ( name serving.coffee_prices, kind INCREMENTAL_BY_TIME_RANGE ( time_column trade_date ), grain ( trade_date ), start '1971-08-16', cron '@daily' ); WITH base AS ( SELECT f.trade_date, f.open, f.high, f.low, f.close, f.adj_close, f.volume, ROUND( ( f.close - LAG(f.close, 1) OVER (ORDER BY f.trade_date) ) / NULLIF(LAG(f.close, 1) OVER (ORDER BY f.trade_date), 0) * 100, 4 ) AS daily_return_pct, /* Daily return: (close - prev_close) / prev_close * 100 */ ROUND( AVG(f.close) OVER (ORDER BY f.trade_date ROWS BETWEEN 19 PRECEDING AND CURRENT ROW), 4 ) AS sma_20d, /* 20-day simple moving average (1 trading month) */ ROUND( AVG(f.close) OVER (ORDER BY f.trade_date ROWS BETWEEN 49 PRECEDING AND CURRENT ROW), 4 ) AS sma_50d, /* 50-day simple moving average (2.5 trading months) */ MAX(f.high) OVER (ORDER BY f.trade_date ROWS BETWEEN 251 PRECEDING AND CURRENT ROW) AS high_52w, /* 52-week high (approximately 252 trading days) */ MIN(f.low) OVER (ORDER BY f.trade_date ROWS BETWEEN 251 PRECEDING AND CURRENT ROW) AS low_52w /* 52-week low */ FROM foundation.fct_coffee_prices AS f WHERE f.trade_date BETWEEN @start_ds AND @end_ds ) SELECT b.trade_date, d.commodity_name, d.ticker, b.open, b.high, b.low, b.close, b.adj_close, b.volume, b.daily_return_pct, b.sma_20d, b.sma_50d, b.high_52w, b.low_52w FROM base AS b CROSS JOIN foundation.dim_commodity AS d WHERE d.ticker = 'KC=F' ORDER BY b.trade_date