Monthly Archives: June 2013

Graphing with fPortfolio

Now to making pretty-looking graphs and charts for portfolio optimization! The first thing we will do is determine the frontier for our combination of securities. Remember, the variable returnsMatrix below is a matrix of returns for all the securities in your portfolio.

This gives us the frontier. If you type in ?frontierPlot and read through, you will find out all the interesting plots you can make.
frontier=portfolioFrontier(as.timeSeries(returnsMatrix))

We can plot this by:
frontierPlot(frontier)
grid()

Image

The circles in dark mark the efficient frontier and the grid() function just makes it look nicer. We can now add to this plot by doing the following:

minvariancePoints(frontier,col=’red’,pch=20)
cmlPoints(frontier,col=’blue’,pch=20)
tangencyPoints(frontier,col=’yellow’,pch=4)

Image

This added the minimum variance point, the capital market point and the tangency point. The tangency point is marked with an ‘x’ in yellow and lies in exactly the same location as the capital market point in blue. We can pile on even more stuff:

tangencyLines(frontier,col=’blue’)
sharpeRatioLines(frontier,col=’orange’,lwd=2)
twoAssetsLines(frontier,col=’green’,lwd=2)
singleAssetPoints(frontier,col=’black’,pch=20)

Image

So we now have the tangency line in blue, the Sharpe ratio line in orange, some of the visible asset points in black and the efficient frontiers for all possible combinations of two assets in our portfolio. Looking at this we can kind of see how the assets contribute to the portfolio efficient frontier, and why some assets are highly weighted while others are weighted at 0. Another very interesting chart is obtained by:

weightsPlot(frontier)

Image

This displays the weights on the different securities, the risk, and the return along the frontier. The black line through the chart indicates the minimum variance portfolio. Let’s create some graphs for the tangency portfolio:

tgPort=tangencyPortfolio(returnsMatrix)
weightsPie(tgPort)

Image

This gives a pie-chart of the weights on the securities in the tangency portfolio.

weightedReturnsPie(tgPort)

Image

This gives a pie-chart of the weighted returns of the tangency portfolio.

Advertisements

Leave a comment

Filed under Finance, Portfolio Optimization

Portfolio Optimization with fPortfolio

fPortfolio contains a number of function to make portfolio optimization easier. I can compare the results I get from the functions in fPortfolio to the results from my function from the previous post. I don’t expect them to be exactly the same, but they should be broadly similar.

First, install and load the package:
install.packages(‘fPortfolio’)
library(‘fPortfolio’)

Next, you need to build a returns matrix for the securities you are interested in. You can create return vectors for the different tickers (using methods from an earlier post) and then combine them together using cbind(). The function I wrote in the previous post also returns a matrix of security returns, so you can just use that code as well.

This is the function for the tangency or (highest Sharpe ratio) portfolio:
tangencyPortfolio(as.timeSeries(matrix),constraints=’maxW[1:9]=0.2′)

Here I set the same constraints as in the function I wrote. maxW[1:9]=0.2 says that for securities from 1 to 9 (which is all of them) set the maximum weight for each of them as 20%.

The output from this function call is:

Title:
MV Tangency Portfolio
Estimator: covEstimator
Solver: solveRquadprog
Optimize: minRisk
Constraints: maxW

Portfolio Weights:
NVDA.Adjusted     YHOO.Adjusted     GOOG.Adjusted    CAT.Adjusted   BNS.Adjusted
      0.0000                0.0000                 0.2000                0.0335         0.2000
POT.Adjusted       STO.Adjusted        MBT.Adjusted       SNE.Adjusted
      0.2000               0.1760                  0.1905               0.0000

Covariance Risk Budgets:
NVDA.Adjusted     YHOO.Adjusted    GOOG.Adjusted    CAT.Adjusted   BNS.Adjusted
      0.0000                0.0000                0.1301               0.0286           0.1409
