Skip to content

Commit c033470

Browse files
committed
Finish prediction risk and fix type hierarchy
1 parent 1a4bd2c commit c033470

File tree

6 files changed

+68
-15
lines changed

6 files changed

+68
-15
lines changed

src/13_Prior/01_Base_Prior.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ Abstract supertype for all prior result types.
155155
"""
156156
abstract type AbstractPriorResult <: AbstractResult end
157157
const PrE_Pr = Union{<:AbstractPriorEstimator, <:AbstractPriorResult}
158-
const Pr_RR = Union{<:AbstractPriorResult, <:AbstractReturnsResult}
158+
const Pr_RR = Union{<:AbstractPriorResult, <:ReturnsResult}
159159
"""
160160
prior(pr::AbstractPriorEstimator, rd::ReturnsResult; kwargs...)
161161

src/19_RiskMeasures/01_Base_RiskMeasures.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,9 +527,10 @@ function solver_selector(::Nothing, ::Nothing)
527527
throw(ArgumentError("Both risk_solver and prior_solver are nothing, cannot solve JuMP model."))
528528
end
529529
function expected_risk end
530+
function predicted_risk end
530531
function no_bounds_risk_measure end
531532
function no_bounds_no_risk_expr_risk_measure end
532533

533534
export Frontier, RiskMeasureSettings, HierarchicalRiskMeasureSettings, SumScalariser,
534-
MaxScalariser, MinScalariser, LogSumExpScalariser, expected_risk, RiskMeasure,
535-
HierarchicalRiskMeasure
535+
MaxScalariser, MinScalariser, LogSumExpScalariser, expected_risk, predicted_risk,
536+
RiskMeasure, HierarchicalRiskMeasure
Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
struct RiskRatioRiskMeasure{T1, T2} <: HierarchicalRiskMeasure
22
r1::T1
33
r2::T2
4-
function RiskRatioRiskMeasure(r1::AbstractBaseRiskMeasure, r2::AbstractBaseRiskMeasure)
4+
function RiskRatioRiskMeasure(r1::OptimisationRiskMeasure, r2::OptimisationRiskMeasure)
55
return new{typeof(r1), typeof(r2)}(r1, r2)
66
end
77
end
8-
function RiskRatioRiskMeasure(; r1::AbstractBaseRiskMeasure = Variance(),
9-
r2::AbstractBaseRiskMeasure = ConditionalValueatRisk())
8+
function RiskRatioRiskMeasure(; r1::OptimisationRiskMeasure = Variance(),
9+
r2::OptimisationRiskMeasure = ConditionalValueatRisk())
1010
return RiskRatioRiskMeasure(r1, r2)
1111
end
1212
function factory(r::RiskRatioRiskMeasure, pr::AbstractPriorResult, args...; kwargs...)
@@ -17,5 +17,27 @@ end
1717
function factory(r::RiskRatioRiskMeasure, w::VecNum)
1818
return RiskRatioRiskMeasure(; r1 = factory(r.r1, w), r2 = factory(r.r2, w))
1919
end
20+
struct NonOptimisationRiskRatioRiskMeasure{T1, T2} <: NonOptimisationRiskMeasure
21+
r1::T1
22+
r2::T2
23+
function NonOptimisationRiskRatioRiskMeasure(r1::AbstractBaseRiskMeasure,
24+
r2::AbstractBaseRiskMeasure)
25+
return new{typeof(r1), typeof(r2)}(r1, r2)
26+
end
27+
end
28+
function NonOptimisationRiskRatioRiskMeasure(; r1::AbstractBaseRiskMeasure = Variance(),
29+
r2::AbstractBaseRiskMeasure = ConditionalValueatRisk())
30+
return NonOptimisationRiskRatioRiskMeasure(r1, r2)
31+
end
32+
function factory(r::NonOptimisationRiskRatioRiskMeasure, pr::AbstractPriorResult, args...;
33+
kwargs...)
34+
r1 = factory(r.r1, pr, args...; kwargs...)
35+
r2 = factory(r.r2, pr, args...; kwargs...)
36+
return NonOptimisationRiskRatioRiskMeasure(; r1 = r1, r2 = r2)
37+
end
38+
function factory(r::NonOptimisationRiskRatioRiskMeasure, w::VecNum)
39+
return NonOptimisationRiskRatioRiskMeasure(; r1 = factory(r.r1, w),
40+
r2 = factory(r.r2, w))
41+
end
2042

