Path: blob/master/sandbox/paper_analysis/R_interpretation/performanceanalysis.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 ratios91011estyears = 8;12frequency = "quarterly" ;yearly = F;13CC = TRUE14# Load additional programs to interpret the data1516library(zoo); library("PerformanceAnalytics"); source("R_interpretation/pfolioreturn.R");17library(reldist) ; library(sandwich); library(zoo);18source("R_Allocation/estimators.R")19histVaR = function( series ){ return(-quantile(series,probs=0.05) ) }20histCVaR = function( series ){ series = as.numeric(series) ; q = as.numeric(histVaR(series)) ; return( -mean( series[series<(-q)] )) }2122# Define optimization criteria2324names = c( "EqualWeight" , "MinRisk" , "MinRisk_PositionLimit" , "MinRisk_RiskLimit" ,25"MinRiskConc" , "MinRiskConc_PositionLimit", "EqualRisk" ,26"MinRisk_ReturnTarget", "MinRiskConc_ReturnTarget" )27if(CC){ names= paste( names, "_CC", sep="") }2829namelabels = c( "Equal Weight" , "Min CVaR" , "Min CVaR + Position Limit" , "Min CVaR + CVaR Alloc Limit" ,30"Min CVaR Conc" , "Min CVaR Conc + 40% Position Limit", "Min CVaR + ERC constraint" , "Min CVaR + Return Target" , "Min CVaR Conc + Return Target" )3132sel = c(1,2:4,7,5:6)33names = names[sel]; namelabels = namelabels[sel];343536####################################################################3738for( mincriterion in c( "mES" , "StdDev" ) ){3940criteria = paste( rep("weights/",length(names) ) , rep(mincriterion,length(names) ) , "/", names , sep="")41criteria[ criteria == "weights/StdDev/EqualWeight" ] = "weights/mES/EqualWeight"4243# Load the data44firstyear = 1976 ; firstquarter = 1; lastyear = 2010; lastquarter = 2;45data = read.table( file= paste("data/","data.txt",sep="") ,header=T)46date = as.Date(data[,1],format="%Y-%m-%d")4748nominalreturns = T;49if(nominalreturns){ monthlyR = zoo( data[,2:ncol(data)] , order.by = date ) }else{50monthlyR = zoo( data[,2:(ncol(data)-1)] , order.by = date ) - zoo( data[,ncol(data)] , order.by = date )51}52monthlyR = monthlyR[,1:4]5354# Define rebalancing periods:5556ep = endpoints(monthlyR,on='quarters')57# select those for estimation period58ep.start = ep[(1+estyears*4):(length(ep)-1)]+159from = time(monthlyR)[ep.start]60from = seq( as.Date( paste( as.character(firstyear+estyears),"-01-01",sep="")), as.Date("2010-04-01"), by="3 month")61ep.end = ep[(1+estyears*4):(length(ep)-1)]+362to = time(monthlyR)[ep.end]6364# Compute daily out of sample returns, accounting for compounding effects6566Returns.rebalancing( R = monthlyR , criteria = criteria, from = from, to = to , folder="/oosreturns/" )67oosdates = time( window (monthlyR , start = from[1] , end = to[ length(to) ] ) )6869load(paste(getwd(),"/oosreturns/", "simplereturns",".Rdata" ,sep="") )70save(simplereturns, file=paste(getwd(),"/","/oosreturns/", "simplereturns_",mincriterion ,".Rdata" ,sep="") )71}7273############################################################################################################################747576# Bear periods77sp500 = window (monthlyR , start = from[1] , end = to[ length(to) ] )[,2]78bear = c(1:length(sp500))[sp500<mean(sp500)]79bear = c(1:length(sp500))[sp500<(-0.12)]80m.bear.dates = list();81i=1;82for( b in bear){83m.bear.dates[[i]] = c( b-0.5, b+0.5)84i = i + 1;85}8687# http://www.aheadofthecurve-thebook.com/charts.html88# Vertical yellow bars in most charts denote bear markets (declines in the S&P 500 Index of 12% or more).89# IMPORTANT: The leading edge (left side) of the vertical yellow bars are thus stock market peaks,90# and the trailing edge (right side) are stock market troughs.9192#source( paste(getwd(),"/R_interpretation/findDrawdowns.R",sep="") )93out = table.Drawdowns(sp500,top=10)94start.bear = out$From[out$Depth<(-0.12)]95end.bear = out$Trough[out$Depth<(-0.12)]96start.bear.index = c(1:length(sp500))[ time(sp500) ]97m.bear.dates = list()98v.bear.dates = c()99for( i in 1:length(start.bear) ){100m.bear.dates[[i]] = c( as.yearmon(start.bear[i]) , as.yearmon(end.bear[i]) )101v.bear.dates = c( v.bear.dates , seq(start.bear[i],end.bear[i],"days") )102}103v.bear.dates = as.Date( v.bear.dates )104105# Mean, Standard Deviation, CVaR106histVaR = function( series ){ return(-quantile(series,probs=0.05) ) }107histCVaR = function( series ){ series = as.numeric(series) ; q = as.numeric(histVaR(series)) ; return( -mean( series[series<(-q)] )) }108109############################################################################################################################110111mincriterion = "StdDev" # "mES" , "StdDev"112load(paste(getwd(),"/","/oosreturns/", "simplereturns_",mincriterion ,".Rdata" ,sep="") )113114criteria = paste( rep("weights/",length(names) ) , rep(mincriterion,length(names) ) , "/", names , sep="")115criteria[ criteria == "weights/StdDev/EqualWeight" ] = "weights/mES/EqualWeight"116117colnames(simplereturns) = names118date = time(simplereturns)119120makeChart = FALSE121122if(makeChart){123# Chart of relative performance strategies vs Equal-Weight124if(CC){125postscript( file="RelPerf_EW_CC.eps" )126}else{127postscript( file="RelPerf_EW.eps" )128}129# zelf opslaan anders worden de cijfers niet gedraaid in de y-as130par( mfrow = c(2,1) , mar =c(2,5,2,2), cex.axis = 0.7 , cex.main=0.7 )131# EqualWeight, MinCVaR, MinCVaRConcentration132chart.RelativePerformance( simplereturns[,c(2,3,4)] , simplereturns[,c(1)] ,133main = "" , lty=c("solid","solid","solid") , ylab="Relative performance vs equal-weight", xlab="",134col=c("black","darkgray","darkgray") , las=1, lwd=c(2,2,5) ,135auto.grid = TRUE, minor.ticks = FALSE ,ylim=c(0.7,1.65),136period.areas = m.bear.dates , period.color="lightgray",137date.format.in = "%Y-%m-%d",date.format = "%b %Y")138legend("topleft", legend = c("Min CVaR","Min CVaR + 40% Position Limit", "Min CVaR + 40% Risk Allocation Limit"),139col=c("black","darkgray","darkgray"), lty=c("solid","solid","solid"), lwd=c(2,2,5) ,cex=0.7)140141chart.RelativePerformance( simplereturns[,c(5,6,7)] , simplereturns[,c(1)] ,142main = "" , lty=c("solid","solid","solid") , ylab="Relative performance vs equal-weight",143col=c("black","darkgray","darkgray") , lwd=c(2,2,5), las=1 ,144auto.grid = TRUE, minor.ticks = FALSE , ylim=c(0.7,1.65),145period.areas = m.bear.dates , period.color="lightgray",146date.format.in = "%Y-%m-%d",date.format = "%b %Y")147148legend("topleft", legend = c("Min CVaR Concentration","Min CVaR Concentration + 40% Position Limit", "Min CVaR + ERC constraint"),149col=c("black","darkgray","darkgray"), lty=c("solid","solid","solid"), lwd=c(2,2,5) ,cex=0.7)150dev.off()151}152153# Table of summary statistics on out-of-sample returns154155library(PerformanceAnalytics)156library(zoo)157oosreturns = zoo(simplereturns[,c(1:length(names))],order.by = seq.Date(as.Date(from[1])+31, as.Date(tail(to,1)) + 1, by ="month") - 1)158159v.nobear.dates = as.Date(setdiff( time(oosreturns) , v.bear.dates ))160161oosreturns = window(oosreturns , start=as.Date("1984-01-01") , end=tail(time(oosreturns),1) )162Tstart = 1+(8-estyears)*4163#Tstart = 1164165out_full = out_bear = out_bull = c()166167print("Full period") #median, skew; exkur; histVaR168out_full = rbind( out_full , apply( oosreturns , 2 , 'mean' )*100*12 ) ;169out_full = rbind( out_full , apply( oosreturns , 2 , 'sd' )*100*sqrt(12))170out_full = rbind( out_full , apply( oosreturns , 2 , 'skewness' ))171out_full = rbind( out_full , apply( oosreturns , 2 , 'kurtosis' ))172out_full = rbind( out_full , 100*apply( oosreturns , 2 , 'histCVaR'))173#out_full = rbind( out_full , -100*apply( oosreturns , 2 , 'ES') )174175oosreturns_bear = oosreturns[ v.bear.dates ]; oosreturns_bull = oosreturns[ v.nobear.dates ]176177print("Bear market")178out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'mean' )*100*12);179out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'sd' )*100*sqrt(12))180out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'skewness' ))181out_bear = rbind( out_bear , apply( oosreturns_bear , 2 , 'kurtosis' ))182out_bear = rbind( out_bear , 100*apply( oosreturns_bear , 2 , 'histCVaR'))183#out_bear = rbind( out_bear , -100*apply( oosreturns_bear , 2 , 'ES'))184185print("Bull market")186out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'mean' )*100*12 ) ;187out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'sd' )*100*sqrt(12))188out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'skewness' ))189out_bull = rbind( out_bull , apply( oosreturns_bull , 2 , 'kurtosis' ))190out_bull = rbind( out_bull , 100*apply( oosreturns_bull , 2 , 'histCVaR'))191#out_bull = rbind( out_bull , -100*apply( oosreturns_bull , 2 , 'ES'))192193# Portfolio turnover per strategy:194195pfgini = c();196turnover = c();197198# Compute for each rebalancing period, the cumulative return:199200cumR = c()201oosR = window (monthlyR , start = from[1] , end = to[ length(to) ] )202cRebalancing = length(from)203204for( i in 1:cRebalancing ){205sel = seq( (i-1)*3+1 , i*3 )206cumR = rbind( cumR , apply((1+oosR[sel,]),2,'cumprod')[3,] )207}208209# Load portfolio weights:210211for( strat in 1:length(criteria) ){212criterion = criteria[strat];213wstart = read.csv( file = paste( criterion,".csv",sep=""),header = TRUE, sep = ",", na.strings = "NA", dec = ".")214wend = (wstart[Tstart:cRebalancing,]*cumR)/rowSums( wstart[Tstart:cRebalancing,]*cumR )215# out = (1/nrow(wstart))*sum( abs( wstart[(Tstart+1):cRebalancing,]-wend[Tstart:(cRebalancing-1),] ))216out = rowSums( abs( wstart[(Tstart+1):cRebalancing,]-wend[Tstart:(cRebalancing-1),] ))217turnover = cbind( turnover , out )218pfgini = c( pfgini , mean(apply( wstart, 1 , 'gini' )) )219}220221pfturnover = colMeans( turnover )222out_full = rbind( out_full , pfgini , pfturnover*100 )223224library(xtable)225xtable(out_full); xtable(out_bear); xtable(out_bull)226227save( turnover , file=paste(getwd(),"/","/oosreturns/", "turnover_" , mincriterion ,".Rdata" ,sep="") )228229# DRAWDOWNS230231for( i in 1:length(criteria) ){ # Print the drawdowns232print( namelabels[i] )233out = table.Drawdowns(oosreturns[,i],top=10)234out = out[out$Depth<=(-0.1),]235print( out )236}237238# Risk concentration239240outnumber = outloss = outriskconc = c();241242for( strat in 1:length(criteria) ){243criterion = criteria[strat];244#print( criterion );245weightedR = c(); portfolioVaR = c();246weights = read.csv( file = paste( criterion,".csv",sep=""),header = TRUE, sep = ",", na.strings = "NA", dec = ".")247248# Step 1: compute for each optimal weight the corresponding historical quantile249250for (row in 1:length(from)){251# For the determination of the historical quantile all returns preceding the rebalancing period are taken252previousR = window(monthlyR, start = time(monthlyR)[1] , end = as.Date(from[row]-1)) ;253pfoosR = rowSums( matrix( rep( as.numeric(weights[row,]),nrow(previousR)) , nrow = nrow(previousR) )*previousR )254# The weighted returns need the returns of the rebalancing period255Rrebalperiod = window(monthlyR, start = as.Date(from[row]) , end = as.Date(to[row])) ;256weightedR = rbind( weightedR , matrix( rep( as.numeric(weights[row,]),nrow(Rrebalperiod)) , nrow = nrow(Rrebalperiod) )*Rrebalperiod );257portfolioVaR = c( portfolioVaR , histVaR( pfoosR ) ) ;258}259260# Step 2: compute the mean squared weighted return over months with beyond VaR losses261262series = rowSums(weightedR) ;263#out = mean(weightedR[series<(-portfolioVaR),]^2);264downsidelosses = weightedR[series<(-portfolioVaR),]265#downsidelosses = weightedR[series<=-0.10,]266vES = rowSums(downsidelosses)267268outnumber = c( outnumber , nrow(downsidelosses) )269#print("Total portfolio loss")270out = apply( -downsidelosses , 1 , 'sum')271outloss = cbind( outloss , c( median(out) , max(out) ) )272#print("Max percentage loss")273out = apply( downsidelosses/ apply( downsidelosses , 1 , 'sum') , 1 , 'max')274# outriskconc = cbind( outriskconc , c( median(out) , max(out) ) )275outriskconc = cbind( outriskconc , c( mean(out) , max(out) ) )276}277278outnumber279xtable(outloss)280xtable(outriskconc)281282283############################################################################################################################284285# Test significance of difference286287mincriterion = "mES"288load(paste(getwd(),"/","/oosreturns/", "simplereturns_",mincriterion ,".Rdata" ,sep="") )289mES_simplereturns = simplereturns290colnames(mES_simplereturns) = names ; date = time(mES_simplereturns)291292mincriterion = "StdDev"293load(paste(getwd(),"/","/oosreturns/", "simplereturns_",mincriterion ,".Rdata" ,sep="") )294StdDev_simplereturns = simplereturns295colnames(StdDev_simplereturns) = names ; date = time(StdDev_simplereturns)296297#298299300for( col in 2:ncol(simplereturns) ){301rdata = cbind( StdDev_simplereturns[,col] , mES_simplereturns[,col])302colnames( rdata ) = c( "y" , "x" )303fm = lm( y~x , data =rdata )304tstat = fm$coef[1]/sqrt(NeweyWest( fm )[1,1])305print( (1-pnorm( abs(tstat) ))*2 )306}307308for( col in 2:ncol(simplereturns) ){309rdata = cbind( StdDev_simplereturns[,col] , mES_simplereturns[,col])310colnames( rdata ) = c( "y" , "x" )311fm = lm( y^2~x^2 , data =rdata )312tstat = fm$coef[1]/sqrt(NeweyWest( fm )[1,1])313print( (1-pnorm( abs(tstat) ))*2 )314}315316source("R_interpretation/Sharpe_functions_Wolf.R")317318for( col in 2:ncol(simplereturns) ){319out = hac.inference(ret = cbind( as.numeric(StdDev_simplereturns[,col]) , as.numeric(mES_simplereturns[,col])) )$p.Values320print(out)321}322323324325326327