Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: optimization based on historical data

Tags:

optimization

r

I have a matrix of monthly returns and a vector of forecasts. I want to minimize my risk for a given level of return (based on the forecast). The forecasts are just the anticipated % change in value of the asset. The risk is based on the 5th percentile of the vector that is the result of passing a given portfolio through the monthly returns:

library(nloptr)
library(ggplot2)

#load csv files
balances<-as.matrix(t(c(-3300000, 2000000, -7700000, 5500000, -4000000, 1000000)))
forecast<-as.matrix(t(c(-0.000768006, 0.000635124, 0.001526249, -0.008919934, 0.000152549, 0.001271481)))
mReturns<-read.csv(file="C:/Users/Desktop/mReturns.csv", header=TRUE, sep=",", row.names=1)

mReturns<-round(mReturns, digits=8)
forecast<-round(forecast, digits=8)

colnames(balances)<-letters[1:ncol(balances)]
colnames(forecast)<-letters[1:ncol(forecast)]
colnames(mReturns)<-letters[1:ncol(forecast)]

#Minimize Variance:
fn <- function(H) {
    X<-balances * (1 - H)
    Y<-t(t(mReturns) * as.vector(X))
    return(quantile(rowSums(Y), .05, na.rm=TRUE))
}

fn2 <- function(H) {
    return(-fn(H))
}

#For a given forecast:
target<-0
eqn <- function(H) {
    X <- balances * (H)
    return(sum(X * forecast) - target)
}

loops<-6
n<-length(balances)

# Initialize a matrix to contain allocation and statistics
eff<-matrix(nrow=2+loops, ncol=n+3)
colnames(eff) <- c(colnames(balances), "Target", "Variance", "Forecast")

#Find the forecast for the 100% strategy
pars <-rep(1, n)
eff[1,1:n]<-pars
eff[1,n+2]<-fn(pars)
eff[1,n+3]<-eqn(pars)

#Find the strategy that maximizes forecast
pars2<-rep(0,n)
pars2[which(balances*forecast>=0)]<-1
eff[2,1:n]<-pars2
eff[2,n+2]<-fn(pars2)
eff[2,n+3]<-eqn(pars2)

#Constrain the values in H
lH<-rep(0, ncol(balances))
uH<-rep(1,ncol(balances))

pars2<-rep(1, n)  #initial guess is all 1's

increment = (eff[2,n+3]-eff[1,n+3])/(loops+1)
for (i in 1:loops) {
    target<-c(eff[2,n+3]-(i)*increment)  #target forecast
    sol <- auglag(pars, fn=fn2, gr=NULL, heq=eqn, lower=lH, upper=uH, nl.info = FALSE, control = list(xtol_rel = 1e-8, maxeval = 20000))
    targetHolder<-target
    target<-0
    eff[i+2,]<-c(sol$par, targetHolder, fn(sol$par), eqn(sol$par))
}

#Random Portfolios
set.seed(10)
randoms<-matrix(runif(10000*ncol(balances)), ncol=ncol(balances))
dots<-cbind(apply(randoms, 1, fn), apply(randoms, 1, eqn))

#graph
x11()
eff<-as.data.frame(eff)
dots<-as.data.frame(dots)

ggplot() +
    geom_point(data=dots, aes(V1, V2),size=3, color=rgb(115,150,0,max=255)) +
    geom_line(data=eff, aes(Variance, Forecast), size=1, color=rgb(187,8,38, max=255)) +
    geom_hline(yintercept = 0) + geom_vline(xintercept = 0) +
    ggtitle("Frontier") +
    labs(x="Variance", y="Forecast") +
    theme_bw() +
    scale_x_continuous(labels = comma) +
    scale_y_continuous(labels = comma) +
    geom_point(data=eff, aes(Variance, Forecast),size=3, color=rgb(187,8,38,max=255))

monthly returns (this is the best set I can get for illustrating the problem):

                    AAA           BBB           CCC           DDD           EEE           FFF
