[R-SIG-Finance] PortfolioAnalytics question re: showing results

Brian G. Peterson brian at braverock.com
Fri Mar 18 22:07:44 CET 2016


create.EfficientFrontier should be able to create an efficient frontier
with arbitrary return/risk columns to compare.

chart.EfficientFrontier has a hardcoded 'mean' and a flexible x axis
column.  It should be pretty straightforward to allow it to use
arbitrary columns as well.

Regards,

Brian


On Fri, 2016-03-18 at 14:37 -0500, matt at considine.net wrote:
>  
> Hi Ross, 
> 
> Thanks - that helps alot. It looks like part of what was tripping me up
> is that the guts of the create/chart EfficientFrontier functions expect
> hard-coded column headings. I.e. that those routines as written aren't
> flexible enough to deal with the custom optimizing functions. Is that
> correct or is there a more flexible set of those that I have overlooked?
> The presentation graphs the create are quite clean. 
> 
> In any case, thank you for the example and feedback. 
> 
> Matt 
> 
> On 2016-03-18 10:54, Ross Bennett wrote: 
> 
> > Hi Matt,
> > 
> > You are very close in your script. Note that create.EfficientFrontier with type="mean-StdDev" is a special case for an efficient frontier that can be formulated and solved with a QP solver. 
> > 
> > Also note that your second call to add.objective should add to the SD.portf portfolio and not init.portf
> > # Add measure 2, annualized standard deviation
> > # note that you want to add this to the SD.portf portfolio, not init.portf
> > SD.portf <- add.objective(portfolio=SD.portf,
> > type="risk", # the kind of objective this is
> > name="pasd1", # to minimize from the sample
> > enabled=TRUE, # enable or disable the objective
> > multiplier=0 # calculate it but don't use it in the objective
> > )
> > 
> > I recommend actually running an optimization using random portfolios so you get the entire feasible space given the constraints and objectives in your portfolio. 
> > 
> > rp <- random_portfolios(SD.portf, 5000)
> > # make sure to run with trace=TRUE for the extract stats output
> > opt <- optimize.portfolio(R, SD.portf, optimize_method="random", trace=TRUE) 
> > chart.RiskReward(opt, risk.col="pasd1.pasd1", return.col="pamean1.pamean1")
> > 
> > # use the output of extractStats to find portfolio with max return at a given 
> > # risk level and portfolio with min risk at a given return level
> > ex <- extractStats(opt)
> > head(ex)
> > 
> > # This should get you started
> > # order by max pamean1
> > head(ex[order(ex[,"pamean1.pamean1"], decreasing=TRUE),])
> > 
> > # order by min pasd1
> > head(ex[order(ex[,"pasd1.pasd1"], decreasing=FALSE),])
> > 
> > Hope this helps, let me know if you need any other pointers. 
> > 
> > Regards, 
> > Ross 
> > 
> > On Fri, Mar 18, 2016 at 8:13 AM, <matt at considine.net> wrote:
> > 
> >> Hi Brian,
> >> 
> >> Thanks for the offer of some code. I had wanted to try to figure this out for myself, but I'm not making the headway I thought. IF you have some code or a worked example you can send, I'd be appreciative.
> >> 
> >> That said here is what I am working with. Perhaps someone can suggest what I am doing wrong?
> >> 
> >> Goal : generate/plot an efficient frontier (with annualized axes) using PortfolioAnalytics, using monthly return data. (Ideally, I'd also want to isolate the tangency/max Sharpe portfolio, a portfolio with max return at a specific risk level and a portfolio with a min risk at a specific return. But I'll deal with that later.)
> >> 
> >> Code : I tried to use code from some of the presentations, demos (DEoptim and random portfolios, specifically) and vignettes. Also, I'm using the latest version of the code from R-forge.
> >> 
> >> #-----------------------------
> >> library(PortfolioAnalytics)
> >> 
> >> # Define pamean function
> >> pamean1 <- function(R, weights, n=60, geometric=FALSE){
> >> as.vector(sum(Return.annualized(last(R,n), geometric=geometric)*weights))
> >> }
> >> 
> >> # Define pasd function
> >> pasd1 <- function(R, weights=NULL){
> >> as.numeric(StdDev(R=R, weights=weights)*sqrt(12)) # hardcoded for monthly data
> >> }
> >> 
> >> data(edhec)
> >> 
> >> # Use the first 4 columns in edhec for a returns object
> >> R <- edhec[, 1:4]
> >> colnames(R) <- c("CA", "CTAG", "DS", "EM")
> >> head(R, 5)
> >> 
> >> # Get a character vector of the fund names
> >> funds <- colnames(R)
> >> 
> >> # Construct initial portfolio with basic constraints.
> >> init.portf <- portfolio.spec(assets=funds)
> >> init.portf <- add.constraint(portfolio=init.portf, type="full_investment")
> >> init.portf <- add.constraint(portfolio=init.portf, type="box", min=0.0, max=1.0)
> >> 
> >> # Portfolio with standard deviation as an objective
> >> #SD.portf <- add.objective(portfolio=init.portf, type="risk", name="pasd1") #pasd1 doesn't work?
> >> #SD.portf <- add.objective(portfolio=SD.portf, type="return", name="mean") #pamean1 doesn't work?
> >> 
> >> #Ok, let's try this :
> >> #Add measure 1, annualized return
> >> SD.portf <- add.objective(portfolio=init.portf,
> >> type="return", # the kind of objective this is
> >> name="pamean1", # name of the function
> >> enabled=TRUE, # enable or disable the objective
> >> multiplier=0 # calculate it but don't use it in the objective
> >> )
> >> 
> >> # Add measure 2, annualized standard deviation
> >> SD.portf <- add.objective(portfolio=init.portf,
> >> type="risk", # the kind of objective this is
> >> name="pasd1", # to minimize from the sample
> >> enabled=TRUE, # enable or disable the objective
> >> multiplier=0 # calculate it but don't use it in the objective
> >> )
> >> 
> >> #Create efficient frontier
> >> init.portf.ef <- create.EfficientFrontier(R=R, portfolio=SD.portf, type="mean-StdDev")
> >> 
> >> #This chart never seems to show annualized axes
> >> chart.EfficientFrontier(init.portf.ef, match.col="StdDev")
> >> 
> >> sd.moments <- set.portfolio.moments(R, SD.portf)
> >> names(sd.moments) #returning NULL with pasd1/pamean1
> >> print(sd.moments) #returning NULL with pasd1/pamean1
> >> 
> >> #Just a reality check to see what the axes ranges should roughly look like
> >> ra <- Return.annualized(R[, , drop = FALSE], scale = 12, geometric = FALSE)
> >> sda <- StdDev.annualized(R[, , drop = FALSE], scale = 12)
> >> sra <- SharpeRatio.annualized(R[, , drop = FALSE], scale = 12, Rf = 0.00, geometric = FALSE)
> >> 
> >> pamean1(R)
> >> ra
> >> 
> >> pasd1(R)
> >> sda
> >> #----------------------------------
> >> Regards,
> >> Matt 
> >> 
> >> _______________________________________________
> >> R-SIG-Finance at r-project.org mailing list
> >> https://stat.ethz.ch/mailman/listinfo/r-sig-finance [1]
> >> -- Subscriber-posting only. If you want to post, subscribe first.
> >> -- Also note that this is not the r-help list where general R questions should go.
> 
>  
> 
> Links:
> ------
> [1] https://stat.ethz.ch/mailman/listinfo/r-sig-finance
> 
> 	[[alternative HTML version deleted]]
> 
> _______________________________________________
> R-SIG-Finance at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-sig-finance
> -- Subscriber-posting only. If you want to post, subscribe first.
> -- Also note that this is not the r-help list where general R questions should go.



More information about the R-SIG-Finance mailing list