17 using System.Collections.Generic;
19 using MathNet.Numerics;
20 using MathNet.Numerics.LinearAlgebra.Double;
21 using MathNet.Numerics.LinearRegression;
36 private List<double> _residuals;
37 private readonly
bool _intercept;
44 private readonly
int _diffOrder;
49 private readonly
int _arOrder;
54 private readonly
int _maOrder;
74 public override bool IsReady => _rollingData.IsReady;
111 bool intercept =
true
115 if (arOrder < 0 || maOrder < 0)
117 throw new ArgumentException(
"AR/MA orders cannot be negative.");
122 throw new ArgumentException(
"arOrder (p) must be greater than zero for all " +
123 "currently available fitting methods.");
126 if (period < Math.Max(arOrder, maOrder))
128 throw new ArgumentException(
"Period must exceed both arOrder and maOrder");
133 _diffOrder = diffOrder;
136 _intercept = intercept;
159 : this($
"ARIMA(({arOrder}, {diffOrder}, {maOrder}), {period}, {intercept})", arOrder, diffOrder, maOrder,
170 _rollingData.Reset();
180 _rollingData.Add((
double)input.
Value);
181 if (_rollingData.IsReady)
183 var arrayData = _rollingData.ToArray();
185 TwoStepFit(arrayData);
189 for (var i = 0; i < _arOrder; i++)
197 for (var i = 0; i < _maOrder; i++)
199 summants +=
MaParameters[i] * _residuals[_maOrder + i + 1];
207 var dataCast = arrayData.ToList();
208 dataCast.Insert(0, summants);
212 return (decimal)summants;
228 private void TwoStepFit(
double[] series)
230 _residuals =
new List<double>();
233 var lags = _arOrder > 0 ?
LaggedSeries(_arOrder, series) : new[] {series};
235 AutoRegressiveStep(lags, series, errorAr);
242 MovingAverageStep(lags, series, errorMa);
251 private void MovingAverageStep(
double[][] lags,
double[] data,
double errorMa)
253 var appendedData =
new List<double[]>();
254 var laggedErrors =
LaggedSeries(_maOrder, _residuals.ToArray());
255 for (var i = 0; i < laggedErrors.Length; i++)
257 var doubles = lags[i].ToList();
258 doubles.AddRange(laggedErrors[i]);
259 appendedData.Add(doubles.ToArray());
262 var maFits = Fit.MultiDim(appendedData.ToArray(), data.Skip(_maOrder).ToArray(),
263 method: DirectRegressionMethod.NormalEquations, intercept: _intercept);
264 for (var i = _maOrder; i < data.Length; i++)
266 var paramVector = _intercept
267 ? Vector.Build.Dense(maFits.Skip(1).ToArray())
268 : Vector.Build.Dense(maFits);
269 var residual = data[i] - Vector.Build.Dense(appendedData[i - _maOrder]).DotProduct(paramVector);
270 errorMa += Math.Pow(residual, 2);
276 MaResidualError = errorMa / (data.Length - Math.Max(_arOrder, _maOrder) - 1);
282 MaResidualError = errorMa / (data.Length - Math.Max(_arOrder, _maOrder) - 1);
295 private void AutoRegressiveStep(
double[][] lags,
double[] data,
double errorAr)
299 arFits = Fit.MultiDim(lags, data.Skip(_arOrder).ToArray(),
300 method: DirectRegressionMethod.NormalEquations);
301 var fittedVec = Vector.Build.Dense(arFits);
303 for (var i = 0; i < data.Length; i++)
311 var residual = data[i] - Vector.Build.Dense(lags[i - _arOrder]).DotProduct(fittedVec);
312 errorAr += Math.Pow(residual, 2);
313 _residuals.Add(residual);