skfolio.prior.CharacteristicsFactorModel#

class skfolio.prior.CharacteristicsFactorModel(*, factors, currency_factor=None, exposure_lag=1, cs_regressor=None, neutralize_against=None, constrained_families=None, benchmark_mcap_power=1.0, regression_mcap_power=0.5, inv_idio_variance_weight_shrinkage=0.0, inv_idio_variance_max_weight_ratio=20.0, factor_prior_estimator=None, alpha_estimator=None, spanned_alpha_shrinkage=1.0, orthogonal_alpha_confidence=1.0, idio_variance_estimator=None, idio_corr_estimator=None, idio_corr_threshold=0.0, max_history=None, min_regression_assets=None, n_jobs=1)[source]#

Characteristics-based cross-sectional factor model.

CharacteristicsFactorModel estimates a point-in-time, cross-sectional equity factor model from asset characteristics stored in an AssetPanel [1].

The model is fitted as follows:

  1. Start from point-in-time asset characteristics stored as panel fields (e.g., returns, market_cap, book_equity, industry, country).

  2. Compute descriptor values from these fields, or pass through existing fields unchanged, using descriptor estimators (e.g. BookToPrice, EWMomentum, Passthrough).

  3. Build factor exposures. Style factors are typically formed by combining one or more descriptors and applying cross-sectional transformation such as winsorization and z-scoring, for example with FixedWeightedFactor. Categorical factors (e.g. industry, country, currency) are represented by one-hot exposures with OneHotCategoricalFactors.

  4. Orthogonalize selected exposures against other factors or families when neutralize_against is provided.

  5. Reparameterize constrained families when constrained_families is provided. This enforces the benchmark-weighted zero-sum constraint on factor returns within each constrained family and produces a full-rank basis for factor-level estimators, such as the factor covariance estimator.

  6. Lag exposures by exposure_lag periods and estimate realized factor returns with cs_regressor on the estimation universe defined by the panel’s estimation_mask. By default, regression weights are based on market capitalization through regression_mcap_power. When inv_idio_variance_weight_shrinkage > 0, a two-pass procedure blends those weights with inverse-idiosyncratic-variance weights estimated from first-pass residuals.

  7. Estimate the factor return distribution with factor_prior_estimator, including expected factor returns (factor premia), factor covariance, and factor return scenarios. This step can introduce factor covariance shrinkage, short-term volatility updating, or Newey-West HAC correction.

  8. Estimate idiosyncratic variances with idio_variance_estimator, then form the idiosyncratic covariance as a diagonal matrix or, when idio_corr_threshold > 0, as a sparse covariance using correlation thresholding.

  9. If provided, fit alpha_estimator to produce an alpha forecast. Decompose it into factor-spanned and orthogonal alphas, blend factor-implied asset expected returns with the spanned alpha using spanned_alpha_shrinkage, shrink the orthogonal alpha with orthogonal_alpha_confidence and assemble the final \(\mu\), \(\Sigma\) and asset return scenarios on the investment universe.

For asset \(i\) and observation \(t\), factor returns are estimated from the cross-sectional regression

\[R_i(t) = B_i(t - \ell)\,f(t) + \epsilon_i(t)\]

where \(R_i(t)\) is the local excess return, \(B_i(t-\ell)\) denotes asset \(i\)’s factor exposure vector, \(f(t)\) is the vector of realized factor returns, \(\ell\) is the exposure lag and \(\epsilon_i(t)\) is the idiosyncratic return.

At each observation, this regression estimates realized factor returns and idiosyncratic returns [2]. Expected asset returns are subsequently constructed from expected factor returns and, when configured, an alpha forecast.

The estimator follows skfolio’s as-of time-indexing convention: all time-varying inputs at observation \(t\) reflect information available up to and including the end of period \(t\). Point-in-time fields and derived values store the latest available value for observation \(t\). Returns stored at observation \(t\) cover the period ending at \(t\), namely \((t-1, t]\).

