public override TimeSeries BuildForecasts(TimeSeries simulatedData, List <DateTime> futureTimes) { // fit model first, using maximum likelihood estimation var model = new ARMAModel(mAROrder, mMAOrder); // create the model object model.TheData = simulatedData; // this is the data we want to fit the model to model.FitByMLE(mNumberIterLDS, mNumberIterOpt, 0, null); // first param is # low discrepancy sequence iterations, should be at least about 200 // second param is # standard optimizer iterations, should be at least about 100 // now do some forecasting beyond the end of the data var forecaster = new ForecastTransform(); forecaster.FutureTimes = futureTimes.ToArray(); // these are future times at which we want forecasts // for now, ARMA models do not use the times in any meaningful way when forecasting, // they just assume that these are the timestamps for the next sequential points // after the end of the existing time series forecaster.SetInput(0, model, null); // the ARMA model used for forecasting forecaster.SetInput(1, simulatedData, null); // the original data // normally you would call the Recompute() method of a transform, but there is no need // here; it is automatically called as soon as all inputs are set to valid values (in the 2 statements above) var predictors = forecaster.GetOutput(0) as TimeSeries; return(predictors); }
// given a file, x attr, y attr, date delimiter, has time boolean, how many values to include in the model, how many to predict, // whether the data should be reversed to have the dates increasing, and the significance level for the stationarity test, // the predicted values, the actual values, and the MAE, RMSE, and MAPE errors. public static void forecasttest(string file, string outfile, string xattr, char delimiter, bool hastime, bool change, double split, bool reverse, double siglevel, bool log) { var data = GetData(file, xattr, hastime).Select(a => TimeSeriesWrapper.getDataObject(a, change)); if (reverse) { data = data.Reverse(); } var splitData = DivideData(data.ToArray(), split); TimeSeriesWrapper ts = new TimeSeriesWrapper(); ARMAModel model = ts.buildARMAModel(splitData.Item1.ToArray(), siglevel, -1, log: log); List <DateTime> futureTimes = splitData.Item2.Select(a => a.Date).ToList(); TimeSeries mergedtimeseries = ts.predictARMA(futureTimes, model); var points = GetPoints(mergedtimeseries, splitData); ChartPoints(file.Split('/').Last(), points.Item1, points.Item2); double[] errresults = TimeSeriesWrapper.evaluatePrediction(mergedtimeseries, splitData.Item2, outfile); Console.WriteLine("Mean absolute error (MAE): " + errresults[0]); Console.WriteLine("Root mean squared error (RMSE): " + errresults[1]); Console.WriteLine("Mean absolute percentage error (MAPE): " + errresults[2]); }
public void ArmaFromExtData() { var arma = new ARMAModel(1, 1, _extData); Assert.IsTrue(arma.CanUseMLE()); arma.FitByMLE(200, 100, 0, null); Write($"Sample mean: {_extData.SampleMean()}, From model: {arma.Mu} \n"); Write($"Desc: {arma.Description}"); }
public void ArmaSimulates() { var _arma = new ARMAModel(1, 1); var simulateData = _arma.SimulateData(_dates, 22); Assert.NotNull(simulateData); Assert.IsTrue(simulateData.Count > 0); Write($"Sample mean: {simulateData.SampleMean()}"); _arma.TheData = simulateData; // Feed back in _arma.FitByMLE(200, 100, 0, null); Write(_arma.Description); }
protected override TimeSeries _BuildOutput(TimeSeries simulatedData, object userState = null) { ARMAModel model = new ARMAModel(mAROrder, mMAOrder); model.SetInput(0, simulatedData, null); //Maximum Likelihood Estimation model.FitByMLE(mNumberIterLDS, mNumberIterOpt, 0, null); // first param is # low discrepancy sequence iterations, should be at least about 200 // second param is # standard optimizer iterations, should be at least about 100 //Compute the residuals model.ComputeResidualsAndOutputs(); //model1.GetOutputName(3); //model1.Description; //Get the predicted values return(model.GetOutput(3) as TimeSeries); }
// forecasts values for the given dates from the model public TimeSeries predictARMA(List <DateTime> futureTimes, ARMAModel model) { var forecaster = new ForecastTransform(); forecaster.FutureTimes = futureTimes.ToArray(); forecaster.SetInput(0, model, null); forecaster.SetInput(1, model.TheData, null); var predictors = forecaster.GetOutput(0) as TimeSeries; // now we need to merge the forecast time series and the original time series with the original data var merger = new MergeTransform(); merger.SetInput(0, model.TheData, null); merger.SetInput(1, predictors, null); merger.Recompute(); return(merger.GetOutput(0) as TimeSeries); }
public bool AuxiliaryFunction(int index, out object output) { var approx = new ARMAModel(0, maxLag); // we should be able to get close with an MA var hlds = new HaltonSequence(maxLag); double bestError = double.MaxValue; var bestMAPolynomial = Vector <double> .Build.Dense(maxLag);//new Polynomial(maxLag); for (int i = 0; i < 200000; ++i) { var cube = hlds.GetNext(); // this is the MA part to try in the ARMA var curCube = approx.ParameterToCube(approx.Parameters); // el. 0=mu, el. 1=d, el. 2=sigma for (int j = 0; j < maxLag; ++j) { curCube[j + 3] = cube[j]; } approx.SetParameters(approx.CubeToParameter(curCube)); // now compare autocorrelation function (don't care about mean or sigma) var acf = approx.ComputeACF(maxLag, true); double error = 0; for (int j = 0; j < maxLag; ++j) { error += Math.Abs(acf[j + 1] - Rho(j)); } if (error < bestError) { bestError = error; bestMAPolynomial = approx.GetMAPolynomial(); } } approx.SetMAPolynomial(bestMAPolynomial); approx.Mu = Mu; output = approx; return(true); }
public ArmaEngine() { armaModel = new ARMAModel(4, 2); }
// 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); }
// given a file, x attr, y attr, date delimiter, has time boolean, how many values to include in the model, how many to predict, // whether the data should be reversed to have the dates increasing, and the significance level for the stationarity test, // the predicted values, the actual values, and the MAE, RMSE, and MAPE errors. public void forecasttest(string file, string outfile, string xattr, char delimiter, bool hastime, bool change, double inmodel, double numpredict, bool reverse, double siglevel, bool log) { CSVReader reader = new CSVReader(); string[] headers = reader.getHeaders(file, ','); int xindex = -1; for (int j = 0; j < headers.Length; j++) { if (String.Compare(headers[j], xattr) == 0) { xindex = j; } } List <String[]> data = new List <String[]>(); data = reader.getData(xindex, 0, file, ',', hastime); if (numpredict < 1) { numpredict = (int)(data.Count * numpredict); } if (inmodel < 1) { inmodel = (int)(data.Count * inmodel); } int trainnum = (int)inmodel; Console.WriteLine("Model will contain " + trainnum.ToString() + " events."); List <double> predicted = new List <double>(); TimeSeriesWrapper ts = new TimeSeriesWrapper(); DataObject[] series = new DataObject[1]; if (reverse) { data.Reverse(); series = ts.getSeries(data, trainnum, change); } else { series = ts.getSeries(data, trainnum, change); } ARMAModel model = ts.beginARMAProcess(series, siglevel, -1, log: log); DataObject[] Y = series; List <DateTime> futureTimes = new List <DateTime>(); int totaldata = trainnum + (int)numpredict; DateTime last = ((TimeSeries)model.TheData).GetLastTime(); Console.WriteLine(last.ToString()); DataObject[] yactual = ts.getSeries(data, (int)numpredict, change, start: trainnum); for (int t = 0; t < yactual.Length; ++t) { futureTimes.Add(yactual[t].Date); } var mergedtimeseries = ts.predictARMA(futureTimes, model); double[] errresults = TimeSeriesWrapper.evaluatePrediction(mergedtimeseries, yactual, futureTimes, outfile, trainnum); Console.WriteLine("Mean absolute error (MAE): " + errresults[0].ToString()); Console.WriteLine("Root mean squared error (RMSE): " + errresults[1].ToString()); Console.WriteLine("Mean absolute percentage error (MAPE): " + errresults[2].ToString()); }