linearmodels.asset_pricing.model.LinearFactorModel¶
-
class linearmodels.asset_pricing.model.LinearFactorModel(portfolios: IVData | ndarray | DataArray | DataFrame | Series | list[Any] | tuple[Any, ...], factors: IVData | ndarray | DataArray | DataFrame | Series | list[Any] | tuple[Any, ...], *, risk_free: bool =
False, sigma: ndarray | DataArray | DataFrame | Series | list[Any] | tuple[Any, ...] | None =None)[source]¶ Linear factor model estimator.
- Parameters:¶
- portfolios: IVData | ndarray | DataArray | DataFrame | Series | list[Any] | tuple[Any, ...]¶
Test portfolio returns (nobs by nportfolio).
- factors: IVData | ndarray | DataArray | DataFrame | Series | list[Any] | tuple[Any, ...]¶
Priced factor returns (nobs by nfactor).
- risk_free: bool =
False¶ Flag indicating whether the risk-free rate should be estimated from returns along other risk premia. If False, the returns are assumed to be excess returns using the correct risk-free rate. The default is False.
- sigma: ndarray | DataArray | DataFrame | Series | list[Any] | tuple[Any, ...] | None =
None¶ Positive definite residual covariance (nportfolio by nportfolio) that weights the test portfolios in the second stage. A
ValueErroris raised if it does not have this shape, contains missing or infinite values, or is not symmetric and positive definite. If not provided, the identity matrix is used.
Notes
Suitable for traded or non-traded factors.
Implements a 2-step estimator of risk premia, factor loadings and model tests.
The first stage model estimated is
\[r_{it} = c_i + f_t \beta_i + \epsilon_{it}\]where \(r_{it}\) is the return on test portfolio i and \(f_t\) are the traded factor returns. The parameters \(c_i\) are required to allow non-traded to be tested, but are not economically interesting. These are not reported.
The second stage model uses the estimated factor loadings from the first and is
\[\bar{r}_i = \lambda_0 + \hat{\beta}_i^\prime \lambda + \eta_i\]where \(\bar{r}_i\) is the average excess return to portfolio i and \(\lambda_0\) is only included if estimating the risk-free rate. GLS is used in the second stage if
sigmais provided.The model is tested using the estimated values \(\hat{\alpha}_i=\hat{\eta}_i\), the pricing errors. With \(N\) test portfolios, \(K\) factors and \(n_{rf}\) equal to 1 if the risk-free rate is estimated and 0 if it is not, the second stage estimates make the pricing errors orthogonal to the \(K + n_{rf}\) columns of \(\Sigma^{-1}\hat{\beta}_c\). Here \(\hat{\beta}_c\) contains the estimated factor loadings, preceded by a column of ones if the risk-free rate is estimated, and \(\Sigma\) is
sigma, or the identity if it is not provided. The pricing errors therefore lie in a space with \(N - K - n_{rf}\) dimensions, and the covariance of the pricing errors has rank \(N - K - n_{rf}\).The J-statistic is the Wald statistic of the pricing errors in the space where they lie,
\[J = (Q^\prime\hat{\alpha})^\prime (Q^\prime \hat{V} Q)^{-1} (Q^\prime\hat{\alpha})\]where \(\hat{V}\) is the estimated covariance of the pricing errors and \(Q\) is an \(N\) by \(N - K - n_{rf}\) matrix whose orthonormal columns span the space that is orthogonal to the columns of \(\Sigma^{-1}\hat{\beta}_c\). The \(N - K - n_{rf}\) elements of \(Q^\prime\hat{\alpha}\) are the coordinates of the pricing errors in that space, and \(Q^\prime \hat{V} Q\) is their estimated covariance. The statistic tests the null that all of the pricing errors are zero, and has an asymptotic \(\chi^2_{N-K-n_{rf}}\) distribution. It can also be written \(\hat{\alpha}^\prime \hat{V}^{+} \hat{\alpha}\) for \(\hat{V}^{+}=Q(Q^\prime \hat{V} Q)^{-1}Q^\prime\), which has rank \(N - K - n_{rf}\). If \(\hat{V}\) were exactly singular in the directions of the columns of \(\Sigma^{-1}\hat{\beta}_c\), as the covariance of the pricing errors is in theory, \(\hat{V}^{+}\) would be its Moore-Penrose pseudo-inverse.
In a sample, \(\hat{V}\) is not exactly singular. The Moore-Penrose pseudo-inverse of \(\hat{V}\) would either invert the directions that are null in theory, which makes the statistic too large, or need a tolerance that decides which eigenvalues are treated as zero. The J-statistic instead projects the pricing errors on the space where they lie and uses the rank that the model implies, \(N - K - n_{rf}\), so that no tolerance decides which eigenvalues are treated as zero.
The statistic depends on the space and not on the basis of the space: any other orthonormal basis, \(QR\) for an orthogonal matrix \(R\), gives the same value. It therefore does not depend on the order of the test portfolios. Reordering the columns of
portfolios, and the rows and columns ofsigmain the same way, reorders \(\hat{\alpha}\), \(\hat{V}\) and the rows of \(\Sigma^{-1}\hat{\beta}_c\) in the same way and does not change the statistic. It also does not depend on the order of the observations ifcov_typeis"robust", but the kernel covariance estimators use the order of the observations.If \(Q^\prime \hat{V} Q\) is numerically singular, which can occur when there are few observations, the J-statistic is an
InvalidTestStatistic. If the number of test portfolios is the number of risk premia, \(N = K + n_{rf}\), the pricing errors are zero and the statistic is 0 with 0 degrees of freedom.Changed in version 7.1: The J-statistic used the Moore-Penrose pseudo-inverse of \(\hat{V}\) with its default tolerance, which also inverts the directions in which the covariance is null in theory. Its eigenvalues are small but not zero in a sample. The statistic was therefore too large: by 4% in the median and by up to 30% in 200 simulated samples of a correct model with 250 observations, 25 portfolios and 3 factors, where the 5% test rejected 12.5% of the samples (10.0% now; with 1,000 observations 7.5% and 5.5%). The covariance can be far from singular in those directions when there are few portfolios: the J-statistic of the five portfolios and three factors of the Fama-French example in the documentation is 41.6 and was 100.6. If the risk-free rate was estimated, an eigenvalue that is numerically zero was inverted as well, and the statistic changed in the third digit when the observations were only reordered.
Rows are paired by position, so that the first row of
factorsis the factor return in the period of the first row ofportfolios. If bothportfoliosandfactorscarry labels (a pandas Series or DataFrame with an index other than the default 0, 1, …, n-1, or an xarray DataArray with coordinates),factorsmust use the same index, in the same order, asportfolios, so that a return cannot be attached to the wrong period. AValueErroris raised if the index differs. Either reindexfactorsto the index ofportfolios, or callto_numpy()to pair its values by position. NumPy arrays and pandas objects with a default index do not carry labels and are always paired by position. Dates and time deltas are compared by value, so that the same dates at different resolutions, e.g.,datetime64[us]anddatetime64[ns], are the same labels.Methods
fit([cov_type, debiased])Estimate model parameters.
from_formula(formula, data, *[, portfolios, ...])Specify a model using the formula interface.
Properties
Formula used to construct the model, if it was constructed using one.