POT.Adjusted       STO.Adjusted       MBT.Adjusted      SNE.Adjusted
     0.2407               0.1773                0.2823                0.0000 

Target Return and Risks:
  mean        mu        Cov      Sigma      CVaR       VaR
0.0006   0.0006  0.0161   0.0161   0.0398   0.0224

This obviously runs much faster, and gives greater and more readable information than the function I wrote. Oh well. It is interesting to see that the weights given for a couple of the securities are different. Not having read the code written by the authors of this function, I am more inclined to trust the results of the brute force function I wrote, however the difference is most likely due to different covariance estimation methods/procedures.

It is commonly known that portfolio weights in a Markowitz mean-variance optimization framework are very sensitive to the estimated means and covariances, and even differences in rounding can lead to fairly different weights. Also, technically, we are supposed to be using expected returns as input and not historical returns. Using historical returns assumes that the returns of each period are independent, come from the same distribution and sample the true distribution of the security. All of these assumptions can be very easily shown to be false.

In the next post, I will experiment with some of the graphs and plots we can make using fPortfolio.

2 Comments

Filed under Finance, Portfolio Optimization

Portfolio Optimization

Changing tracks, I want to now look at portfolio optimization. Although this is very different from developing trading strategies, it is useful to know how to construct minimum-variance portfolios and the like, if only for curiosity’s sake. Also, just a -I hope unnecessary- note, portfolio optimization and parameter optimization (which I covered in the last post) are two completely different things.

Minimum-variance portfolio optimization has a lot of problems associated with it, but it makes for a good starting point as it is the most commonly discussed optimization technique in classroom-finance. One of my biggest issues is with the measurement of risk via volatility. Security out-performance contributes as much to volatility -hence risk- as security under-performance, which ideally shouldn’t be the case.

First, install the package tseries:
install.packages(‘tseries’)

The function of interest is portfolio.optim(). I decided to write my own function to enter in a vector of tickers, start and end dates for the dataset, min and max weight constraints and short-selling constraints. This function first processes the data and then passes it to portfolio.optim to determine the minimum variance portfolio for a given level of return. It then cycles through increasingly higher returns to check how high the Sharpe ratio can go.

Here is the code with comments:

minVarPortfolio= function(tickers,start='2000-01-01',end=Sys.Date(),
riskfree=0,short=TRUE,lowestWeight=-1,highestWeight=1){

# Load up the package
require(tseries)

#Initialize all the variables we will be using. returnMatrix is 
#initailized as a vector,with length equal to one of the input 
#ticker vectors (dependent on the start and end dates).
#Sharpe is set to 0. The weights vector is set equal in 
#length to the number of tickers. The portfolio is set to 
#NULL. A 'constraint' variable is created to pass on the 
#short parameter to the portfolio.optim function. And vectors 
#are created with the low and high weight restrictions, which
#are then passed to the portfolio.optim function as well. ##

returnMatrix=vector(length=length(getSymbols(tickers[1],
auto.assign=FALSE,from=start,to=end)))
sharpe=0
weights=vector(,length(tickers))
port=NULL
constraint=short
lowVec=rep(lowestWeight,length(tickers))
hiVec=rep(highestWeight,length(tickers))

#This is a for-loop which cycles through the tickers, calculates 
#their return, and stores the returns in a matrix, adding 
#the return vector for each ticker to the matrix

   for(i in 1:length(tickers)){
	temp=getSymbols(tickers[i],auto.assign=FALSE,from=start,to=end)
	if(i==1){
	returnMatrix=diff(log(Ad(temp)))
	}
	else{
	returnMatrix=cbind(returnMatrix,diff(log(Ad(temp))))
	}
    }

    returnMatrix[is.na(returnMatrix)]=0
    it

#This for-loop cycles through returns to test the portfolio.optim function 
#for the highest Sharpe ratio.
    for(j in 1:100){

#Stores the log of the return in retcalc
	retcalc=log((1+j/100))
	retcalc=retcalc/252
	print(paste("Ret Calc:",retcalc))

#Tries to see if the specified return from retcalc can result 
#in an efficient portfolio
	try(port<-portfolio.optim(returnMatrix,pm=retcalc,shorts=constraint,
reslow=lowVec,reshigh=hiVec,riskfree=riskfree),silent=T)

#If the portfolio exists, it is compared against previous portfolios 
#for different returns using the #Sharpe ratio. If it has the highest 
#Sharpe ratio, it is stored and the old one is discarded.
        if(!is.null(port)){
        print('Not Null')
        sd=port$ps
        tSharpe=((retcalc-riskfree)/sd)
        print(paste("Sharpe",tSharpe))

        if(tSharpe>sharpe){
	    sharpe=tSharpe
	    weights=port$pw
	}}

  }
    print(paste('Sharpe:', sharpe))
    print(rbind(tickers,weights))
    return(returnMatrix)

}

