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

matt at considine.net matt at considine.net
Mon Mar 21 13:42:46 CET 2016


 

Hi again, 

In running the chart.RiskReward code, the "Optimal" portfolio is being
plotted in the middle of the feasible portfolio set. Why would that be
happening? Or is it because I am using customized risk/return calcs and
the corresponding values for the optimal portfolio are not being scaled?


I tried to get at the underlying plotting code, but the View function
returns "uses method chart.RiskReward". Is there an easy way to see and
edit that underlying code? Apologies if the answer to this is incredibly
straightforward, but the answer will also help me create versions of the
*.EfficientFrontier functions to use with customized risk/return
functions 

Thanks, 

Matt 

On 2016-03-18 14:37, 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]]



More information about the R-SIG-Finance mailing list