21-
export RiskRatioRiskMeasure
43+
export RiskRatioRiskMeasure, NonOptimisationRiskRatioRiskMeasure

src/19_RiskMeasures/25_ExpectedRisk.jl

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const MatNum_Pr = Union{<:MatNum, <:AbstractPriorResult}
1+
const MatNum_Pr = Union{<:MatNum, <:AbstractPriorResult, <:ReturnsResult}
22
const ERkNetRet = Union{<:WorstRealisation, <:ValueatRisk, <:ValueatRiskRange,
33
<:ConditionalValueatRisk,
44
<:DistributionallyRobustConditionalValueatRisk,
@@ -20,14 +20,15 @@ const ERkNetRet = Union{<:WorstRealisation, <:ValueatRisk, <:ValueatRiskRange,
2020
const ERkwXFees = Union{<:LowOrderMoment, <:HighOrderMoment, <:TrackingRiskMeasure,
2121
<:RiskTrackingRiskMeasure, <:Kurtosis, <:ThirdCentralMoment,
2222
<:Skewness, <:MedianAbsoluteDeviation}
23+
const ERkX = Union{<:ERkNetRet, <:ERkwXFees}
2324
const ERkw = Union{<:StandardDeviation, <:NegativeSkewness, <:TurnoverRiskMeasure,
2425
<:Variance, <:UncertaintySetVariance, <:EqualRiskMeasure}
2526
const TnTrRM = Union{<:TurnoverRiskMeasure, <:TrRM}
2627
const SlvRM = Union{<:EntropicValueatRisk, <:EntropicValueatRiskRange,
2728
<:EntropicDrawdownatRisk, <:RelativeEntropicDrawdownatRisk,
2829
<:RelativisticValueatRisk, <:RelativisticValueatRiskRange,
2930
<:RelativisticDrawdownatRisk, <:RelativeRelativisticDrawdownatRisk}
30-
const PerfRM = Union{<:MeanReturn, <:RiskRatioRiskMeasure}
31+
const RkRatioRM = Union{<:RiskRatioRiskMeasure, <:NonOptimisationRiskRatioRiskMeasure}
3132
function expected_risk(r::ERkNetRet, w::VecNum, X::MatNum, fees::Option{<:Fees} = nothing;
3233
kwargs...)
3334
return r(calc_net_returns(w, X, fees))
@@ -47,20 +48,32 @@ end
4748
function expected_risk(r::ERkw, w::VecNum, args...; kwargs...)
4849
return r(w)
4950
end
50-
function expected_risk(r::RiskRatioRiskMeasure, w::VecNum, X::MatNum,
51-
fees::Option{<:Fees} = nothing; kwargs...)
51+
function expected_risk(r::RkRatioRM, w::VecNum, X::MatNum, fees::Option{<:Fees} = nothing;
52+
kwargs...)
5253
return expected_risk(r.r1, w, X, fees; kwargs...) /
5354
expected_risk(r.r2, w, X, fees; kwargs...)
5455
end
55-
function expected_risk(r::RiskRatioRiskMeasure, w::VecNum,
56-
pr::Union{<:AbstractPriorResult <: AbstractReturnsResult},
57-
fees::Option{<:Fees} = nothing; kwargs...)
56+
function expected_risk(r::RkRatioRM, w::VecNum, pr::Pr_RR, fees::Option{<:Fees} = nothing;
57+
kwargs...)
5858
return expected_risk(r.r1, w, pr.X, fees; kwargs...) /
5959
expected_risk(r.r2, w, pr.X, fees; kwargs...)
6060
end
6161
function expected_risk(r::AbstractBaseRiskMeasure, w::VecVecNum, args...; kwargs...)
6262
return [expected_risk(r, wi, args...; kwargs...) for wi in w]
6363
end
64+
function predicted_risk(r::Union{<:ERkNetRet, <:ERkwXFees}, X::VecNum; kwargs...)
65+
return r(X)
66+
end
67+
function predicted_risk(r::AbstractBaseRiskMeasure, X::VecVecNum; kwargs...)
68+
return [r(Xi; kwargs...) for Xi in X]
69+
end
70+
function predicted_risk(r::RkRatioRM, X::VecNum; kwargs...)
71+
return predicted_risk(r.r1, X; kwargs...) / predicted_risk(r.r2, X; kwargs...)
72+
end
73+
function predicted_risk(r::ERkw, args...; kwargs...)
74+
throw(MethodError(predicted_risk,
75+
"cannot be computed for $r because the risk measure uses internal quantities and asset weights which are not defined for the result of a prediction of portfolio returns. For:\n- `StandardDeviation`: `LowOrderMoment(; alg = SecondMoment(; alg = Full(), alg2 = SOCRiskExpr())`.\n- Semi `StandardDeviation`: `LowOrderMoment(; alg = SecondMoment(; alg = Semi(), alg2 = SOCRiskExpr())`.\n- Variance: `LowOrderMoment(; alg = SecondMoment(; alg = Full(), alg2 = QuadRiskExpr())`, `alg2` can also be `SquaredSOCRiskExpr()` or `RSOCRiskExpr()`.\n- Semi Variance: `LowOrderMoment(; alg = SecondMoment(; alg = Semi(), alg2 = QuadRiskExpr())`, `alg2` can also be `SquaredSOCRiskExpr()` or `RSOCRiskExpr()`.\n- UncertaintySetVariance: use one of the variance recommendations.\n- NegativeSkewness: the closest is to use `Skewness`.\n- TurnoverRiskMeasure and EqualRiskMeasure: not applicable."))
76+
end
6477
function number_effective_assets(w::VecNum)
6578
return inv(LinearAlgebra.dot(w, w))
6679
end

src/21_ExpectedReturns.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,19 @@ function expected_risk(r::ReturnRiskMeasure, w::VecNum, pr::AbstractPriorResult,
376376
fees::Option{<:Fees} = nothing; kwargs...)
377377
return expected_return(r.rt, w, pr, fees)
378378
end
379+
function predicted_risk(r::ReturnRiskMeasure{<:ArithmeticReturn}, X::AbstractVector;
380+
kwargs...)
381+
return Statistics.mean(X)
382+
end
383+
function predicted_risk(r::ReturnRiskMeasure{<:LogarithmicReturn}, X::AbstractVector;
384+
kwargs...)
385+
w = r.rt.w
386+
return if isnothing(w)
387+
Statistics.mean(log1p.(X))
388+
else
389+
Statistics.mean(log1p.(X), w)
390+
end
391+
end
379392
"""
380393
struct ReturnRiskRatioRiskMeasure{T1, T2, T3} <: NonOptimisationRiskMeasure
381394
rt::T1
@@ -606,6 +619,10 @@ function expected_risk(r::ReturnRiskRatioRiskMeasure, w::VecNum, pr::AbstractPri
606619
fees::Option{<:Fees} = nothing; kwargs...)
607620
return expected_ratio(r.rk, r.rt, w, pr, fees; rf = r.rf, kwargs...)
608621
end
622+
function predicted_risk(r::ReturnRiskRatioRiskMeasure, X::AbstractVector; kwargs...)
623+
return (predicted_risk(r.rt, X; kwargs...) - r.rf) / predicted_risk(r.rk, X; kwargs...)
624+
end
625+
const PerfRM = Union{<:MeanReturn, <:ReturnRiskMeasure, <:ReturnRiskRatioRiskMeasure}
609626
"""
610627
brinson_attribution(X::TimeArray, w::VecNum, wb::VecNum,
611628
asset_classes::DataFrame, col; date0 = nothing, date1 = nothing)

test/test_24_docs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010
push!(no_docs, sym)
1111
end
1212
end
13-
@test length(no_docs) == 437
13+
@test length(no_docs) == 439
1414
end

0 commit comments

Comments
 (0)