Black-Litterman Prior
PortfolioOptimisers.BlackLittermanPrior — Type
struct BlackLittermanPrior{__T_pe, __T_mp, __T_views, __T_sets, __T_views_conf, __T_rf, __T_tau} <: AbstractLowOrderPriorEstimator_AFBlack-Litterman prior estimator for asset returns.
BlackLittermanPrior is a low order prior estimator that computes the mean and covariance of asset returns using the Black-Litterman model. It combines a prior estimator, matrix post-processing, user or algorithmic views, asset sets, view confidences, risk-free rate, and a blending parameter tau. The estimator supports both direct and constraint-based views, and allows for flexible confidence specification and matrix processing.
Fields
pe: Prior estimator.
mp: Matrix processing estimator.
views: Views estimator or result.
sets: Sets used to map estimator values to assets.
views_conf: Views confidence estimator or result.
rf: Risk-free rate. The Black-Litterman update blends the prior mean against the view returns, so it runs on the total-return scale those are written on. A mean taken from a wrapped prior estimator is on that scale already; an equilibrium mean is a bare risk premium, and the rate converts it before the update. A member with no equilibrium branch has nothing to convert and adds the rate to the posterior asset expected returns instead. It is added exactly once either way, and the wrapped prior estimators are left alone, so a risk-free rate one of them applied internally stays where it is.
tau: Blending parameter controlling the weight given to the prior relative to the views.
Constructors
BlackLittermanPrior(; pe::Onl{<:AbstractLowOrderPriorEstimator_A_F_AF} = EmpiricalPrior(; me = EquilibriumExpectedReturns() ), mp::AbstractMatrixProcessingEstimator = MatrixProcessing(), views::Lc_BLV, sets::Option{<:UniverseSets} = nothing, views_conf::Option{<:Num_VecNum} = nothing, rf::Number = 0.0, tau::Option{<:Number} = nothing) -> BlackLittermanPriorKeywords correspond to the struct's fields.
Composition: what this estimator forwards
The views are applied to the assets. The wrapped prior is forwarded whole and only the deviations are spelled out: mu and sigma become the posterior, and chol is dropped because the posterior covariance supersedes the one it factorises. Everything else forwards — Black-Litterman leaves the observation axis untouched, so w, ens, kld, ow and Z all still describe the axis they were computed over, and rr and the factor block fpr are structural, over data the views do not modify.
The returned mu and sigma are the Black-Litterman posterior, but w is the wrapped prior's observation weighting, forwarded unchanged. Black-Litterman produces no observation-level posterior, so there is no Black-Litterman-consistent alternative to forward — and dropping w would substitute the unweighted empirical distribution, which is further from the caller's intent than the weights they computed. A caller reading pr.w, pr.ens, pr.kld or pr.ow is therefore reading a property of the prior, not of the posterior.
When the wrapped prior carries a factor block, pr.fpr describes the prior factor distribution while pr.mu is a posterior asset mean, so pr.mu != pr.rr.M * pr.fpr.mu + pr.rr.b. The block stays structurally true — the regression is over data Black-Litterman does not modify — while becoming distributionally inconsistent with the asset block. There is nothing better to report: the views land on the assets, so this estimator never computes a posterior factor distribution at all.
Its siblings differ, and the difference is worth knowing. FactorBlackLittermanPrior and BayesianBlackLittermanPrior apply their views to the factors and report the resulting posterior block, so both satisfy mu == rr.M * fpr.mu + rr.b exactly. AugmentedBlackLittermanPrior reports a posterior factor block too, but stays inconsistent for a different reason — see its own warning.
Validation
- If
viewsis aLinearConstraintEstimator,!isnothing(sets). - If
views_confis notnothing,views_confis validated withassert_bl_views_conf. - If
tauis notnothing,tau > 0.
Propagated parameters
When factory is called on this type, the following @fprop-tagged fields are automatically propagated:
pe: Recursively updated viafactory.
View parameters
When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:
pe: Recursively viewed viaport_opt_view.sets: Sliced to the selected indices viaport_opt_view.
Examples
julia> BlackLittermanPrior(; sets = UniverseSets(; xkey = "nx", dict = Dict("nx" => ["A", "B", "C"])), views = LinearConstraintEstimator(; val = ["A == 0.03", "B + C == 0.04"]))BlackLittermanPrior pe ┼ EmpiricalPrior │ ce ┼ PortfolioOptimisersCovariance │ │ ce ┼ Covariance │ │ │ me ┼ SimpleExpectedReturns │ │ │ │ w ┴ nothing │ │ │ ce ┼ GeneralCovariance │ │ │ │ ce ┼ StatsBase.SimpleCovariance: StatsBase.SimpleCovariance(true) │ │ │ │ w ┴ nothing │ │ │ alg ┼ FullMoment() │ │ │ w ┴ nothing │ │ mp ┼ MatrixProcessing │ │ │ pdm ┼ Posdef │ │ │ │ alg ┼ UnionAll: NearestCorrelationMatrix.Newton │ │ │ │ kwargs ┴ @NamedTuple{}: NamedTuple() │ │ │ dn ┼ nothing │ │ │ dt ┼ nothing │ │ │ alg ┼ nothing │ │ │ order ┴ NTuple{4, Symbol}: (:pdm, :dn, :dt, :alg) │ me ┼ EquilibriumExpectedReturns │ │ ce ┼ PortfolioOptimisersCovariance │ │ │ ce ┼ Covariance │ │ │ │ me ┼ SimpleExpectedReturns │ │ │ │ │ w ┴ nothing │ │ │ │ ce ┼ GeneralCovariance │ │ │ │ │ ce ┼ StatsBase.SimpleCovariance: StatsBase.SimpleCovariance(true) │ │ │ │ │ w ┴ nothing │ │ │ │ alg ┼ FullMoment() │ │ │ │ w ┴ nothing │ │ │ mp ┼ MatrixProcessing │ │ │ │ pdm ┼ Posdef │ │ │ │ │ alg ┼ UnionAll: NearestCorrelationMatrix.Newton │ │ │ │ │ kwargs ┴ @NamedTuple{}: NamedTuple() │ │ │ │ dn ┼ nothing │ │ │ │ dt ┼ nothing │ │ │ │ alg ┼ nothing │ │ │ │ order ┴ NTuple{4, Symbol}: (:pdm, :dn, :dt, :alg) │ │ w ┼ nothing │ │ l ┴ Int64: 1 │ horizon ┼ nothing │ fill_limit ┴ nothing mp ┼ MatrixProcessing │ pdm ┼ Posdef │ │ alg ┼ UnionAll: NearestCorrelationMatrix.Newton │ │ kwargs ┴ @NamedTuple{}: NamedTuple() │ dn ┼ nothing │ dt ┼ nothing │ alg ┼ nothing │ order ┴ NTuple{4, Symbol}: (:pdm, :dn, :dt, :alg) views ┼ LinearConstraintEstimator │ val ┼ Vector{String}: ["A == 0.03", "B + C == 0.04"] │ key ┴ nothing sets ┼ UniverseSets │ xkey ┼ String: "nx" │ uxkey ┼ String: "ux" │ tfkey ┼ String: "nf" │ utfkey ┼ String: "uf" │ cfkey ┼ String: "ncf" │ ucfkey ┼ String: "ucf" │ nikey ┼ String: "ni" │ dict ┴ Dict{String, Vector{String}}: Dict("nx" => ["A", "B", "C"]) views_conf ┼ nothing rf ┼ Float64: 0.0 tau ┴ nothingRelated
AbstractLowOrderPriorEstimator_AFEmpiricalPriorBlackLittermanViewsUniverseSetsLowOrderPriorpriorfactoryport_opt_view
References
- [29] F. Black and R. Litterman. Global portfolio optimization. Financial Analysts Journal 48, 28–43 (1992).
- [5] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Section 5.1, Equations 5.13 to 5.15.
- [74] J. Walters. The Black-Litterman model in detail. SSRN Electronic Journal (2011).
- [75] T. Idzorek. A step-by-step guide to the Black-Litterman model: incorporating user-specified confidence levels. In: Forecasting Expected Returns in the Financial Markets (Academic Press, 2007); pp. 17–38. For the
views_confbranch ofcalc_omega.
PortfolioOptimisers.prior — Function
prior(pe::BlackLittermanPrior, X::MatNum, F::Option{<:MatNum} = nothing,
pnl::Option{<:AssetPanel} = nothing;
dims::Int = 1, strict::Bool = false, kwargs...)Compute the Black-Litterman prior moments for asset returns.
prior estimates the mean and covariance of asset returns using the Black-Litterman model, combining a prior estimator, matrix post-processing, user or algorithmic views, asset sets, view confidences, risk-free rate, and blending parameter tau. The method supports both direct and constraint-based views, flexible confidence specification, and matrix processing.
When pe.tau is nothing the blending parameter is 1/T, where T is the number of observations of the oriented X. pe.rf reaches the answer once, on the posterior asset expected returns; apply_rf owns that contract.
Mathematical definition
The Black-Litterman posterior distribution combines the prior $(\boldsymbol{\Pi}, \tau \mathbf{\Sigma})$ with investor views $(\mathbf{P}, \boldsymbol{q}, \mathbf{\Omega})$. vanilla_posteriors computes the algebraically equivalent inverse-free form:
\[\begin{align} \hat{\boldsymbol{\mu}}_{BL} &= \left[(\tau\mathbf{\Sigma})^{-1} + \mathbf{P}^\intercal \mathbf{\Omega}^{-1} \mathbf{P}\right]^{-1} \left[(\tau\mathbf{\Sigma})^{-1} \boldsymbol{\Pi} + \mathbf{P}^\intercal \mathbf{\Omega}^{-1} \boldsymbol{q}\right]\,. \end{align}\]
\[\begin{align} \hat{\mathbf{\Sigma}}_{BL} &= \mathbf{\Sigma} + \left[(\tau\mathbf{\Sigma})^{-1} + \mathbf{P}^\intercal \mathbf{\Omega}^{-1} \mathbf{P}\right]^{-1}\,. \end{align}\]
Where:
- $\boldsymbol{\Pi}$:
N × 1prior (equilibrium) expected returns. - $\mathbf{\Sigma}$:
N × Nprior covariance matrix. - $\tau$: Scaling parameter for the uncertainty in the prior.
- $\mathbf{P}$:
K × Nviews matrix (each row is one view). - $\boldsymbol{q}$:
K × 1views vector. - $\mathbf{\Omega}$:
K × Kviews uncertainty matrix.
Algorithm
- Orient
XandFwithdims_oriented, toobservations × assetsandobservations × factors. - When
pe.viewsresolves names, check that the asset universe is as long asXis wide. A precomputedBlackLittermanViewsresolves no name, so it is not checked here; step 4 checks its width instead. - Fit the wrapped prior
pe.peon(X, F), givingprior_model. - Derive the Investable Mask and the reduced view universe with
investable_views, and refuse a precomputed view matrix over a gapped universe withassert_bl_precomputed_universe. - View the fitted prior at the mask with
investable_prior, and readposterior_X,prior_muandprior_sigmaoff that. - Assemble the views and their uncertainty with
bl_preroll, over the reducedprior_sigmaandsize(X, 1)observations, givingP,Q,tauandomega, ornothingwhen a departure took the last view. The axis is left at its default,:xkey, because these views land on the assets. - Run the master equations with
bl_posteriors, givingposterior_muandposterior_sigmaover the investable assets. - Add
pe.rftoposterior_muwithapply_rf. This is the one site that adds it. - Process
posterior_sigmain place withmatrix_processing!, underpe.mpandposterior_X, while it is still the reduced block a factorisation exists for. - Announce the departures once with
announce_bl_departures. - Write both posteriors back onto the full asset universe with
expand_moment, so a non-investable asset carriesNaNinmuand on the diagonal ofsigma. - Forward the whole of
prior_modelwithforward_prior, replacingmuandsigmaby the expanded pair and droppingchol.
Arguments
pe: Black-Litterman prior estimator.X: Asset returns matrix (observations × assets).F: Optional factor matrix.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.dims: Dimension along which to perform the computation.strict: Iftrue, enforce strict validation of views and sets. Default isfalse.kwargs...: Additional keyword arguments passed to underlying estimators and matrix processing.
Validation
dims in (1, 2).- If
pe.viewsis aLinearConstraintEstimator,length(pe.sets.dict[pe.sets.xkey]) == size(X, 2).
Returns
pr::LowOrderPrior: Result object containing asset returns, posterior mean vector, and posterior covariance matrix.
Related
BlackLittermanPriorLowOrderPriorpriorbl_prerollAssemblesP,Q,tauandomega, and resolvespe.tauto1/Twhen the estimator carries none.calc_omegavanilla_posteriorsapply_rfforward_prior
References
- [5]
- D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025).
- [29]
- F. Black and R. Litterman. Global portfolio optimization. Financial Analysts Journal 48, 28–43 (1992).
- [74]
- J. Walters. The Black-Litterman model in detail. SSRN Electronic Journal (2011).
- [75]
- T. Idzorek. A step-by-step guide to the Black-Litterman model: incorporating user-specified confidence levels. In: Forecasting Expected Returns in the Financial Markets (Academic Press, 2007); pp. 17–38.