Skip to content

Barra-like risk model kernel

Language: English · 简体中文

portfolio_backtester.risk_model provides a small, public, strategy-agnostic risk model for research diagnostics. It is deliberately a Barra-like kernel, not a claim of compatibility with any commercial vendor model.

Responsibility boundary

The caller owns the point-in-time (PIT) construction of exposures and returns. The kernel does not fetch data, infer a security universe, build A-share factors, or apply an index methodology. A-share factor builders and report adapters belong in quant-market-research; private cash-flow, micro-cap, and DailyWatch20 holdings belong in quant-research.

Input contract

Exposures are a wide pandas.DataFrame with a two-level index named as_of_date and symbol. Each remaining column is one factor exposure. The return panel is a Series (or one-column DataFrame named total_return) with the same index. Duplicate keys and non-finite returns are rejected. Missing factor exposures are not silently imputed; rows lacking a complete set of factors are excluded from that day's regression and appear in its diagnostics.

The PIT owner should record, alongside these frames, the source version, publication timestamp, eligibility rules, corporate-action basis, and the factor definition version. Those metadata are intentionally not guessed by this numerical kernel.

Estimation

estimate_factor_returns runs one weighted cross-sectional ridge regression per date:

[ r_{i,t} = X_{i,t} f_t + e_{i,t}. ]

The kernel does not add an intercept. Supply an intercept exposure column if the model specification requires one. The result contains factor returns, fitted and residual asset returns, and date-level observation/rank/condition number/weighted-R² diagnostics.

build_risk_model estimates an exponentially weighted factor covariance from the trailing factor-return history, shrinks it toward a diagonal matrix, and projects numerical negative eigenvalues to zero. Specific variance is the exponentially weighted residual variance by symbol. These are statistical stabilizers, not economic guarantees.

For portfolio weights (w), exposures (B), factor covariance (\Sigma), and diagonal specific variance (D):

[ b = B^T w,\qquad \sigma^2_{factor} = b^T\Sigma b,\qquad \sigma^2_{specific} = \sum_i w_i^2 D_i. ]

attribute_portfolio_risk returns the factor exposure, Euler factor variance contributions (b_j(\Sigma b)_j), specific variance, total variance, and volatility. Contributions reconcile to factor variance by construction.

Synthetic example

factor_result = estimate_factor_returns(exposures, returns)
risk = build_risk_model(
    factor_result.factor_returns,
    factor_result.residual_returns,
)
attribution = attribute_portfolio_risk(
    weights,
    exposures_for_model_date,
    risk.factor_covariance,
    risk.specific_variance,
)

Use the diagnostics before interpreting a report: insufficient cross-sections, poor matrix conditioning, missing PIT exposures, short residual histories, and unstable covariance eigenvalues should be surfaced as evidence limitations.