Created by Pretty R at inside-R.org

This code works fine except for when the restrictions are too strict, the portfolio.optim function can’t find a minimum variance portfolio. This happens if the optimum portfolio has negative returns, which my code doesn’t test for. For this reason, I wanted to try out other ways of finding the highest Sharpe portfolio. There are numerous tutorials out there on how to do this. Some of them are:

1-http://blog.streeteye.com/blog/2012/01/portfolio-optimization-and-efficient-frontiers-in-r/
2-http://quantivity.wordpress.com/2011/04/17/minimum-variance-portfolios/
3-http://www.rinfinance.com/RinFinance2009/presentations/yollin_slides.pdf
4-http://systematicinvestor.wordpress.com/2013/03/22/maximum-sharpe-portfolio/
5-http://alphaism.wordpress.com/2012/05/04/finding-efficient-frontier-and-optimal-portfolio-in-r/

After I run my function, with the following tickers and constraints:

matrix=minVarPortfolio(c(‘NVDA’, ‘YHOO’, ‘GOOG’, ‘CAT’, ‘BNS’, ‘POT’, ‘STO’, ‘MBT’ ,’SNE’),lowestWeight=0,highestWeight=0.2,start=’2000-01-01′, end=’2013-06-01′)

This is the output I get:

[1] “Sharpe: 0.177751547083007”

tickers                “NVDA”                                   “YHOO”                        “GOOG”
weights “-1.58276161084957e-19”      “2.02785605793095e-17”           “0.2”
tickers                 “CAT”                                       “BNS”                           “POT”
weights “0.104269676769825”                           “0.2”                             “0.2”

tickers                 “STO”                                       “MBT”
weights “0.189985091184918”             “0.105745232045257”

tickers                 “SNE”
weights “-2.85654465380669e-17”

The ‘e-XX’ weights basically indicate a weighting of zero on that particular security (NVDA, YHOO and SNE above). In the next post I will look at how all this can be done using a package called ‘fPortfolio’. Happy trading!

Leave a comment

Filed under Finance, Portfolio Optimization

Parameter Optimization for Strategy 2

Now, let’s try some parameter optimisation for the SMA strategy! There probably are functions out there on R which I can use to do this, but I figured it would take me as long to actually code it as it would to find something usable on the internet, and I enjoy coding much more than looking stuff up on the internet.

My aim is to find out which SMA is the best to use for going long, and which SMA is the best to use for going short on the S&P 500. Ideally, I should optimize the short SMA for each long SMA (or vice-versa) to find the best combination, but I don’t think optimizing them independently (as I did here) would make much of a difference in this case. This is the code I wrote:

optimizeSMA=function(mainVector,returnsVector,smaInit=3,smaEnd=200,long=TRUE){

   bestSMA=0
   bestSharpe=0

   for( i in smaInit:smaEnd){
      smaVec=SMA(mainVector,i)
      if(long==T){

	binVec=lag(ifelse(mainVector>smaVec,1,0),1)
	binVec[is.na(binVec)]=0
	stratRets=binVec*returnsVector
	sharpe=SharpeRatio.annualized(stratRets, scale=252)
	if(sharpe>bestSharpe){
	  bestSMA=i
	  bestSharpe=sharpe
	}

      }else{

	binVec=lag(ifelse(mainVector<smaVec,-1,0),1)
	binVec[is.na(binVec)]=0
	stratRets=binVec*returnsVector
	sharpe=SharpeRatio.annualized(stratRets, scale=252)
	if(sharpe>bestSharpe){
	  bestSMA=i
	  bestSharpe=sharpe
	}
      }
   }

   print(cbind(bestSMA, bestSharpe))
}

Created by Pretty R at inside-R.org

It is pretty straight-forward and self-explanatory. It initiates a loop which goes through each SMA from smaInit to smaEnd and stores the one with the highest Sharpe ratio. For more complicated strategies, we will need to do a little bit more heavy-lifting when it comes to parameter optimization. This code maximizes the Sharpe ratio, but you can easily modify it to maximize returns, minimize volatility, etc. The highest Sharpe ratio SMA to use for the long position is the 70-Day SMA and for the short position is the 84-day SMA.

After running the strategy with the optimized parameters, these are the performance results:

Optimized:

Cumulative Return: 0.31104898   Annual Return: 0.04286661

Annualized Sharpe Ratio: 0.18405777   Win %: 0.53078556

Annualized Volatility: 0.23289757    Maximum Drawdown: -0.28943309

Max Length Drawdown: 1078.00000000

Not a huge difference from what we had before. And the little bit of performance improvement that we achieved is probably more a result of curve-fitting than anything else. If your initial parameter values conform with some market intuition -and thus capture most of the obtainable market return- parameter optimization will not be that helpful in a paper-trading implementation of your strategy, as the improvements will mostly be due to curve-fitting the historical data.

Leave a comment

Filed under Finance, Trading Strategies

Strategy 2: Riding the SMA Curve

This is the least complicated trend strategy in existance. You buy and hold the security as long as the security price is above a XXX-Day Simple Moving Average (SMA), and you can short it if it is below the SMA curve. The important question with this strategy is what the length in days of the SMA should be. We can run a test of different SMAs to see which one is most profitable/ least risky, and then choose accordingly. The intuition in choosing this should be based on an understanding of how long price trends usually last for a given security. This will obviously vary for different markets, different securities and across time periods.

A more technical approach to estimating the optimal variant of the SMA to use could be derived from one of the many parameter optimisation techniques avaiable through R, or through coding it yourself. These run the risk of curve-fitting, but as long as you are aware of the dangers associated with that, this could be one thing for you to try. I’ve found through experience that the 200-Day SMA works best for the S&P 500 as a whole, so I will be running this backtest using that.

Let’s say that if the market closes above its 200-Day Daily High SMA on any given day, we go long the next day and if it closes below it 200-Day Daily Low, we go short.

1-Get the data:
getSymbols(‘SPY’)

2-Calculate the 200-Day SMAs:
smaHi200=SMA(Hi(SPY),200)
smaLo200=SMA(Lo(SPY),200)

3-Calculate the lagged trading signal vector:
binVec=lag(ifelse(Cl(SPY)>smaHi200,1,0)+ifelse(Cl(SPY)<smaLo200,-1,0),1)

4-Get rid of the NAs:
binVec[is.na(binVec)]=0

5-Calculate returns vector and multiply out the trading vector with the returns vector to get the strategy return:
rets=diff(log(Ad(SPY)))
stratRets=binVec*rets

6-Run performance analytics:
charts.PerformanceSummary(cbind(rets,stratRets))
Performance(stratRets)

sma200ls

Note: The Performance function I got from somewhere on the internet. I can’t remember where exactly so unfortunately I can’t directly credit the source. Regardless, I’m thankful to whoever wrote it. Here is the code:

