Price-level expected returns: private API
PortfolioOptimisers.assert_price_window — Function
assert_price_window(window::Integer)
Refuses a price-level window below two levels.
One level is the current price, and its ratio to itself forecasts nothing.
Validation
window >= 2. ADomainErroris thrown otherwise.
Related
PortfolioOptimisers.push_memory — Function
push_memory(
alg::AbstractPriceLevelStatistic,
hist::Union{Nothing, AbstractMatrix},
x::AbstractVector
) -> Any
Appends the price relative of a row to the memory of a statistic and keeps the last memory_rows relatives.
Algorithm
- Read
m, the number of relatives the statistic carries. Returnnothingwhenmis zero. - Make
row, the relativexas a one-row matrix. Return it whenhistisnothing. - Stack
rowunderhist, givingH, and return the lastmrows ofH.
Arguments
alg: The statistic.hist: The carried memory, ornothing.x: The price relative of the row.
Returns
hist'::Union{Nothing, Matrix}: The memory after the row, a new matrix.
Related
PortfolioOptimisers.price_levels — Function
price_levels(
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> Matrix
Reconstructs the price levels of a window of returns, with the last level at one.
The last row of the result is ones, and the row above it is 1 ./ (1 .+ r_T), where r_T is the last row of X. Each earlier row divides the row below it by one plus the return between them, back to the level before the first row of X. So the result holds size(X, 1) + 1 rows. The statistic reads the last window of them, or all of them when the window truncates.
Mathematical definition
\[\begin{align} \boldsymbol{p}_{T} &= \boldsymbol{1}\,,\quad \boldsymbol{p}_{t-1} = \boldsymbol{p}_{t} \oslash (\boldsymbol{1} + \boldsymbol{r}_{t})\,,\quad t = T, \ldots, 1\,. \end{align}\]
Where:
- $\boldsymbol{p}_t$: Price level vector of period $t$, one entry per asset.
- $\boldsymbol{r}_{t}$: Returns vector of period $t$, one entry per asset.
- $T$: Number of observations.
Arguments
X: Returns,observations × assets.
Returns
P::Matrix: The levels,(observations + 1) × assets, the last row ones.
Related
PortfolioOptimisers.fold_levels — Function
fold_levels(
alg::AbstractPriceLevelStatistic,
P::AbstractMatrix
) -> Any
Runs the batch form of a folding statistic over a matrix of levels, from the first row.
Algorithm
- Start with no carried statistic
statand no memoryhist. - For each row
tfrom the second, form the price relativexof rowtover rowt - 1. - Append
xtohistwithpush_memory. - Step
statwithfold_statistic_row. - Multiply
statby the last level and return it. For a single level there is no relative, and the result is the last level.
Arguments
alg: The folding statistic.P: The levels,levels × assets, the last row the current level.
Returns
stat::Vector: The statistic per asset, in units of the levels.
Related
PortfolioOptimisers.fold_statistic_row — Function
fold_statistic_row(
alg::AbstractPriceLevelStatistic,
stat::Union{Nothing, AbstractVector},
hist::Union{Nothing, AbstractMatrix},
x::AbstractVector
) -> Any
Runs one row of the recursion of a folding statistic, at the arity that its memory needs.
A statistic that carries no memory takes the three-argument fold_statistic, and a statistic that carries one takes the four-argument form.
Arguments
alg: The folding statistic.stat: The carried statistic, ornothingbefore the first row.hist: The carried memory with the row appended, ornothing.x: The price relative of the row,1 .+ r.
Returns
stat'::AbstractVector: The statistic after the row, a new vector.
Related
PortfolioOptimisers.fold_active — Function
fold_active(
alg::AbstractPriceLevelStatistic,
stat::AbstractVector,
hist::Union{Nothing, AbstractMatrix},
x::AbstractVector,
active::AbstractVector{<:Bool}
) -> Any
Runs one row of the recursion of a folding statistic over the active assets alone, and writes the result back into the carried statistic.
The caller has already written the cold seed into stat at every asset that the mask turns off. So an inactive asset keeps that seed, and it starts the recursion from its seed when it relists. The active assets are the Coverage Universe of the row, and the recursion reads them alone. So a statistic that couples the assets, such as the regression of the kernel trend pattern, pools the listed assets and needs no mask of its own.
Algorithm
- When every asset is active, return the row of the recursion from
fold_statistic_row. - Find
i, the indices of the active assets. Wheniis empty, return a copy ofstat, which holds the cold seed at every asset. - Run the row of the recursion on the active entries of
stat, of the columnsiofhistand ofx, givingy. - Make
out, a copy ofstatin the promoted element type, writeyati, and return it.
Arguments
alg: The folding statistic.stat: The carried statistic, the cold seed at every inactive asset.hist: The carried memory with the row appended, ornothing.x: The price relative of the row, one at every asset the fold holds.active: The active assets of the row.
Returns
stat'::AbstractVector: The statistic after the row, a new vector.
Related
PortfolioOptimisers.weiszfeld_sums — Function
weiszfeld_sums(
P::AbstractMatrix,
y::AbstractVector
) -> Tuple{Any, Any, Any, Int64}
The three sums of one step of the modified Weiszfeld iteration at a point y, over the rows of P that differ from y, and the number of rows equal to it.
Mathematical definition
\[\begin{align} \boldsymbol{s}(\boldsymbol{y}) &= \sum_{i : \boldsymbol{p}_i \neq \boldsymbol{y}} \frac{\boldsymbol{p}_i}{\lVert \boldsymbol{p}_i - \boldsymbol{y} \rVert}\,,\quad d(\boldsymbol{y}) = \sum_{i : \boldsymbol{p}_i \neq \boldsymbol{y}} \frac{1}{\lVert \boldsymbol{p}_i - \boldsymbol{y} \rVert}\,,\\ r(\boldsymbol{y}) &= \left\lVert \sum_{i : \boldsymbol{p}_i \neq \boldsymbol{y}} \frac{\boldsymbol{p}_i - \boldsymbol{y}}{\lVert \boldsymbol{p}_i - \boldsymbol{y} \rVert} \right\rVert\,,\quad \eta(\boldsymbol{y}) = \left\lvert \{ i : \boldsymbol{p}_i = \boldsymbol{y} \} \right\rvert\,. \end{align}\]
Where:
- $\boldsymbol{p}_i$: Row $i$ of
P, one point. - $\boldsymbol{y}$: The point the sums are taken at.
- $r(\boldsymbol{y})$: The norm of the sum of the unit vectors from $\boldsymbol{y}$ to the other points, which is the norm of the gradient of the sum of distances where no point equals $\boldsymbol{y}$.
- $\eta(\boldsymbol{y})$: The number of points equal to $\boldsymbol{y}$.
Arguments
P: The points, one per row.y: The point.
Returns
num::Vector: The sum $\boldsymbol{s}(\boldsymbol{y})$.den::Number: The sum $d(\boldsymbol{y})$, zero when every row equalsy.R::Number: The norm $r(\boldsymbol{y})$.eta::Int: The count $\eta(\boldsymbol{y})$.
Related
PortfolioOptimisers.spatial_median — Function
spatial_median(
P::AbstractMatrix,
iters::Integer,
tol::Real
) -> Any
The spatial median of the rows of P, by the modified Weiszfeld iteration of Vardi and Zhang (2000).
The plain Weiszfeld iteration converges slowly when the median is one of the points, and it cannot step from an iterate that equals a point. The function first tests every point with the optimality condition of Vardi and Zhang, so a median that is one of the points is found exactly. The iteration then uses the modified map, which stays defined on a point.
Mathematical definition
\[\begin{align} \boldsymbol{m} &= \underset{\boldsymbol{y}}{\arg\min} \sum_{i} \lVert \boldsymbol{p}_i - \boldsymbol{y} \rVert\,,\\ \boldsymbol{p}_k = \boldsymbol{m} &\iff r(\boldsymbol{p}_k) \leq \eta(\boldsymbol{p}_k)\,,\\ T(\boldsymbol{y}) &= \max\left(0, 1 - \frac{\eta(\boldsymbol{y})}{r(\boldsymbol{y})}\right) \frac{\boldsymbol{s}(\boldsymbol{y})}{d(\boldsymbol{y})} + \min\left(1, \frac{\eta(\boldsymbol{y})}{r(\boldsymbol{y})}\right) \boldsymbol{y}\,. \end{align}\]
Where:
- $\boldsymbol{m}$: The spatial median.
- $\boldsymbol{p}_i$: Row $i$ of
P, one point. - $\boldsymbol{s}$, $d$, $r$, $\eta$: The sums and the count of
weiszfeld_sums. - $T$: The modified Weiszfeld map. At a point that equals no row it is the plain Weiszfeld step $\boldsymbol{s} / d$, and the median is its fixed point.
Algorithm
- For each row
kofP, take the sums at the row withweiszfeld_sums. WhenR <= eta, the row is the median, and the function returns it. - Otherwise seed
yat the coordinatewise median of the rows. - Take the sums at
y, and form the next iterateynewwith the map $T$. - Return
ynewwhen its Euclidean distance toyis belowtol. Otherwise sety = ynewand repeat step 3, at mostiterstimes, and then returny.
Arguments
P: The points, one per row.iters: Maximum number of iterations.tol: Convergence tolerance on the Euclidean distance between two successive iterates.
Returns
y::Vector: The spatial median.
Related
References
- [51] Y. Vardi and C.-H. Zhang. The multivariate L1-median and associated data depth. Proceedings of the National Academy of Sciences 97, 1423–1426 (2000).
PortfolioOptimisers.assert_folding_statistic — Function
assert_folding_statistic(alg::AbstractPriceLevelStatistic)
Refuses a fold of a statistic that has no exact recursion, by name.
Validation
folds(alg). AnArgumentErrorthat names the statistic is thrown otherwise.
Related
References
- [51]
- Y. Vardi and C.-H. Zhang. The multivariate L1-median and associated data depth. Proceedings of the National Academy of Sciences 97, 1423–1426 (2000).