Factor-return regressions estimate the factor returns realized over \((t-1, t]\). The exposure matrix must therefore describe the assets before that return interval begins. exposure_lag selects that exposure date.

The fitted covariance uses the latest available exposures \(B(T)\):

\[\Sigma = B(T)\,F\,B(T)^\top + D\]

where \(F\) is the factor return covariance and \(D\) is the idiosyncratic covariance.

With the default settings and no alpha estimator, the fitted expected-return vector is \(\mu = B(T)\,\mu_f\), where \(\mu_f\) contains expected factor returns. When an alpha estimator is provided, its forecast is decomposed as

\[\alpha = \alpha^{\parallel} + \alpha^{\perp}, \qquad \alpha^{\parallel} = B(T)\,g\]

where \(\alpha^{\parallel}\) is the spanned alpha and \(\alpha^{\perp}\) is the orthogonal alpha. Expected returns are assembled as

\[\mu = \lambda\,B(T)\,\mu_f + (1 - \lambda)\,\alpha^{\parallel} + c\,\alpha^{\perp},\]

where \(\lambda\) is spanned_alpha_shrinkage and \(c\) is orthogonal_alpha_confidence. Direct currency expected returns are added when currency factors are present.

Asset return scenarios in return_distribution_.returns are built by mapping factor-prior scenarios through the latest loading matrix and adding idiosyncratic scenarios calibrated to the latest idiosyncratic-risk forecast. They therefore include both factor and idiosyncratic return components for downstream optimizers that use scenario-based risk measures such as CVaR.

The estimator distinguishes the coverage, estimation and investment universes:

  • The coverage universe is the set of assets stored in characteristics. The panel’s active_mask identifies which asset-observation pairs are active within that universe. If active_mask=True and a value is NaN, the observation is treated as missing data (e.g., holiday or missing quote). If active_mask=False, the asset is inactive at that observation (e.g., pre-listing or post-delisting period). AssetPanel applies each field’s inactive_policy outside active_mask, commonly NaN for numeric fields and MISSING=-1 for categorical fields.

  • The estimation universe is defined by the panel’s estimation_mask, which is enforced as a subset of active_mask. It selects the active pairs used to fit cross-sectional statistics, factor-return regressions, benchmark and regression weights, alpha estimators and regime statistics. Other active pairs can still receive transformed values, exposures and forecasts, but they do not contribute to those fitted statistics.

  • The investment universe is defined by X.columns when X is provided. X is the skfolio API input for asset returns and is used by downstream workflows for validation, cross-validation, prediction, and scoring. If X is None, the investment universe is the full coverage universe.

Fitting is performed on the coverage universe to use all available cross-sectional information, then the outputs are reduced to the investment universe. Within that investment universe, NaNs in fitted moments mark assets that are currently unavailable or not yet warmed up. Compatible downstream optimizers infer the investable subset from finite moments, solve on that subset and expand weights back with zero weight for unavailable assets.

For the complete factor-model user guide, see Factor Models. For more details on the input panel format, see Asset Data Representation.

Parameters:
factorslist of (str, BaseFactorExposure) tuples

Named factor exposure estimators. Each tuple (name, estimator) defines a factor whose exposure is computed from the AssetPanel. Every estimator must have a family attribute (e.g., "market", "style", "industry", "country"). Factor families are used for neutralization, zero-sum constraints and reporting.

currency_factorBaseFactorExposure, optional

Optional factor exposure estimator for a multi-currency universe. This is expected to be a OneHotCategoricalFactors estimator on the point-in-time asset currency field, or an equivalent estimator returning one-hot currency exposures.

For asset \(i\) with primary currency \(C_i(t)\) at observation \(t\), the exposure to currency factor \(c\) is:

\[\begin{split}x^{ccy}_{i,c}(t) = \begin{cases} 1, & C_i(t) = c, \\ 0, & C_i(t) \ne c. \end{cases}\end{split}\]

Currency factor returns are supplied through currency_excess_returns. The base-currency excess return is:

