## Sunday, October 19, 2014

### Portfolio Optimisation - I

Chapter 2 in the book Introduction to R for Quantitative Finance, gives a good example of how to extract data on data on returns on 5 US companies and use to to create an optimum portfolio and draw the efficient frontier. The actual working code for this is available here.

While the program works, one thing that is a little confusing is how the daily returns on the 5 stocks is calculated by taking the log of ratios of two subsequent daily closing prices! return <- log(tail(assets, -1) / head(assets, -1))

To understand how this is arrived at, see Zivot's notes on calculating returns or his slide deck.

We next tried to see how the same technique can be applied to 5 India companies that are listed in the NSE. The following R program shows how this data can be extracted from Quandl and converted into a CSV file for repeated usage.

``````
========================================
getwd()
library(Quandl)
Quandl.auth("xxxxxxxxxxxxxxxx")
FRel1314 <- Quandl("NSE/RELIANCE", trim_start="2013-01-01", trim_end="2014-06-30")
FTisco1314 <- Quandl("NSE/TATASTEEL", trim_start="2013-01-01", trim_end="2014-06-30")
FLT1314 <- Quandl("NSE/LT", trim_start="2013-01-01", trim_end="2014-06-30")
FHDFC1314 <- Quandl("GOOG/BOM_500180", trim_start="2013-01-01", trim_end="2014-06-30")
FHUL1314 <- Quandl("GOOG/NSE_HINDUNILVR", trim_start="2013-01-01", trim_end="2014-06-30")
library(plyr)
CREL <- FRel1314[,c('Date','Close')]
CTIS <- FTisco1314[,c('Date','Close')]
CLNT <- FLT1314[,c('Date','Close')]
CHUL <- FHUL1314[,c('Date','Close')]
CHDF <- FHDFC1314[,c('Date','Close')]
Stocks <- merge(CREL,CHDF,by.x='Date',by.y='Date')
Stocks <- rename(Stocks,c("Close.x"="Rel","Close.y"="HDFC"))
Stocks <- merge(Stocks,CTIS,by.x='Date',by.y='Date')
Stocks <- rename(Stocks,c("Close"="Tisco"))
Stocks <- merge(Stocks,CLNT,by.x='Date',by.y='Date')
Stocks <- rename(Stocks,c("Close"="LnT"))
Stocks <- merge(Stocks,CHUL,by.x='Date',by.y='Date')
Stocks <- rename(Stocks,c("Close"="HUL"))
write.csv(Stocks,"India5.csv")
========================================
```
```

Please note that  you need to get your own Quandl authorisation code by registering ( free of course) at Quandl. Also note that the data comes from two different sources so in each case you need to chose the fields that are required, in this case, Date and Closing Prices. However not all the data has closing prices for all days and so we need to merge the data (something like an SQL join) to make sure that your data frame has closing prices for all 5 companies for the same dates and they are in the same row. Once the data is ready, they are stored in a CSV file that will be accessed in the next program.

``````
========================================
getwd()

## select the data for the 5 companies in columns 3 to 7
assets <- India5[,3:7]

## calulate the returns
returns <- log(tail(assets, -1) / head(assets, -1))

## Define a function to calculate the optimum portfolio weights
OptWeights <- function(return, mu = 0.005) {
Q <- rbind(cov(return), rep(1, ncol(assets)), colMeans(return))
Q <- cbind(Q, rbind(t(tail(Q, 2)), matrix(0, 2, 2)))
b <- c(rep(0, ncol(assets)), 1, mu)
}

## Call the function with data and note that the weights add up to 1
OptWeights(returns)
sum(OptWeights(returns))

## Define a function to create the graph of the Efficient frontier
frontier <- function(return,minRet,maxRet){
Q <- cov(return)
n <- ncol(assets)
r <- colMeans(return)
Q1 <- rbind(Q,rep(1,n),r)
Q1 <- cbind(Q1,rbind(t(tail(Q1,2)),matrix(0,2,2)))
rbase <- seq(minRet,maxRet,length=100)
s <- sapply(rbase,function(x){
y %*% Q %*% y
})
plot(s,rbase,xlab="Variance",ylab="Return", main = "Custom")
}

## Call the function with the data and plot the frontier between two values
## of returns

frontier(returns,-0.0005,0.05)
========================================
```
```

The optimum weights are calculated as follows and they do add up to 1 as expected

> OptWeights(returns)
Rel       HDFC      Tisco        LnT        HUL
4.869750   5.651428   3.375111 -10.711613  -2.184675
> sum(OptWeights(returns))
 1

However we note that some of the weights are negative, which means that the portfolio allows "short" positions. It is possible to bar short positions. This will demonstrated in the next post.

1. 2. 