The Listing Span: private API
Types
PortfolioOptimisers.ListingSpan — Type
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 carrieslast[i] < first[i], the empty interval.
n: Length of the clock the span is stated on.
Constructors
ListingSpan(first::VecInt, last::VecInt, n::Integer) -> ListingSpanValidation
length(first) == length(last). Raises aDimensionMismatch.n >= 0. Raises aDomainError.
Examples
julia> PortfolioOptimisers.ListingSpan([1, 2], [3, 3], 3)ListingSpan(3 × 2)Related
Functions
PortfolioOptimisers.project_span — Function
project_span(span::ListingSpan, m::Integer) -> ListingSpan
project_span(span::AbstractMatrix{Bool}, m::Integer) -> BitMatrixProject 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.
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.- Any other
AbstractMatrix{Bool}: writespan[a, i] && span[a + 1, i]into rowa + 1 - oof the result, whereois 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