\[R^{excess,base}_i(t) = R^{excess,local}_i(t) + R^{ccy}_{C_i(t)}(t)\]

where:

\[R^{ccy}_{C_i(t)}(t) = R^{FX}_{C_i(t)}(t) + r^{cash}_{C_i(t)}(t) - r^{cash}_{base}(t) + R^{local}_i(t) R^{FX}_{C_i(t)}(t).\]

Non-currency factor returns are estimated from local excess returns by cross-sectional regression. Currency factor returns are not estimated by that regression because they are observed FX series in the investor’s numeraire. They are appended directly to the factor return distribution with family "currency". The family name "currency" is reserved for this estimator.

exposure_lagint, default=1

Number of periods by which factor exposures are lagged in the cross-sectional regression. Must be >= 1.

The estimator follows skfolio’s as-of time-indexing convention: all time-varying inputs at observation \(t\) reflect information available up to and including the end of period \(t\). Point-in-time fields and derived values store the latest available value for observation \(t\). Returns stored at observation \(t\) cover the period ending at \(t\), namely \((t-1, t]\).

Factor-return regressions estimate the factor returns realized over \((t-1, t]\). The exposure matrix must therefore describe the assets before that return interval begins. exposure_lag selects that exposure date. The regression model is:

\[R(t) = B(t - \ell)\,f(t) + \epsilon(t)\]

where \(\ell\) is exposure_lag. With the default \(\ell = 1\), returns over \((t-1, t]\) are regressed on exposures measured at \(t-1\).

cs_regressorBaseCSLinearModel, optional

Cross-sectional regression estimator used to estimate factor returns from asset returns and lagged exposures. Must have fit_intercept=False. To model an cross-sectional intercept, include a GlobalFactor in factors. The default (None) is to use CSLinearRegression.

Note

Unlike factor exposures, which are typically winsorized and standardized by the exposure estimators, asset returns enter the cross-sectional regression unadjusted. Cleaning return data errors is an upstream responsibility, since the same returns drive benchmark weights, realized performance and downstream optimization. Winsorizing legitimate extreme returns would break the reconciliation of \(R = B\,f + \epsilon\) and understate idiosyncratic risk for heavy-tailed assets; outlier influence is instead limited through exposure winsorization, regression_mcap_power and inv_idio_variance_weight_shrinkage. For bounded-influence estimation of factor returns, supply a robust cs_regressor.

neutralize_againstdict of {str: list[str]}, optional

Keys are factor names or family names to neutralize and values are lists of factor names or family names to neutralize against. When a key is a family name, every factor in that family is neutralized independently against the same targets. Entries are processed in insertion order: later entries see exposures already modified by earlier ones.

For example:

  • {"volatility": ["beta"]}: orthogonalizes the volatility factor exposure against the beta factor exposure.

  • {"momentum": ["industry"]}: orthogonalizes the momentum factor exposure against all industry factor exposures.

  • {"style": ["industry"]}: orthogonalizes every style factor exposure against all industry factor exposures.

Note

When industry factors are one-hot encoded, neutralizing against industry is equivalent to applying within-industry demeaning. Using FixedWeightedFactor with transform_by_group="industry" and cross-sectional scoring that support group demeaning (e.g. CSStandardScaler) achieves the same result and is preferred for performance.

constrained_familieslist[tuple[str, str | None]], optional

Zero-sum constraints applied within factor families. This is useful for one-hot families such as industry or country, whose exposures are collinear with GlobalFactor when all categories are included.

Economically, the market factor captures the benchmark portfolio return. Constrained family factors capture relative effects around it. For example, constrained industry factors measure industry effects whose benchmark-weighted average is zero.

Each tuple (family, factor_to_drop) specifies a family to reparameterize. The model removes one redundant factor and rewrites the family exposures in an equivalent full-rank basis. If factor_to_drop is None, the redundant factor is selected automatically to improve numerical conditioning.

The same full-rank basis is used by downstream factor-level estimators, such as the factor prior and covariance estimator.

