code wiki / (root) / sketch_holt_vs_ewma_trended_bench.nx

sketch_holt_vs_ewma_trended_bench.nx source

↩ module page · 79 lines · 2729 B

1// sketch_holt_vs_ewma_trended_bench.nx -- trend tracking paired bench. 2// 3// CLAIM TO VALIDATE: 4// Holt's method (Holt 1957) = EWMA + linear trend component. On 5// trended data, Holt's h-step forecast extrapolates the trend. 6// EWMA tracks level only -- its forecast is FLAT (=current level), 7// so it lags behind the trend. 8// 9// WORKLOAD: 10// y_t = 100 + 5*t (linear trend, slope=5) 11// Stream t=1..50 into both. 12// Forecast h=5 steps ahead: truth y_55 = 100 + 5*55 = 375. 13// At step 50: y_50 = 350. 14// Holt forecast(5) ~ y_50 + 5*trend = 350 + 25 = 375 (matches truth) 15// EWMA forecast = y_50 ~ 350 (flat extrapolation; lags by 25) 16// 17// MEASUREMENT: 18// ACCURACY axis vs truth 375. 19 20import "syscalls.nx" 21import "sketch_holt.nx" 22import "sketch_ewma.nx" 23import "sketch_comparator.nx" 24import "sketch_types.nx" 25 26func iabs_he(x: i64) -> i64 { 27 if x < 0 { return -x } 28 return x 29} 30 31func main() -> i64 { 32 let alpha_ppm: i64 = 300000 // 0.3 33 let beta_ppm: i64 = 200000 // 0.2 trend smoothing 34 35 let holt: *Holt = nx_holt_alloc(alpha_ppm, beta_ppm) 36 let ewma: *Ewma = nx_ewma_alloc(alpha_ppm) 37 if holt == (0 as *Holt) { return __syscall(93, 1, 0, 0, 0, 0, 0) } 38 if ewma == (0 as *Ewma) { return __syscall(93, 2, 0, 0, 0, 0, 0) } 39 40 // ---- Stream trended series y_t = 100 + 5*t ---- 41 var t: i64 = 1 42 while t <= 50 { 43 let y: i64 = 100 + 5 * t 44 nx_holt_add(holt, y) 45 nx_ewma_add(ewma, y) 46 t = t + 1 47 } 48 49 // ---- Forecast 5 steps ahead ---- 50 let truth: i64 = 100 + 5 * 55 // 375 51 let holt_fc: i64 = nx_holt_forecast(holt, 5) 52 let ewma_fc: i64 = nx_ewma_value(ewma) // flat forecast = current level 53 54 // ---- Sanity: both produced reasonable values ---- 55 if holt_fc <= 0 { return __syscall(93, 5, 0, 0, 0, 0, 0) } 56 if ewma_fc <= 0 { return __syscall(93, 6, 0, 0, 0, 0, 0) } 57 58 // ---- ACCURACY: Holt closer to truth=375 ---- 59 let acc: *ComparisonResult = nx_cmp_accuracy(holt_fc, ewma_fc, truth, 10000) 60 if acc.verdict != NX_CMP_VERDICT_BEATS { 61 return __syscall(93, 10, 0, 0, 0, 0, 0) 62 } 63 // Holt should be materially closer (EWMA lags by ~25 on slope=5,h=5). 64 if acc.delta_ppm < 30000 { // require >=3% improvement-of-truth 65 return __syscall(93, 11, 0, 0, 0, 0, 0) 66 } 67 68 // ---- Sanity: Holt's forecast within 10% of truth ---- 69 if iabs_he(holt_fc - truth) > (truth * 10) / 100 { 70 return __syscall(93, 20, 0, 0, 0, 0, 0) 71 } 72 // ---- Sanity: EWMA forecast is materially BELOW truth (lag confirmed) ---- 73 if ewma_fc >= truth { 74 // EWMA shouldn't beat truth -- it lags 75 return __syscall(93, 30, 0, 0, 0, 0, 0) 76 } 77 78 return 0 79}