Robust Portfolio Optimization
Robust Return as Risk Constraint
using HiGHS
using Clarabel
using Distributions
using PortfolioOpt
using PortfolioOpt.TestUtilsRead Prices
prices = get_test_data();
numD, numA = size(prices) # A: Assets D: Days(316, 6)Calculating returns
returns_series = percentchange(prices);315×6 TimeSeries.TimeArray{Float64, 2, Dates.Date, Matrix{Float64}} 2009-09-02 to 2010-12-01
┌────────────┬──────────────┬──────────────┬─────────────┬─────────────┬────────
│ │ AAPL │ BA │ DELL │ CAT │ EBAY ⋯
├────────────┼──────────────┼──────────────┼─────────────┼─────────────┼────────
│ 2009-09-02 │ -0.000725953 │ -0.00758663 │ 0.00920447 │ -0.00752737 │ -0.0 ⋯
│ 2009-09-03 │ 0.00829398 │ 0.00123967 │ -0.00651466 │ 0.0351643 │ 0.00 ⋯
│ 2009-09-04 │ 0.0225758 │ 0.0142385 │ 0.0288525 │ 0.0237567 │ 0.0 ⋯
│ 2009-09-08 │ 0.0153837 │ 0.00712106 │ 0.0172084 │ 0.0186511 │ -0.0 ⋯
│ 2009-09-09 │ -0.010351 │ 0.0208081 │ -0.00250627 │ 0.0306579 │ 0.0 ⋯
│ 2009-09-10 │ 0.0082973 │ -0.000791609 │ 0.040201 │ 0.00578393 │ 0.0 ⋯
│ 2009-09-11 │ -0.00231803 │ 0.0170331 │ 0.00241546 │ -0.0032861 │ 0.00 ⋯
│ 2009-09-14 │ 0.00906134 │ -0.00740019 │ -0.0126506 │ 0.00494539 │ 0.0 ⋯
│ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋱
│ 2010-11-22 │ 0.0216151 │ 0.00691933 │ 0.00431655 │ 0.00035727 │ 0.0 ⋯
│ 2010-11-23 │ -0.0147753 │ -0.0067156 │ -0.0100287 │ -0.0163095 │ -0.0 ⋯
│ 2010-11-24 │ 0.0196612 │ 0.0284591 │ 0.00434153 │ 0.0249304 │ 0.0 ⋯
│ 2010-11-26 │ 0.000635324 │ -0.00932579 │ -0.0165706 │ -0.00661235 │ -0.00 ⋯
│ 2010-11-29 │ 0.00593651 │ -0.00679012 │ -0.00586081 │ -0.00546773 │ -0.0 ⋯
│ 2010-11-30 │ -0.0180516 │ -0.00916718 │ -0.0257922 │ 0.0111151 │ -0.0 ⋯
│ 2010-12-01 │ 0.0168729 │ 0.0305786 │ 0.0143722 │ 0.0336879 │ 0.00 ⋯
└────────────┴──────────────┴──────────────┴─────────────┴─────────────┴────────
2 columns and 300 rows omittedBacktest parameters
DEFAULT_SOLVER = optimizer_with_attributes(
HiGHS.Optimizer, "presolve" => "on", "time_limit" => 60.0, "log_to_console" => false
)
Clarabel_SOLVER = optimizer_with_attributes(
Clarabel.Optimizer, "verbose" => false, "max_iter" => 900000
)
date_range = timestamp(returns_series)[100:end];216-element Vector{Dates.Date}:
2010-01-26
2010-01-27
2010-01-28
2010-01-29
2010-02-01
2010-02-02
2010-02-03
2010-02-04
2010-02-05
2010-02-08
⋮
2010-11-18
2010-11-19
2010-11-22
2010-11-23
2010-11-24
2010-11-26
2010-11-29
2010-11-30
2010-12-01Backtest Soyster's robust return
backtest_results = Dict()
backtest_results["Soyster"], _ = sequential_backtest_market(
VolumeMarketHistory(returns_series), date_range,
) do market, past_returns, ext
numD, numA = size(past_returns)
returns = values(past_returns)
k_back = 30
Σ, r̄ = mean_variance(returns[(end - k_back):end, :])
d = MvNormal(r̄, Σ)
R = -0.015 / market_budget(market)
formulation = PortfolioFormulation(MAX_SENSE,
ObjectiveTerm(ExpectedReturn(d)),
RiskConstraint(ExpectedReturn(BudgetSet(d; Δ=maximum(abs.(returns); dims=1)'[:] .- r̄, Γ=numA * 1.0)), GreaterThan(R)),
)
pointers = change_bids!(market, formulation, DEFAULT_SOLVER)
return pointers
end(Dict{Symbol, PortfolioOpt.StateRecorder}(:decisions => PortfolioOpt.DecisionRecorder{Float64}(2-dimensional DenseAxisArray{Float64,2,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
Dimension 2, 1:6
And data, a 216×6 Matrix{Float64}:
-0.0 -0.0 -0.0 0.0 -0.0 0.22133782399067825
0.0 -0.0 -0.0 -0.0 -0.0 0.22274374461691798
-0.0 -0.0 -0.0 0.0 -0.0 0.22346785096665636
-0.0 -0.0 -0.0 0.0 -0.0 0.22264233125936214
0.0 -0.0 0.0 0.0 -0.0 0.2130308591611971
-0.0 -0.0 0.0 0.0 -0.0 0.21026542724706543
-0.0 -0.0 0.0 0.0 -0.0 0.21181605677601587
-0.0 -0.0 0.0 0.0 -0.0 0.21732069450387714
0.0 -0.0 0.0 0.0 0.0 0.2040926851602658
0.0 -0.0 0.0 0.0 -0.0 0.2024300359954988
⋮ ⋮
-0.0 0.0 0.0 -0.0 -0.0 0.20601915037031057
-0.0 0.0 -0.0 -0.0 0.1944466634604701 -0.0
-0.0 0.0 -0.0 -0.0 -0.0 0.19850920482854967
-0.0 0.0 -0.0 -0.0 0.1941799010326254 -0.0
-0.0 0.0 -0.0 -0.0 0.19434675809892202 -0.0
-0.0 0.0 -0.0 -0.0 0.198113869042182 -0.0
-0.0 0.0 0.0 -0.0 0.19472377696208812 -0.0
-0.0 0.0 0.0 -0.0 0.1878552264024443 -0.0
0.0 0.0 0.0 -0.0 -0.0 0.1903899042825381), :wealth => PortfolioOpt.WealthRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01"), Dates.Date("2010-12-02")]
And data, a 217-element Vector{Float64}:
1.0
1.0032107027958757
1.0103767213894495
1.0076680201656112
0.996545660058877
1.002048302177432
1.007153667767064
1.011802834948276
1.0009741405485983
0.9982061565726453
⋮
1.0904873347476276
1.0887699451783006
1.087794469970298
1.0848792364691553
1.0915120118449635
1.0911311457077468
1.0853800742854316
1.0786065977131964
1.0848175607136306), :returns => PortfolioOpt.ReturnsRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
And data, a 216-element Vector{Float64}:
0.0032107027958756342
0.007143084272927611
-0.0026808824535400387
-0.011037722627047565
0.0055217160026865535
0.005094929634168496
0.00461614481484187
-0.010702376021936383
-0.002765290194645818
0.0011152730505045718
⋮
-0.006302792592161171
-0.0015748826369675444
-0.0008959424461730876
-0.0026799488153512454
0.006113837515588495
-0.0003489344442236808
-0.005270742609574128
-0.006240649457927837
0.005758320979680924)), nothing)Backtest Bertsimas's robust return
backtest_results["Bertsimas"], _ = sequential_backtest_market(
VolumeMarketHistory(returns_series), date_range,
) do market, past_returns, ext
numD, numA = size(past_returns)
returns = values(past_returns)
k_back = 30
Σ, r̄ = mean_variance(returns[(end - k_back):end, :])
d = MvNormal(r̄, Σ)
R = -0.015 / market_budget(market)
formulation = PortfolioFormulation(MAX_SENSE,
ObjectiveTerm(ExpectedReturn(d)),
RiskConstraint(ExpectedReturn(BudgetSet(d; Δ=maximum(abs.(returns); dims=1)'[:] .- r̄, Γ=numA * 0.3)), GreaterThan(R)),
)
pointers = change_bids!(market, formulation, DEFAULT_SOLVER)
return pointers
end(Dict{Symbol, PortfolioOpt.StateRecorder}(:decisions => PortfolioOpt.DecisionRecorder{Float64}(2-dimensional DenseAxisArray{Float64,2,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
Dimension 2, 1:6
And data, a 216×6 Matrix{Float64}:
0.20289308736653008 0.24486952446614163 … 0.12726584082925055
0.1953388446189664 0.24063740619103535 0.12537474874411006
0.1988578503457958 0.13702293602214888 0.1268202707862655
0.19187430733948374 0.13507535643019292 0.12469450606375979
0.0 -0.0 0.2154258801732391
0.18592588582365166 0.1317305186810252 … 0.1189860566133338
0.18584228910267342 0.1323870870545527 0.1195078623397213
0.19412986482017278 0.13552701359555935 0.12379524488343199
0.0 0.13060766191114231 0.11618447426663105
0.0 -0.0 0.20716602453458405
⋮ ⋱ ⋮
0.10960021189313257 0.0 0.11094174387120354
0.11196184769442043 0.0 0.10966622870818174
0.1115496686720318 0.0 0.10970771038082248
0.10985249024803737 0.0 … 0.10644013245886837
0.10734653247722736 0.0 0.10316144334132374
0.10918578734767424 0.0 0.10521880851067232
0.10834929035351762 0.0 0.10547950413651319
0.10650457785573118 0.0 0.10278488574177262
0.0 0.0 … 0.10091695075143108), :wealth => PortfolioOpt.WealthRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01"), Dates.Date("2010-12-02")]
And data, a 217-element Vector{Float64}:
1.0
1.004043437302107
1.0202303887788664
1.0070587774742485
0.9854664536358562
0.9910309597657923
0.9950883355571601
1.000583481647906
0.9789876757052475
0.9753863292008882
⋮
1.1539393095922201
1.1560936487758386
1.1595648969049797
1.1503998592100997
1.160801926795803
1.1595378469378816
1.1562190604616973
1.1511262663057789
1.1585028008715885), :returns => PortfolioOpt.ReturnsRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
And data, a 216-element Vector{Float64}:
0.004043437302106927
0.016121764134283106
-0.0129104283203946
-0.02144097675465071
0.005646570828875985
0.004094095902237762
0.005522269626112103
-0.021583212534241898
-0.003678643351424106
0.0011680686489537598
⋮
0.0029311006049640483
0.0018669432315116582
0.003002566559219948
-0.007903859214212586
0.009042132179019523
-0.0010889711920195457
-0.002862163132448594
-0.0044046965926032135
0.006408102031658544)), nothing)Backtest BenTal's robust return
backtest_results["Ben-Tal"], _ = sequential_backtest_market(
VolumeMarketHistory(returns_series), date_range,
) do market, past_returns, ext
numD, numA = size(past_returns)
returns = values(past_returns)
k_back = 30
Σ, r̄ = mean_variance(returns[(end - k_back):end, :])
d = MvNormal(r̄, Σ)
R = -0.015 / market_budget(market)
formulation = PortfolioFormulation(MAX_SENSE,
ObjectiveTerm(ExpectedReturn(d)),
RiskConstraint(ExpectedReturn(EllipticalSet(d, 2.0)), GreaterThan(R)),
)
pointers = change_bids!(market, formulation, Clarabel_SOLVER)
return pointers
end(Dict{Symbol, PortfolioOpt.StateRecorder}(:decisions => PortfolioOpt.DecisionRecorder{Float64}(2-dimensional DenseAxisArray{Float64,2,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
Dimension 2, 1:6
And data, a 216×6 Matrix{Float64}:
1.953750376702485e-8 7.025472955979495e-9 … 0.342140933687292
3.96090721012351e-9 6.6318609167045756e-9 0.33987060133631314
1.3407283779960735e-9 0.06512234201679544 0.3053961968537018
2.804460203239087e-9 0.07426220781807129 0.306833429315792
2.2879538447115884e-9 0.016657406505337105 0.29736403494631136
7.35999272263343e-9 0.11106934895245675 … 0.23824691768713605
1.2041452997539148e-8 0.1272772387792013 0.2352175021996021
2.335676317517586e-9 0.0907094579912142 0.2632190360508985
9.925301757699927e-9 0.1977684904161402 0.16077040064835238
7.27809461926594e-10 0.0700029414940135 0.24191246600811098
⋮ ⋱ ⋮
7.166804930182915e-9 1.0772871379598368e-9 0.26327171069493666
8.351208424634045e-8 7.987067784579986e-9 0.16164072704616314
4.199109772237179e-9 5.304780998172504e-10 0.16572020827786332
4.244210041717217e-8 6.3876952005225965e-9 … 0.13471016471924654
1.8625511275596066e-8 2.923903335514406e-9 0.06102260286574373
6.734977243898777e-9 1.6710051770082912e-9 0.047450096895602915
1.0917791271534785e-8 2.027643097063392e-9 0.1098637406129015
1.176679735517942e-8 1.3728026997598458e-9 0.13622355558429472
7.190699361866859e-9 3.4797036557484183e-9 … 0.1655853161401984), :wealth => PortfolioOpt.WealthRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01"), Dates.Date("2010-12-02")]
And data, a 217-element Vector{Float64}:
1.0
1.0066085078924247
1.0170827713016226
1.0109174905842748
0.9925290224085236
1.0007245829599003
1.0066711801387995
1.0109720227895242
0.9936284031284671
0.9883807619717272
⋮
1.1951435152478667
1.193716378022437
1.1972137347670935
1.1856565903029583
1.203484856027495
1.2024019666072292
1.1903401633595043
1.1774781210752185
1.1875447021507928), :returns => PortfolioOpt.ReturnsRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
And data, a 216-element Vector{Float64}:
0.006608507892424813
0.010405498589643515
-0.0060617295772868035
-0.018189880328535357
0.008257250283209845
0.005942291495738559
0.0042723410936744335
-0.017155390327421503
-0.00528129141660766
0.0007275340087576167
⋮
-0.0034607820882346114
-0.001194113683605354
0.002929805445453077
-0.009653367755911546
0.015036618419150672
-0.0008997948040994325
-0.01003142341970655
-0.010805350168127646
0.008549272292534757)), nothing)Backtest Betina's robust return
backtest_results["Betina"], _ = sequential_backtest_market(
VolumeMarketHistory(returns_series), date_range,
) do market, past_returns, ext
numD, numA = size(past_returns)
returns = values(past_returns)
k_back = 30
j_robust = 25
R = -0.015 / market_budget(market)
Σ, r̄ = mean_variance(returns[(end - k_back):end, :])
d = MvNormal(r̄, Σ)
formulation = PortfolioFormulation(MAX_SENSE,
ObjectiveTerm(ExpectedReturn(d)),
RiskConstraint(ConditionalExpectedReturn(DeterministicSamples(returns'[:, (end - j_robust):end]); α=0.0), GreaterThan(R)),
)
pointers = change_bids!(market, formulation, DEFAULT_SOLVER)
return pointers
end(Dict{Symbol, PortfolioOpt.StateRecorder}(:decisions => PortfolioOpt.DecisionRecorder{Float64}(2-dimensional DenseAxisArray{Float64,2,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
Dimension 2, 1:6
And data, a 216×6 Matrix{Float64}:
0.0 0.0 0.0 … 0.2540909090909085
0.0 0.0 0.0 0.253157816077229
0.0 0.6137185446847665 0.0 0.0
0.0 0.6099549849010794 0.0 0.0
0.0 0.21204802641048387 0.0 0.16758912938636167
0.0 0.21032620965256546 0.0 … 0.16622831610124383
0.0 0.4731002693601723 0.0 0.0
0.0 0.21007840953985046 0.0 0.16603247082102715
0.0 0.43394409169277687 0.0 0.0
0.0 0.16439121677363955 0.0 0.19043039900320258
⋮ ⋱ ⋮
0.0 0.0 0.0 0.24588303002828832
0.0 0.0 0.0 0.24645308960922777
0.0 0.0 0.0 0.24666240630857042
0.0 0.0 0.0 … 0.0
0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0
0.0028475918799927055 0.0 0.0 0.2121355167856915
0.0 0.0 0.0 … 0.18627628419120565), :wealth => PortfolioOpt.WealthRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01"), Dates.Date("2010-12-02")]
And data, a 217-element Vector{Float64}:
1.0
1.003685815544383
1.0118303029248839
1.0180735240318015
0.9989636811544662
1.0071416082402296
1.011995852066605
1.008329592310504
0.9927416936197444
0.9860116099319938
⋮
1.170063782201865
1.1690708709083437
1.172231785304725
1.1631317480801486
1.1839803372023316
1.1828266167725399
1.1650848739777329
1.1483533787052287
1.1598597607037724), :returns => PortfolioOpt.ReturnsRecorder{Float64}(1-dimensional DenseAxisArray{Float64,1,...} with index sets:
Dimension 1, [Dates.Date("2010-01-26"), Dates.Date("2010-01-27"), Dates.Date("2010-01-28"), Dates.Date("2010-01-29"), Dates.Date("2010-02-01"), Dates.Date("2010-02-02"), Dates.Date("2010-02-03"), Dates.Date("2010-02-04"), Dates.Date("2010-02-05"), Dates.Date("2010-02-08") … Dates.Date("2010-11-17"), Dates.Date("2010-11-18"), Dates.Date("2010-11-19"), Dates.Date("2010-11-22"), Dates.Date("2010-11-23"), Dates.Date("2010-11-24"), Dates.Date("2010-11-26"), Dates.Date("2010-11-29"), Dates.Date("2010-11-30"), Dates.Date("2010-12-01")]
And data, a 216-element Vector{Float64}:
0.0036858155443830498
0.008114578540779065
0.0061702254704868965
-0.018770592129393616
0.008186410817570983
0.004819822541993041
-0.0036228011692084187
-0.01545913043674663
-0.006779289850526293
-0.0003938374594896224
⋮
-0.0023130551207262086
-0.0008485958702634104
0.002703783384770584
-0.007763001599731331
0.017924529320599753
-0.0009744422213278007
-0.01499944501013777
-0.014360752290415528
0.010019896498686912)), nothing)Plot
using Plots
using Plots.PlotMeasures
plt = plot(;title="Culmulative Wealth",
xlabel="Time",
ylabel="Wealth",
legend=:outertopright,
left_margin=10mm
);
for (strategy_name, recorders) in backtest_results
plot!(plt,
axes(get_records(recorders[:wealth]), 1), get_records(recorders[:wealth]).data;
label=strategy_name,
)
end
pltThis page was generated using Literate.jl.