Asset Panel builder: private API

Types

PortfolioOptimisers.AbstractAssetPanelEstimatorType
abstract type AbstractAssetPanelEstimator <: AbstractEstimator

Abstract supertype for every producer that builds an AssetPanel at the point of use.

A producer is configuration, not data: FeatureDistance holds one in its ape slot, a view passes it through unchanged, and a fold refits it on the subproblem's own prior and returns. It answers one verb, asset_panel(ape, pr, rd, X), and returns a static AssetPanel holding one TensorPanelField: a loadings matrix and a proximity matrix are each one quantity with a labelled third axis.

The family is open: a producer that reads a source no shipped member reads defines a member and an asset_panel method for it.

nothing in the slot is not a member. It reads the panel the data carrier already holds, which is what the same verb answers for it.

Related

source

Functions

PortfolioOptimisers.panel_build_observationsFunction
panel_build_observations(inputs::AbstractVector{<:AbstractPanelFieldInput},
                         amsk::Option{<:AbstractMatrix{Bool}},
                         emsk::Option{<:AbstractMatrix{Bool}}) -> Option{Int}

Return the observation count an asset_panel build takes, or nothing when the build is static.

The build is time-varying when any input carries an observation axis, or when a universe mask is given. The masks are the second signal because an AssetPanel couples them to the shape: they are nothing if and only if the panel is static, so masks beside static inputs alone are a request for observations rather than a contradiction. A static input of a time-varying build is lifted by panel_field_lift.

Algorithm

  1. Return the leading axis of the first time-varying input, when there is one.
  2. Otherwise return the leading axis of amsk, then of emsk, whichever is given.
  3. Otherwise return nothing, which is the static build.

Arguments

  • inputs: The raw Panel Fields.
  • amsk: The active mask, or nothing.
  • emsk: The estimation mask, or nothing.

Returns

  • T::Option{Int}: The observation count, or nothing for a static build.

Related

source
PortfolioOptimisers.panel_fill_arrayFunction
panel_fill_array(vals::AbstractArray, alg::AbstractPanelFillAlgorithm, name::AbstractString, tv::Bool)

Resolve the blanks of one raw Panel Field, and return the filled array.

The fill runs per asset, along the observation axis, which is the only axis a point-in-time panel blanks along: an asset lists late or delists, so its history has a head or a tail of blanks, and the cross-section at one observation is not the thing being carried across.

A static raw Panel Field has no observation axis. Its two admitted policies are cell-wise, so the whole array is resolved as one flat run and reshaped back.

Algorithm

  1. When the raw Panel Field is static, resolve vec(vals) with panel_fill and reshape the result.
  2. Otherwise walk the trailing axes, and resolve each column of the observation axis with panel_fill.

Arguments

  • vals: The raw values, blanks included.
  • alg: The fill policy.
  • name: The Panel Field's name, displayed in the error messages.
  • tv: Whether the raw values carry an observation axis.

Returns

  • filled::AbstractArray: The same size as vals, and free of blanks.

Related

source
PortfolioOptimisers.panel_directional_fillFunction
panel_directional_fill(
    v::AbstractVector,
    val,
    lim::Union{Nothing, Integer},
    order
) -> Any

Carry the last observed value along one traversal of the observation axis.

The one body behind ForwardPanelFill and BackwardPanelFill: the two differ only in the order they walk v, so they pass a different order and share everything else.

Algorithm

  1. Start with no carried value and a run length of zero.
  2. Walk order. On an observed cell, take it as the carried value and reset the run to zero.
  3. On a blank cell, raise the run by one. Write the carried value when one exists and the run is within lim, and write val otherwise.

Arguments

  • v: One asset's raw values along the observation axis, blanks included.
  • val: The value a cell becomes when nothing can be carried into it.
  • lim: Longest run of consecutive blanks a value is carried across, or nothing for no limit.
  • order: The traversal order of the observation axis.

Returns

  • filled::Vector: The same length as v, and free of blanks. Its element type is the union of the raw column's and val's, so panel_value_eltype narrows it by the cells it holds: a column that carried no blank keeps its own type, and val widens it only where it was written.

Related

source
PortfolioOptimisers.is_panel_blankFunction
is_panel_blank(x) -> Bool

Return whether one raw cell of a Panel Field is blank.

A raw Panel Field carries its blanks in whichever of the three conventions its source used, and all three mean the same thing here: missing, which a tabular source writes; nothing, which a source parsed from a document with an explicit null writes; and a floating-point NaN.

Algorithm

  1. Return true when the cell is missing or nothing.
  2. Return true when the cell is a Number and isnan of it.
  3. Return false otherwise.

Arguments

  • x: One raw cell.

Returns

  • blank::Bool: Whether the cell is blank.

Related

source
PortfolioOptimisers.assert_panel_fillFunction
assert_panel_fill(val::Union{<:Number, <:AbstractString}, lim::Option{<:Integer}) -> nothing

Check the terminal value and the run limit shared by the two directional fill policies.

Algorithm

  1. When val is a Number, check that it is finite.
  2. When lim is not nothing, check that it is > 0.

Arguments

  • val: The value a cell becomes when the fill has nothing to carry into it.
  • lim: Longest run of consecutive blanks the fill carries a value across, or nothing.

Validation

  • isfinite(val) when val is a Number. Raises an IsNonFiniteError.
  • lim > 0 when lim is not nothing. Raises a DomainError.

Returns

  • nothing.

Related

source
PortfolioOptimisers.assert_categorical_fillFunction
assert_categorical_fill(alg::NoPanelFill, name::AbstractString) -> nothing
assert_categorical_fill(alg::AbstractPanelFillAlgorithm, name::AbstractString) -> nothing

Check that the fill policy of a categorical input writes a label.

Every fill policy but NoPanelFill carries a val, and the three default it to 0.0, which is the right default for a number and a wrong one for a label: a categorical input that met it would gain a level named "0.0", in silence when its levels are derived. So a categorical input refuses a val that is not an AbstractString.

Arguments

  • alg: The fill policy.
  • name: The Panel Field's name, displayed in the error message.

Validation

  • alg.val isa AbstractString, for a policy that carries one. Raises an ArgumentError.

Returns

  • nothing.

Related

source
PortfolioOptimisers.assert_panel_input_fillFunction
assert_panel_input_fill(inp::AbstractPanelFieldInput) -> nothing

Check that a static raw Panel Field does not carry a directional fill policy.

ForwardPanelFill and BackwardPanelFill carry the last observed value along the observation axis, and a static Panel Field has none. Carrying along the asset axis instead would give asset k the value of asset k - 1, which is not a fill but a fabrication, so the two are refused rather than reinterpreted. NoPanelFill and ConstantPanelFill are cell-wise and are admitted.

Algorithm

  1. Return when the raw Panel Field is time-varying.
  2. Throw when its fill policy is directional.

Arguments

  • inp: The raw Panel Field.

Validation

  • The fill policy of a static raw Panel Field is not directional. Raises an ArgumentError.

Returns

  • nothing.

Related

source