Simple expected returns: private API
The most basic moment is the simple expected return. These types and functions implement it.
PortfolioOptimisers.show_fields — Method
show_fields(
me::SimpleExpectedReturns
) -> Union{Tuple{Symbol}, Tuple{Symbol, Symbol}}
Renders every field of a SimpleExpectedReturns except cache, and cvg only where a policy is set.
The state a cache holds is the running detail of an incremental fit, not the configuration a reader looks the type up for, and it prints under the estimator at every site that renders one. Set set_show_nothing_fields!(:SimpleExpectedReturns, true) to render it. cvg is read from the instance rather than from the type, because an opt-in that a caller has not taken is not part of the configuration they chose: an estimator whose cvg is nothing renders exactly as it did before the field existed, and one that carries a CoveragePolicy renders it.
Arguments
me: Expected returns estimator, read for itscvgfield.
Returns
fields::Tuple: The field names to render, which is(:w,)with no policy and(:w, :cvg)with one.
Related
Incremental fit
The sample mean folds one observation at a time, so a long history need not be held or re-read. partial_fit! returns a new estimator whose cache field carries the state, and mean reads the fit off the estimator alone.
PortfolioOptimisers.SimpleExpectedReturnsState — Type
struct SimpleExpectedReturnsState{__T_n, __T_mu, __T_cvg} <: AbstractPartialFitStateCarries the running observation count and mean of an incremental sample-mean fit.
The state of SimpleExpectedReturns under partial_fit!. It holds no second-moment accumulator, because a mean is the whole estimate, so merge_states folds the two counts and the two means and discards the accumulator chan_merge returns.
Fields
n: Number of observations folded into the state.
mu: Running mean of the observations folded into the state,assets × 1.
cvg: OptionalCoverageCounts, the per-cell denominators and per-asset bookkeeping of an available-case fold. It isnothingwhen the estimator carries noCoveragePolicy, so the plain state costs nothing.
Constructors
SimpleExpectedReturnsState(; n::Integer = 0, mu::VecNum, cvg::Option{<:CoverageCounts} = nothing) -> SimpleExpectedReturnsStateKeywords correspond to the struct's fields. A state seeded for N assets is SimpleExpectedReturnsState(; mu = zeros(N)), which partial_fit! builds when the cache field of the estimator holds nothing.
Validation
n >= 0. ADomainErroris thrown otherwise.!isempty(mu). AnIsEmptyErroris thrown otherwise.- Every entry of
muis finite. AnIsNonFiniteErroris thrown otherwise.
View parameters
When port_opt_view is called on this type, its fields are subset to the selected assets:
mu: Sliced to the selected indices viaport_opt_view.
Examples
julia> PortfolioOptimisers.SimpleExpectedReturnsState(; mu = [0.0, 0.0])PortfolioOptimisers.SimpleExpectedReturnsState n ┼ Int64: 0 mu ┼ Vector{Float64}: [0.0, 0.0] cvg ┴ nothingRelated
PortfolioOptimisers.expected_returns_state_seed — Function
expected_returns_state_seed(
cache::Union{Nothing, SimpleExpectedReturnsState},
x::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> Any
expected_returns_state_seed(
cache::Union{Nothing, SimpleExpectedReturnsState},
x::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
cvg::Union{Nothing, CoveragePolicy}
) -> Any
Returns the SimpleExpectedReturnsState an incremental mean fit folds into, seeding one of zeros when the estimator carries none.
The seed is written here rather than inside partial_fit!, so the fold reads as one line and the branch that reads the cache field has one home.
Arguments
cache: The state the estimator carries, ornothing.x: One observation,assets × 1, read for its length and its element type.cvg: The policy the estimator carries, which decides whether the seed carries per-asset counts.
Returns
state::SimpleExpectedReturnsState: The statecacheholds, or a state of zeros overlength(x)assets.
Related
Base.copy — Method
copy(
x::SimpleExpectedReturnsState
) -> SimpleExpectedReturnsState
Copies a SimpleExpectedReturnsState, so the copy shares no array with the original.
The copy method of the AbstractPartialFitState interface, which partial_fit calls before it folds. The count is a scalar and passes through, and the running mean is copied.
Arguments
x: The state to copy.
Returns
state::SimpleExpectedReturnsState: A fresh state, equal tox, whosemuis a fresh vector.
Related
Available-case fit
With a CoveragePolicy in its cvg field the estimator fits each asset on that asset's own finite and active observations, and PortfolioOptimisers.coverage_mean routes between that arm and the Coverage Universe one.
PortfolioOptimisers.coverage_mean — Function
coverage_mean(me, cvg, X; dims::Int = 1, active_mask = nothing, kwargs...) -> ArrNumRoutes a sample-mean fit to the Coverage Universe arm or to the available-case arm.
The cvg field of the estimator is passed as the second argument, so the arm is chosen by dispatch on the policy rather than by a branch on its value. An estimator that carries no policy therefore pays nothing for the field: the Nothing method is the body mean(me::SimpleExpectedReturns, X::MatNum; dims::Int = 1, kwargs...) has always had, and it is statically resolved because the field's type is concrete.
Arguments
me: Expected returns estimator.cvg: The policy the estimator carries, which selects the arm.X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.dims: Dimension along which to perform the computation.active_mask: The active mask of the Asset Panel,observations × assets, ornothing. The Coverage Universe arm ignores it.kwargs...: Additional keyword arguments passed toStatistics.mean.
Returns
mu::ArrNum: Expected returns vectorassets x 1if thedimskeyword does not exist ordims = 2,1 x assetsifdims = 1.
Related
PortfolioOptimisers.coverage_mean — Method
coverage_mean(
me::SimpleExpectedReturns,
::Nothing,
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}};
dims,
active_mask,
kwargs...
) -> Any
Nothing method of coverage_mean. The Coverage Universe arm, which is the sample mean of a window every asset covers, and the answer mean(me::SimpleExpectedReturns, X::MatNum; dims::Int = 1, kwargs...) gave before the cvg field existed. It refuses a gapped sample with assert_finite_sample and ignores the active mask, because an estimator with no policy reads the universe through coverage_reduction and never sees a gap.
Related
PortfolioOptimisers.coverage_mean — Method
coverage_mean(
me::SimpleExpectedReturns,
cvg::CoveragePolicy,
X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}};
dims,
active_mask,
kwargs...
) -> Any
CoveragePolicy method of coverage_mean. The available-case arm: each asset's mean is fitted on that asset's own finite and active observations, and the batch answer is the incremental one, because the arm folds the block through partial_fit! and reads the state out.
Writing the batch arm as the fold is what makes the map's oracle hold to the last bit rather than to a tolerance: there is one recursion, and a caller who hands the same rows over one at a time reaches the same floating-point number.
Algorithm
- Fold every row of
Xinto a fresh state withpartial_fit!, carrying the active mask. - Read the state out with
mean(me::SimpleExpectedReturns, state::SimpleExpectedReturnsState). - Orient the answer as the caller's
dimsasks.
Related
PortfolioOptimisers.coverage_mean — Method
coverage_mean(
_::SimpleExpectedReturns,
_::Nothing,
state::SimpleExpectedReturnsState
) -> Any
Nothing method of the read-out arm of coverage_mean. Every asset shares one count, so the whole answer is NaN before the first observation and the running mean afterwards.
The running mean is copied rather than handed out. partial_fit! writes the Welford recursion into state.mu in place, so a read-out that returned the accumulator itself would hand the caller a vector that the next fold silently rewrites — and a prior that read its mu out and carried it into a Result would find the Result changed under it at the next observation. The CoveragePolicy method beside this one copies for the same reason, through coverage_frame.
Related
PortfolioOptimisers.coverage_mean — Method
coverage_mean(
_::SimpleExpectedReturns,
cvg::CoveragePolicy,
state::SimpleExpectedReturnsState
) -> Any
CoveragePolicy method of the read-out arm of coverage_mean. Each asset's mean is read out against that asset's own count, and an asset the policy refuses is NaN.
Algorithm
- Read the admitted assets with
coverage_admission. - Frame the running mean with
coverage_frame, which copies it where its asset has an observation. A running per-asset mean is already the ratio, so it is never divided again.
Related