Prices to returns: private API
Functions
PortfolioOptimisers.append_carrier_block! — Function
append_carrier_block!(P::DataFrames.DataFrame, A::Nothing, ts, sym::Symbol) -> Vector{String}
append_carrier_block!(P::DataFrames.DataFrame, A::TimeSeries.TimeArray, ts, sym::Symbol) -> Vector{String}Lay one of the carrier's price blocks beside the asset block, on the asset clock.
The carrier states one clock, so a factor or benchmark series is read at the asset timestamps rather than joined onto them: a join adds or drops observations, which is a clock move, and every clock move belongs to price_ingestion. Laying the columns out one by one also frees prices_to_returns of TimeSeries.merge's one-value-type requirement, so a Float32 factor table beside a Float64 asset table converts instead of raising a MethodError.
Algorithm
- A block that is
nothingcontributes no column and no name. - Otherwise check that the block states the asset clock, and refuse by name if it does not.
- Spell every absent price
NaNwithunify_gaps, the verb the ingestion door runs. It is idempotent on a carrier the layer built, and it is what makes a hand-built carrier holdingmissingconvert like one holdingNaN. - Write each of the block's columns into
Punder its own name, and return the names in order.
Arguments
P: The table the conversion is assembling, already carrying the clock and the asset columns.A: The factor or benchmark price series, ornothing.ts: The asset timestamps, which are the carrier's clock.sym: The block's name in the refusal,:For:B.
Validation
TimeSeries.timestamp(A) == ts. Raises aConflictingArgumentErrornamingprice_ingestion, which is what puts two series on one clock.
Returns
n::Vector{String}: The block's column names, empty when the block isnothing.
Related
PortfolioOptimisers.gap_return_writable — Function
gap_return_writable(
p::AbstractVector,
r::AbstractVector
) -> BitVector
Derive the cells of one column a Gap Return algorithm is allowed to write.
This is the family's invariant, held once rather than re-argued per algorithm. apply_gap_return restores every cell outside the returned set, so no algorithm can rewrite a return computed from two observed prices, manufacture one before an asset's first price, or resurrect a delisting.
The bounds are the Span Rule and its projection, the same ones listing_span and PortfolioOptimisers.project_span state for a whole panel. They are read here off the one price column the conversion is holding, because the writable set is per column and the table reaching prices_to_returns's conversion step is the filtered one rather than the caller's.
Algorithm
- Read the offset between the two clocks as
length(p) - length(r), which is0whenpaddingkept the first observation and1when it did not. Return celljis then the change onto price rowj + off. - Locate the column's Listing Span on the price clock: the first observed price and the last. A column with no observed price admits nothing.
- Admit return cell
jwhen its price row lies in[first + 1, last]— the span projected onto the returns clock, since a return consumes the earlier price of its pair — and the default rule left the cell non-finite.
Arguments
p: One column's prices along the observation axis, gaps included.r: The returnsTimeSeries.percentchangecomputed fromp.
Returns
w::BitVector: The same length asr, true on the cells an algorithm may write.
Related
PortfolioOptimisers.gap_return_value — Function
gap_return_value(
ret_method::Symbol,
pt::Number,
p0::Number
) -> Any
Compute one return from a pair of prices that need not be consecutive.
The one place the ret_method branches are spelled for the Gap Return family, so a new algorithm states which pair of prices it reads and never which formula turns them into a return. It mirrors TimeSeries.percentchange, which computes both branches through logarithms, so a value written here sits on the same arithmetic as the cells around it.
Arguments
ret_method::simpleor:log.pt: The later price.p0: The earlier price, the return's anchor.
Returns
r::Number: $\ln P_t - \ln P_0$ under:log, andexpm1of it otherwise.
Related
PortfolioOptimisers.apply_gap_return — Function
apply_gap_return(alg::Nothing, R::DataFrames.DataFrame, P::DataFrames.DataFrame, ret_method::Symbol) -> DataFrames.DataFrame
apply_gap_return(alg::AbstractGapReturnAlgorithm, R::DataFrames.DataFrame, P::DataFrames.DataFrame, ret_method::Symbol) -> DataFrames.DataFrameApply the gap_return_alg given to prices_to_returns to the converted table.
The seam that keeps the family optional and holds its invariant. nothing is the default path, and its method returns the table untouched, so the arithmetic TimeSeries.percentchange produced is bit-identical to what it was before the family existed.
The rule is per-column arithmetic on consecutive observations and reads no asset axis, so it applies to every series of the converted table alike — asset, factor and benchmark.
Algorithm
- Walk the series columns of
R, taking each column's prices fromPby name. - Derive the writable cells with
gap_return_writable. - Call
gap_returnon the column and copy back only the writable cells, so every other cell is frozen whatever the algorithm returned. - Report an
@infowhen no column admitted a single cell. A table that holds no gap admits none, which is the ordinary case rather than a mistake, so this is neither a refusal, which would reject a configuration that computes a correct answer, nor a warning, which could not tell that case from one where the caller expected a gap.
Arguments
alg: The Gap Return algorithm, ornothingfor the default rule.R: The converted table,:timestampfirst and one column per series.P: The price table reaching the conversion, with the same series columns.ret_method::simpleor:log.
Returns
R::DataFrames.DataFrame: The converted table, with the writable cells resolved.
Related