Class SignalEvaluator

java.lang.Object
com.quantfinlib.alpha.SignalEvaluator

public final class SignalEvaluator extends Object
Signal evaluation — the metrics that decide whether a factor is worth constructing a portfolio from, computed before any backtest so weak signals die cheaply:
  • IC (information coefficient) — Spearman rank correlation between scores at t and forward returns over (t, t+horizon], per evaluation date. Rank (not Pearson) because factor scores have arbitrary units and fat tails; rank IC is invariant to any monotone transform of the signal.
  • IRmean(IC) / std(IC): signal strength per unit of signal inconsistency, the standard Grinold-Kahn quality number (0.05 mean IC with steady sign beats 0.10 that flips).
  • t-statmean(IC) / (std(IC)/√n): is the mean IC distinguishable from zero given how many dates we observed.
  • Hit rate — fraction of (symbol, date) pairs where the score sign called the forward-return sign.
  • Turnover — half the L1 change in normalized weights between consecutive evaluation dates: how much trading the signal demands, the denominator of "does the alpha survive costs".
  • Factor exposure — mean cross-sectional rank correlation against another factor: a "new" signal that is 0.9 rank-correlated with momentum is momentum.

Evaluation dates step by horizon so forward-return windows don't overlap — overlapping windows inflate the t-stat through serial correlation, the classic way factor research fools itself.

  • Method Details

    • evaluate

      public static SignalEvaluator.Report evaluate(AlphaContext ctx, AlphaFactor factor, int startIndex, int horizon)
      Evaluates a factor over [startIndex, ctx.bars() − horizon), stepping by horizon (non-overlapping forward windows).
      Parameters:
      horizon - forward-return horizon in bars (also the step)
    • quantileReturns

      public static SignalEvaluator.QuantileReport quantileReturns(AlphaContext ctx, AlphaFactor factor, int startIndex, int horizon, int quantiles)
      Buckets each evaluation date's cross-section into quantiles score-ranked groups and averages the forward returns per group, over the same non-overlapping date grid as evaluate(AlphaContext, AlphaFactor, int, int): dates step by horizon from startIndex, a NaN score or NaN forward return drops that (symbol, date) pair, and a date with fewer complete pairs than quantiles contributes to no bucket at all. Bucketing is by ascending score rank (rank * quantiles / n), so groups are as equal-sized as the cross-section allows; ties are split by input order at the boundary — quantile membership, unlike the rank IC, is not fully tie-invariant, stated.
      Parameters:
      quantiles - number of buckets, ≥ 2 (5 = quintiles, 10 = deciles)
    • factorExposure

      public static double factorExposure(AlphaContext ctx, AlphaFactor a, AlphaFactor b, int startIndex, int step)
      Mean cross-sectional rank correlation between two factors' scores — how much of factor B is already inside factor A. Above ~0.7 the "new" factor adds little beyond the old one.