Feature distance active rows: private API
PortfolioOptimisers.active_window — Function
active_window(amsk, Z::Arr3Num, dims::Integer)Check the active mask of a window against the window, and give it only when a cell of it is inactive.
The active mask marks, for each observation of the window and each asset, whether the asset is in the universe. A window with no inactive cell reads as nothing, so the collapse takes the path that reads every row, and its result is the one it gives with no mask.
Algorithm
amskisnothing: returnnothing.- Otherwise check that
amskisobservations × assetsfor the layout thatdimsdeclares, and returnnothingwhen every entry istrue, oramskotherwise.
Arguments
amsk: The active mask of the window,observations × assets, ornothingwhen every cell is active.Z: Feature matrixassets × featuresifdims = 1,features × assetswhendims = 2. May also be a 3-D array of time-varying features, in which case the observation axis always leads:observations × assets × featuresifdims = 1,observations × features × assetswhendims = 2.dims: Dimension along which to perform the computation.
Validation
size(amsk) == (size(Z, 1), assets). Raises aDimensionMismatch.
Returns
A::Option{<:AbstractMatrix{Bool}}: The active mask, ornothingwhen every cell is active.
Related
PortfolioOptimisers.blank_unreadable — Function
blank_unreadable(Z::Arr3Num, A::AbstractMatrix{Bool}, dims::Integer)Give a copy of a window of time-varying features with a zero at each cell that the mask A marks unreadable.
A collapse reads each asset, or each pair of assets, only at its own readable rows, so the value of an unreadable cell must reach neither the distance nor a refusal. distance checks this copy with assert_feature_matrix and collapses it. A NaN, or a value outside the domain of the metric, at an unreadable cell then refuses nothing, and no pass of a collapse reads it: StackObservations measures the whole stack before it measures a pair again on its shared rows, and AggregateDistances measures every asset at each row before it keeps the pairs that both are active at. The zero is the value that feature_window writes at a placeholder, and that the panel collapse of a meta-optimiser writes at an inactive cell. The copy keeps the element type of Z.
Arguments
Z: Feature matrixassets × featuresifdims = 1,features × assetswhendims = 2. May also be a 3-D array of time-varying features, in which case the observation axis always leads:observations × assets × featuresifdims = 1,observations × features × assetswhendims = 2.A: The mask of readable cells of the window,observations × assets.dims: Dimension along which to perform the computation.
Returns
Zr::Array: The window, the same size and element type asZ, with a zero at each unreadable cell.
Related
PortfolioOptimisers.feature_asset_labels — Function
feature_asset_labels(nx, i::AbstractVector{<:Integer}) -> String
feature_asset_labels(nx, E::AbstractVector{<:Tuple}) -> StringName the assets at the positions i, or the pairs of positions E, for a refusal: by their names when nx holds them, and by their positions otherwise.
Related
PortfolioOptimisers.assert_feature_readable — Function
assert_feature_readable(alg, A, nx)Refuse a window in which the collapse has no value to read for an asset, and name each such asset.
Inside a fit, feature_readable_mask drops such an asset at the entry of the optimiser, so the collapse never meets it. A direct call of distance, cor_and_dist or clusterise has no entry of a fit, so it refuses here.
Arguments
alg: The collapse algorithm.A: The active mask of the window,observations × assets, ornothingwhen every cell is active.nx: The asset names, ornothing.
Validation
- Every asset is readable by
feature_readable. Raises anArgumentErrorthat names each other asset and the remedy.
Returns
nothing.
Related
PortfolioOptimisers.unreadable_message — Function
unreadable_message(alg::AbstractFeatureCollapseAlgorithm) -> StringState why a collapse has no value to read for an asset, and the remedy, for the refusal of assert_feature_readable. LastRow reads the last row alone, so it names LastActiveRow as a remedy too.
Related
PortfolioOptimisers.asset_major — Function
asset_major(Z::Arr3Num, dims::Integer)Give a window of time-varying features in the layout observations × assets × features, whichever trailing axis dims says the assets occupy.
Related
PortfolioOptimisers.active_collapse — Function
active_collapse(alg::AbstractCollapseAlgorithm, Zd::Arr3Num, w, A, nx)Collapse each asset's features over its own active rows, with the weights of those rows.
The weights are resolved once against the whole window. Each asset keeps the entries of its active rows, and the collapse divides by their sum, so an inactive cell has no weight.
\[\begin{align} \bar{z}_{i,\,k} &= \dfrac{\sum\limits_{t=1}^{T} w_{t} a_{t,\,i} z_{t,\,i,\,k}}{\sum\limits_{t=1}^{T} w_{t} a_{t,\,i}}\,, \end{align}\]
Where:
- $\bar{z}_{i,\,k}$: Collapsed feature $k$ of asset $i$, the aggregate of $z_{t,\,i,\,k}$ over the observation axis.
- $z_{t,\,i,\,k}$: Feature window entry: feature $k$ of asset $i$ at observation $t$.
- $a_{t,\,i}$: Entry of the active mask,
1when asset $i$ is active at observation $t$ and0otherwise. - $w_{t}$: Observation weight of observation $t$.
- $T$: Number of observations.
MedianCollapse takes the same restricted weights.
Algorithm
- Find the active rows of each asset.
- Check that the weights of each asset's active rows sum to more than zero.
- Collapse each asset over its active rows with
collapse_features, under the weights of those rows, and stack the results by asset.
Arguments
alg: The collapse algorithm.Zd: The window,observations × assets × features.w: The resolved observation weights of the window, ornothing.A: The active mask of the window,observations × assets.nx: The asset names, ornothing.
Validation
- The weights of the active rows of each asset sum to more than zero. Raises an
ArgumentErrorthat names each other asset.
Returns
Zc::Matrix{<:Number}: The collapsed features,assets × features.
Related
PortfolioOptimisers.active_weights — Function
active_weights(w, r::AbstractVector{<:Integer})Restrict the resolved observation weights of a window to the rows r at which an asset is active, keeping the kind of the weights through nothing_scalar_array_getindex. No weights stay nothing.
Related
PortfolioOptimisers.pair_distance — Function
pair_distance(metric::Distances.SemiMetric, a::AbstractVector, b::AbstractVector)Measure one pair of feature vectors, and apply the zero-feature-vector convention of patch_zero_feature_vectors! to the result.
Related
PortfolioOptimisers.stack_metric — Function
stack_metric(metric::Distances.SemiMetric, idx::AbstractVector{<:Integer})Restrict a metric to the coordinates idx of a stack. A weighted metric keeps the weights of those coordinates, and every other metric is returned unchanged.
Related
PortfolioOptimisers.stack_rescale — Function
stack_rescale(metric::Distances.SemiMetric, d::Number, idx::AbstractVector{<:Integer}, len::Integer)Rescale the distance d of a pair, measured on the coordinates idx of a stack, to all len coordinates of the stack.
StackObservations measures a pair on the rows at which both assets are active. A metric that sums over the coordinates then sums over fewer of them, and gives a smaller distance than the whole window would. The rescale is the one that makes the sum an estimate of the sum over the whole window.
| Metric | Rescale |
|---|---|
Distances.Cityblock, Distances.TotalVariation, Distances.SqEuclidean, Distances.ChiSqDist | $d \cdot L / n$ |
Distances.Euclidean | $d \cdot \sqrt{L / n}$ |
Distances.Minkowski | $d \cdot (L / n)^{1/p}$ |
| A weighted form | the ratio of the weight sums in place of $L / n$ |
AngularDist, Distances.CosineDist, Distances.CorrDist, Distances.Jaccard, Distances.BrayCurtis, and the three mean deviations | none |
Where $L$ is len and $n$ is the length of idx. Every coordinate of a row carries the features of one observation, so $L / n$ is $T / n$ in rows. Another metric has no method, and it refuses. The message names the method to add.
Arguments
metric: The distance metric.d: The distance of the pair on the coordinatesidx.idx: The coordinates of the stack that the pair shares.len: The number of coordinates of the stack.
Returns
d: The rescaled distance.
Related
PortfolioOptimisers.fallback_features — Function
fallback_features(alg::AbstractFeatureCollapseAlgorithm, z::AbstractVector, T::Integer)Lay out an asset's collapsed features as the collapse reads one asset. AggregateDistances reads the features of one row, z itself. StackObservations reads the stack of every row, so z fills each of the T rows.
Related
PortfolioOptimisers.resolve_empty_pairs! — Function
resolve_empty_pairs!(D::MatNum, pair::AbstractEmptyPairAlgorithm, E, de::FeatureDistance, win)Hand the empty pairs E to empty_pair_distance!, or return D unchanged when no pair is empty.
Related
PortfolioOptimisers.active_feature_distance — Function
active_feature_distance(de::FeatureDistance, win::NamedTuple)Turn a window of time-varying features that holds an inactive cell into a distance matrix, reading each asset or each pair at its own active rows.
win holds the window Z, its layout dims, its active mask A and the asset names nx. Z holds a zero at each cell that A marks false, from blank_unreadable, so no step of a collapse reads the stored value of such a cell. distance calls this function only when a cell of the window is inactive, and only after assert_feature_readable checked that the collapse can read each asset. A window with no inactive cell takes the path of feature_distance, so its result does not change.
Algorithm
The type of de.alg selects one of four methods.
LastObservation: underLastRow, or when every asset is active at the last row, measure the last row. Otherwise measure each asset at its last active row.AggregateFeatures: resolve the weights withcollapse_weights, collapse each asset over its own active rows withactive_collapse, and measure the collapsed matrix.AggregateDistances: measure each row, and add each entry of a pair only at a row where both assets are active, with that row's weight. Check that the weight total of each asset, on the diagonal, is more than zero. Divide each entry by its own weight total, and give each pair with a zero total toresolve_empty_pairs!.StackObservations: measure the whole stack. Measure each pair that shares fewer rows than the window again, on the coordinates of its shared rows, withstack_metric, and rescale it withstack_rescale. Give each pair with no shared row toresolve_empty_pairs!.
Arguments
de: Feature distance estimator.win: The window, aNamedTupleofZ,dims,Aandnx.
Returns
D::MatNum: Distance matrixassets x assets, in the units the distance algorithm defines.
Related
PortfolioOptimisers.accumulate_active_pairs! — Function
accumulate_active_pairs!(D::MatNum, S::MatNum, Dt::MatNum, wt::Number, m::AbstractVector{Bool})Add one row of AggregateDistances to its accumulators: wt * Dt[i, j] to D[i, j] and wt to the weight total S[i, j] of each pair whose two assets are both active at the row, as m marks them.
Related
PortfolioOptimisers.shared_stack_distance — Function
shared_stack_distance(metric::Distances.SemiMetric, Zs::MatNum, (i, j), rows::AbstractVector, T::Integer)Measure the pair (i, j) of a stack Zs, assets × (observations · features), on the coordinates of its shared active rows, and rescale the distance to the whole window of T rows.
Algorithm
- Name the coordinates of the shared rows,
t + (k - 1) Tfor each shared rowtand each featurek. - Measure the two assets on those coordinates with
pair_distance, under the metric restricted bystack_metric. - Rescale the distance to every coordinate of the stack with
stack_rescale.
Related
PortfolioOptimisers.feature_readable_mask — Function
feature_readable_mask(x, imsk::Option{<:BitVector}, rd) -> Option{BitVector}Compose the Investable Mask of a prior with the assets that each FeatureDistance inside x can read, at the entry of a fit.
A fit reduces its prior, its optimiser and its returns data to the Investable Mask once, at its entry, with investable_reduction. An asset that the prior admits can still have no value that a FeatureDistance of the fit can read in the window of its Asset Panel. A cell is readable where the asset is active and every value column of the Feature Selector holds data, observed or filled. LastRow reads nothing for an asset whose last cell is not readable, and every collapse reads nothing for an asset with no readable row. A static panel has one row, so an asset with a placeholder has none. This function drops such an asset from the mask before the reduction. The asset then departs as a non-investable asset: the reduction announces it, the fit gives it a zero weight, and it is listed on the Non-Investable Axis. Under DropFewerRows it also drops, from each pair with no shared active row, the asset with fewer active rows, until no pair is empty.
A default prior drops every asset that is not active over its whole window, so under it this function drops only an asset with a placeholder.
Every fit that clusters or builds a phylogeny calls it: HierarchicalRiskParity, HierarchicalEqualRiskContribution, SchurComplementHierarchicalRiskParity, NestedClustered, and a JuMPOptimiser through its phylogeny and centrality estimators. Stacking and SubsetResampling cluster only inside their inner optimisers, and each of those calls it at its own entry.
Algorithm
The method that Julia selects is the algorithm.
- A
Tupleor a vector: compose the mask of each entry in turn. - An estimator that holds a distance estimator, such as a
ClustersEstimator: forward to the estimator it holds. - A
FeatureDistancewith no producer, on returns data that holds a panel: take the mask of readable cells in the rows that the collapse reads, withentry_activity. Mark the readable assets withfeature_readable, keep those thatimskkeeps, and hand the result todrop_empty_pairs!. Returnnothingwhenimskisnothingand every asset stays. - Every other case, a producer included, a panel whose every cell is readable, and no panel: return
imskunchanged.
Arguments
x: An estimator, a vector or aTupleof estimators.imsk: The Investable Mask of the prior, ornothingwhen every asset is investable.rd: The returns result to use.
Validation
- At least one asset stays. Raises an
IsEmptyError.
Returns
imsk::Option{BitVector}: The composed mask, ornothingwhen every asset stays.
Related
PortfolioOptimisers.compose_readable_mask — Function
compose_readable_mask(alg::AbstractFeatureCollapseAlgorithm, A, imsk::Option{<:BitVector})Compose the Investable Mask imsk with the assets that the collapse alg can read in a window whose active mask is A. This is step 3 of feature_readable_mask, which states it. A window with no active mask, A === nothing, keeps imsk.
Related
PortfolioOptimisers.entry_activity — Function
entry_activity(de::FeatureDistance, pnl)Give the mask of the cells that de can read in the window of the panel pnl, with feature_window_mask, for the entry of a fit. Returns data with no panel gives nothing.
Related
PortfolioOptimisers.feature_window_mask — Function
feature_window_mask(alg, pnl::AssetPanel, cols::AbstractVector{Tuple{Int, Int, Symbol}}) -> (rows, A)Name the rows that a collapse reads, and cut the mask of the cells it can read to them.
A cell is readable where the asset is active and every value column of cols holds data: readable_cells joins the active mask of the panel with feature_data_cells. A cell that holds the placeholder of a blank that no fill reached holds no data. So a collapse reads it as it reads an inactive cell: each asset and each pair at its own readable rows. readable_window_rows names the rows on this mask, so LastActiveRow reads the last readable row of each asset. window_activity cuts the mask to the rows.
Arguments
alg: The collapse algorithm.pnl: The Asset Panel.cols: The resolved columns, fromselect_fields.
Returns
rows: Therowskeyword offeature_matrix.A::Option{<:AbstractMatrix{Bool}}: The mask of readable cells in those rows, seewindow_activity.
Related
PortfolioOptimisers.readable_cells — Function
readable_cells(amsk, o)Join the active mask amsk of a panel with the mask o of its cells that hold data: a cell is readable where both are true. Either mask can be nothing, which marks every cell true.
Related
PortfolioOptimisers.readable_window_rows — Function
readable_window_rows(alg, pnl::AssetPanel, R)Name the rows that a collapse reads on the mask R of readable cells. LastObservation forwards to its rule. LastActiveRow on a time-varying panel names them with last_active_rows on R, so an asset whose last active cell holds a placeholder is read at its last readable row. Every other case is collapse_rows.
Related
PortfolioOptimisers.last_active_rows — Function
last_active_rows(A)Name the rows from the earliest last true row of an asset in the mask A, observations × assets, to the last row: r0:nobs, where r0 is nobs when no asset has a true row. These rows hold the last true row of every asset that has one. nothing names every row, Colon().
Related
PortfolioOptimisers.static_window — Function
static_window(amsk, Z::MatNum, dims::Integer)Check the one-row mask of a static Feature Matrix against the matrix. A static matrix has one row of cells, so its mask is 1 × assets, and nothing marks every asset readable.
Validation
size(amsk) == (1, assets), wheredimsnames the asset axis ofZ. Raises aDimensionMismatch.
Related
PortfolioOptimisers.empty_pair_rule — Function
empty_pair_rule(alg::AbstractFeatureCollapseAlgorithm)Give the rule for a pair with no shared active row that a collapse carries: the pair field of AggregateDistances and StackObservations, and nothing for a collapse that reads no pair.
Related
PortfolioOptimisers.first_empty_pair — Function
first_empty_pair(keep::BitVector, A::AbstractMatrix{Bool})Find the first pair (i, j) of kept assets, with i < j, that shares no active row of A, in the order of j and then of i, or nothing when no pair is empty.
Related