Pre-processing
Prices to returns
Other than FiniteAllocationOptimisationEstimator, all optimisations work based off returns data rather than price data. These functions and types are involved in computing returns.
PortfolioOptimisers.AbstractReturnsResult Type
abstract type AbstractReturnsResult <: AbstractResultAbstract supertype for all returns result types in PortfolioOptimisers.jl.
All concrete and/or types representing the result of returns calculations should be subtypes of AbstractReturnsResult.
Related
sourcePortfolioOptimisers.ReturnsResult Type
struct ReturnsResult{__T_nx, __T_X, __T_nf, __T_F, __T_nb, __T_B, __T_ts, __T_iv, __T_ivpa} <: AbstractReturnsResultA flexible container type for storing the results of asset and factor returns calculations in PortfolioOptimisers.jl.
ReturnsResult is the standard result type returned by returns-processing routines, such as prices_to_returns.
It supports both asset and factor returns, as well as optional time series and implied volatility information, and is designed for downstream compatibility with optimisation and analysis routines.
Fields
nx: Names or identifiers of asset columns (assets × 1).X: Asset returns matrix (observations × assets).nf: Names or identifiers of factor columns (factors × 1).F: Factor returns matrix (observations × factors).nb: Names or identifiers of benchmark columns (observations × 1) or (observations × assets).B: Benchmark prices (observations × 1) or (observations × assets).ts: Optional timestamps for each observation (observations × 1).iv: Implied volatilities matrix (observations × assets).ivpa: Implied volatility risk premium adjustment, if a vector (assets × 1).
Constructors
ReturnsResult(;
nx::Option{<:VecStr} = nothing,
X::Option{<:MatNum} = nothing,
nf::Option{<:VecStr} = nothing,
F::Option{<:MatNum} = nothing,
nb::Option{<:VecStr} = nothing,
B::Option{<:VecNum_MatNum} = nothing,
ts::Option{<:VecDate} = nothing,
iv::Option{<:MatNum} = nothing,
ivpa::Option{<:Num_VecNum} = nothing,
) -> ReturnsResultKeywords correspond to the struct's fields.
Validation
If
nxorXis notnothing,!isempty(nx),!isempty(X), andlength(nx) == size(X, 2).If
nforFis notnothing,!isempty(nf),!isempty(F),length(nf) == size(F, 2), andsize(X, 1) == size(F, 1).If
nborBis notnothingandBis a matrix:!isempty(nb),!isempty(B), andlength(nb) == size(B, 2).If
nborBis notnothingandBis a vector:length(nb) == 1.If
XandBare notnothing: ifBis a vector,size(X, 1) == size(B, 1); ifBis a matrix,size(X) == size(B).If
tsis notnothing,!isempty(ts), andlength(ts) == size(X, 1).If
tsandBare notnothing:length(ts) == size(B, 1).If
ivis notnothing,!isempty(iv),all(x -> x >= 0, iv),size(iv) == size(X).If
ivpais notnothing,all(x -> x >= 0, ivpa),all(x -> isfinite(x), ivpa); if a vector,length(ivpa) == size(iv, 2).
Examples
julia> ReturnsResult(; nx = ["A", "B"], X = [0.1 0.2; 0.3 0.4])
ReturnsResult
nx ┼ Vector{String}: ["A", "B"]
X ┼ 2×2 Matrix{Float64}
nf ┼ nothing
F ┼ nothing
nb ┼ nothing
B ┼ nothing
ts ┼ nothing
iv ┼ nothing
ivpa ┴ nothingRelated
sourcePortfolioOptimisers._check_names_and_returns_matrix Function
_check_names_and_returns_matrix(
names::Union{Nothing, AbstractVector{<:AbstractString}},
mat::Union{Nothing, AbstractMatrix{<:Union{var"#s19", var"#s18"} where {var"#s19"<:Number, var"#s18"<:AbstractJuMPScalar}}},
names_sym::Symbol,
mat_sym::Symbol
)Validate that asset or factor names and their corresponding returns matrix are provided and consistent.
Arguments
names: Asset or factor names.mat: Returns matrix.names_sym: Symbolic name for the names argument displayed in error messages.mat_sym: Symbolic name for the matrix argument displayed in error messages.
Returns
nothing.
Details
- If either
namesormatis notnothing:!isnothing(names)and!isnothing(mat).!isempty(names)and!isempty(mat).length(names) == size(mat, 2).
Related
sourcePortfolioOptimisers.prices_to_returns Function
prices_to_returns(
X::TimeSeries.TimeArray,
F::Option{<:TimeSeries.TimeArray} = nothing;
B::Option{<:TimeSeries.TimeArray} = nothing,
iv::Option{<:TimeSeries.TimeArray} = nothing,
ivpa::Option{<:Num_VecNum} = nothing,
ret_method::Symbol = :simple, padding::Bool = false,
missing_col_percent::Number = 1.0,
missing_row_percent::Option{<:Number} = 1.0,
collapse_args::Tuple = (),
map_func::Option{<:Function} = nothing,
join_method::Symbol = :outer,
impute_method::Option{<:Impute.Imputor} = nothing
) -> ReturnsResultConvert price data (and optionally factor data) in TimeSeries.TimeArray format to returns, with flexible handling of missing data, imputation, and optional implied volatility information.
Arguments
X: Asset price data (observations × assets).F: Optional Factor price data (observations × factors).B: Optional Benchmark price data (observations × assets) or (observations × 1).iv: Optional Implied volatility data.ivpa: Optional Implied volatility risk premium adjustment.ret_method: Return calculation method (:simpleor:log).padding: Whether to pad missing values in returns calculation.missing_col_percent: Maximum allowed fraction(0, 1]of missing values per column (asset + factor).missing_row_percent: Maximum allowed fraction(0, 1]of missing values per row (timestamp).collapse_args: Arguments for collapsing the time series (e.g., to lower frequency).map_func: Optional function to apply to the data before returns calculation.join_method: How to join asset, factor data and benchmark data (:outer,:inner, etc.).impute_method: Optional imputation method for missing data.
Returns
rr::ReturnsResult: Struct containing asset/factor returns, names, time series, and optional implied volatility data.
Validation
!isempty(X).0 < missing_col_percent <= 10 < missing_row_percent <= 1.If
Fis notnothing,!isempty(F).If
Bis notnothing,!isempty(B), andsize(values(B), 2) in (1, size(values(X), 2)).If
ivis notnothing, the timestamp of the merged data matrix must be a subset ofTimeSeries.timestamp(iv), theniv = values(iv),!isempty(iv),all(x -> x >= 0, iv),size(iv) == size(X).If
ivpais notnothing,all(x -> x >= 0, ivpa),all(x -> isfinite(x), ivpa); if a vector,length(ivpa) == size(iv, 2).
Details
Joins asset, factor, and benchmark data as specified.
Optionally applies a mapping function and/or collapses the time series.
Handles missing values by filtering, imputation, and dropping as configured.
Computes returns using the specified method.
- If
Bis notnothing, it is subtracted from asset returns. Used for returns tracking error optimisations.
- If
Returns a
ReturnsResultwith asset/factor names, returns, timestamps, and optional implied volatility data.
Examples
julia> X = TimeArray(Date(2020, 1, 1):Day(1):Date(2020, 1, 3), [100 101; 102 103; 104 105],
["A", "B"])
3×2 TimeSeries.TimeArray{Int64, 2, Dates.Date, Matrix{Int64}} 2020-01-01 to 2020-01-03
┌────────────┬─────┬─────┐
│ │ A │ B │
├────────────┼─────┼─────┤
│ 2020-01-01 │ 100 │ 101 │
│ 2020-01-02 │ 102 │ 103 │
│ 2020-01-03 │ 104 │ 105 │
└────────────┴─────┴─────┘
julia> prices_to_returns(X)
ReturnsResult
nx ┼ Vector{String}: ["A", "B"]
X ┼ 2×2 Matrix{Float64}
nf ┼ nothing
F ┼ nothing
nb ┼ nothing
B ┼ nothing
ts ┼ Vector{Dates.Date}: [Dates.Date("2020-01-02"), Dates.Date("2020-01-03")]
iv ┼ nothing
ivpa ┴ nothingRelated
sourcePortfolioOptimisers.returns_result_view Function
returns_result_view(rd::ReturnsResult, i) -> ReturnsResultReturn a view of the ReturnsResult object for the assets at indices i.
Arguments
rd: AReturnsResultobject containing asset and/or factor returns.i: Indices of the assets to view.
Returns
new_rr::ReturnsResult: A newReturnsResultcontaining only the data for the specified index.
Details
Extracts the asset name, returns, implied volatility, and risk premium adjustment for indices
i.Preserves factor, timestamp, and other fields from the original object.
Returns
nothingfor fields that are not present.
Examples
julia> rd = ReturnsResult(; nx = ["A", "B"], X = [0.1 0.2; 0.3 0.4])
ReturnsResult
nx ┼ Vector{String}: ["A", "B"]
X ┼ 2×2 Matrix{Float64}
nf ┼ nothing
F ┼ nothing
nb ┼ nothing
B ┼ nothing
ts ┼ nothing
iv ┼ nothing
ivpa ┴ nothing
julia> PortfolioOptimisers.returns_result_view(rd, 2:2)
ReturnsResult
nx ┼ SubArray{String, 1, Vector{String}, Tuple{UnitRange{Int64}}, true}: ["B"]
X ┼ 2×1 SubArray{Float64, 2, Matrix{Float64}, Tuple{Base.Slice{Base.OneTo{Int64}}, UnitRange{Int64}}, true}
nf ┼ nothing
F ┼ nothing
nb ┼ nothing
B ┼ nothing
ts ┼ nothing
iv ┼ nothing
ivpa ┴ nothingRelated
sourcereturns_result_view(
rd::ReturnsResult,
i,
j,
k = :
) -> ReturnsResultReturn a view of the ReturnsResult object for assets at indices j, observations at indices i, and factors at indices k.
Arguments
rd: AReturnsResultobject containing asset and/or factor returns.i: Index or indices of the observation(s) to view.j: Index or indices of the assets to view.k: Index or indices of the factors to view.
Returns
new_rr::ReturnsResult: A newReturnsResultcontaining only the data for the specified indices.
Details
Extracts the asset name, returns, implied volatility, and risk premium adjustment for indices
jand observation(s)i.Extracts the factor names and returns for indices
kand observationsi.Preserves factor names and returns for the selected observations.
Preserves timestamps for the selected observations.
Returns
nothingfor fields that are not present in the original object.
Related
sourcePortfolioOptimisers.returns_result_picker Function
returns_result_picker(rd::ReturnsResult, brt::Bool) -> ReturnsResultReturn a ReturnsResult appropriate for benchmark-tracking optimisations.
This helper inspects the ReturnsResult's benchmark field B and the boolean flag brt (benchmark-tracking). If brt is true and a benchmark B is present it returns a new ReturnsResult in which asset returns X have the benchmark removed (i.e. X - B or broadcast X .- B for vector benchmarks). If brt is false or no benchmark is present, the original ReturnsResult is returned unchanged.
Arguments
rd: AReturnsResultobject containing asset, factor and/or benchmark returns.brt: Boolean flag indicating whether benchmark-tracking behaviour should be applied. Whentrue, asset returns are adjusted by subtracting the benchmarkB(if present).
Returns
rd::ReturnsResult:If
brtistrueand a benchmarkBis present: A newReturnsResultwith adjusted asset returnsOtherwise: The
rdis returned unchanged.
Details
When an adjustment is required and
Bis present, a newReturnsResultis returned leaving the originalrdunmodified.If no adjustment is required or
Bisnothing, the originalReturnsResultis returned unchanged.For vector benchmarks (
VecNum) subtraction uses broadcasting (X .- B) to subtract the per-observation benchmark from each asset column (index tracking).For matrix benchmarks (
MatNum) subtraction uses matrix subtraction (X - B).Other fields (
nx,nf,F,ts,iv,ivpa) are preserved in the returned object.
Examples
julia> rd = ReturnsResult(; nx = ["A", "B"], X = [0.10 0.20; 0.30 0.40], nb = ["BM"],
B = [0.01; 0.02])
ReturnsResult
nx ┼ Vector{String}: ["A", "B"]
X ┼ 2×2 Matrix{Float64}
nf ┼ nothing
F ┼ nothing
nb ┼ Vector{String}: ["BM"]
B ┼ Vector{Float64}: [0.01, 0.02]
ts ┼ nothing
iv ┼ nothing
ivpa ┴ nothing
julia> rd2 = returns_result_picker(rd, false) # no change when brt is false
ReturnsResult
nx ┼ Vector{String}: ["A", "B"]
X ┼ 2×2 Matrix{Float64}
nf ┼ nothing
F ┼ nothing
nb ┼ Vector{String}: ["BM"]
B ┼ Vector{Float64}: [0.01, 0.02]
ts ┼ nothing
iv ┼ nothing
ivpa ┴ nothing
julia> rd === rd2
true
julia> rd3 = returns_result_picker(rd, true)
ReturnsResult
nx ┼ Vector{String}: ["A", "B"]
X ┼ 2×2 Matrix{Float64}
nf ┼ nothing
F ┼ nothing
nb ┼ nothing
B ┼ nothing
ts ┼ nothing
iv ┼ nothing
ivpa ┴ nothing
julia> rd.X .- rd.B == rd3.X
trueRelated
sourcePre-filtering
Price data is often incomplete or noisy, so it can be worthwhile having some pre-filtering steps to remove data that does not contribute meaningful information and may pollute calculations.
PortfolioOptimisers.find_complete_indices Function
find_complete_indices(X::AbstractMatrix; dims::Int = 1) -> VecIntReturn the indices of columns (or rows) in matrix X that do not contain any missing or NaN values.
This function scans the specified dimension of the input matrix and returns the indices of columns (or rows) that are complete, i.e., contain no missing or NaN values.
Arguments
X: Data matrixobservations × featuresif thedimskeyword does not exist ordims = 1,features × observationswhendims = 2.dims: Dimension along which to perform the computation.
Validation
dims in (1, 2).
Returns
res::VecInt: Indices of columns (or rows) inXthat are complete.
Details
If
dims == 2, the matrix is transposed and columns are checked.Any column (or row) containing at least one
missingorNaNvalue is excluded.The result is a vector of indices of complete columns (or rows).
Examples
julia> X = [1.0 2.0 NaN; 4.0 missing 6.0];
julia> find_complete_indices(X)
1-element Vector{Int64}:
1
julia> find_complete_indices(X; dims = 2)
Int64[]Related
source