Path: blob/master/sandbox/paper_analysis/R_interpretation/performanceanalysis_tactical.R
1433 views
1# ----------------------------------------------------------------------------------2# In this script the out-of-sample returns of the optimized portfolios is analyzed3#4# ----------------------------------------------------------------------------------56setwd("c:/Documents and Settings/Administrator/Desktop/risk budget programs")78# Optimized portfolio you want to analyse out-of-sample performance through (Component) Sharpe ratios910riskcrit = mincriterion = percriskcontribcriterion ="mES"; # "mES" "StdDev" "GES"11estyears = 8;12frequency = "quarterly" ;yearly = F;13CC = TRUE14# Load additional programs to interpret the data1516library(zoo); library("PerformanceAnalytics"); source("R_interpretation/pfolioreturn.R");17source("R_Allocation/estimators.R"); library(zoo);18library(reldist) ; library(sandwich); library(zoo);1920histVaR = function( series ){ return(-quantile(series,probs=0.05) ) }21histCVaR = function( series ){ series = as.numeric(series) ; q = as.numeric(histVaR(series)) ; return( -mean( series[series<(-q)] )) }2223# Define optimization criteria2425names = c( "EqualWeight" , "MinRisk" , "MinRisk_PositionLimit" , "MinRisk_RiskLimit" ,26"MinRiskConc" , "MinRiskConc_PositionLimit", "EqualRisk" ,27"MinRisk_ReturnTarget", "MinRiskConc_ReturnTarget" )28if(CC){ names= paste( names, "_CC", sep="") }2930namelabels = c( "Equal Weight" , "Min CVaR" , "Min CVaR + Position Limit" , "Min CVaR + CVaR Alloc Limit" ,31"Min CVaR Conc" , "Min CVaR Conc + 40% Position Limit", "Min CVaR + ERC constraint" , "Min CVaR + Return Target" , "Min CVaR Conc + Return Target" )3233if(mincriterion=="mES"){ sel = c(1,2:4,7,5:6) }else{ sel = c(1,2:4,7,5:6) }3435#sel = c(1,2,5)36names = names[sel]; namelabels = namelabels[sel];3738criteria = paste( rep("weights/",length(names) ) , rep(mincriterion,length(names) ) , "/", names , sep="")39criteria[ criteria == "weights/StdDev/EqualWeight" ] = "weights/mES/EqualWeight"4041# Load the data4243firstyear = 1976 ; firstquarter = 1; lastyear = 2010; lastquarter = 2;44data = read.table( file= paste("data/","data.txt",sep="") ,header=T)45date = as.Date(data[,1],format="%Y-%m-%d")4647nominalreturns = T;48if(nominalreturns){ monthlyR = zoo( data[,2:ncol(data)] , order.by = date ) }else{49monthlyR = zoo( data[,2:(ncol(data)-1)] , order.by = date ) - zoo( data[,ncol(data)] , order.by = date )50}51monthlyR = monthlyR[,1:4]5253# estimation periods54ep = endpoints(monthlyR,on='quarters')55# select those for estimation period56ep.start = ep[1:(length(ep)-estyears*4)]+157from = time(monthlyR)[ep.start]58from.estimation = seq( as.Date(paste(firstyear,"-01-01",sep="")), as.Date(paste(lastyear-estyears,"-07-01",sep="")), by="3 month")59ep.end = ep[(1+estyears*4):length(ep)]60to.estimation = time(monthlyR)[ep.end]61cPeriods = length(from);6263# Define rebalancing periods:6465ep = endpoints(monthlyR,on='quarters')66# select those for estimation period67ep.start = ep[(1+estyears*4):(length(ep)-1)]+168from = time(monthlyR)[ep.start]69from = seq( as.Date( paste( as.character(firstyear+estyears),"-01-01",sep="")), as.Date("2010-04-01"), by="3 month")70ep.end = ep[(1+estyears*4):(length(ep)-1)]+371to = time(monthlyR)[ep.end]7273oosdates = time( window (monthlyR , start = from[1] , end = to[ length(to) ] ) )7475makeTacticalWeights = TRUE7677if(makeTacticalWeights){7879# Compute daily out of sample returns, accounting for compounding effects80Returns.rebalancing( R = monthlyR , criteria = criteria, from = from, to = to , folder="/oosreturns/" )8182load(paste(getwd(),"/","/oosreturns/", "simplereturns.Rdata" ,sep="") )8384colnames(simplereturns) = names; date = time(simplereturns)8586library("TTR")87weights_MinRisk = read.csv( file = paste("weights/", riskcrit , "/", "MinRisk_CC", ".csv" , sep="") );8889names_alternatives = c( "EqualWeight" , "MinRisk_PositionLimit" , "MinRisk_RiskLimit" ,90"EqualRisk" , "MinRiskConc" , "MinRiskConc_PositionLimit")91if(CC){ names_alternatives = paste( names_alternatives, "_CC", sep="") }9293for(name in names_alternatives){94weights_alternative = read.csv( file = paste("weights/", riskcrit , "/", name , ".csv" , sep="") );95weights_tact = weights_alternative96z = simplereturns[,name]97cz = cumprod( 1+z ) ; smaz = SMA(cz , n = 10)98risky = 1*(cz > smaz ) ; risky[is.na(risky)] = 0;99# end of rebal period value100risky = risky[to]101# we shift since for first rebal period no obs102risky = as.numeric(c( 0 , risky[-1] ))103weights_tact[ risky==0 , ] = weights_MinRisk[ risky==0 , ]104write.table( weights_tact , file = paste("weights/", riskcrit , "/", "tact_" , name , ".csv" , sep=""),105append = FALSE, quote = TRUE, sep = ",", eol = "\n", na = "NA", dec = ".", row.names = TRUE,col.names = TRUE, qmethod = "escape")106}107108}109110newnames = paste( rep( "tact_" , length(names_alternatives) ) , names_alternatives, sep="" )111tact_criteria = paste( rep("weights/",length(newnames) ) , rep(mincriterion,length(newnames) ) , "/", newnames , sep="")112113Returns.rebalancing( R = monthlyR , criteria = tact_criteria, from = from, to = to , folder="/oosreturns/" )114load(paste(getwd(),"/","/oosreturns/", "simplereturns.Rdata" ,sep="") )115colnames(simplereturns) = names_alternatives; date = time(simplereturns)116117118119# Bear periods120sp500 = window (monthlyR , start = from[1] , end = to[ length(to) ] )[,2]121bear = c(1:length(sp500))[sp500<mean(sp500)]122bear = c(1:length(sp500))[sp500<(-0.12)]123m.bear.dates = list();124i=1;125for( b in bear){126m.bear.dates[[i]] = c( b-0.5, b+0.5)127i = i + 1;128}129130# http://www.aheadofthecurve-thebook.com/charts.html131# Vertical yellow bars in most charts denote bear markets (declines in the S&P 500 Index of 12% or more).132# IMPORTANT: The leading edge (left side) of the vertical yellow bars are thus stock market peaks,133# and the trailing edge (right side) are stock market troughs.134135#source( paste(getwd(),"/R_interpretation/findDrawdowns.R",sep="") )136out = table.Drawdowns(sp500,top=10)137start.bear = out$From[out$Depth<(-0.12)]138end.bear = out$Trough[out$Depth<(-0.12)]139start.bear.index = c(1:length(sp500))[ time(sp500) ]140m.bear.dates = list()141v.bear.dates = c()142for( i in 1:length(start.bear) ){143m.bear.dates[[i]] = c( as.yearmon(start.bear[i]) , as.yearmon(end.bear[i]) )144v.bear.dates = c( v.bear.dates , seq(start.bear[i],end.bear[i],"days") )145}146v.bear.dates = as.Date( v.bear.dates )147148# Table of summary statistics on out-of-sample returns149150library(PerformanceAnalytics)151library(zoo)152oosreturns = simplereturns;153#zoo(simplereturns[,c(1:length(sel))],order.by = seq.Date(as.Date(from[1])+31, as.Date(tail(to,1)) + 1, by ="month") - 1)154155v.nobear.dates = as.Date(setdiff( time(oosreturns) , v.bear.dates ))156157# Mean, Standard Deviation, CVaR158histVaR = function( series ){ return(-quantile(series,probs=0.05) ) }159histCVaR = function( series ){ series = as.numeric(series) ; q = as.numeric(histVaR(series)) ; return( -mean( series[series<(-q)] )) }160161162########################################################################163164165oosreturns = window(oosreturns , start=as.Date("1984-01-01") , end=tail(time(oosreturns),1) )166Tstart = 1+(8-estyears)*4167#Tstart = 1168169out_full = out_bear = out_bull = c()170171print("Full period") #median, skew; exkur; histVaR172out_full = rbind( out_full , apply( oosreturns , 2 , 'mean' )*100*12 )173out_full = rbind( out_full , apply( oosreturns , 2 , 'sd' )*100*sqrt(12))174out_full = rbind( out_full , apply( oosreturns , 2 , 'skewness' ))175out_full = rbind( out_full , apply( oosreturns , 2 , 'kurtosis' ))176out_full = rbind( out_full , 100*apply( oosreturns , 2 , 'histCVaR'))177out_full = rbind( out_full , -100*apply( oosreturns , 2 , 'ES') )178179180oosreturns_bear = oosreturns[ v.bear.dates ]181oosreturns_bull = oosreturns[ v.nobear.dates ]182183print("Bear market")184out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'mean' )*100*12);185out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'sd' )*100*sqrt(12))186out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'skewness' ))187out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'kurtosis' ))188out_bear = rbind( out_bear , 100*apply( oosreturns_bear , 2 , 'histCVaR'))189out_bear = rbind( out_bear , -100*apply( oosreturns_bear , 2 , 'ES'))190191print("Bull market")192out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'mean' )*100*12 ) ;193out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'sd' )*100*sqrt(12))194out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'skewness' ))195out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'kurtosis' ))196out_bull = rbind( out_bull , 100*apply( oosreturns_bull , 2 , 'histCVaR'))197out_bull = rbind( out_bull , -100*apply( oosreturns_bull , 2 , 'ES'))198199200201202# Portfolio turnover per strategy:203204pfgini = c();205turnover = c();206207208# Compute for each rebalancing period, the cumulative return:209210cumR = c()211oosR = window (monthlyR , start = from[1] , end = to[ length(to) ] )212cRebalancing = length(from)213214for( i in 1:cRebalancing ){215sel = seq( (i-1)*3+1 , i*3 )216cumR = rbind( cumR , apply((1+oosR[sel,]),2,'cumprod')[3,] )217}218219# Load portfolio weights:220221for( strat in 1:length(tact_criteria) ){222criterion = tact_criteria[strat];223wstart = read.csv( file = paste( criterion,".csv",sep=""),header = TRUE, sep = ",", na.strings = "NA", dec = ".")224wend = (wstart[Tstart:cRebalancing,]*cumR)/rowSums( wstart[Tstart:cRebalancing,]*cumR )225out = rowSums( abs( wstart[(Tstart+1):cRebalancing,]-wend[Tstart:(cRebalancing-1),] ))226turnover = cbind( turnover , out )227pfgini = c( pfgini , mean(apply( wstart, 1 , 'gini' )) )228}229230pfturnover = colMeans( turnover )231out_full = rbind( out_full , pfgini , pfturnover*100 )232233#out_full = rbind( out_full , turnover*100 )234235library(xtable)236237xtable(out_full)238xtable(out_bear)239xtable(out_bull)240241# DRAWDOWNS242243for( i in 1:length(tact_criteria) ){ # Print the drawdowns244print( tact_criteria[i] )245out = table.Drawdowns(oosreturns[,i],top=10)246out = out[out$Depth<=(-0.1),]247print( out )248}249250# Risk concentration251252outloss = outriskconc = c();253254for( strat in 1:length(tact_criteria) ){255criterion = tact_criteria[strat];256#print( criterion );257weightedR = c(); portfolioVaR = c();258weights = read.csv( file = paste( criterion,".csv",sep=""),header = TRUE, sep = ",", na.strings = "NA", dec = ".")259260# Step 1: compute for each optimal weight the corresponding historical quantile261262for (row in 1:length(from)){263# For the determination of the historical quantile all returns preceding the rebalancing period are taken264previousR = window(monthlyR, start = time(monthlyR)[1] , end = as.Date(from[row]-1)) ;265pfoosR = rowSums( matrix( rep( as.numeric(weights[row,]),nrow(previousR)) , nrow = nrow(previousR) )*previousR )266# The weighted returns need the returns of the rebalancing period267Rrebalperiod = window(monthlyR, start = as.Date(from[row]) , end = as.Date(to[row])) ;268weightedR = rbind( weightedR , matrix( rep( as.numeric(weights[row,]),nrow(Rrebalperiod)) , nrow = nrow(Rrebalperiod) )*Rrebalperiod );269portfolioVaR = c( portfolioVaR , histVaR( pfoosR ) ) ;270}271272# Step 2: compute the mean squared weighted return over months with beyond VaR losses273274series = rowSums(weightedR) ;275#out = mean(weightedR[series<(-portfolioVaR),]^2);276downsidelosses = weightedR[series<(-portfolioVaR),]277#downsidelosses = weightedR[series<=-0.10,]278vES = rowSums(downsidelosses)279280#print("Total portfolio loss")281out = apply( -downsidelosses , 1 , 'sum')282outloss = cbind( outloss , c( median(out) , max(out) ) )283#print("Max percentage loss")284out = apply( downsidelosses/ apply( downsidelosses , 1 , 'sum') , 1 , 'max')285outriskconc = cbind( outriskconc , c( mean(out) , max(out) ) )286}287288xtable(outloss)289xtable(outriskconc)290291292