Class OnlineAlphaLearner

java.lang.Object
com.quantfinlib.microstructure.OnlineAlphaLearner

public final class OnlineAlphaLearner extends Object
Online alpha-weight learning: upgrades SignalEngine.alpha(int)'s fixed composite weights to weights learned from realized returns — an online ridge regression (SGD with L2 shrinkage) from the four dimensionless signal ingredients (queue imbalance, trade imbalance, normalized OFI, momentum-Z) to the next-interval return.

The honesty mechanism: prequential out-of-sample IC

The trap with any self-updating alpha is grading its own homework. This learner can't: train(double, double, double, double, double) records the prediction made with the CURRENT weights before the realized return updates them (predict-then-train, "prequential" evaluation), and maintains a time-decayed correlation between those genuinely out-of-sample predictions and the outcomes — outOfSampleIC(). Gate any use of the learned alpha on that number: persistently positive (intraday, ~0.02–0.10 is real) means the weights found signal; an IC hovering at zero means they found noise, and normalizedPrediction(double, double, double, double) should be treated as such. This diagnostic is a live tripwire, not a validation — before trading a weighting seriously, run it through the alpha package's walk-forward and permutation machinery like any other signal.

One instance per symbol (or one pooled across a homogeneous group — pooling trades specificity for sample count; the caller chooses). Cross-asset: ingredients are dimensionless and the target is a return. Zero allocation per event, single writer.

  • Constructor Summary

    Constructors
    Constructor
    Description
    lr 0.01, ridge 1e-4, IC memory ~200 samples.
    OnlineAlphaLearner(double learningRate, double ridgeLambda, double icAlpha)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    double
    normalizedPrediction(double queueImbalance, double tradeImbalance, double normalizedOfi, double momentumZ)
    The prediction scaled by its own typical magnitude and clamped to [-1, 1] — the BenchmarkExecutor.MarketState.alpha-ready form.
    double
    The prequential (out-of-sample) information coefficient: time-decayed correlation between the predictions made BEFORE each outcome and the outcomes themselves.
    double
    predict(double queueImbalance, double tradeImbalance, double normalizedOfi, double momentumZ)
    The learned prediction of the next-interval return from the four SignalEngine ingredients (each expected in ~[-1, 1]).
    double
    predictFrom(SignalEngine engine, int symbolId)
    predict(double, double, double, double) pulling the ingredients straight from a SignalEngine.
    void
    Restores weights and IC evidence; the trainFrom feature snapshot is intraday state and resets.
    long
     
    void
    train(double queueImbalance, double tradeImbalance, double normalizedOfi, double momentumZ, double realizedReturn)
    One learning step: the prediction made with the current weights is scored against realizedReturn (this is what makes outOfSampleIC() honest), THEN the weights update by ridge-SGD.
    void
    trainFrom(SignalEngine engine, int symbolId, double realizedReturn)
    The aligned learning step over a SignalEngine: trains on the ingredients snapshotted at the PREVIOUS call (which predate the interval realizedReturn covers), then snapshots the current ingredients for the next call.
    double
    weight(int i)
    The learned weight for feature i (0=queueImb, 1=tradeImb, 2=OFI, 3=momZ).
    void
    Persists the weights AND the prequential IC evidence — restored trust must be earned trust: a learner reloaded without its IC history would start silent again (normalizedPrediction(double, double, double, double) gates on the IC), which is exactly right for weights with no demonstrated track record.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • OnlineAlphaLearner

      public OnlineAlphaLearner(double learningRate, double ridgeLambda, double icAlpha)
      Parameters:
      learningRate - SGD step, e.g. 0.01 — larger adapts faster, overshoots noisier targets
      ridgeLambda - L2 shrinkage toward 0 per step, e.g. 1e-4 — keeps weights from chasing one lucky streak
      icAlpha - EWMA weight of the IC statistics, e.g. 0.01 (≈ a few-hundred-sample memory)
    • OnlineAlphaLearner

      public OnlineAlphaLearner()
      lr 0.01, ridge 1e-4, IC memory ~200 samples.
  • Method Details

    • predict

      public double predict(double queueImbalance, double tradeImbalance, double normalizedOfi, double momentumZ)
      The learned prediction of the next-interval return from the four SignalEngine ingredients (each expected in ~[-1, 1]). Raw units = whatever return you train against.
    • predictFrom

      public double predictFrom(SignalEngine engine, int symbolId)
      predict(double, double, double, double) pulling the ingredients straight from a SignalEngine.
    • train

      public void train(double queueImbalance, double tradeImbalance, double normalizedOfi, double momentumZ, double realizedReturn)
      One learning step: the prediction made with the current weights is scored against realizedReturn (this is what makes outOfSampleIC() honest), THEN the weights update by ridge-SGD. Non-finite inputs are skipped entirely — a NaN must neither poison the weights nor sneak into the IC.

      Alignment is the caller's contract here: the four features must have been observed BEFORE the interval realizedReturn covers. Passing the current features with the return that just ended fits a nowcast — the features already contain the move — and the IC will read high on pure leakage. trainFrom(com.quantfinlib.microstructure.SignalEngine, int, double) handles this alignment automatically; use it unless you keep your own snapshots.

    • trainFrom

      public void trainFrom(SignalEngine engine, int symbolId, double realizedReturn)
      The aligned learning step over a SignalEngine: trains on the ingredients snapshotted at the PREVIOUS call (which predate the interval realizedReturn covers), then snapshots the current ingredients for the next call. The first call only snapshots — there is nothing aligned to train on yet. Call once per interval, with the return realized since the previous call; feeding it the current features directly would let the momentum echo of the return grade itself (see train(double, double, double, double, double)).
    • outOfSampleIC

      public double outOfSampleIC()
      The prequential (out-of-sample) information coefficient: time-decayed correlation between the predictions made BEFORE each outcome and the outcomes themselves. The gate for using the learned alpha; 0 before enough variance exists to measure.
    • normalizedPrediction

      public double normalizedPrediction(double queueImbalance, double tradeImbalance, double normalizedOfi, double momentumZ)
      The prediction scaled by its own typical magnitude and clamped to [-1, 1] — the BenchmarkExecutor.MarketState.alpha-ready form. Returns 0 while the out-of-sample IC is not positive OR the track record is shorter than one IC memory (~1/icAlpha samples): a learner that hasn't demonstrated live predictive power over a meaningful window emits no signal — a lucky first hour is not evidence.
    • weight

      public double weight(int i)
      The learned weight for feature i (0=queueImb, 1=tradeImb, 2=OFI, 3=momZ).
    • samples

      public long samples()
    • writeState

      public void writeState(DataOutput out) throws IOException
      Persists the weights AND the prequential IC evidence — restored trust must be earned trust: a learner reloaded without its IC history would start silent again (normalizedPrediction(double, double, double, double) gates on the IC), which is exactly right for weights with no demonstrated track record.
      Throws:
      IOException
    • readState

      public void readState(DataInput in) throws IOException
      Restores weights and IC evidence; the trainFrom feature snapshot is intraday state and resets. Throws on a version mismatch.
      Throws:
      IOException