benchmark_mcap_powerfloat, default=1.0

Exponent applied to market capitalization to define the model benchmark weights:

\[w_i \propto \mathrm{mcap}_i^p\]

where \(p\) is benchmark_mcap_power. These weights are used for weighted cross-sectional centering, zero-sum family constraints and the reference portfolio associated with the global factor.

Typical choices:

  • 0.0: equal-weighted

  • 0.5: square-root market-cap-weighted

  • 1.0: market-cap-weighted (default)

regression_mcap_powerfloat, default=0.5

Exponent applied to market capitalization to define the initial weights used in the cross-sectional regression:

\[w_i \propto \mathrm{mcap}_i^p\]

where \(p\) is regression_mcap_power. These weights are used for regression estimation only and do not affect the model benchmark weights. When inv_idio_variance_weight_shrinkage > 0, these market-cap-based weights are blended with inverse-idiosyncratic-variance weights before the second-pass cross-sectional regression.

Like the exposures, market caps are lagged by exposure_lag. Regression weights at observation \(t\) use market caps from the selected exposure date, so the weights are fixed before the return interval being regressed.

Typical choices:

  • 0.0: equal-weighted

  • 0.5: square-root market-cap-weighted (default)

  • 1.0: market-cap-weighted

inv_idio_variance_weight_shrinkagefloat, default=0.0

Shrinkage toward inverse-idiosyncratic-variance regression weights. When nonzero, the initial market-cap-based regression weights are blended with inverse idiosyncratic-variance weights in a two-pass WLS procedure. This approximates GLS by using estimated idiosyncratic variances as regression weights.

The blended regression weight for each asset is:

\[w_i = \lambda\,w_i^{\text{inv-var}} + (1 - \lambda)\,w_i^{\text{cap}}\]

where \(\lambda\) is inv_idio_variance_weight_shrinkage. Larger values give more weight to inverse idiosyncratic variance, while 0.0 uses only the market-cap-based regression weights. Must satisfy 0 <= inv_idio_variance_weight_shrinkage <= 1.

This is a standard two-step feasible GLS: the variances feeding the weights are estimated from the cap-weighted first-pass residuals, so the regression weights never depend on their own output, avoiding the feedback loop of recursive weighting schemes where a low estimated variance increases an asset’s weight and, in turn, its influence on later residuals. The weights used at date \(t\) are estimated from residuals up to \(t - 1\) only.

inv_idio_variance_max_weight_ratiofloat, default=20

Maximum ratio between any inverse-idiosyncratic-variance weight and the cross-sectional median inverse-idiosyncratic-variance weight. This caps extreme regression weights for assets with very low estimated idiosyncratic variance.

factor_prior_estimatorBasePrior, optional

Prior estimator for the factor return distribution: expected returns (factor premia), covariance and factor return scenarios. It is fitted on the estimated factor return time series.

The default (None) is to use EmpiricalPrior with EWMu and RegimeAdjustedEWCovariance.

alpha_estimatorBaseAlpha, optional

Estimator producing an expected-return forecast for each asset from idiosyncratic returns and alpha signals computed from AssetPanel fields. The forecast is subsequently decomposed into spanned alpha and orthogonal alpha.

If None (default), expected asset returns are determined entirely by the expected factor returns estimated by factor_prior_estimator (factor premia).

The alpha should be expressed in expected-return units when it is combined with expected factor returns or used by optimizers that trade it off against realized-return quantities (e.g., transaction costs, market impact, turnover constraints or return targets). Unitless cross-sectional scores are appropriate only when the downstream objective treats them purely as ordinal signals.

spanned_alpha_shrinkagefloat, default=1.0

Shrinkage applied to spanned alpha. The alpha forecast is decomposed as \(\alpha = \alpha^{\parallel} + \alpha^{\perp}\), with \(\alpha^{\parallel} = B(T)\,g\). The factor-implied asset expected returns \(B(T)\,\mu_f\) are blended with the spanned alpha:

