The Listing Span: private API

Types

PortfolioOptimisers.ListingSpanType
struct ListingSpan <: AbstractMatrix{Bool}

Reads a per-asset listing interval as a matrix of booleans, storing two integers per asset.

ListingSpan is the Listing Span: the interval of the price clock over which an asset is listed, from its first priced observation to its last. It answers size as (observations, assets) and getindex(s, t, i) as first[i] <= t <= last[i], so it is an ordinary AbstractMatrix{Bool} to every reader, and it costs two integers per asset rather than one boolean per cell. The compression is exact rather than approximate: under the Span Rule an interior gap leaves an asset listed, so an asset's active set is that interval. A column that is a gap throughout is the empty interval, first[i] > last[i].

It is unexported and Base-only: it owns size, getindex and show, and nothing else in the library dispatches on it. The public bound is AbstractMatrix{Bool}, which is what a caller writes against and what a caller's own declaration — a listing calendar, or a constituency that leaves and rejoins — enters as.

Fields

  • first: Index of each asset's first priced observation, on the clock the span is stated on.
  • last: Index of each asset's last priced observation, on the clock the span is stated on. An asset that is a gap throughout carries last[i] < first[i], the empty interval.
  • n: Length of the clock the span is stated on.

Constructors

ListingSpan(first::VecInt, last::VecInt, n::Integer) -> ListingSpan

Validation

  • length(first) == length(last). Raises a DimensionMismatch.
  • n >= 0. Raises a DomainError.

Examples

julia> PortfolioOptimisers.ListingSpan([1, 2], [3, 3], 3)ListingSpan(3 × 2)

Related

source

Functions

PortfolioOptimisers.project_spanFunction
project_span(span::ListingSpan, m::Integer) -> ListingSpan
project_span(span::AbstractMatrix{Bool}, m::Integer) -> BitMatrix

Project a price-clock listing statement onto a returns clock of m observations.

A return is the change between two consecutive observations, so a return is active exactly when both prices of its pair lie inside the asset's listing. That reading fixes the projection, and it is the same one under either padding convention: with padding the clocks align row for row and the pair of observation t is (t - 1, t), so the leading row is active for nobody; without padding the returns clock is one observation shorter and the pair of observation s is (s, s + 1). Under it the active mask bounds exactly the run of a column's finite returns at both ends, and no asset's inception emits a Held Gap.

On a PortfolioOptimisers.ListingSpan the projection is [first + 1, last] under padding and [first, last - 1] without it, so the two integers per asset survive the crossing rather than being expanded and discarded at it. An asset with a single priced observation gives the empty interval, which is correct: one price yields no return. On any other AbstractMatrix{Bool}, which is how a caller's own declaration enters, the same rule is applied cell by cell, so a constituency that leaves and rejoins books no return across its absence.

Algorithm

The method that Julia selects is the algorithm.

  1. PortfolioOptimisers.ListingSpan: shift the opening bound up by one when the clocks align row for row, and the closing bound down by one when they do not.
  2. Any other AbstractMatrix{Bool}: write span[a, i] && span[a + 1, i] into row a + 1 - o of the result, where o is the row count the returns clock lost.

Arguments

  • span: The listing statement, price observations × assets.
  • m::Integer: Length of the returns clock to project onto.

Returns

  • amsk: The active mask, m × assets, on the returns clock.

Related

source