Class SpreadForecaster
java.lang.Object
com.quantfinlib.microstructure.SpreadForecaster
Short-term spread prediction. The bid/ask spread an execution algo will
pay in a few seconds is well modelled by two components a live feed gives
you for free:
- A time-of-day baseline — spreads are wide at the open, tight
midday, wide into the close (and, in FX, wide across the rollover /
thin liquidity hours). Each session accumulates a per-bucket mean;
rollDay()folds it into the baseline with thedayAlphaday-over-day EWMA (the first session seeds it directly) — the spread analogue ofVolumeCurve; - A fast mean-reverting deviation — the current spread relative
to its time-of-day baseline, blended per observation with
DEVIATION_ALPHAand decayed toward 0 with the configured half-life. Spreads spike on events and revert; blending the live deviation with the baseline forecasts the near-term spread better than either alone.
forecast(int, long) returns the predicted spread over the next moment —
the BenchmarkExecutor.MarketState.spread input, projected rather
than merely observed, so the algo damps aggression before a
known-wide window (the close) instead of reacting after. Before the first
rollDay() there is no learned baseline yet, so the forecast
degrades honestly to the last observed spread. Volatility is the
correlated cousin — a wide-spread forecast usually coincides with high
volPerSqrtSecond from SignalEngine, and an algo should
treat both as timing-cost signals. Cross-asset, zero allocation, single
writer.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final doublePer-observation blend weight of the live deviation (distinct fromdayAlpha, which is the DAY-over-day baseline weight — the two timescales must not share a knob). -
Constructor Summary
ConstructorsConstructorDescription78 equity buckets, 10% day weight, 5-second reversion.SpreadForecaster(int buckets, double dayAlpha, long deviationHalfLifeNanos) -
Method Summary
Modifier and TypeMethodDescriptiondoublebaseline(int bucket) The learned time-of-day baseline spread for a bucket (0 until learned).intbuckets()doublecurrentDeviation(long nowNanos) Current deviation from baseline (decayed to now).intdoubleforecast(int bucket, long nowNanos) Forecast spread atbucketas ofnowNanos: the learned time-of-day baseline plus the mean-reverting live deviation.voidonSpread(int bucket, double spread, long timestampNanos) Observed spread atbucket.voidRestores the learned baseline; the intraday deviation, last observed spread and today's accumulation reset (restore at session start).voidrollDay()Closes the session: folds today's per-bucket mean spreads into the baseline with the day-over-day EWMA (buckets with no observations keep their learned value) and resets the intraday state.seedBaseline(double[] spreadPerBucket) Seeds the time-of-day baseline from a known shape — optional.voidwriteState(DataOutput out) Persists the learned baseline (cross-day state) — seepersist.Checkpoint.
-
Field Details
-
DEVIATION_ALPHA
public static final double DEVIATION_ALPHAPer-observation blend weight of the live deviation (distinct fromdayAlpha, which is the DAY-over-day baseline weight — the two timescales must not share a knob).- See Also:
-
-
Constructor Details
-
SpreadForecaster
public SpreadForecaster(int buckets, double dayAlpha, long deviationHalfLifeNanos) - Parameters:
buckets- time buckets per session (e.g. 78 for equities, 288 for a 24h FX day)dayAlpha- baseline EWMA weight across days, e.g. 0.1deviationHalfLifeNanos- how fast a spread shock reverts to baseline
-
SpreadForecaster
public SpreadForecaster()78 equity buckets, 10% day weight, 5-second reversion.
-
-
Method Details
-
seedBaseline
Seeds the time-of-day baseline from a known shape — optional. -
onSpread
public void onSpread(int bucket, double spread, long timestampNanos) Observed spread atbucket. Accumulates today's per-bucket mean (folded into the baseline atrollDay()) and updates the mean-reverting deviation from the learned baseline. Non-finite or negative spreads are ignored — one +∞ must not poison a bucket forever. -
rollDay
public void rollDay()Closes the session: folds today's per-bucket mean spreads into the baseline with the day-over-day EWMA (buckets with no observations keep their learned value) and resets the intraday state. Seeding is PER BUCKET — a bucket first observed on a later day (feed started mid-session, half day) seeds from its own first observation rather than EWMA-ramping from 0 and forecasting too-tight spreads at that hour for weeks. -
forecast
public double forecast(int bucket, long nowNanos) Forecast spread atbucketas ofnowNanos: the learned time-of-day baseline plus the mean-reverting live deviation. Before the firstrollDay()/seed there is no baseline, so it returns the last observed spread (the honest live estimate), or NaN before any observation at all. -
baseline
public double baseline(int bucket) The learned time-of-day baseline spread for a bucket (0 until learned). -
currentDeviation
public double currentDeviation(long nowNanos) Current deviation from baseline (decayed to now). -
writeState
Persists the learned baseline (cross-day state) — seepersist.Checkpoint.- Throws:
IOException
-
readState
Restores the learned baseline; the intraday deviation, last observed spread and today's accumulation reset (restore at session start). Throws on a bucket-count or version mismatch.- Throws:
IOException
-
buckets
public int buckets() -
daysLearned
public int daysLearned()
-