Performance <- function(x) {

	cumRetx = Return.cumulative(x)
	annRetx = Return.annualized(x, scale=252)
	sharpex = SharpeRatio.annualized(x, scale=252)
	winpctx = length(x[x > 0])/length(x[x != 0])
	annSDx = sd.annualized(x, scale=252)

	DDs <- findDrawdowns(x)
	maxDDx = min(DDs$return)
	maxLx = max(DDs$length)

	Perf = c(cumRetx, annRetx, sharpex, winpctx, annSDx, maxDDx, maxLx)
	names(Perf) = c("Cumulative Return", "Annual Return","Annualized Sharpe Ratio",
		"Win %", "Annualized Volatility", "Maximum Drawdown", "Max Length Drawdown")
	return(Perf)
}

Created by Pretty R at inside-R.org

We get the following results (our sample period is 2007-01-01 to 2013-06-19):

Market
Cumulative Return: 0.10875991   Annual Return: 0.01613934

Annualized Sharpe Ratio: 0.06700363   Win %: 0.55157505

Annualized Volatility: 0.24087258   Maximum Drawdown: -0.59577736

Max Length Drawdown: 1411.00000000

Strategy
Cumulative Return: 0.30075987  Annual Return: 0.04159395

Annualized Sharpe Ratio: 0.17975121 Win %: 0.53215078   

Annualized Volatility: 0.23139732   Maximum Drawdown: -0.35921405  

Max Length Drawdown: 1078.00000000 

So this strategy performed remarkably well compared to the market. 1-0 for Trend strategies! Looking at the graphs it’s easy to see the points where the strategy mirrors the market returns (and hence is short) and where the strategy follows the market returns (and hence is long). So does that mean we can start trading using this algorithm and make money? Not really- one important point to keep in mind is that backtesting can only be used to reject strategies, not to accept them. It is possible that this strategy can make money going forward, but who really know what the market will do? At least we can’t outright reject this strategy as useless.

What we are essentially saying is that under the conditions we used, our strategy was profitable. If those conditions were to continue, or repeat themselves, than we would have a profitable strategy in our hands. Are those conditions likely to repeat themselves? If market reactions to different stimuli are consistent across time, and if those stimuli re-occur then yes, perhaps. There’s also something to be said here about interactions between the different reactions or stimuli and on their subsequent effects on market outcomes. Is this something we can test for? Maybe, but its not something I’ll be getting into for now.

Leave a comment

Filed under Finance, Trading Strategies

Strategy 1 Extended (Part 2)

We can extend our strategy and make it more profitable by incorporating short selling. Our annualized volatility will go up, but it will be interesting to see what happens to the annualized return. This is a very simple modification to make.

1-First we create a short selling vector:

shortVec=ifelse(((Cl(SPY)<Op(SPY))),-1,0) * ifelse(lag(Cl(SPY),1)<lag(Op(SPY),1),-1,0) * ifelse(lag(Cl(SPY),2)<lag(Op(SPY),2),-1,0) #This is saying that if the stock closes down for three consecutive days, short it.

2-As before, we lag it and get rid of the NAs:

shortVec=lag(binVec3Day,1)
shortVec[is.na(binVec3Day)]=0

3-Now we add the short-signal vector to the lagged and NA-removed long-signal vector we had before:
longShortVec=binVec3Day+shortVec

4-And as before, multiply the trading vector with the S&P return vector to get daily strategy returns, then run performance analytics.

Image

So with this modification, the annualized volatility rises to 9.40% approximately, and the annualized return falls to -7.10%. Not too good.

The strategy above, and all the subsequent modifications, were momentum based strategies. They rely on large, directed, short-term price movements to be profitable and don’t do too well when the price movements are small and directionless, but the market itself is following an overall trend. The strategies which do well in a trending market are called (!!!) trend strategies. We will look at one in the next post.

