Construction of a Portfolio Efficient Frontier

The task for Project 2 will be to generate a strategic asset allocation with the Markowitz-method and test it.

  1. Use the data from 01.01.2014 to 30.06.2016 to determine monthly returns.
  2. Construct a SAA with the following expected returns for the asset classes (annual and discrete numbers):
    • European government bonds: Rgovt = 1.5%.
    • European high yield corporate bonds: Rhy = 3.0%.
    • Worldwide equities: Req = 6.0%.
  3. Each student is asked to obtain an optimal portfolio for a different level of risk! (for your target portfolio standard deviation see the PDF file IAM Project 2 - Target Portfolio annualized standard deviation.pdf) - 9 points

  4. Test the calculated SAAs on the data from 30.06.2016 to 31.12.2016 by calculating the annualized return, some risk measures and risk-adjusted return measures (given in the Excel File IAM Project 2.xlsx) - 11 points

  5. Upload your results until April 18th, 2017 23:55.

This code was copied from: https://elliotnoma.wordpress.com/2013/01/22/construct-a-stock-portfolio-using-r/.

The first step is to select some assets to compose the Portfolio:
- WRDE (World Equities) - EGVB (European Government Bonds) - EHYB (European High Yield Bonds)

# create list of stock tickers – replace the tickers here with those you want to use in your portfolio
TickerList <- c("WRDE", "EGVB", "EHYB")

# read closing prices from Yahoo keeping only the closing prices

ClosingPricesRead <- NULL 

ClosingPricesRead <- read.xlsx(file = "//Volumes/Vol1/FHonedrive/ARIMA2/Asset Management/Project 2/P2 Solution Package/Project2_data.xlsx", sheetName = "data", stringsAsFactors = FALSE)


#for (Ticker in TickerList)
#  ClosingPricesRead <- cbind(ClosingPricesRead,
#                    getSymbols.yahoo(Ticker, from="1950-01-01",
#                    verbose=FALSE, auto.assign=FALSE)[,6]) # [,6] = keep the adjusted prices


# keep only the dates that have closing prices for all tickers
ClosingPrices <- ClosingPricesRead[apply(ClosingPricesRead,1,function(x) all(!is.na(x))),]

# and transform the dataframe into a time series (xts) format
# for information on how to treat dates and times
# https://www.stat.berkeley.edu/~s133/dates.html
# http://biostat.mc.vanderbilt.edu/wiki/pub/Main/ColeBeck/datestimes.pdf
# https://faculty.washington.edu/ezivot/econ424/Working%20with%20Time%20Series%20Data%20in%20R.pdf

ClosingPrices[,1] <- as.Date(ClosingPrices[, 1])
ClosingPrices <- xts(ClosingPrices[, -1], order.by=ClosingPrices$Date)

# convert prices to daily returns
#returns <- as.timeSeries((tail(ClosingPrices,-1) / as.numeric(head(ClosingPrices,-1)) -1))
returns <- as.xts((tail(ClosingPrices,-1) / as.numeric(head(ClosingPrices,-1)) -1))

# getwd()
# write.xlsx(returns, "returns.xlsx")

# hard learned lesson: portfolioFrontier functions needs a timeSeries object
# timeSeries objects are subset differently than xts objects
# while xts objects work with a vector of strings, eg: returns[as.Date(c("2014-01-02","2016-06-30"))]
# timeSeries are subset with window, eg : window(sbux.ts, start=c(1993, 3), end=c(1993,8))
# or a 
   start.date <- as.Date("2014-01-02")
   end.date <- as.Date("2016-06-30")
returns.Sample <-   returns[paste(start.date,end.date,sep="/")] # can also be "::"


# and then convert back to timeSeries
returns.Sample <- as.timeSeries(returns.Sample)

# calculate the efficient frontier
Frontier <- portfolioFrontier(returns.Sample)

# plot frontier
plot(Frontier, c(1,2,3,4,7)) # can also call the plot routine and decide other info to plot:

# plot(Frontier)

Portfolio Profile

Return and Risk

addtional code to get a better look at the portfolios – annualize the returns and risk

