Example: Statistical factor risk model

Objective

The following example shows how to use the library factor-pricing-model-universe and factor-pricing-model-risk-model to build a statistical factor risk model and benchmark with other models provided by, for example, vendors.

Data

First, we need daily data on price, volume and marketcap to construct the universe. (TBC)

Building the universe

Given that the price, volume and marketcap data are provided, we can then build the estimation and model universe.

Parameter

Estimation

Model

Marketcap ranking

Top 90%

Top 50%

Rolling 63-day liquidity

90% availability

90% availability

The following graph shows the number of instruments in U.S. equities in the major indices.

Build first PCA factor model

We can now start building the first PCA factor model for testing. First, create a PCA model with 20 components. Second, pass the daily returns of adjusted close prices of the estimation universe (selecting only estimation universe returns by where). Fill the missing returns by 0.0, especially when the particular instruments were halted trading. Finally, fit the PCA model with the given daily returns.

from fpm_risk_model.statistics import PCA

estimation_returns = (
    adjusted_close_returns
    .where(estimation_validity)
    .fillna(0.0)
)
pca = PCA(n_components=20)
pca.fit(estimation_returns)

We can then examine the factor returns and exposures on the fitted model.

pca.factor_returns
pca.factor_exposures

And also the pairwise covariance of the estimation universe.

pca.cov()

Once the model is fit, we can transform the model with a (larger) model universe.

transformed_pca = pca.transform(model_returns)

And, again, its pairwise covariance can be estimated

transformed_pca.cov()

The covariance contains most instruments in the whole universe scope.

Evaluation on rolling basis

The above example returns a factor model using the full history of daily returns. However, in practical usage, the factor model is evaluated in a rolling basis.

from fpm_risk_model import RollingFactorRiskModel
from fpm_risk_model.statistics import PCA

pca = PCA(n_components=20)
rolling_pca = RollingFactorRiskModel(model=pca, window=252)
rolling_pca.fit(estimation_returns)

Similarly, the rolling factor model can be transformed with model universe, and the pairwise covariance can be retrieved given a specified date.

rolling_pca = rolling_pca.transform(model_returns)
rolling_pca.get("2019-06-13").cov()

Evaluation

Once the risk model is built, we may want to evaluate its accuracy, comparing with the existing risk models, or risk models provided by vendors. Currently, there are two metrics are provided in the library for accuracy evaluation.

  • Bias

  • Value-at-Risk (VaR)