// this method fits an ARMA model to the data and returns it, in the process testing for non-stationarity and calculating the orders of the // MA and AR terms of the model public ARMAModel buildARMAModel(DataObject[] series, double siglevel, int len = 50, bool print = true, bool log = false) { bool nonstationarity = testStationarity(series, siglevel); if (print) { Console.WriteLine("non-stationarity: " + nonstationarity.ToString()); } int d = 0; if (nonstationarity) { d = 1; } var tSeries = series; //Difference the series if (d != 0) { double[] dcol = new double[tSeries.Length]; for (int i = 0; i < dcol.Length; i++) { dcol[i] = (tSeries[i].Value); } double[] xdiff = ArrayManipulation.diff(dcol); for (int i = dcol.Length - xdiff.Length; i < xdiff.Length; i++) { tSeries[i] = new DataObject(tSeries[i].Date, xdiff[i]); } } var ts = new TimeSeries { Title = "Time Series", Description = "TS Description" }; for (int i = 0; i < series.GetLength(0); i++) { ts.Add(tSeries[i].Date, (tSeries[i].Value), false); //datetime, value, false } if (log) { //log transform the time series var logTransform = new LogTransform(); logTransform.SetInput(0, ts, null); logTransform.Recompute(); ts = logTransform.GetOutput(0) as TimeSeries; } //Use ACF and PACF to find ARMA parameters var highInterval = 1.96 / Math.Sqrt(series.Length); var acf = ts.ComputeACF(20, false); int p = 1; var low = acf[0]; for (int i = 0; i < acf.Count; i++) { if (Math.Min(low, acf[i]) <= highInterval && highInterval < Math.Max(acf[i], low)) { p = i; if (p != 0) { p--; } if (p == 0) { p = 1; } break; } low = acf[i]; } var pacf = TimeSeries.GetPACFFrom(acf); int q = 1; low = pacf[0]; for (int i = 0; i < pacf.Count; i++) { if (Math.Min(low, pacf[i]) <= highInterval && highInterval < Math.Max(pacf[i], low)) { q = i; if (q != 0) { q--; } if (q == 0) { q = 1; } break; } low = pacf[i]; } if (p > 4) { p = 4; } if (q > 4) { q = 4; } if (print) { Console.WriteLine("p: " + p.ToString() + " q: " + q.ToString()); Console.WriteLine("Fitting the model..."); } var model = new ARMAModel(p, q); model.TheData = ts; Stopwatch watch = new Stopwatch(); watch.Start(); model.FitByMLE(200, 100, 0, null); watch.Stop(); if (print) { Console.WriteLine("Model took " + watch.Elapsed.TotalSeconds.ToString() + " seconds to fit parameters to the data."); Console.WriteLine("Model has been fitted."); } return(model); }