<a id="skfolio-alpha-predictoralpha"></a>

# skfolio.alpha.PredictorAlpha

<a id="skfolio.alpha.PredictorAlpha"></a>

### *class* skfolio.alpha.PredictorAlpha(\*, predictor, descriptors, horizon=1, signal_lag=1, neutralize_against=None, outlier_transformer=None, scoring_transformer=None, target_outlier_transformer=None, target_scoring_transformer=None, transform_by_group=None, forecast_unit=IDIO_RETURN, calibrate_to_return_units=True, forecast_scale=1.0, half_life=20, cv=None, n_jobs=1)

Predictor alpha estimator using a user-provided regressor.

This estimator converts descriptors into cross-sectional scores, optionally
neutralizes those scores against factor exposures and fits a scikit-learn compatible
regressor where each observation-asset pair is one training sample. It supports
nonlinear signal combinations while keeping the final forecast in expected
idiosyncratic return units when calibration is enabled [[1]](#r221c08910397-1).

The predictor supports two forecast units. With
`forecast_unit=ForecastUnit.IDIO_RETURN`, it is fitted to the forward mean
idiosyncratic return $\epsilon_{t,i}$. With
`forecast_unit=ForecastUnit.IDIO_SHARPE`, it is fitted to
$\epsilon_{t,i} / \sigma_{t,i}$ and the forecast is multiplied by current
idiosyncratic volatility so `alpha_` remains in expected return units. This is
useful when signals are assumed to forecast idiosyncratic Sharpe rather than raw
idiosyncratic return.

When `calibrate_to_return_units=True`, the raw predictor output
$\hat a_{t,i}$ is calibrated to expected-return units with scalar
exponentially weighted least squares:

$$
\beta_t = \arg\min_\beta \sum_i
\frac{(\epsilon_{t,i} - \hat a_{t,i}\beta)^2}{\sigma_{t,i}^2}
$$

The calibration coefficient is estimated with exponentially weighted least squares:

$$
A_t^{EW} = \lambda A_{t-1}^{EW}
+ (1 - \lambda)\hat a_t^\top W_t \hat a_t
$$

$$
b_t^{EW} = \lambda b_{t-1}^{EW}
+ (1 - \lambda)\hat a_t^\top W_t \epsilon_t,
\quad \lambda = 2^{-1/\text{half-life}}
$$

and the ridge-stabilized coefficient is:

$$
\beta_t = b_t^{EW} / (A_t^{EW} + \rho_t)
$$

This produces alpha in expected return units, which is required whenever the
optimizer is trading off alpha against real costs and constraints such as
transaction costs, market impact, borrow costs, or turnover constraints.

In batch mode, calibration uses predictions from held-out CV folds when enough
samples are available. This reduces the in-sample scale inflation from fitting
and calibrating on the same predictions. These predictions are used only for
scale calibration, not as a time-series performance estimate. The default splitter
treats valid observation-asset pairs as approximately exchangeable. Pass a
date-aware or purged splitter through `cv` when the calibration itself should
enforce stricter temporal separation.

The estimator supports [`fit`](#skfolio.alpha.PredictorAlpha.fit) and [`partial_fit`](#skfolio.alpha.PredictorAlpha.partial_fit). In online mode,
samples are trained when their forward-return targets become observable,
including rows carried in the target-maturity buffer. The predictor must
support `partial_fit` after the first fitted update.

* **Parameters:**
  **predictor** *estimator*
  : Regressor that implements `fit` and `predict`. For online mode, the predictor
    must also implement `partial_fit`. The predictor receives one sample per valid
    observation-asset pair, with shape `(n_observations * n_assets, n_descriptors)`,
    and predicts the transformed target.

  **descriptors** *list of (name, estimator) tuples*
  : List of descriptors that compute signals from characteristics. Each tuple
    contains a string name and a descriptor estimator. Multiple descriptors are
    aggregated into a single alpha using multivariate regression. The descriptors
    are evaluated in parallel if `n_jobs > 1`.

  **half_life** *float, default=20*
  : Half-life of the EWLS calibration statistics in number of observations. Only
    used when `calibrate_to_return_units=True`.
    * Larger half-life: More stable alpha estimates, slower adaptation
    * Smaller half-life: More responsive estimates, faster adaptation

  **horizon** *int, default=1*
  : Number of forward periods to average for the target idiosyncratic return.
    Must be >= 1. The target for observation $t$ is
    `mean(idio_returns[t+signal_lag : t+signal_lag+horizon])`.
    * `horizon=1`: Predicts one-period idiosyncratic return starting after `signal_lag`
    * `horizon>1`: Predicts the mean of `horizon` idiosyncratic returns starting
      after `signal_lag`.

  **signal_lag** *int, default=1*
  : Number of periods between the signal observation and the first return in the
    target window. Must be >= 1. Under skfolio’s as-of time-indexing convention,
    `signal_lag=0` would use information observed at the end of $t$ to
    predict return at $t$, which is look-ahead. Values larger than 1 can
    model conservative data availability or execution delays.

  **neutralize_against** *list of str, optional*
  : Factor names or families to neutralize scores against. If provided, scores are
    orthogonalized with respect to the specified factor exposures before prediction.

  **outlier_transformer** *BaseCSTransformer or “passthrough”, optional*
  : Cross-sectional transformer for descriptor outlier handling. If `None`,
    defaults to `CSWinsorizer()`. Use `"passthrough"` to skip.

  **scoring_transformer** *BaseCSTransformer or “passthrough”, optional*
  : Cross-sectional transformer for descriptor scoring applied after outlier
    handling. If None, defaults to `CSStandardScaler()`. Use “passthrough” to skip.

  **target_outlier_transformer** *BaseCSTransformer or “passthrough”, optional*
  : Cross-sectional transformer for target outlier handling. If `None`, defaults
    to `CSWinsorizer()`. Use `"passthrough"` to skip.

  **target_scoring_transformer** *BaseCSTransformer or “passthrough”, optional*
  : Cross-sectional transformer for target scoring. If `None`, defaults to
    `"passthrough"`. The calibration stage calibrates the predictor output back
    to expected-return units when `calibrate_to_return_units=True`.

  **transform_by_group** *str, optional*
  : Name of a categorical characteristic in the AssetPanel to use for group-wise
    transformations. If provided, cross-sectional transformations are applied
    within each group separately.

  **forecast_unit** *ForecastUnit, default=ForecastUnit.IDIO_RETURN*
  : Unit of the intermediate forecast learned by the predictor. With
    `ForecastUnit.IDIO_RETURN`, the predictor is trained on forward mean
    idiosyncratic return. With `ForecastUnit.IDIO_SHARPE`, the target is divided by
    forecast idiosyncratic volatility and the resulting idiosyncratic-Sharpe
    forecast is converted back to return units by multiplying by current
    idiosyncratic volatility.

  **calibrate_to_return_units** *bool, default=True*
  : If `True`, calibrate raw predictor output to expected return units using
    scalar EWLS. If `False`, return the predictor output after any volatility
    conversion implied by `forecast_unit`.

  **forecast_scale** *float, default=1.0*
  : Multiplicative scale applied to the final alpha forecast after optional
    return-unit calibration. This controls alpha strength without changing the
    predictor or calibration coefficient estimates.

  **cv** *cross-validator, int, optional*
  : Cross-validation strategy used to obtain predictions from held-out folds for
    return-unit calibration. When `None`, uses `KFold(5)`. CV is used only in
    batch mode when `calibrate_to_return_units=True` and there are enough
    samples.

  **n_jobs** *int, default=1*
  : Number of parallel jobs for descriptor computation and cross-validation.
* **Attributes:**
  **alpha_** *ndarray of shape (n_assets,) or None*
  : Estimated alpha for each asset, after applying `forecast_scale`. If
    `calibrate_to_return_units=True`, this is in expected return units. Otherwise,
    it is the predictor output after any volatility conversion. Returns `None`
    during warmup.

  **predictor_** *estimator*
  : Fitted predictor instance.

  **descriptors_** *list of BaseDescriptor*
  : Fitted descriptor estimators.

  **named_descriptors_** *dict of {str: BaseDescriptor}*
  : Dictionary mapping descriptor names to fitted estimators.

  **outlier_transformer_** *BaseCSTransformer or str*
  : Fitted descriptor outlier transformer.

  **scoring_transformer_** *BaseCSTransformer or str*
  : Fitted descriptor scoring transformer.

  **target_outlier_transformer_** *BaseCSTransformer or str*
  : Fitted target outlier transformer.

  **target_scoring_transformer_** *BaseCSTransformer or str*
  : Fitted target scoring transformer.

  **n_assets_** *int*
  : Number of assets seen during fitting.

  **asset_names_** *ndarray*
  : Names of assets in the coverage universe.

### Methods

| [`fit`](#skfolio.alpha.PredictorAlpha.fit)(X[, y])            | Fit the alpha model from scratch (batch mode).                         |
|-------------------------------------------------------------------------|------------------------------------------------------------------------|
| [`get_metadata_routing`](#skfolio.alpha.PredictorAlpha.get_metadata_routing)() | Return metadata routing for descriptors and the predictor.             |
| [`get_params`](#skfolio.alpha.PredictorAlpha.get_params)([deep])     | Get the parameters of an estimator from the ensemble.                  |
| [`partial_fit`](#skfolio.alpha.PredictorAlpha.partial_fit)(X[, y])    | Incrementally fit the alpha model with new observations (online mode). |
| [`set_params`](#skfolio.alpha.PredictorAlpha.set_params)(\*\*params) | Set the parameters of a factor from the ensemble.                      |

#### SEE ALSO
[`EWSharpeOptimalAlpha`](https://skfolio.org/generated/skfolio.alpha.EWSharpeOptimalAlpha.html.md#skfolio.alpha.EWSharpeOptimalAlpha)
: Linear signal aggregation with Sharpe-optimal WLS weighting.

### References

* <a id='r221c08910397-1'>**[1]**</a> “Active Portfolio Management: A Quantitative Approach for Producing Superior Returns and Controlling Risk”, McGraw-Hill, Grinold & Kahn (1999).

### Examples

```pycon
>>> import numpy as np
>>> from sklearn.linear_model import SGDRegressor
>>> from skfolio.datasets import make_synthetic_characteristics
>>> from skfolio.alpha import ForecastUnit, PredictorAlpha
>>> from skfolio.descriptor import EWMomentum, BookToPrice, Reversal, Passthrough
>>>
>>> X = make_synthetic_characteristics(
...     n_assets=100, n_observations=504, n_industries=5, random_state=0
... )
>>> rng = np.random.default_rng(0)
>>>
>>> # Alpha models regress forward idiosyncratic returns. In production these
>>> # come from a fitted CharacteristicsFactorModel.
>>> idio_returns = rng.standard_normal((X.n_observations, X.n_assets))
>>> idio_returns[~X.active_mask] = np.nan
>>> X["idio_returns"] = idio_returns
>>>
>>> # Required when forecast_unit=ForecastUnit.IDIO_SHARPE to scale targets and alphas.
>>> idio_variances = rng.uniform(0.01, 0.05, (X.n_observations, X.n_assets))
>>> idio_variances[~X.active_mask] = np.nan
>>> X["idio_variances"] = idio_variances
>>>
>>> # Required when neutralize_against is set. In production these are factor
>>> # exposures from the characteristics factor model.
>>> exposures = rng.standard_normal((X.n_observations, X.n_assets, 3))
>>> exposures[~X.active_mask] = np.nan
>>> X.add_3d_field(
...     "exposures",
...     exposures,
...     third_axis_name="factors",
...     third_axis_labels=["market", "beta", "size"],
... )
AssetPanel(n_observations=504, n_assets=100, n_fields=25)
>>>
>>> alpha_model = PredictorAlpha(
...     predictor=SGDRegressor(random_state=0),
...     descriptors=[
...         ("momentum", EWMomentum()),
...         ("book_to_price", BookToPrice()),
...         ("reversal", Reversal()),
...         ("eps_ntm", Passthrough("eps_ntm")),
...     ],
...     horizon=5,
...     half_life=21,
...     neutralize_against=["market", "beta", "size"],
...     forecast_unit=ForecastUnit.IDIO_SHARPE,
... )
>>>
>>> alpha_model.fit(X[:-5])
PredictorAlpha(...)
>>> # Preview five forecasts; NaN means no forecast is available.
>>> print(alpha_model.alpha_[:5])
[-0.000494... nan          0.000636...  -0.000259... nan]
>>>
>>> # Update with the next five observations (requires partial_fit support)
>>> alpha_model.partial_fit(X[-5:])
PredictorAlpha(...)
>>> print(alpha_model.alpha_[:5])
[-0.00538... nan         0.0129...   0.00477...  nan]
```

<a id="skfolio.alpha.PredictorAlpha.fit"></a>

#### fit(X, y=None, \*\*fit_params)

Fit the alpha model from scratch (batch mode).

This method works with any sklearn-compatible predictor. It resets all
internal state and fits on the provided data. When calibration is enabled,
predictions from held-out CV folds can be used to calibrate the return-unit
scale.

* **Parameters:**
  **X** *AssetPanel*
  : Input panel containing “idio_returns”, descriptor fields and optionally
    “idio_variances” for calibration or volatility-scaled targets, and
    “exposures” for score neutralization.

  **y** *None*
  : Ignored. Present for compatibility with scikit-learn’s API.

  **\*\*fit_params** *dict*
  : Additional fit parameters passed to descriptors and predictor.
* **Returns:**
  **self** *PredictorAlpha*
  : Fitted estimator.

<a id="skfolio.alpha.PredictorAlpha.get_metadata_routing"></a>

#### get_metadata_routing()

Return metadata routing for descriptors and the predictor.

<a id="skfolio.alpha.PredictorAlpha.get_params"></a>

#### get_params(deep=True)

Get the parameters of an estimator from the ensemble.

Returns the parameters given in the constructor as well as the
estimators contained within the `estimators` parameter.

* **Parameters:**
  **deep** *bool, default=True*
  : Setting it to True gets the various estimators and the parameters
    of the estimators as well.
* **Returns:**
  **params** *dict*
  : Parameter and estimator names mapped to their values or parameter
    names mapped to their values.

<a id="skfolio.alpha.PredictorAlpha.named_descriptors"></a>

#### *property* named_descriptors

Dictionary to access any fitted factors by name.

* **Returns:**
  `Bunch`

<a id="skfolio.alpha.PredictorAlpha.partial_fit"></a>

#### partial_fit(X, y=None, \*\*fit_params)

Incrementally fit the alpha model with new observations (online mode).

This method supports streaming/online updates. It maintains internal
buffers to compute forward returns across partial_fit calls. Only samples
whose targets have newly matured are used for training, avoiding
double-counting while still training buffered rows once their labels are
observable.

On the first call, the predictor is trained using `fit()`. On subsequent
calls, the predictor is updated using `partial_fit()`, which requires
the predictor to support this method.

* **Parameters:**
  **X** *AssetPanel*
  : Input panel containing “idio_returns”, descriptor fields and optionally
    “idio_variances” for calibration or volatility-scaled targets, and
    “exposures” for score neutralization.

  **y** *None*
  : Ignored. Present for compatibility with scikit-learn’s API.

  **\*\*fit_params** *dict*
  : Additional fit parameters passed to descriptors and predictor.
* **Returns:**
  **self** *PredictorAlpha*
  : Fitted estimator.
* **Raises:**
  TypeError
  : If the predictor does not support `partial_fit` (raised on second
    or subsequent calls).

<a id="skfolio.alpha.PredictorAlpha.set_params"></a>

#### set_params(\*\*params)

Set the parameters of a factor from the ensemble.

Valid parameter keys can be listed with `get_params()`. Note that you
can directly set the parameters of the estimators contained in
`estimators`.

* **Parameters:**
  **\*\*params** *keyword arguments*
  : Specific parameters using e.g.
    `set_params(parameter_name=new_value)`. In addition, to setting the
    parameters of the estimator, the individual estimator of the
    estimators can also be set, or can be removed by setting them to
    ‘drop’.
* **Returns:**
  **self** *object*
  : Estimator instance.