10/1/2006 -0.0273758311 -0.0173219254 -0.0092231793 -0.0138312574 -0.0124329157 -0.0124668848
11/1/2006  0.0386007238  0.0195502377  0.0097401588  0.0115189105 -0.0125419543  0.0065488401
12/1/2006  0.0180668473  0.0380363598  0.0137722146 -0.0103839765 -0.0110926718  0.0454652348
1/1/2007   0.0006337939 -0.0111542926 -0.0301578502  0.0142295446 -0.0180118359 -0.0101971958
2/1/2007  -0.0193818090  0.0038791343 -0.0147327469  0.0171395937 -0.0106915572 -0.0135595788
3/1/2007   0.0136933213 -0.0042708969  0.0272062488 -0.0086841626  0.0051172709  0.0125940716
4/1/2007   0.0304574997  0.0047998366 -0.0017821783  0.0288433537  0.0160311962  0.0127407857
5/1/2007   0.0233737324  0.0157028153 -0.0170184226  0.0122388783  0.0387973703  0.0187209825
6/1/2007   0.0067673716 -0.0081553009 -0.0182637526  0.0680350676  0.0472285071 -0.0113937077
7/1/2007   0.0195654783  0.0132667474 -0.0086871710 -0.0124935191 -0.0042241618  0.0068406573
8/1/2007   0.0076524606  0.0118484592  0.0353900671  0.0249734320  0.0087112958  0.0093050735
9/1/2007  -0.0435798575 -0.0075768758  0.0275545857 -0.0407258270  0.0004736651 -0.0027072510
10/1/2007  0.0924749572  0.0130880968  0.0002592090  0.0845218362  0.0644348088  0.0440939105
11/1/2007  0.0201274740  0.0179104478  0.0093311906  0.0350746684  0.0427970555  0.0136322114
12/1/2007 -0.0305820454 -0.0114417576  0.0308341887 -0.0249386286 -0.0477620911  0.0144194107
1/1/2008  -0.0093848937 -0.0339930944 -0.0036721437  0.0069662916  0.0061454765 -0.0028018861
2/1/2008   0.0321881064 -0.0107229158  0.0484552051  0.0198235360 -0.0027127500  0.0143914474
3/1/2008   0.0294150171  0.0122131189  0.0265085560  0.0323534622  0.0075926301  0.0254695311
4/1/2008  -0.0254592330 -0.0066361671  0.0185567006 -0.0307842234 -0.0328013313  0.0286580144
5/1/2008   0.0291005291 -0.0005567083 -0.0247055516  0.0492000484  0.0012745099 -0.0089663123
6/1/2008   0.0239931448  0.0037978529 -0.0103297983  0.0218807620  0.0267767258  0.0051699625
7/1/2008  -0.0010460251  0.0063562528 -0.0057476747  0.0181476849 -0.0281745247  0.0153658223
8/1/2008  -0.0270157068 -0.0099754374 -0.0146689710  0.0243589740 -0.0048676019 -0.0145000950
9/1/2008  -0.0848041326 -0.0878987342 -0.0039763301 -0.0543735223 -0.0370300926 -0.0608455410
10/1/2008 -0.0740827846 -0.0175974242  0.0228906428 -0.1397058821  0.0037639971 -0.0415954026
11/1/2008 -0.1518923038 -0.0915974459  0.0736264752 -0.1118110238 -0.1235463915 -0.0915839817
12/1/2008 -0.0413297394 -0.0741477980  0.0566584579 -0.0762846012 -0.0286790030 -0.0090366179
1/1/2009   0.1018431740 -0.0138403655  0.0268870859  0.0098509388  0.0231128587  0.1137102530
2/1/2009  -0.0962574426 -0.0094018259  0.0092303638 -0.0036590625 -0.0077260893 -0.0877180491
3/1/2009   0.0023529412 -0.0152682256 -0.0784996236 -0.0266487893 -0.0365901429 -0.0112385858
4/1/2009   0.0943661972  0.0104763235 -0.0096417819  0.0496085860  0.0129365079  0.0457810403
5/1/2009   0.0447590448  0.0313104783 -0.0059523944  0.0459061643  0.0631117103  0.0018114575
6/1/2009   0.1088146729  0.1020038871  0.0261932537  0.1138436318  0.0838591685  0.0667520530
7/1/2009  -0.0019750648  0.0021285653 -0.0007242318  0.0099870620 -0.0487995829 -0.0012006498
8/1/2009   0.0338899196  0.0142614395  0.0209125845  0.0361374737  0.0668151452  0.0081318060
9/1/2009  -0.0118435220 -0.0330880153  0.0189410175 -0.0253958301 -0.0240898396 -0.0023146525
10/1/2009  0.0529055690 -0.0126856436  0.0369378363  0.0711407143  0.0187286653  0.0225674916
11/1/2009  0.0344946533  0.0312127860 -0.0053280313  0.0144219837 -0.0008296452  0.0119628738
12/1/2009  0.0281204846  0.0096031119  0.0393401412  0.0235369340  0.0368954311  0.0245940621
1/1/2010  -0.0291891892 -0.0276924929 -0.0683577530 -0.0136428779 -0.0062689978 -0.0501956104
2/1/2010  -0.0073496659 -0.0119497245  0.0268182226 -0.0560575728 -0.0073543270 -0.0274364703
3/1/2010   0.0106573929 -0.0605965660  0.0166050081  0.0279786409  0.0184367195 -0.0266312540
4/1/2010   0.0224220224  0.0200787139 -0.0499893623  0.0188144624  0.0325203247  0.0021386431
5/1/2010   0.0034741070 -0.0011770861 -0.0003196447  0.0144877542 -0.0091364566 -0.0217087350
6/1/2010  -0.1007248729 -0.0407882676  0.0318856314 -0.0586643576 -0.0355315523 -0.0801113284
7/1/2010   0.0146775746  0.0359019862  0.0382420201  0.0316565244 -0.0039637605  0.0243683048
8/1/2010   0.0720891629  0.0337352573  0.0130681681  0.0206279554  0.0290375846  0.0419094755
9/1/2010   0.0082946251 -0.0149149085  0.0240407343  0.0050973650 -0.0191465044 -0.0186178363
10/1/2010  0.0665789185  0.0238757684  0.0146598812  0.0333195239  0.0295184853  0.0766648450
11/1/2010  0.0151172357  0.0133973711  0.0336604101 -0.0078097478  0.0044326247  0.0073961279
12/1/2010 -0.0190456894 -0.0257545523 -0.0437106512 -0.0011144347 -0.0017699119 -0.0542719355
1/1/2011   0.0568005783 -0.0007040901  0.0378451737  0.0262445077  0.0190380763  0.0186467768
2/1/2011  -0.0119222124  0.0339482449 -0.0028272754 -0.0018625333  0.0074702196  0.0332486551
3/1/2011   0.0022747503  0.0077437740 -0.0062301897  0.0003004991  0.0162084538 -0.0037602140
4/1/2011   0.0249654628 -0.0095899674 -0.0261717073  0.0354075923  0.0120431890  0.0333889816
5/1/2011   0.0562241263  0.0369933586  0.0353491621  0.0200583972  0.0191514125  0.0400365245
6/1/2011  -0.0325403336 -0.0223259711  0.0029648152 -0.0117927481 -0.0328489560 -0.0323495644
7/1/2011   0.0146975692 -0.0159177176  0.0014845420  0.0245501284  0.0195096504  0.0138190955
8/1/2011   0.0186629526  0.0138111236  0.0468851189 -0.0064491408  0.0015673977 -0.0190004131
9/1/2011  -0.0226961991 -0.0071796760  0.0036396795 -0.0330925481 -0.0203705594  0.0006315789
10/1/2011 -0.0988621526 -0.0367760677 -0.0016869980 -0.1381365404 -0.0698847952 -0.0611543587
11/1/2011  0.0690333264  0.0234214579 -0.0167155471  0.0770244711  0.0293022346  0.0236049899
12/1/2011 -0.0082292574 -0.0162392626  0.0086228941 -0.0306649633  0.0064108885 -0.0176603663
1/1/2012  -0.0034166341 -0.0093690249  0.0102717068 -0.0357295909 -0.0072456670 -0.0371443429
2/1/2012   0.0485845822  0.0187222544  0.0093176468  0.0763997010  0.0227318248  0.0154309081
3/1/2012   0.0097150864  0.0077680940 -0.0606509309  0.0117255850  0.0132927441  0.0113973102
4/1/2012  -0.0428346748  0.0031960895 -0.0211174021 -0.0616378357 -0.0132171821  0.0024040267
5/1/2012  -0.0011598685  0.0133058471  0.0347109283 -0.0427081690  0.0134970570 -0.0079442404
6/1/2012  -0.0612541126 -0.0528943962  0.0265316552 -0.0646046778 -0.0534101827 -0.0606632923
7/1/2012   0.0553551180  0.0223914600 -0.0221831931  0.0152781926  0.0240015740  0.0187389416
8/1/2012   0.0217815980 -0.0108868657  0.0172106230 -0.0170718584  0.0109387431 -0.0348938186
9/1/2012  -0.0132874486  0.0212409887  0.0006377956  0.0066476282  0.0195680830  0.0289570552
10/1/2012  0.0037783375  0.0166393546  0.0051289010  0.0019735538  0.0040720757  0.0245647508
11/1/2012  0.0038606312  0.0000000000 -0.0265851526 -0.0022644484 -0.0142498744  0.0042675357
12/1/2012  0.0025959042 -0.0072535648 -0.0286130154 -0.0489700375  0.0021118266  0.0033222591
1/1/2013  -0.0031645570  0.0147380254 -0.0486735937  0.0411386231  0.0010066431  0.0167873094
2/1/2013   0.0011544012 -0.0342174903 -0.0654305847  0.0319919529 -0.0031108877  0.0330202969
3/1/2013  -0.0196021908 -0.0417383547 -0.0087616625  0.0041925528 -0.0295091542 -0.0453079179
4/1/2013   0.0215622856  0.0127011571  0.0038614299 -0.0203384796  0.0098347756 -0.0132852096
5/1/2013  -0.0138156001  0.0214065270 -0.0427148166  0.0097436671  0.0084300305  0.0257607596
6/1/2013  -0.0688782956 -0.0229508197 -0.0304629093 -0.0652935412 -0.0281445781 -0.0137329287
7/1/2013  -0.0347926027  0.0012501645  0.0079269110 -0.0394347242 -0.0116223686  0.0050003846
8/1/2013  -0.0338817926 -0.0063744496  0.0012055870 -0.0326360551  0.0145950131  0.0109461115
9/1/2013  -0.0026890756  0.0253968254  0.0139553083 -0.0340809061 -0.0181266017  0.0011357613
10/1/2013  0.0558364229  0.0445691434  0.0017347621  0.0762463339  0.0208292961  0.0229919831
11/1/2013  0.0042562247 -0.0166100648 -0.0067903218 -0.0165498253 -0.0094049904 -0.0028833358
12/1/2013 -0.0349650350  0.0277533593 -0.0368020343 -0.0351883563 -0.0182777460  0.0077111292
1/1/2014  -0.0243741765  0.0120967742 -0.0266983220 -0.0110494902 -0.0028184893  0.0126554337
2/1/2014  -0.0146297547 -0.0076663045  0.0314581713 -0.0210129322 -0.0434938896 -0.0201264259
3/1/2014   0.0191868433  0.0186142709  0.0023576343  0.0292198115  0.0057845269  0.0234317070
4/1/2014   0.0361945316 -0.0068677217 -0.0178485935  0.0364295499  0.0036284465 -0.0006520794
5/1/2014   0.0029198659  0.0158147925  0.0128994503  0.0132598662  0.0062066454  0.0055825419
6/1/2014   0.0038818201 -0.0081690641  0.0055025913 -0.0041043938  0.0101419878 -0.0169430425
7/1/2014   0.0200859291  0.0235750522  0.0023639137  0.0179844668  0.0201279157  0.0032269894
8/1/2014  -0.0194798357 -0.0191836735 -0.0105253101 -0.0247154181 -0.0260168559 -0.0184223993
9/1/2014   0.0021477663 -0.0126627430 -0.0166746378  0.0052540178  0.0041394531 -0.0222685633
10/1/2014 -0.0636519503 -0.0254094412 -0.0416934585 -0.0947966609 -0.0261578426 -0.0384673979
11/1/2014  0.0068665599 -0.0118003213 -0.0305377641  0.0013318247 -0.0091425528 -0.0077636061
12/1/2014 -0.0348942942 -0.0165676774 -0.0513513556 -0.0323739586 -0.0055609505 -0.0043912176
1/1/2015  -0.0362737016 -0.0091544819 -0.0111909311 -0.0364614693 -0.0242873130 -0.0293504411
2/1/2015  -0.0514481242 -0.0337482356  0.0191506171 -0.0094300950 -0.0880458693 -0.0671678784
3/1/2015   0.0059263077  0.0250996016 -0.0178885567 -0.0557158943  0.0173391939 -0.0084137809
4/1/2015  -0.0266393443 -0.0398367664 -0.0010855227 -0.1022781142 -0.0083987014 -0.0386745266
5/1/2015   0.0330263158  0.0219253862 -0.0032458554  0.0498921894  0.0379965466  0.0405091517
6/1/2015  -0.0312062158  0.0034988117 -0.0370281860 -0.0485734132 -0.0289889795 -0.0242878828
7/1/2015   0.0051275309  0.0273666206  0.0129901792  0.0060967874 -0.0054011118  0.0115310698
8/1/2015  -0.0440810988  0.0003201639 -0.0058116534 -0.0795580758 -0.0382705683 -0.0062426491
9/1/2015  -0.0395457033 -0.0203559083  0.0378654941 -0.0749722897 -0.0126706388  0.0301347414
10/1/2015  0.0015671748 -0.0113042342 -0.0046693964 -0.0775158974 -0.0006783238 -0.0106053911
11/1/2015  0.0153627312  0.0196285771 -0.0057204213  0.0398620240  0.0143730891 -0.0168825368
12/1/2015  0.0259176240 -0.0224267565 -0.0183120461  0.0007267065 -0.0208114991 -0.0338906051
1/1/2016  -0.0027311211 -0.0222782124  0.0192451285 -0.0272167213 -0.0358715265  0.0209724443
2/1/2016  -0.0258797754 -0.0212260952 -0.0036366319 -0.0007064285 -0.0066676232  0.0029476787
3/1/2016   0.0085746416 -0.0333264048  0.0612226330  0.0074985366  0.0401193145 -0.0018368846
4/1/2016   0.0699651568  0.0197104358  0.0207718249  0.1070122134  0.0306663595  0.0481229297
5/1/2016  -0.0096391820  0.0270612216  0.0487323576  0.0343442572  0.0362376556  0.0052673163
6/1/2016  -0.0455083520 -0.0134136326 -0.0277524101 -0.0460086088 -0.0399143600 -0.0229674264
7/1/2016   0.0332093151 -0.0797031077  0.0684744419  0.1128105301  0.0128562573 -0.0046478370
8/1/2016   0.0050680181 -0.0066329992  0.0012697102 -0.0089113465 -0.0161536118  0.0024245690
9/1/2016   0.0019904459  0.0067531679 -0.0081372403  0.0025174229  0.0016026871  0.003045776

