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

Ross Bennett rossbennett34 at gmail.com
Fri Mar 18 21:17:31 CET 2016


Matt,

I'm glad it was helpful. That is correct, the *.EfficientFrontier routines
are not flexible in some cases. create.EfficientFrontier can create an
efficient.frontier object with custom objective/moment functions by
specifying type="random" or type="DEoptim". Under the hood, it is just
running an optimization and handing back the data needed for the chart. In
most cases, it is better to run the optimization with trace=TRUE so that
you have all the data you need for creating charts and doing other analysis.

Ross

On Fri, Mar 18, 2016 at 2:37 PM, <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
>> -- 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.
>>
>
>
>

	[[alternative HTML version deleted]]



More information about the R-SIG-Finance mailing list