moving-average-arima
Version:
ARIMA, SARIMA, SARIMAX and AutoARIMA models for time series analysis and forecasting
111 lines (110 loc) • 5.62 kB
JavaScript
;
var ARIMA = require('.');
var test = require('tape');
function mse(yt, yp) {
return yt.reduce(function (a, v, i) { return a + Math.pow(v - yp[i], 2) / yt.length; }, 0);
}
function rmse(yt, yp) {
return Math.sqrt(mse(yt, yp));
}
function uniq(arr) {
var uniq = [];
arr.forEach(function (v) {
if (!uniq.includes(v)) {
uniq.push(v);
}
});
return uniq;
}
test('Old API', function (_) {
var 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];
var tstest = [417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432];
var N = 50;
var _a = ARIMA(ts, tstest.length, {
p: 0,
d: 1,
q: 1,
P: 0,
D: 1,
Q: 1,
s: 12,
verbose: false
}), pred = _a[0], errors = _a[1];
var loss = rmse(pred, tstest);
_.true(loss < 22);
_.end();
});
test('SARIMA', function (_) {
var 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];
var tstest = [417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432];
var N = 50;
var losses = [];
for (var i = 0; i < N; i++) {
var arima = new ARIMA({
p: 0,
d: 1,
q: 1,
P: 0,
D: 1,
Q: 1,
s: 12,
verbose: false
});
arima.fit(ts);
var res = arima.predict(12);
losses.push(rmse(res[0], tstest));
}
var ul = uniq(losses);
_.equal(ul.length, 1);
_.true(Math.max.apply(Math, ul) < 22);
_.end();
});
test('AutoARIMA', function (_) {
var 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];
var tstest = [17.4, 17.4, 17.0001, 18.0001, 18.2001, 17.5999, 17.7996, 17.6992, 17.2002, 17.4027];
var N = 10;
var losses = [];
for (var i = 0; i < N; i++) {
var arima = new ARIMA({
auto: true,
verbose: false,
search: 0,
aproximation: 0
});
arima.fit(ts);
var res = arima.predict(10);
losses.push(rmse(res[0], tstest));
}
var ul = uniq(losses);
_.equal(ul.length, 1);
_.true(Math.max.apply(Math, ul) < 1);
_.end();
});
test('SARIMAX with 2 exogenous variables', function (_) {
var N = 30;
var f = function (a, b) { return a * 2 + b * 5; };
var losses = [];
for (var i = 0; i < N; i++) {
var exog = Array(30).fill(0).map(function (x) { return [Math.random(), Math.random()]; });
var exognew = Array(10).fill(0).map(function (x) { return [Math.random(), Math.random()]; });
var ts = exog.map(function (x) { return f(x[0], x[1]) + Math.random() / 5; });
for (var j = 0; j < 10; j++) {
var arima = new ARIMA({
p: 1,
d: 0,
q: 1,
transpose: true,
verbose: false
});
arima.fit(ts, exog);
var res = arima.predict(10, exognew);
var ytrue = exognew.map(function (x) { return f(x[0], x[1]); });
var ypred = res[0];
losses.push(rmse(ytrue, ypred));
}
}
var ul = uniq(losses);
_.equal(ul.length, N);
_.true(Math.max.apply(Math, ul) < 2);
_.end();
});