As you can see, the red line is not the most efficient set of solutions: enter image description here

like image 357
user3390169 Avatar asked Sep 12 '16 01:09

user3390169


3 Answers

I would go with quantile spline regression (package fields). Here I did the model to fit 10% of the points (just to run it faster for the example).

library(fields)
dots <- dots[base::sample(NROW(dots), 1000), ]
fit90 = qsreg(x=dots$V1, y=dots$V2, alpha=0.95, lam=1E7)
plot(x=dots$V1, y=dots$V2, main=("alpha=95%"))
points(x=dots$V1, y=fitted(fit90), col="red")

Then you can tweek the parameters to choose the threshold that suits you (90%, 95%, 99% of the limit of your points) and then play with the lambda argument to get the smoothing you want (it goes fro 0 to infinite..)

enter image description here

like image 125
agenis Avatar answered Nov 09 '22 07:11

agenis


One thing that will help with the visualization is to show opacity. By adding an alpha to your aesthetics you will see the data in depth better.

For example:

ggplot() +
    geom_point(data=dots, aes(V1, V2),size=3, color=rgb(115,150,0,max=255), alpha=0.05) +
    geom_line(data=eff, aes(Variance, Forecast), size=1, color=rgb(187,8,38, max=255)) +
    geom_hline(yintercept = 0) + geom_vline(xintercept = 0) +
    ggtitle("Frontier") +
    labs(x="Variance", y="Forecast") +
    theme_bw() +
    scale_x_continuous(labels = comma) +
    scale_y_continuous(labels = comma) +
    geom_point(data=eff, aes(Variance, Forecast),size=3, color=rgb(187,8,38,max=255))