Another very important thing I ignored in computing the returns is adjustments for splits and dividends. This can be done using the adjusted price information provided for most equities, and that is what I will be using to calculate returns from now on. By using the adjusted price information however, we are not able to simulate when exactly we enter and exit the market (Open, Close), and that is a tradeoff we’ll have to make for greater convenience. However, I will still be using opening and closing price information to compute the trading signals.

Leave a comment

Filed under Finance, Trading Strategies

Strategy 1 Extended (Part 1)

Like I said in my previous post, there are two ways I could think of, off the top of my head, to implement a 2-day or 5-day extension to the previous strategy. One way would be just a simple extension of the approach above, using multiple conditions in the if-else statement with lagged vectors. This is how I will solve it here.

The second method, and one that I would be more comfortable with, is just coding it using a for loop and if statements. Its pretty straightforward if you know even the very basics of coding, and if you do, you can probably figure it out on your own.

I tried stringing together a bunch of ‘and’ conditions but it didn’t seem to work. This is what I had typed in:
binVec3Day=ifelse(((Cl(SPY)>Op(SPY)) && (lag(Cl(SPY),1)>lag(Cl(SPY),1)) && (lag(Cl(SPY),2)>lag(Op(SPY),2))),1,0)

So I just replace the ‘&&’ operator with the multiplication operator, and strung the whole thing together with multiple ifelse statements. Here is what I had:
binVec3Day=ifelse(((Cl(SPY)>Op(SPY))),1,0) * ifelse(lag(Cl(SPY),1)>lag(Op(SPY),1),1,0) * ifelse(lag(Cl(SPY),2)>lag(Op(SPY),2),1,0)

Now we need to lag the trading signal vector by a day and get rid of the two NAs which have shown up for our first two days (as it is impossible to know how to trade on the first three days if you need three days of historical data for a trading signal). This is easily done by:

binVec3Day=lag(binVec3Day,1)
binVec3Day[is.na(binVec3Day)]=0

Out of curiosity, I ran sum(binVec3Day) to see how many trades in total there would be from Jan 1st 2007 to now, June 18 2013, using this strategy. The total came out to 230, which brings me to another very important point. The tests I am conducting now do not include transaction costs or an allowance for slippage. Slippage refers to not getting exactly the price required for the trade. These costs can have a significant impact on strategy returns and I will incorporate them into my strategies later on.

Multiplying by the returns vector and plotting the performance summary, again we see that this strategy did not do too well. This is most likely because our dataset starts from 2007, and thus our strategy has to suffer through the financial crash of 2008. We get a cumulative return from 2007 of approximately -18.00% and an annualized return of approximately -3.00%.

Image

Lets look at a subset of our data, to see if the cumulative returns improve. We can assume an investor decides to enter the market in 2010 using this strategy. To subset our data, we can do this:

rets2010=strat3Day[‘2010-01-01/2013-06-01’]

Now we can plot it using performance summary.

Image

We can combine our strategy’s returns with benchmark returns on the same graph for comparison purposes. This is done by:

combinedReturns=cbind(retVec,Strat3Day)

(cbind actually stands for column bind, and isn’t short for ‘combined’ which you could mistake from my use of variable names above)

Now when we plot combinedReturns using Performance Summary, we can see that it has underperformed the benchmark so far, in terms of cumulative return. Where our strategy stands out though is the reduced drawdown we suffer in down markets. Annualized volatility is reduced from approximately 18.00% to 4.00%. We can’t really use the Sharpe ratio for comparison here as the excess returns are negative.

Image

You can get the annualized Sharpe ratio and volatility for the S&P by entering:
SharpeRatio.annualized(retVec, scale=252)

sd.annualized(retVec, scale=252)

So why are we getting negative cumulative returns? Because the strategy is not in the market enough due to market conditions. Hence the low volatility and negative return. If we can make use of any available big downward moves, we may be able to turn a profit by shorting. Onwards to the next post!

Leave a comment

Filed under Finance, Trading Strategies