\[\mu^{\parallel} = \lambda\,B(T)\,\mu_f + (1 - \lambda)\,\alpha^{\parallel}\]

where \(\mu_f\) contains expected factor returns and \(\lambda\) is spanned_alpha_shrinkage.

  • 0: use only the spanned alpha. When alpha_estimator=None, this sets the non-currency factor-spanned expected return to zero.

  • 1 (default): use only factor-implied asset expected returns.

  • Between 0 and 1: blend factor-implied asset expected returns with the spanned alpha.

Must satisfy 0 <= spanned_alpha_shrinkage <= 1.

orthogonal_alpha_confidencefloat, default=1.0

Confidence weight applied to orthogonal alpha. After the alpha forecast is decomposed into \(\alpha^{\parallel}\) and \(\alpha^{\perp}\), the orthogonal alpha is shrunk toward zero:

\[\mu = \mu^{\parallel} + c\,\alpha^{\perp}\]

where \(c\) is orthogonal_alpha_confidence.

  • 0: discard the orthogonal alpha.

  • 1 (default): use the orthogonal alpha as-is.

  • Between 0 and 1: partially shrink the orthogonal alpha toward zero.

Must satisfy 0 <= orthogonal_alpha_confidence <= 1.

As an alternative to shrinking the point estimate, orthogonal uncertainty can be handled at the optimizer level with OrthogonalMuUncertaintySet or OrthogonalCovarianceUncertaintySet.

idio_variance_estimatorBaseVariance, optional

Variance estimator for idiosyncratic returns. It must support partial_fit so the model can recover per-asset variance estimates at each observation. These estimates are stored in factor_model_.idio_variances. The default (None) is RegimeAdjustedEWVariance.

idio_corr_estimatorBaseCovariance, optional

Estimator for idiosyncratic correlation thresholding. Although this parameter accepts a BaseCovariance estimator, only the correlation component of its output is retained.

The estimator is fitted on idiosyncratic returns standardized by their contemporaneous idiosyncratic volatility from idio_variance_estimator. The resulting covariance matrix is converted to a correlation matrix, thresholded with idio_corr_threshold and recombined with the latest per-asset idiosyncratic variances to produce the final idiosyncratic covariance.

By construction, idiosyncratic returns should be nearly uncorrelated after removing the factor structure, so the idiosyncratic covariance is diagonal by default. Correlation thresholding addresses cases where this assumption can break down, such as linked securities, multiple share classes, ADRs versus ordinary shares, or dual listings. Without it, optimizers may treat highly related securities as diversified sources of idiosyncratic risk.

Variances and correlations are estimated separately because a single full covariance estimator would mix per-asset variance estimation with off-diagonal correlation noise. This keeps per-asset variances driven by idio_variance_estimator and applies correlation thresholding only where residual correlations are large enough to retain.

The default (None) is EWCovariance [3]. Correlation thresholding is used only when idio_corr_threshold > 0.

idio_corr_thresholdfloat, default=0.0

Absolute correlation threshold \(\tau\) used for idiosyncratic correlation thresholding. Off-diagonal correlations with \(|\rho_{ij}| \le \tau\) are set to zero. If 0 (default), correlation thresholding is disabled and the idiosyncratic covariance is diagonal.

max_historyint, optional

Maximum number of fitted observations to retain in time-series outputs and asset return scenarios. This applies to return_distribution_.returns and to fitted factor_model_ histories such as factor_returns, idio_returns, idio_variances, exposures, and regression_weights.

In incremental learning, setting max_history limits memory usage and keeps optimization with scenario-based risk measures, such as CVaR, computed on a rolling window of recent scenarios.

  • If None (default), all fitted observations are retained.

  • If an integer, only the last max_history fitted observations are retained.

min_regression_assetsint, optional

Minimum number of assets that must have all factor exposures finite and belong to the estimation universe at every post-warmup observation. If any observation falls below this threshold, a ValueError is raised. If None (default), the threshold is set automatically to max(2 * n_factors, 30) to reduce the risk of underspecified regressions and unstable factor-return estimates.