This provides: enter image description here

Now your optimization looks a lot better.

like image 40
Brian O'Donnell Avatar answered Nov 09 '22 07:11

Brian O'Donnell


I don't have a high enough score to comment, but it looks like you need a mean-variance optimisation function. (That said, there are difficulties in this approach: see a paper that I wrote for more details.)

Anyway, you could try the portfolio.optim function from the package tseries. Here's an example of the code:

portfolio.optim(x, pm = mean(x), riskless = FALSE, shorts = FALSE,
rf = 0.0, reslow = NULL, reshigh = NULL, covmat = cov(x), ...)

To give you some more background, you may find these slides useful.

I hope that helps you.


EDIT (I've now had a bit more time to consider the details.)

From what it seems to me, your investments are a bit counterintuitive. After all, some higher risk investments have the lowest expected returns and vice-versa. Here's the detail:

library(ggplot2)
library(tseries)
library(scales)
library(dplyr)

# Load csv files (with a modified reference in my code)
forecast<-as.matrix(t(c(-0.000768006, 0.000635124, 0.001526249, -0.008919934, 0.000152549, 0.001271481)))
mReturns<-read.csv(file="mReturns.csv", header=TRUE, sep=",", row.names=1)

# Consider inputs to mean-variance optimiser
mRet <- matrix(unlist(mReturns), nrow = 120, ncol = 6, byrow = FALSE)
colnames(mRet) <- c("AAA", "BBB", "CCC", "DDD", "EEE", "FFF")
vc <- cov(mRet)
cor <- cor(mRet)
print(round(cor, 2))

That code yields this correlation matrix of monthly returns:

     AAA   BBB   CCC  DDD  EEE  FFF
AAA 1.00  0.58  0.05 0.77 0.73 0.74
BBB 0.58  1.00 -0.10 0.45 0.57 0.61
CCC 0.05 -0.10  1.00 0.02 0.01 0.05
DDD 0.77  0.45  0.02 1.00 0.64 0.53
EEE 0.73  0.57  0.01 0.64 1.00 0.57
FFF 0.74  0.61  0.05 0.53 0.57 1.00

And now for the other inputs to the optimiser:

returnStats <- data_frame(name = c("AAA", "BBB", "CCC", "DDD", "EEE", "FFF"), 
                          ret = as.numeric(forecast), 
                          vol = sqrt(apply(mRet, 2, var)))
inputs <- returnStats
inputs[, 2:3] <- round(100*inputs[, 2:3], 2)
print(inputs)

And this yields the expected (forecast) return and volatility of each investment:

   name   ret   vol
  <chr> <dbl> <dbl>
1   AAA -0.08  4.17
2   BBB  0.06  2.74
3   CCC  0.15  2.84
4   DDD -0.89  4.60
5   EEE  0.02  2.94
6   FFF  0.13  3.12

So, as I mentioned above, these are strange inputs (as they've been entered above):

  • The investment with the second-lowest volatility has the highest expected return (CCC)
  • The highest-volatility investment has the lowest expected return (DDD)

All this makes the prima facie answer quite simple: Allocate lots to CCC. Sure, the second-order impact of diversification may mean that you don't allocate everything to CCC, opting also for some FFF, given its risk-return profile and the low correlation between these two investments.

And all this is confirmed by the end points of the efficient frontier. (I've kept the frontier in return space, as it is easier to interpret. BTW, you could also use the package PortfolioAnalytics if you wanted.)

# Build efficient frontier
effFrontier = function (averet, rcov, nports = 8, shorts=FALSE, wmax=1)
{
  mxret = max(abs(averet))
  mnret = -mxret
  n.assets = ncol(averet)
  reshigh = rep(wmax,n.assets)
  if( shorts )
  {
    reslow = rep(-wmax,n.assets)
  } else {
    reslow = rep(0,n.assets)
  }
  min.rets = seq(mnret, mxret, len = nports)
  vol = rep(NA, nports)
  ret = rep(NA, nports)
  for (k in 1:nports)
  {
    port.sol = NULL
    try(port.sol <- portfolio.optim(x=averet, pm=min.rets[k], covmat=rcov,
                                    reshigh=reshigh, reslow=reslow,shorts=shorts),silent=T)
    if ( !is.null(port.sol) )
    {
      vol[k] = sqrt(as.vector(port.sol$pw %*% rcov %*% port.sol$pw))
      ret[k] = averet %*% port.sol$pw
    }
  }
  return(list(vol = vol, ret = ret))
}

# Run efficient frontier
eF <- effFrontier(averet=forecast, rcov=vc, shorts = FALSE, nports = 100)
eff <- as_data_frame(eF)

All that remains is to plot this frontier:

ggplot() +
  geom_line(data=eff, aes(vol, ret), size=1, color=rgb(187,8,38, max=255)) +
  geom_hline(yintercept = 0) + geom_vline(xintercept = 0) +
  ggtitle("Frontier") +
  labs(x="Volatility", y="Forecast") +
  theme_bw() +
  scale_x_continuous(labels = percent) +
  scale_y_continuous(labels = percent) +
  geom_point(data=eff, aes(vol, ret), size=3, color=rgb(187,8,38,max=255))

And that code produces this chart:

Portfolio optimisation

The discontinuity at around 2% volatility and the inversion of this frontier speak to the nature of your investment inputs.

Sorry that the extended answer took a while, but I hope this helps you a bit more.

like image 2
p0bs Avatar answered Nov 09 '22 05:11

p0bs