adf function
Implementation
ADFResult adf(List<double> x, {int? maxLags}) {
final n = x.length;
if (n < 10) return ADFResult(double.nan, 0);
final d = List<double>.generate(n - 1, (i) => x[i + 1] - x[i]);
final y1 = x.sublist(0, n - 1);
final y = x.sublist(1);
final k = maxLags ?? math.max(0, (math.pow(n / 100.0, 0.25)).floor());
final rows = y.length - k;
if (rows <= 2) return ADFResult(double.nan, k);
final X = List.generate(rows, (_) => <double>[]);
final yy = List<double>.filled(rows, 0.0);
for (int t = k; t < y.length; t++) {
final r = <double>[1.0, y1[t]]; // sabit + y_{t-1}
for (int i = 1; i <= k; i++) r.add(d[t - i]);
X[t - k] = r;
yy[t - k] = y[t];
}
final beta = _solveOLS(X, yy); // beta[1] ~ y_{t-1} katsayısı
final kcols = X[0].length;
final yhat = List<double>.generate(rows, (i) {
var s = 0.0;
for (int j = 0; j < kcols; j++) s += X[i][j] * beta[j];
return s;
});
var sse = 0.0;
for (int i = 0; i < rows; i++) {
final e = yy[i] - yhat[i];
sse += e * e;
}
final sigma2 = sse / math.max(1, rows - kcols);
// XtX^-1 için basit yeniden kurulum
final XtX = List.generate(kcols, (_) => List<double>.filled(kcols, 0.0));
for (int i = 0; i < rows; i++) {
for (int a = 0; a < kcols; a++) {
for (int b = 0; b < kcols; b++) XtX[a][b] += X[i][a] * X[i][b];
}
}
// Gauss-Jordan inverse
final inv = List.generate(kcols, (i) => List<double>.filled(kcols, 0.0));
for (int i = 0; i < kcols; i++) inv[i][i] = 1.0;
final A = List.generate(kcols, (i) => List<double>.from(XtX[i]));
for (int i = 0; i < kcols; i++) {
int piv = i;
double mx = A[i][i].abs();
for (int r = i + 1; r < kcols; r++) {
final v = A[r][i].abs();
if (v > mx) {
mx = v;
piv = r;
}
}
if (piv != i) {
final tmp = A[i];
A[i] = A[piv];
A[piv] = tmp;
final tmp2 = inv[i];
inv[i] = inv[piv];
inv[piv] = tmp2;
}
final dgg = A[i][i].abs() < 1e-18 ? (A[i][i] >= 0 ? 1e-18 : -1e-18) : A[i][i];
for (int c = 0; c < kcols; c++) {
A[i][c] /= dgg;
inv[i][c] /= dgg;
}
for (int r = 0; r < kcols; r++) {
if (r == i) continue;
final f = A[r][i];
for (int c = 0; c < kcols; c++) {
A[r][c] -= f * A[i][c];
inv[r][c] -= f * inv[i][c];
}
}
}
final seAlpha = math.sqrt((sigma2.abs()) * inv[1][1].abs());
final tau = beta[1] / (seAlpha == 0 ? 1e-9 : seAlpha);
return ADFResult(tau, k);
}