n_jobsint, default=1

Number of parallel jobs used to compute factor exposures. Factors in the same dependency layer are computed in parallel using threads, avoiding copies of the underlying AssetPanel. Set to -1 to use all available processors.

Attributes:
return_distribution_ReturnDistribution

Fitted ReturnDistribution containing the expected asset returns, covariance matrix, asset return scenarios and reference to the fitted FactorModel.

factor_model_FactorModel

Fitted FactorModel containing factor exposures, factor returns, factor covariance, idiosyncratic returns, idiosyncratic variances and idiosyncratic covariance. Stored exposures follow the as-of time-indexing convention for each observation.

cs_regressor_BaseCSLinearModel

Fitted cross-sectional regression estimator.

factor_prior_estimator_BasePrior

Fitted factor prior estimator.

alpha_estimator_BaseAlpha or None

Fitted alpha estimator or None if no alpha estimator was provided.

idio_variance_estimator_BaseVariance

Fitted idiosyncratic variance estimator.

idio_corr_estimator_BaseCovariance

Fitted idiosyncratic correlation estimator.

n_assets_int

Number of assets seen during fitting.

asset_names_ndarray of shape (n_assets,)

Asset names in the coverage universe.

n_features_in_int

Number of assets in the investment universe.

feature_names_in_ndarray of shape (n_features_in,)

Asset names in the investment universe. When X is None, equals asset_names_.

Methods

fit([X, y, currency_excess_returns])

Fit the characteristics factor model.

get_metadata_routing()

Get metadata routing for this estimator.

get_params([deep])

Get the parameters of this estimator.

partial_fit([X, y, currency_excess_returns])

Incrementally fit the characteristics factor model.

set_fit_request(*[, characteristics, ...])

Configure whether metadata should be requested to be passed to the fit method.

set_params(**params)

Set the parameters of this estimator.

set_partial_fit_request(*[, ...])

Configure whether metadata should be requested to be passed to the partial_fit method.

Notes

When the factor list includes a GlobalFactor, that factor acts as the cross-sectional regression intercept because its exposure is one for every asset. Its estimated return is close to the return of the market (defined as the benchmark-weighted portfolio on the estimation universe).

When remaining factor exposures are centered so their benchmark-weighted average is zero, as produced by CSStandardScaler and family constraints, they satisfy:

\[\sum_i w_i^{\text{bench}}\,B_{ij} = 0 \quad \forall\; j \neq 0\]

This centers these factors around the market, so the global factor captures the market return. If regression weights differ from benchmark weights, small tilts can remain:

\[\sum_i w_i^{\text{reg}} B_{ij}\]

These tilts explain why the global factor return may differ slightly from the exact market return.

When regression_mcap_power == benchmark_mcap_power and inv_idio_variance_weight_shrinkage == 0, regression weights are proportional to benchmark weights, the tilts vanish and the identity becomes exact:

\[\hat{f}_0(t) = \sum_i \hat{w}_i^{\text{bench}} R_i(t)\]

References

[1]

“The Elements of Quantitative Investing”, Wiley Finance, Giuseppe A. Paleologo (2025).

[2]

“Active Portfolio Management: A Quantitative Approach for Producing Superior Returns and Controlling Risk”, McGraw-Hill, Grinold & Kahn (1999).

[3]

“Multivariate Exponentially Weighted Moving Covariance Matrix”, Technometrics, Hawkins & Maboudou-Tchao (2008).

Examples

Build a characteristics factor model from market, industry and style exposures:

