Carrier views: private API

PortfolioOptimisers.feature_row_indicesFunction
feature_row_indices(pnl::Nothing, ts_new, ts_old) -> Colon
feature_row_indices(pnl::AssetPanel, ts_new, ts_old) -> Union{Colon, VecInt}

Recover the positional row indices of a time-varying AssetPanel from a timestamp window.

A Panel Field holds a plain array, so its observation axis is parallel to the carrier's clock positionally rather than aligned by timestamp. Whenever a routine selects rows of X by timestamp, the surviving timestamps are matched back into the original clock to recover the rows the panel must keep. A surviving timestamp absent from that clock throws: it means the row bookkeeping has been broken (a synthesised timestamp, or an outer join that introduced a row X never had), and slicing the panel positionally from there would silently pair each asset with another period's values.

Two sites use it. At price level the clock is TimeSeries.timestamp(X) and the selection is a timestamp window. At the cross-validation assembly seam the clock is ReturnsResult.ts and the selection is a fold: fold_row_indices recovers a fold's rows from the timestamps its view of the returns already carries, which is why ts must be unique — it keys the observation axis rather than merely labelling it.

The static and absent shapes have no observation axis, so they return Colon and cost nothing.

Algorithm

The method that Julia selects is the algorithm.

  1. pnl is nothing, or static: return Colon(). Neither has an observation axis, so there is no row to recover and the timestamps are not read.
  2. pnl is time-varying: match ts_new into ts_old with matched_row_indices, which throws when the selection kept no timestamp, or when a surviving timestamp is absent from the original clock.

Arguments

  • pnl: The Asset Panel, or nothing.
  • ts_new: Timestamps surviving the selection.
  • ts_old: Timestamps of the clock the panel's observation axis is parallel to.

Validation

  • ts_new is not nothing when the panel is time-varying.
  • Every entry of ts_new appears in ts_old.

Returns

  • Colon for a static or absent panel; otherwise the row indices, as a Vector{Int}.

Related

source
PortfolioOptimisers.matched_row_indicesFunction
matched_row_indices(ts_new::Nothing, ts_old) -> Union{}
matched_row_indices(ts_new, ts_old) -> Vector{Int}

Match the surviving timestamps back into the original clock, and return the rows they hold.

The body feature_row_indices shares between the time-varying feature matrix and the time-varying AssetPanel: both hold their observation axis parallel to the carrier's clock positionally, so both recover their rows the same way.

Algorithm

The method that Julia selects is the algorithm.

  1. ts_new is nothing: throw. The selection kept no timestamp, so the rows to keep cannot be named.
  2. Otherwise match ts_new into ts_old with indexin, check that every surviving timestamp was found, and return the positions as a Vector{Int}.

Arguments

  • ts_new: Timestamps that survived the selection.
  • ts_old: Timestamps of the clock the observation axis is parallel to.

Validation

  • ts_new is not nothing. Raises an ArgumentError.
  • Every entry of ts_new appears in ts_old. Raises an ArgumentError.

Returns

  • rows::Vector{Int}: The position each surviving timestamp holds in the original clock.

Related

source
PortfolioOptimisers.panel_feature_namesFunction
panel_feature_names(pnl::Nothing) -> nothing
panel_feature_names(pnl::AssetPanel) -> Vector{String}

Name the columns an AssetPanel derives, without building the Feature Matrix.

A consumer that needs the column names alone reads them here, and the values are not stacked to answer it.

Algorithm

The method that Julia selects is the algorithm.

  1. pnl is nothing: return nothing.
  2. pnl is an AssetPanel: walk its Panel Fields, appending each one's value column names and then its observed-mask column names.

Arguments

  • pnl: The Asset Panel, or nothing.

Returns

  • nz::Option{Vector{String}}: One name per derived column, or nothing.

Related

source
PortfolioOptimisers.panel_carrier_viewFunction
panel_carrier_view(pnl::Nothing, i, j, nx) -> nothing
panel_carrier_view(pnl::AssetPanel, i, j, nx) -> AssetPanel

View a carrier's AssetPanel, or return nothing when the carrier holds none.

The one-line wrapper every carrier view goes through, so the nothing case is written once rather than at each of the six sites that slice a panel.

Algorithm

The method that Julia selects is the algorithm.

  1. pnl is nothing: return nothing.
  2. pnl is an AssetPanel: return port_opt_view of it.

Arguments

  • pnl: The Asset Panel, or nothing.
  • i: Observation index.
  • j: Asset index.
  • nx: The asset names, or nothing, handed to port_opt_view so that a tensor Panel Field whose labels are the asset names is cut on its label axis too.

Returns

  • An Asset Panel over the selected observations and assets, or nothing.

Related

source