Expected Risk: private API

PortfolioOptimisers.resolve_risk_inputsFunction
resolve_risk_inputs(r::BaseRM_VecBaseRM, X::MatNum_Pr)

Turn a value-level data argument into the pair a kernel takes: the measure to evaluate, and the returns matrix to evaluate it on.

A prior result resolves the measure through factory — a Deferred Quantity becomes a value, an unstated slot takes the prior's field — and hands back pr.X. A ReturnsResult carries no moments, so it only unwraps its X. A matrix is already the pair.

Resolution happens once per entry point rather than once per evaluation, which is what keeps risk_contribution from refitting a deferred covariance 2N times.

Related

source
PortfolioOptimisers.original_returnsFunction
original_returns(X::MatNum_Pr)

Take the returns matrix the caller supplied out of whichever carrier holds it.

A prior result answers pr.original_X, a ReturnsResult answers its X, and a matrix answers itself. The three arms agree off a factor route, where pr.original_X === pr.X, and differ on one, where pr.X is the reconstruction F * transpose(M) .+ transpose(b).

This is the read resolve_factor_risk_inputs takes, and it is deliberately not the read resolve_risk_inputs takes. expected_risk evaluates the return distribution the prior asserts, which is pr.X. A factor attribution partitions risk into a factor part and a residual part, and the reconstruction has no residual, so it can only attribute noise to the second.

Arguments

  • X::MatNum_Pr: Returns matrix, prior result, or returns result.

Returns

  • X::MatNum: The returns matrix the caller supplied.

Related

source
PortfolioOptimisers.resolve_factor_risk_inputsFunction
resolve_factor_risk_inputs(r::BaseRM_VecBaseRM, X::MatNum_Pr)

Turn a value-level data argument into the pair a factor attribution takes: the measure to evaluate, and the returns matrix to evaluate it on.

The sibling of resolve_risk_inputs, and it differs in the second half only. The measure resolves the same way, so a Deferred Quantity is still fitted once rather than once per finite difference. The matrix is original_returns rather than pr.X.

Two seams and not one argument, because the two answers are both correct and neither is a default of the other. Every other caller of resolve_risk_inputs wants the distribution the prior asserts.

Related

source
PortfolioOptimisers.resolve_factor_regressionFunction
resolve_factor_regression(re::RegE_Reg, rd::ReturnsResult,
                          pr::Option{<:AbstractPriorResult} = nothing)

Pick the factor loadings a factor attribution decomposes against, from the three carriers that can supply them.

The precedence is fixed, and it is not a source selector:

  1. re when it is already a Regression result. A precomputed result is the caller stating the answer, and it needs no data.
  2. pr.rr when the prior carries a factor block. The loadings are then the ones fitted on pr.original_X, which is the matrix the risk is measured on, so the pair is matched by construction.
  3. regression(re, rd) otherwise, which needs rd.X and rd.F.
Warning

A stated regression estimator loses to a prior that carries loadings. re is honoured only when the prior has none. Pass the loadings as a precomputed Regression to override a factor prior, or pass the returns matrix rather than the prior to keep the refit.

Arguments

  • re::RegE_Reg: Regression result or estimator.
  • rd::ReturnsResult: Returns result carrying X and F.
  • pr::Option{<:AbstractPriorResult}: Prior result, or nothing when the caller passed a bare matrix.

Validation

  • When none of the three arms applies, throws an IsNothingError naming all three.

Returns

  • rr::AbstractLoadingsRegressionResult: The factor loadings.

Related

source
PortfolioOptimisers.adjusted_riskFunction
adjusted_risk(sca::Scalariser, r::BaseRM_VecBaseRM, w::VecNum, X::MatNum,
              fees::Option{<:Fees}, delta::Number; kwargs...)

Evaluate the risk at w with the homogeneity correction already applied, for one measure or several.

The internal seam that lets risk_contribution keep one body across the multiplicity. It exists because the correction cannot be applied to the aggregate.

adjust_risk_contribution is a homogeneity correction: it divides by the measure's own degree, so that Σᵢ wᵢ·rcᵢ recovers the measure's value by Euler's identity. A mixed vector such as [Variance(), ConditionalValueatRisk()] is a sum of a degree-2 and a degree-1 function, so it has no single degree and adjusting the aggregate is not merely awkward but impossible.

Adjusting each element before the scalariser restores the identity exactly:

Σᵢ wᵢ·rcᵢ  =  Σₖ sₖ·aₖ·Σᵢ wᵢ·∂ρₖ/∂wᵢ  =  Σₖ sₖ·aₖ·degₖ·ρₖ  =  Σₖ sₖ·ρₖ

which is expected_risk(rs, w, X, fees) under SumScalariser. The invariant survives an arbitrary mixture of homogeneity degrees, and it survives only because the correction sits inside the loop.

sca is inert on a single measure and scale is inert on a single measure, exactly as they are in expected_risk.

Related

source