# get the means and covariance matrix of the price returns
getStatistics(Frontier)$mean # data input into the efficient frontier calculator
##         WRDE         EGVB         EHYB 
## 3.235921e-04 2.229306e-04 6.638692e-05
cor(returns.Sample)
##           WRDE        EGVB        EHYB
## WRDE 1.0000000 0.129373161 0.576156966
## EGVB 0.1293732 1.000000000 0.009893845
## EHYB 0.5761570 0.009893845 1.000000000
# execute the next commands to plot annualized returns and risk
# convert from daily to annual returns and risk for points on the efficient frontier
# plot efficient frontier using annualized return and risk
riskReturnPoints <- frontierPoints(Frontier) # get risk and return values for points on the efficient frontier

annualizedPoints <- data.frame(targetRisk = riskReturnPoints[, "targetRisk"] * sqrt(252),
                               targetReturn = riskReturnPoints[, "targetReturn"] * sqrt(252))

# In red are the points related to a 4.20% Variance
{
plot(annualizedPoints)
points(annualizedPoints[c(40,41),], col= "red", pch=16)
  }

# write.xlsx(annualizedPoints, "annualizedPoints.xlsx")

Sharpe Ratio

# plot Sharpe ratios for each point on the efficient frontier
riskFreeRate <- 0

{
plot((annualizedPoints[,"targetReturn"] - riskFreeRate) / annualizedPoints[,"targetRisk"],
                                    xlab= "point on efficient frontier", ylab="Sharpe ratio")
  
}

Asset Allocation (Weights)

# plot the allocation to each stock for each point on the efficient frontier
# weightsPlot(Frontier)
allocations <- getWeights(Frontier@portfolio) # get allocations for each instrument for each point on the efficient frontier
colnames(allocations) <- TickerList
barplot(t(allocations), col=rainbow(ncol(allocations)+2), legend=colnames(allocations))

allocations
##              WRDE         EGVB       EHYB
##  [1,] 0.000000000 0.000000e+00 0.99999999
##  [2,] 0.000000000 3.353111e-02 0.96646889
##  [3,] 0.000000000 6.706222e-02 0.93293778
##  [4,] 0.000000000 1.005933e-01 0.89940667
##  [5,] 0.000000000 1.341244e-01 0.86587556
##  [6,] 0.000000000 1.676556e-01 0.83234445
##  [7,] 0.000000000 2.011867e-01 0.79881333
##  [8,] 0.000000000 2.347178e-01 0.76528222
##  [9,] 0.000000000 2.682489e-01 0.73175111
## [10,] 0.000000000 3.017800e-01 0.69822000
## [11,] 0.000000000 3.353111e-01 0.66468889
## [12,] 0.000000000 3.688422e-01 0.63115778
## [13,] 0.000000000 4.023733e-01 0.59762667
## [14,] 0.000000000 4.359044e-01 0.56409556
## [15,] 0.000000000 4.694356e-01 0.53056445
## [16,] 0.000000000 5.029667e-01 0.49703334
## [17,] 0.000000000 5.364978e-01 0.46350222
## [18,] 0.000000000 5.700289e-01 0.42997111
## [19,] 0.000000000 6.035600e-01 0.39644000
## [20,] 0.000000000 6.370911e-01 0.36290889
## [21,] 0.000000000 6.706222e-01 0.32937778
## [22,] 0.000000000 7.041533e-01 0.29584667
## [23,] 0.000000000 7.376844e-01 0.26231556
## [24,] 0.002579215 7.669778e-01 0.23044295
## [25,] 0.009727063 7.887649e-01 0.20150808
## [26,] 0.016874911 8.105519e-01 0.17257321
## [27,] 0.024022760 8.323389e-01 0.14363834
## [28,] 0.031170608 8.541259e-01 0.11470347
## [29,] 0.038318456 8.759129e-01 0.08576860
## [30,] 0.045466304 8.977000e-01 0.05683373
## [31,] 0.052614153 9.194870e-01 0.02789886
## [32,] 0.061373159 9.386268e-01 0.00000000
## [33,] 0.113519094 8.864809e-01 0.00000000
## [34,] 0.165665030 8.343350e-01 0.00000000
## [35,] 0.217810966 7.821890e-01 0.00000000
## [36,] 0.269956901 7.300431e-01 0.00000000
## [37,] 0.322102837 6.778972e-01 0.00000000
## [38,] 0.374248772 6.257512e-01 0.00000000
## [39,] 0.426394708 5.736053e-01 0.00000000
## [40,] 0.478540644 5.214594e-01 0.00000000
## [41,] 0.530686579 4.693134e-01 0.00000000
## [42,] 0.582832515 4.171675e-01 0.00000000
## [43,] 0.634978451 3.650215e-01 0.00000000
## [44,] 0.687124386 3.128756e-01 0.00000000
## [45,] 0.739270322 2.607297e-01 0.00000000
## [46,] 0.791416257 2.085837e-01 0.00000000
## [47,] 0.843562193 1.564378e-01 0.00000000
## [48,] 0.895708129 1.042919e-01 0.00000000
## [49,] 0.947854064 5.214594e-02 0.00000000
## [50,] 0.999999952 4.790213e-08 0.00000000
# write.xlsx(allocations, "allocations.xlsx")