>>> from skfolio.datasets import make_synthetic_characteristics
>>> from skfolio.descriptor import (
...     BookToPrice,
...     EWMomentum,
...     EWMarketBeta,
...     ForwardEarningsToPrice,
...     LogMarketCap,
... )
>>> from skfolio.factor_exposure import (
...     DerivedFactor,
...     FixedWeightedFactor,
...     GlobalFactor,
...     OneHotCategoricalFactors,
... )
>>> from skfolio.moments import EWMu, RegimeAdjustedEWCovariance
>>> from skfolio.prior import CharacteristicsFactorModel, EmpiricalPrior
>>>
>>> characteristics = make_synthetic_characteristics()
>>>
>>> # Market and industry factors.
>>> market_factor = GlobalFactor()
>>> industry_factors = OneHotCategoricalFactors(
...     category="industry",
...     family="industry",
... )
>>>
>>> # Style factors built from descriptors.
>>> beta_factor = FixedWeightedFactor(
...     descriptors=[("market_beta", EWMarketBeta(half_life=63))],
...     family="style",
...     transform_by_group="industry",
... )
>>> momentum_factor = FixedWeightedFactor(
...     descriptors=[("momentum", EWMomentum(half_life=126, skip=21))],
...     family="style",
...     transform_by_group="industry",
... )
>>> size_factor = FixedWeightedFactor(
...     descriptors=[("log_market_cap", LogMarketCap())],
...     family="style",
...     transform_by_group="industry",
... )
>>> earnings_yield_factor = FixedWeightedFactor(
...     descriptors=[
...         ("book_to_price", BookToPrice()),
...         ("forward_earnings_to_price", ForwardEarningsToPrice()),
...     ],
...     weights=[0.5, 0.5],
...     family="style",
...     transform_by_group="industry",
... )
>>>
>>> # Style exposure derived from an existing factor.
>>> non_linear_size_factor = DerivedFactor(
...     source="size",
...     func=lambda x: x**3,
...     transform_by_group="industry",
... )
>>>
>>> model = CharacteristicsFactorModel(
...     factors=[
...         ("market", market_factor),
...         ("industry", industry_factors),
...         ("beta", beta_factor),
...         ("momentum", momentum_factor),
...         ("size", size_factor),
...         ("earnings_yield", earnings_yield_factor),
...         ("non_linear_size", non_linear_size_factor),
...     ],
...     neutralize_against={
...         "momentum": ["industry"],
...         "non_linear_size": ["size"],
...     },
...     constrained_families=[("industry", None)],
...     factor_prior_estimator=EmpiricalPrior(
...         mu_estimator=EWMu(),
...         covariance_estimator=RegimeAdjustedEWCovariance(
...             half_life=40,
...             corr_half_life=60,
...         ),
...     ),
...     inv_idio_variance_weight_shrinkage=0.5,
...     n_jobs=-1,
... )
>>> model.fit(characteristics=characteristics)
>>>
>>> # Inspect the fitted factor model and diagnostics.
>>> fm = model.factor_model_
>>> fm.summary()
>>> fm.idio_calibration_summary()
>>> fm.idio_vol_ic
>>> fm.idio_tail_rate()
>>> fm.factor_returns_df
>>> fm.exposures_df

Use partial_fit for online updates:

>>> model.fit(characteristics=characteristics[:400])
>>> for start in range(400, len(characteristics), 5):
...     model.partial_fit(characteristics=characteristics[start : start + 5])
fit(X=None, y=None, *, characteristics, currency_excess_returns=None, **fit_params)[source]#

Fit the characteristics factor model.

Resets all fitted state and estimates the full model pipeline on the provided data. For incremental updates, use partial_fit.

Parameters:
XDataFrame of shape (n_observations, n_assets), optional

Asset returns whose columns define the investment universe, following the standard skfolio estimator API. In this estimator, X.columns define the assets returned in return_distribution_ and factor_model_.

Factor estimation uses the "returns" field of characteristics, which can cover a broader point-in-time universe than X. This keeps the estimator compatible with skfolio pipelines, cross-validation, prediction and scoring, while allowing the factor model to use a wider coverage universe for estimation.

yIgnored

Not used, present for API consistency by convention.

characteristicsAssetPanel

Point-in-time AssetPanel for the coverage universe. Must include "returns" and, when market-cap weighting is used, "market_cap". The panel’s active_mask identifies active asset-observation pairs within the coverage universe and estimation_mask identifies which active pairs contribute to estimation. For more details see Asset Data Representation.

