Hierarchical Risk Parity: private API

PortfolioOptimisers.hierarchical_risk_parity_td_defaultsFunction
hierarchical_risk_parity_td_defaults(

) -> @NamedTuple{r::Variance{RiskMeasureSettings{Float64, Nothing, Bool}, Nothing, Nothing, Nothing, SquaredSOCRiskExpr}, sca::SumScalariser}

Return the static defaults of the HierarchicalRiskParity fields that may hold a TimeDependent.

Shared by the constructor's test-substitution pass and time_dependent_field_defaults, so the fold-less value of a field is declared once. Fields whose static default is nothing are omitted.

Related

source
PortfolioOptimisers.split_factor_weight_constraintsMethod
split_factor_weight_constraints(alpha::Number, wb::WeightBounds, w::VecNum,
                                lc::VecNum, rc::VecNum) -> Number

Clamp a bisection split factor so that neither half of the split leaves its weight bounds.

The recursion scales the left half by alpha and the right half by 1 - alpha. Both halves carry one common weight before the split, so the bounds on that half's total translate into bounds on the factor itself. This method clamps the factor for the left half, then clamps its complement for the right half, and returns what survives both.

Arguments

  • alpha: The unclamped split factor, the left half's share of the part's weight.
  • wb: Resolved weight bounds. wb.lb and wb.ub must be vectors over the whole universe, which is what weight_bounds_constraints returns.
  • w: The current weight vector, before this split is applied.
  • lc: Asset indices of the left half.
  • rc: Asset indices of the right half.

Returns

  • alpha::Number: The clamped split factor. It is a scalar, not a bounds object.

Details

  • Each half's common weight is read from its first member, w[lc[1]] and w[rc[1]], because the recursion has scaled every member of a half by the same factors.
  • A zero common weight is replaced by sqrt(eps(...)), so the division that turns a weight bound into a factor bound cannot divide by zero.
  • The bound on a half is the sum of its members' bounds, so a half whose bounds cannot hold the weight it is given leaves the factor at the nearest reachable value rather than failing.

Related

source
PortfolioOptimisers.hrp_scalarised_riskFunction
hrp_scalarised_risk(sca::Scalariser, wu::MatNum, wk::VecNum, rku::VecNum,
                    lc::VecNum, rc::VecNum, rs::VecOptRM, X::MatNum,
                    fees::Option{<:Fees}) -> Tuple

Combine several risk measures into the one left and one right risk that a bisection step needs.

Each measure builds its own naive risk parity sub-portfolio for the two halves, because the weights follow that measure's own unitary risks. The scalariser then combines the two risk vectors, pair by pair, into a single pair.

Arguments

  • sca: Scalarisation strategy (SumScalariser, MaxScalariser, MinScalariser, or LogSumExpScalariser).
  • wu: Scratch weight matrix, of size size(X, 2) by two. It is refilled per measure.
  • wk: Scratch weight vector for unitary_expected_risks!, of length size(X, 2).
  • rku: Scratch unitary risk vector, of length size(X, 2). It is overwritten per measure.
  • lc: Asset indices of the left half.
  • rc: Asset indices of the right half.
  • rs: Vector of risk measures, already resolved by factory.
  • X: Asset return matrix, observations by assets.
  • fees: Fees, or nothing.

Returns

  • (lrisk, rrisk)::Tuple: The combined left and right risk.

Details

  • Each measure's contribution is multiplied by its own settings.scale before the scalariser sees it.
  • The scalariser reduces over the pair with by = sum, so a MaxScalariser selects the measure with the largest total of the two risks, and returns that measure's own pair.

Related

source