Efficient Frontier with Different Constraints

Examine the efficient frontier for portfolios with different constraints

Allowing Shorting Positions

# Allowing asset weights come down to -100% (fully shorted)
constraints <- "minW[1:length(TickerList)] = -1"
Frontier <- portfolioFrontier(returns.Sample, constraints = constraints)

# default argument for portfolioFrontier constraint is "LongOnly"
Frontier.LongOnly <- portfolioFrontier(returns.Sample)

# Structuring data to construct the comparison graph
# first the Short Positions
riskReturnPoints <- frontierPoints(Frontier)
annualizedPoints <- data.frame(targetRisk = riskReturnPoints[, "targetRisk"] * sqrt(252),
                               targetReturn=riskReturnPoints[, "targetReturn"] * 252)

# ... and then the Long Only
riskReturnPoints.LongOnly <- frontierPoints(Frontier.LongOnly)
annualizedPoints.LongOnly <- data.frame(targetRisk=riskReturnPoints.LongOnly[, "targetRisk"] * sqrt(252),
                              targetReturn=riskReturnPoints.LongOnly[, "targetReturn"] * 252)
# Graph settings
{
xlimit <- range(annualizedPoints[,1], annualizedPoints.LongOnly[,1])
ylimit <- range(annualizedPoints[,2], annualizedPoints.LongOnly[,2])

plot(annualizedPoints.LongOnly, xlim=xlimit, ylim=ylimit, pch=16, col= "blue")
points(annualizedPoints, col= "red", pch=16)
legend("right", legend=c("long ","constrained"), col=c("blue","red"), pch=16)
}

Setting Mininmum and Maximum Weights

# Restricting min 10% and max 60% weight for assets
constraints <- c("minW[1:length(TickerList)]=.10","maxW[1:length(TickerList)]=.60")
Frontier <- portfolioFrontier(returns.Sample, constraints = constraints)

# default argument for portfolioFrontier constraint is "LongOnly"
Frontier.LongOnly <- portfolioFrontier(returns.Sample)

# Structuring data to construct the comparison graph
# first the Short Positions
riskReturnPoints <- frontierPoints(Frontier)
annualizedPoints <- data.frame(targetRisk = riskReturnPoints[, "targetRisk"] * sqrt(252),
                               targetReturn=riskReturnPoints[, "targetReturn"] * 252)

# ... and then the Long Only
riskReturnPoints.LongOnly <- frontierPoints(Frontier.LongOnly)
annualizedPoints.LongOnly <- data.frame(targetRisk=riskReturnPoints.LongOnly[, "targetRisk"] * sqrt(252),
                              targetReturn=riskReturnPoints.LongOnly[, "targetReturn"] * 252)
# Graph settings
{
xlimit <- range(annualizedPoints[,1], annualizedPoints.LongOnly[,1])
ylimit <- range(annualizedPoints[,2], annualizedPoints.LongOnly[,2])
plot(annualizedPoints.LongOnly, xlim=xlimit, ylim=ylimit, pch=16, col= "blue")
points(annualizedPoints, col= "red", pch=16)
legend("right", legend=c("long ","constrained"), col=c("blue","red"), pch=16)
  }

# write data to csv file to import into excel
# write.csv(allocations, "allocations.csv")

rsconnect::setAccountInfo(name=‘juun’, token=‘C1D5B9E32988B3EC61FFCA7A26B41BA1’, secret=‘’)

          failed. You can set up an account manually by using rsconnect::setAccountInfo
          
          type ?rsconnect::setAccountInfo at the R console for more information.