UNPKG

moving-average-arima

Version:

ARIMA, SARIMA, SARIMAX and AutoARIMA models for time series analysis and forecasting

120 lines (109 loc) 4.8 kB
const ARIMA = require('.') var test = require('tape') function mse (yt, yp) { return yt.reduce((a, v, i) => a + Math.pow(v - yp[i], 2) / yt.length, 0) } function rmse (yt, yp) { return Math.sqrt(mse(yt, yp)) } function uniq (arr) { const uniq = [] arr.forEach(v => { if (!uniq.includes(v)) { uniq.push(v) } }) return uniq } test('Old API', (_) => { const ts = [112,118,132,129,121,135,148,148,136,119,104,118,115,126,141,135,125,149,170,170,158,133,114,140,145,150,178,163,172,178,199,199,184,162,146,166,171,180,193,181,183,218,230,242,209,191,172,194,196,196,236,235,229,243,264,272,237,211,180,201,204,188,235,227,234,264,302,293,259,229,203,229,242,233,267,269,270,315,364,347,312,274,237,278,284,277,317,313,318,374,413,405,355,306,271,306,315,301,356,348,355,422,465,467,404,347,305,336,340,318,362,348,363,435,491,505,404,359,310,337,360,342,406,396,420,472,548,559,463,407,362,405] const tstest = [417,391,419,461,472,535,622,606,508,461,390,432] const N = 50 const [pred, errors] = ARIMA(ts, tstest.length, { p: 0, d: 1, q: 1, P: 0, D: 1, Q: 1, s: 12, verbose: false }) const loss = rmse(pred, tstest) _.true(loss < 22) _.end() }) test('SARIMA', (_) => { const ts = [112,118,132,129,121,135,148,148,136,119,104,118,115,126,141,135,125,149,170,170,158,133,114,140,145,150,178,163,172,178,199,199,184,162,146,166,171,180,193,181,183,218,230,242,209,191,172,194,196,196,236,235,229,243,264,272,237,211,180,201,204,188,235,227,234,264,302,293,259,229,203,229,242,233,267,269,270,315,364,347,312,274,237,278,284,277,317,313,318,374,413,405,355,306,271,306,315,301,356,348,355,422,465,467,404,347,305,336,340,318,362,348,363,435,491,505,404,359,310,337,360,342,406,396,420,472,548,559,463,407,362,405] const tstest = [417,391,419,461,472,535,622,606,508,461,390,432] const N = 50 const losses = [] for (let i = 0; i < N; i++) { const arima = new ARIMA({ p: 0, d: 1, q: 1, P: 0, D: 1, Q: 1, s: 12, verbose: false }) arima.fit(ts) const res = arima.predict(12) losses.push(rmse(res[0], tstest)) } const ul = uniq(losses) _.equal(ul.length, 1) _.true(Math.max(...ul) < 22) _.end() }) test('AutoARIMA', (_) => { const ts = [16.9969, 16.5969, 16.3012, 16.1018, 17.0998, 16.8997, 16.8002, 17.4001, 17.0998, 16.9996, 16.6991, 17.3993, 17.2002, 17.4013, 17.4029, 17.0015, 17.2965, 17.1966, 17.4013, 16.802, 17.1, 17.3995, 17.3995, 17.5008, 17.3998, 17.6, 17.4, 17.3, 17, 17.8, 17.5, 18.1, 17.5, 17.4, 17.4, 17.1, 17.6, 17.7, 17.4, 17.8, 17.6, 17.5, 16.5, 17.8, 17.3, 17.3, 17.1, 17.4, 16.9, 17.3, 17.6, 16.9, 16.7, 16.8, 16.8, 17.2, 16.8, 17.6, 17.2, 16.6, 17.1, 16.9, 16.6, 18, 17.2, 17.3, 17, 16.9, 17.3, 16.8, 17.3, 17.4, 17.7, 16.8, 16.9, 17, 16.9, 17, 16.6, 16.7, 16.8, 16.7, 16.4, 16.5, 16.4, 16.6, 16.5, 16.7, 16.4, 16.4, 16.2, 16.4, 16.3, 16.4, 17, 16.9, 17.1, 17.1, 16.7, 16.9, 16.5, 17.2, 16.4, 17, 17, 16.7, 16.2, 16.6, 16.9, 16.5, 16.6, 16.6, 17, 17.1, 17.1, 16.7, 16.8, 16.3, 16.6, 16.8, 16.9, 17.1, 16.8, 17, 17.2, 17.3, 17.2, 17.3, 17.2, 17.2, 17.5, 16.9, 16.9, 16.9, 17.0001, 16.4999, 16.6996, 16.8001, 16.7013, 16.6985, 16.6005, 16.5, 17, 16.7, 16.7, 16.9, 17.4, 17.1, 17, 16.8, 17.2, 17.2, 17.4, 17.2, 16.9, 16.8, 17, 17.4, 17.2, 17.2, 17.1, 17.1, 17.1, 17.4, 17.2, 16.9, 16.9, 17, 16.7, 16.9, 17.3, 17.8, 17.8, 17.6, 17.5, 17, 16.8999, 17.1, 17.2002, 17.3998, 17.5001, 17.9, 17, 17, 17, 17.2, 17.3, 17.4] const tstest = [17.4, 17.4, 17.0001, 18.0001, 18.2001, 17.5999, 17.7996, 17.6992, 17.2002, 17.4027] const N = 10 const losses = [] for (let i = 0; i < N; i++) { const arima = new ARIMA({ auto: true, verbose: false, search: 0, aproximation: 0 }) arima.fit(ts) const res = arima.predict(10) losses.push(rmse(res[0], tstest)) } const ul = uniq(losses) _.equal(ul.length, 1) _.true(Math.max(...ul) < 1) _.end() }) test('SARIMAX with 2 exogenous variables', (_) => { const N = 30 const f = (a, b) => a * 2 + b * 5 const losses = [] for (let i = 0; i < N; i++) { const exog = Array(30).fill(0).map(x => [Math.random(), Math.random()]) const exognew = Array(10).fill(0).map(x => [Math.random(), Math.random()]) const ts = exog.map(x => f(x[0], x[1]) + Math.random() / 5) for (let j = 0; j < 10; j++) { const arima = new ARIMA({ p: 1, d: 0, q: 1, transpose: true, verbose: false }) arima.fit(ts, exog) const res = arima.predict(10, exognew) const ytrue = exognew.map(x => f(x[0], x[1])) const ypred = res[0] losses.push(rmse(ytrue, ypred)) } } const ul = uniq(losses) _.equal(ul.length, N) _.true(Math.max(...ul) < 2) _.end() })