Cross-Sectional Factor Prior
A cross-sectional factor prior estimates a point-in-time factor model from an AssetPanel and lifts it onto the assets, returning a CrossSectionalFactorModel in the rr slot of its LowOrderPrior.
PortfolioOptimisers.CrossSectionalFactorPrior — Type
struct CrossSectionalFactorPrior{__T_factors, __T_neutralise, __T_families, __T_cre, __T_wa, __T_pe, __T_ve, __T_ce, __T_f_mp, __T_mp, __T_th, __T_bp, __T_mcap, __T_bw, __T_lag, __T_minra, __T_rfe, __T_lambda, __T_c} <: AbstractLowOrderPriorEstimator_AEstimates a point-in-time cross-sectional factor model from an Asset Panel, and lifts it onto the assets.
The estimator reads per-asset Panel Fields, builds a Factor Exposure from each one, regresses every observation's returns on the lagged exposures across the assets, and returns the asset moments beside a CrossSectionalFactorModel block. It is the cross-sectional counterpart of FactorPrior, which regresses each asset's returns on a factor-return series over time.
The window a fit needs is cumulative, and a caller who sizes one must add up three warm-ups rather than take the longest. The Descriptors warm up first, and their longest warm-up fixes the first observation of the factor-return history; lag takes one more. pe then warms up over that history, and ve over the idiosyncratic returns beside it. A window that clears the Descriptors alone can still leave pe too little to state a factor covariance from, and the fit refuses by name when it does. This bites hardest in cross-validation, because a fold hands the estimator only its own rows, so the Descriptors restart in every fold and a rolling train window never grows to absorb the warm-up. Size the train window against the sum, not against the Descriptors.
Fields
factors: Pairs offactor name => Exposure Estimator, in the order they take on the factor axis. A one-hot member contributes one factor per level of its categorical Panel Field, so a Pair is not always one factor.
neutralise: Neutralisation, as Pairs ofkey => targetsrun in order, ornothing. A key names a factor or a Factor Family, and so does each target.
families: Constrained Factor Families, as Pairs offamily label => dropped member, ornothing. Anothingright letsfactor_family_basischoose the member to drop.
cre: Cross-Sectional Regression Estimator of the fit, and of the Neutralisation.
wa: Weight policy of the cross-sectional fit. Itspis the power the regression weights raise the market capitalisation to.
pe: Prior estimator. It is fitted on the reduced factor-return series, so a constrained Factor Family gives it a full-rank covariance.
ve: Variance estimator.variance_serieson it gives the idiosyncratic variance history, whose last row is the idiosyncratic risk of the latest observation.
ce: Covariance estimator. It estimates the covariance of the standardised idiosyncratic returns, and it is read only whenthis positive.gap_fill_valueon it decides what an inactive asset's cell is worth: the default answersNaN, so the estimator is handed the gap and the panel's active mask, and a plain moment estimator takes a zero in its place.
f_mp: Factor matrix processing estimator. It processes the factor covariancepeanswered, which is a different matrix from the asset onempprocesses: it lives on the factor axis, it is estimated from the factor-return series, and a Factor Family that sheds a member can leave it singular.cross_sectional_lifttakes its Cholesky factor for the low-rank square root, so a factor covariance that is not positive definite fails there rather than in the asset block.
mp: Matrix processing estimator.
th: Idiosyncratic correlation threshold. A value of zero leaves the idiosyncratic covariance diagonal, and a positive value keeps every correlation above it and zeroes the rest, so the block becomes a matrix.
bp: Power the benchmark weights raise the market capitalisation to. A value of zero gives every asset of the estimation universe the same benchmark weight, and reads no market capitalisation.
mcap: Name of the numeric Panel Field holding the market capitalisation.
bw: Name of the numeric Panel Field the prior writes its benchmark weights onto, and the one every Exposure Estimator reads them from.
lag: Number of observations by which the exposures lag the returns.
minra: Smallest eligible asset count an observation may carry, ornothingformax(2K, 30)over the reduced factor countK.
rfe: Return Forecast Estimator whose forecast entersmu, ornothing. It is fitted on the coverage universe, after the factor model, and its forecast is split against the latest Factor Exposures into the part they span and the part they do not.
lambda: Shrinkage of the expected factor returns towards the spanned part of the Return Forecast, in[0, 1]. A value of one keeps the fitted factor mean, and a value of zero takes the spanned forecast alone. With no Return Forecast Estimator the spanned part is zero, so the value shrinks the factor mean towards zero.
c: Confidence in the orthogonal part of the Return Forecast, in[0, 1]. It scales the part of the forecast the factors do not span, which the block carries inb. A value of zero discards it where it is finite. An asset whose forecast is not finite carriesNaNinbwhatevercis, because0 * NaNisNaN, so the prior states no expected return for it and it leaves the Investable Mask; a forecast that is not finite at every asset is the zero split, and touches nothing.
Constructors
CrossSectionalFactorPrior(; factors::Dict_VecPair, neutralise::Option{<:Dict_VecPair} = nothing, families::Option{<:Dict_VecPair} = nothing, cre::AbstractCrossSectionalRegressionEstimator = CrossSectionalLinearRegression(), wa::AbstractCrossSectionalWeightsAlgorithm = MarketCapWeights(), pe::AbstractLowOrderPriorEstimator_A_AF = EmpiricalPrior(), ve::AbstractCovarianceEstimator = RegimeAdjustedExpWeightedVariance(), ce::StatsBase.CovarianceEstimator = ExpWeightedCovariance(; centred = true), f_mp::AbstractMatrixProcessingEstimator = MatrixProcessing(), mp::AbstractMatrixProcessingEstimator = MatrixProcessing(), th::Real = 0.0, bp::Real = 1.0, mcap::AbstractString = "market_cap", bw::AbstractString = "benchmark_weights", lag::Integer = 1, minra::Option{<:Integer} = nothing, rfe::Option{<:AbstractReturnForecastEstimator} = nothing, lambda::Real = 1.0, c::Real = 1.0)Validation
factorsis not empty and repeats no factor name.neutraliseandfamiliesrepeat no key.thlies in[0, 1].bpis finite and>= 0.lagis> 0.minra, when it is stated, is> 0.lambdaandclie in[0, 1].
Examples
julia> CrossSectionalFactorPrior(; factors = ["mkt" => ConstantExposure()], lag = 2).lag2Related
PortfolioOptimisers.prior — Function
prior(pe::CrossSectionalFactorPrior, X::MatNum, F::Option{<:MatNum} = nothing,
pnl::Option{<:AssetPanel} = nothing; dims::Int = 1, iv::Option{<:MatNum} = nothing,
ivpa::Option{<:Num_VecNum} = nothing, strict::Bool = false,
kwargs...) -> LowOrderPriorFit a cross-sectional factor model on an Asset Panel, and return the asset prior it lifts.
This is the returns-matrix method every prior estimator implements, and it holds the fit. The panel arrives as the third positional argument, so a wrapping prior composes this estimator by forwarding the panel it was handed. The carrier method below unwraps a ReturnsResult onto it.
Algorithm
- Orient
XandFbydims, rebuild the carrier the Descriptors read fromX,F,pnl,ivandivpa, and take the two universe masks offpnlwithcross_sectional_panel_masks. - Build the benchmark weights with
cross_sectional_cap_weights, over the assets of the estimation universe whose return is finite, and write them onto a copy of the Asset Panel withcross_sectional_benchmark_carrier. - Build every Factor Exposure with
cross_sectional_exposure_history, in dependency order, givingMs,nfandfam. - Drop the leading observations the Descriptors warm up over, with
cross_sectional_warmup. - Neutralise the exposures with
cross_sectional_neutralise!, under the benchmark weights and the prior's own regression estimator. - Build the Factor Family Basis with
cross_sectional_family_basis, and reduce the exposures through it. - Lag the reduced exposures and the market capitalisation by
pe.lag, and take the eligibility mask of the fit withcross_sectional_eligible. - Regress each observation's returns on its lagged reduced exposures, through
cs_weights_initial,needs_second_passandcs_weights_refine. - Take the idiosyncratic variance history with
variance_series, standardise the idiosyncratic returns by it withcross_sectional_standardised_residuals, and take the latest idiosyncratic covariance withcross_sectional_idiosyncratic_covariance. - Fit
pe.peon the reduced factor returns, refuse a non-finite factor moment withassert_cross_sectional_factor_moments, and process the factor covariance in place underpe.f_mp, which is the factor axis's own matrix processing estimator and not the asset one.strictreachespe.pe, as it does inFactorPrior, because the slot admitsBlackLittermanPriorandEntropyPoolingPrior, which resolve view names against a universe. - Fit the Return Forecast with
cross_sectional_return_forecast, on the whole carrier, so that a Descriptor of the forecast warms up over every observation the panel has, and blend its spanned part into the factor mean withcross_sectional_forecast_mu. The block carries the orthogonal part inb, and the Result inrf. - Expand the blended factor moments onto the raw factor axis with
cross_sectional_expand, sofprstates the distribution of the factors the caller named. - Rebuild the asset return scenarios with
cross_sectional_scenarios. - Lift the reduced factor distribution onto the investable assets with
cross_sectional_lift, and addbto the expected return it answers.
Arguments
pe: Cross-Sectional Factor Prior estimator.X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.F: Data matrixobservations × factorsif thedimskeyword does not exist ordims = 1,factors × observationswhendims = 2. It is not read by the fit: this estimator builds its own factors out of the panel. It travels only so that the rebuilt carrier states what the caller held.pnl: OptionalAssetPanel, the panel the carrier held. A wrapping prior forwards it unchanged, so that it can compose an estimator that is fitted on a panel. An estimator that reads no panel ignores it. This estimator reads it, and refuses without it.dims: Dimension along which the observations lie.iv: Implied volatilities, written onto the rebuilt carrier.ivpa: Implied-volatility risk-premium adjustment, written onto the rebuilt carrier.strict: Whether to throw an error ifsetsdoes not contain the desired value insets.dict[key]. It is forwarded to the nested factor priorpe.pe.kwargs...: Additional keyword arguments passed to the verbs of the algorithm.
Validation
pnlis notnothing. Raises anIsNothingError.- The Asset Panel is time-varying. Raises an
ArgumentError. - The history is longer than the exposure lag. Raises an
ArgumentError. - At least two observations are left after the Descriptor warm-up and the exposure lag, because a covariance of one observation is not a number. Raises an
ArgumentError. - Every fitted observation carries at least
minraeligible assets. Raises anArgumentError. - The factor prior states a finite factor mean and a finite factor covariance. Raises an
IsNonFiniteError. - At least one asset is investable at the latest observation. Raises an
IsEmptyError. - The rules of every verb the algorithm names.
Returns
pr::LowOrderPrior: The prior on the full asset universe.muand the diagonal ofsigmaareNaNat an asset the estimator states no moment for,rris aCrossSectionalFactorModel, andfpris the factor prior on the raw factor axis.
Related
PortfolioOptimisers.prior — Method
prior(pe::CrossSectionalFactorPrior, rd::ReturnsResult; kwargs...) -> LowOrderPriorFit a Cross-Sectional Factor Prior from a carrier.
The method unwraps the carrier onto the returns-matrix method above, which holds the fit. It is written here rather than taken from prior(pe::AbstractPriorEstimator, rd::ReturnsResult) so that a carrier with no Asset Panel is refused against rd.pnl, in the words of the carrier the caller built.
Algorithm
- Check that
rdcarries asset returns. - Call the returns-matrix method with
rd.X,rd.Fandrd.pnl, forwardingrd.ivandrd.ivpaas keyword arguments alongsidekwargs.
Arguments
pe: Cross-Sectional Factor Prior estimator.rd: The returns result to use. It must carry asset returns inrd.Xand a time-varying Asset Panel inrd.pnl.kwargs...: Additional keyword arguments passed to the returns-matrix method.
Validation
rd.Xis notnothing. Raises anIsNothingError.rd.pnlis notnothing. Raises anIsNothingError.- The rules of the returns-matrix method.
Returns
pr::LowOrderPrior: The prior the returns-matrix method fitted.
Related