Stats TimeSeries serialcorrelation autocorrelation - CyrilB1531/lodestar GitHub Wiki

Home โ€บ Stats-TimeSeries โ€บ Serial correlation

SerialCorrelation.Autocorrelation

The autocorrelation function, with its confidence band.

public static AutocorrelationResult Autocorrelation(ReadOnlySpan<double> series, int lagCount, AutocorrelationOptions options = null)

Parameters โ€” series are the observations, in time order. lagCount is how many lags past zero to report โ€” required rather than defaulted, because the reference defaults it to two different rules depending on which function is asked: min(10ยทlog10(n), n - 1) here, and min(10ยทlog10(n), n/2 - 1) for PartialAutocorrelation โ€” a default that differs between two functions read side by side is a trap, so pass either rule deliberately to reproduce a reference plot. options chooses the estimator, the band shape and its level, or null for the defaults.

Returns โ€” AutocorrelationResult: the correlation at each lag from zero upward, and the band around it.

Exceptions โ€” ArgumentException when series holds fewer than two points, is constant, or carries a non-finite value; or when lagCount reaches series.Length. ArgumentOutOfRangeException when lagCount is below one.

Example โ€” a sawtooth series, and its first four lags.

using Lodestar.Stats.TimeSeries;

double[] series = [1.0, 3.0, 2.0, 5.0, 4.0, 7.0, 6.0, 9.0, 8.0, 11.0, 10.0, 13.0];

AutocorrelationResult result = SerialCorrelation.Autocorrelation(series, lagCount: 4);

double r1 = Math.Round(result.Values[1], 4);              // => 0.5922
double lower1 = Math.Round(result.ConfidenceLower[1], 4);  // => 0.0264
double upper1 = Math.Round(result.ConfidenceUpper[1], 4);  // => 1.158

Remarks โ€” the autocovariance is a direct double sum, where the reference's acf defaults to fft=True. Measured on this branch's own fixtures (tools/generate_oracles.py's _timeseries_fixtures) against statsmodels 0.15.0 directly: the largest gap between acf(x, nlags=m, adjusted=True, fft=False) and the same call with fft=True is 4.44e-16 โ€” two units in the last place of a double, an ordering difference in how the same sum is accumulated, not a definitional one. The oracle corpus itself is generated at fft=False and compares at 1e-9 (docs/equivalence.md), well above either figure, so nothing here is masked by a looser tolerance than the one that would catch a real disagreement.

A constant series is refused. The reference answers NaN with a warning; this throws, as KruskalWallis.Test already refuses a fully tied pooled sample for the same reason โ€” avf[0] is zero, so every ratio would be 0/0.

using Lodestar.Stats.TimeSeries;

string message = "nothing was thrown";
try
{
    SerialCorrelation.Autocorrelation([5.0, 5.0, 5.0], 1);
}
catch (ArgumentException error)
{
    message = error.Message;
}

string what = message;   // => every value is 5โ€ฆ

Adjusted divides by a smaller denominator at every lag past zero. Adjusted = true divides lag k by n - k rather than by n; lag zero divides by n either way, since n - 0 is n.

using Lodestar.Stats.TimeSeries;

double[] series = [1.0, 3.0, 2.0, 5.0, 4.0, 7.0, 6.0, 9.0, 8.0, 11.0, 10.0, 13.0];

AutocorrelationResult biased = SerialCorrelation.Autocorrelation(series, lagCount: 4);
AutocorrelationResult adjusted = SerialCorrelation.Autocorrelation(
    series, lagCount: 4, new AutocorrelationOptions { Adjusted = true });

double r1Biased = Math.Round(biased.Values[1], 4);      // => 0.5922
double r1Adjusted = Math.Round(adjusted.Values[1], 4);  // => 0.646

The flat, non-Bartlett band applies at lag zero too. Bartlett's formula โ€” the default โ€” is exactly zero at lag zero, so ConfidenceLower[0] and ConfidenceUpper[0] are both 1, the point the reference also reports. BartlettConfidenceInterval = false uses a flat variance of 1/n at every lag, lag zero included, because the reference's own non-Bartlett variance is a scalar applied uniformly โ€” this surprised task 5 of #617 enough to earn its own test.

using Lodestar.Stats.TimeSeries;

double[] series = [1.0, 3.0, 2.0, 5.0, 4.0, 7.0, 6.0, 9.0, 8.0, 11.0, 10.0, 13.0];

AutocorrelationResult defaultBand = SerialCorrelation.Autocorrelation(series, lagCount: 4);
AutocorrelationResult flatBand = SerialCorrelation.Autocorrelation(
    series, lagCount: 4, new AutocorrelationOptions { BartlettConfidenceInterval = false });

bool defaultLagZeroIsAPoint = defaultBand.ConfidenceLower[0] == defaultBand.ConfidenceUpper[0];  // => True
bool flatLagZeroIsAPoint = flatBand.ConfidenceLower[0] == flatBand.ConfidenceUpper[0];            // => False

Applies to โ€” net10.0, netstandard2.0.

See also โ€” SerialCorrelation.PartialAutocorrelation, SerialCorrelation.LjungBox, AutocorrelationOptions, the Python equivalence table.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