Base asset selection: private API

Types

PortfolioOptimisers.AbstractAssetSelectorType
abstract type AbstractAssetSelector <: AbstractReturnsPreprocessingEstimator

Abstract supertype for returns-level preprocessing estimators that restrict the asset universe.

An asset selector answers one question on the training window — which asset columns survive? — and that answer is its fitted state. apply_preprocessing replays the fitted universe on unseen windows, so a selector is safe inside cross-validation: the selection is made on train data alone and never re-decided on test data.

Concrete subtypes implement a single method, select_assets; the family shares one fit_preprocessing and one apply_preprocessing.

The funnel reduces the training window to its Coverage Universe before it calls select_assets, so a selector ranks among the assets that are live throughout that window and never among an asset that is not yet listed, is delisted, or is missing a quote. A selector therefore needs no finiteness guard of its own, and CompleteAssetSelector is the identity on the reduced window.

Selectors restrict columns only. Observation filtering is a price-level concern (MissingDataFilter), because a fitted transformation cannot decide which rows of an unseen window to drop without breaking the weights/returns alignment assert_universe_aligned enforces.

See docs/adr/0029-asset-selection-is-returns-preprocessing.md for the design rationale.

Related

source

Functions

PortfolioOptimisers.find_complete_indicesFunction
find_complete_indices(X::AbstractMatrix; dims::Int = 1) -> VecInt

Return the indices of columns (or rows) in matrix X that do not contain any missing or NaN values.

This function scans the specified dimension of the input matrix and returns the indices of columns (or rows) that are complete, i.e., contain no missing or NaN values.

Internal machinery — the caller-facing form is CompleteAssetSelector, which wraps the dims = 1 (complete-column) mode as a fit/apply estimator. The dims = 2 (complete-row) mode has no estimator form: dropping observations is a price-level concern (MissingDataFilter).

Algorithm

  1. Orient X with dims_oriented, so that the axis to test is axis 2 in both modes. dims = 2 transposes the matrix, and dims = 1 leaves it alone.
  2. Read the column count N of the oriented matrix.
  3. For each column of the oriented matrix, test whether it holds a missing entry or a NaN entry. Collect the positions of the columns that do, giving to_remove. One entry is enough to remove the whole column.
  4. Return setdiff(1:N, to_remove), the positions of the complete columns, in ascending order.

Arguments

  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • dims: Dimension along which to perform the computation.

Validation

  • dims in (1, 2).

Returns

  • res::VecInt: Indices of columns (or rows) in X that are complete.

Examples

julia> X = [1.0 2.0 NaN; 4.0 missing 6.0];julia> PortfolioOptimisers.find_complete_indices(X)1-element Vector{Int64}: 1julia> PortfolioOptimisers.find_complete_indices(X; dims = 2)Int64[]

Related

source