currency_excess_returnsDataFrame, optional

Currency excess returns. Required only when currency_factor is set. Columns must contain the unique currency factor names produced by currency_factor. Assets are mapped to these columns through the one-hot currency exposures.

**fit_paramsdict

Parameters passed to underlying estimators. Only available when enable_metadata_routing=True, set with sklearn.set_config(enable_metadata_routing=True). See Metadata Routing User Guide for more details.

Returns:
selfCharacteristicsFactorModel

Fitted estimator.

Raises:
ValueError

If the data does not contain enough observations to estimate the model after warmup and exposure-lag trimming.

get_metadata_routing()[source]#

Get metadata routing for this estimator.

Returns:
routingMetadataRouter

Metadata routing configuration.

get_params(deep=True)[source]#

Get the parameters of this estimator.

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

Parameters:
deepbool, default=True

Setting it to True gets the various estimators and the parameters of the estimators as well.

Returns:
paramsdict

Parameter and estimator names mapped to their values or parameter names mapped to their values.

property named_factors#

Dictionary for accessing factors by name.

Returns:
Bunch
partial_fit(X=None, y=None, *, characteristics, currency_excess_returns=None, **fit_params)[source]#

Incrementally fit the characteristics factor model.

This method allows for streaming/online updates. Each call updates the internal state with new observations without resetting previously accumulated state. All sub-estimators (factor_prior_estimator, idio_variance_estimator, etc.) must implement partial_fit for this method to work.

Parameters:
XDataFrame of shape (n_observations, n_assets), optional

Asset returns whose columns define the investment universe, following the standard skfolio estimator API. In this estimator, X.columns define the assets returned in return_distribution_ and factor_model_.

Factor estimation uses the "returns" field of characteristics, which can cover a broader point-in-time universe than X. This keeps the estimator compatible with skfolio pipelines, cross-validation, prediction and scoring, while allowing the factor model to use a wider coverage universe for estimation.

yIgnored

Not used, present for API consistency by convention.

characteristicsAssetPanel

Point-in-time AssetPanel for the coverage universe. Must include "returns" and, when market-cap weighting is used, "market_cap". The panel’s active_mask identifies active asset-observation pairs within the coverage universe and estimation_mask identifies which active pairs contribute to estimation. For more details see Asset Data Representation.

currency_excess_returnsDataFrame, optional

Currency excess returns. Required only when currency_factor is set. Columns must contain the unique currency factor names produced by currency_factor. Assets are mapped to these columns through the one-hot currency exposures.

**fit_paramsdict

Parameters passed to underlying estimators. Only available when enable_metadata_routing=True, set with sklearn.set_config(enable_metadata_routing=True). See Metadata Routing User Guide for more details.

Returns:
selfCharacteristicsFactorModel

Fitted estimator.

set_fit_request(*, characteristics='$UNCHANGED$', currency_excess_returns='$UNCHANGED$')#

Configure whether metadata should be requested to be passed to the fit method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to fit if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to fit.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:
characteristicsstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for characteristics parameter in fit.

currency_excess_returnsstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for currency_excess_returns parameter in fit.

Returns:
selfobject

The updated object.

set_params(**params)[source]#

Set the parameters of this estimator.

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

Parameters:
**paramskeyword arguments

Specific parameters using e.g. set_params(parameter_name=new_value). In addition to setting the parameters of the estimator, the individual factor estimators can also be set, or can be removed by setting them to ‘drop’.

Returns:
selfobject

Estimator instance.

set_partial_fit_request(*, characteristics='$UNCHANGED$', currency_excess_returns='$UNCHANGED$')#

Configure whether metadata should be requested to be passed to the partial_fit method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to partial_fit if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to partial_fit.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:
characteristicsstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for characteristics parameter in partial_fit.

currency_excess_returnsstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for currency_excess_returns parameter in partial_fit.

Returns:
selfobject

The updated object.