quantlab.analysis.factor_report#

Alphalens-style factor analysis over a (timestamp, symbol) panel.

The analysis asks how well a factor orders symbols by their forward return. It pairs every analyzed factor variable with every forward-return variable (a fret) and reports three groups of metrics, following the alphalens library:

  • Information analysis. The IC (information coefficient) of a period is the Spearman rank correlation between the factor and the forward return across the symbols of that timestamp. The report gives the IC series, its mean, standard deviation, IR (mean over standard deviation), t-statistic and p-value against zero, skew, excess kurtosis and monthly means.

  • Returns analysis. At every timestamp the symbols are split into equal-count quantile buckets by factor value (bucket 1 holds the lowest values). The report gives the mean forward return per bucket and period, the top-minus- bottom spread, and cumulative returns per bucket and for the long-short spread.

  • Turnover analysis. Quantile turnover is the fraction of symbols in a bucket that were not in that bucket at the previous timestamp. Rank autocorrelation is the Spearman correlation of the factor with itself one period earlier; a value near 1 means a slowly changing factor.

FactorAnalyzer computes the metrics, FactorReportFigure draws one composite matplotlib figure per pair, and FactorAnalysis holds the results and writes them to disk. With two or more factor variables the analysis also holds their FactorCorrelation (quantlab.analysis.factor_correlation). Factor.analyze is the usual entry point. The inputs are xarray panels; the results are small tidy pandas tables. matplotlib is imported only when a figure is drawn.

Examples#

The method examples in this module share this session: a signal over 20 symbols and 100 days, and a one-bar forward return it partly predicts.

>>> rng = np.random.default_rng(0)
>>> coords = {"timestamp": pd.date_range("2024-01-01", periods=100),
...           "symbol": [f"S{i}" for i in range(20)]}
>>> raw = rng.normal(size=(100, 20))
>>> signal = xr.DataArray(raw, coords=coords, dims=("timestamp", "symbol"))
>>> ret = xr.DataArray(0.01 * (0.3 * raw + rng.normal(size=(100, 20))),
...                    coords=coords, dims=("timestamp", "symbol"))
>>> pair = FactorAnalyzer().analyze_pair(signal, ret, "signal", "ret_1")
>>> analysis = FactorAnalysis(pairs={pair.key: pair},
...                           figures={pair.key: FactorReportFigure().render(pair)})
>>> round(pair.summary["ic_mean"], 4)
0.2384

Classes

FactorAnalysis

The result of Factor.analyze: one PairAnalysis per pair.

FactorAnalyzer

Compute alphalens-style metrics of factor variables against frets.

FactorReportFigure

Draw one composite matplotlib figure of a PairAnalysis.

Fret

A forward-return panel for FactorAnalyzer.analyze_panels.

PairAnalysis

Metrics of one factor variable against one forward-return variable.

Functions

long_short_statistics

Return annualized statistics of a per-bar long-short return series.

most_common_spacing

Return the most common spacing between consecutive timestamps.

newey_west_lags

Return the Newey-West lag count used for a mean IC.

newey_west_t_stat

Return the t-statistic of the mean of values and its two-sided p-value.

pair_cumulative_ic

Return the running sum of ic with missing periods counted as 0.