adf function

ADFResult adf(
  1. List<double> x, {
  2. int? maxLags,
})

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);
}