Class LeadLagEstimator
Feed one onSample(double, double) per fixed sampling interval with the two
instruments' returns over that interval (mid-to-mid log or simple
returns; the caller owns the sampling clock, e.g. 100 ms for FX
majors, 1 s for equities). The estimator keeps a small ring of the
leader's recent returns and, for each candidate lag
k = 0..maxLag, a time-decayed correlation between the leader's
return k intervals ago and the follower's return now.
O(maxLag) work per sample, zero allocation, single writer.
Reading the output: bestLag() is the k > 0 with the
largest |correlation|, reported only when it clears a multiple-testing
corrected significance band and exceeds the contemporaneous correlation (otherwise 0: the pair
co-moves or the lead is noise). expectedFollowerReturn() turns the best
lag into a prediction via the regression beta at that lag. Like every
streaming estimate here, treat a lead that appears and disappears with
the decay window as noise; only a persistent best lag with stable sign
is structure.
-
Constructor Summary
ConstructorsConstructorDescriptionmaxLag 10 intervals, EWMA memory ~200 samples.LeadLagEstimator(int maxLag, double alpha) -
Method Summary
Modifier and TypeMethodDescriptiondoubleThe signed correlation atbestLag(); 0 when bestLag() is 0.intbestLag()The lagk >= 1with the largest |correlation|, the estimated lead time in sampling intervals, provided it is significant and beats the contemporaneous correlation.doublecorrelationAtLag(int lag) Time-decayed correlation between the leader's returnlagintervals ago and the follower's return now. 0 until enough samples exist at that lag.doubleThe regression prediction of the follower's next-interval return from the leader's return at the best lag:beta(k) x leaderReturn[t-k+1]withbeta = cov/varLead. 0 when no lead has been measured.intmaxLag()voidonSample(double leaderReturn, double followerReturn) One sampling interval: the leader's and follower's returns over the interval that just closed.voidRestores the learned correlations; the leader ring resets, so post-restore samples never pair today's follower with yesterday's pre-close leader across the overnight gap — and lagkresumes updating only once the ring holds k+1 fresh samples, so the restored moments are never diluted by the empty ring either.longsamples()voidwriteState(DataOutput out) Persists the per-lag correlation moments — seepersist.Checkpoint.
-
Constructor Details
-
LeadLagEstimator
public LeadLagEstimator(int maxLag, double alpha) - Parameters:
maxLag- largest lead to test, in sampling intervals (e.g. 10)alpha- EWMA weight of the correlation statistics, e.g. 0.01 (≈ a few-hundred-sample memory)
-
LeadLagEstimator
public LeadLagEstimator()maxLag 10 intervals, EWMA memory ~200 samples.
-
-
Method Details
-
onSample
public void onSample(double leaderReturn, double followerReturn) One sampling interval: the leader's and follower's returns over the interval that just closed. Non-finite inputs are a gap — the sample is dropped entirely (no moment updates, ring untouched) so a bad print can't poison the correlations. Gap caveat: after a dropped interval the ring holds the last valid samples, so lagkmeans "k valid samples ago", which is more than k wall-clock intervals across the gap. On a feed that gaps often, readbestLag()as a lead in valid samples, not wall-clock time. -
correlationAtLag
public double correlationAtLag(int lag) Time-decayed correlation between the leader's returnlagintervals ago and the follower's return now. 0 until enough samples exist at that lag. -
bestLag
public int bestLag()The lagk >= 1with the largest |correlation|, the estimated lead time in sampling intervals, provided it is significant and beats the contemporaneous correlation. Returns 0 (no tradeable lead) when- fewer than 2 samples exist;
- the best |ρ_k| is within
z/√n_effof zero, withn_effthe Kish effective sample size of the EWMA (IcSignificance.effectiveSamples(double, long)) andzthe Šidák critical value formaxLagtwo-sided tests at a 5% family-wise level (z ≈ 2.80for 10 lags). An argmax overmaxLagnoise correlations always finds some lag; with a per-lag 2-SE band a 10-lag noise pair would still report a lead about 40% of the time; |ρ_0| >= |ρ_k|: the pair co-moves, neither side leads.
-
bestCorrelation
public double bestCorrelation()The signed correlation atbestLag(); 0 when bestLag() is 0. -
expectedFollowerReturn
public double expectedFollowerReturn()The regression prediction of the follower's next-interval return from the leader's return at the best lag:beta(k) x leaderReturn[t-k+1]withbeta = cov/varLead. 0 when no lead has been measured. This is a point estimate for hedging/pricing, subject to the same persistence caveat asbestLag(). -
maxLag
public int maxLag() -
samples
public long samples() -
writeState
Persists the per-lag correlation moments — seepersist.Checkpoint.- Throws:
IOException
-
readState
Restores the learned correlations; the leader ring resets, so post-restore samples never pair today's follower with yesterday's pre-close leader across the overnight gap — and lagkresumes updating only once the ring holds k+1 fresh samples, so the restored moments are never diluted by the empty ring either. Throws on a maxLag or version mismatch.- Throws:
IOException
-