Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
braverock
GitHub Repository: braverock/portfolioanalytics
Path: blob/master/sandbox/riskbudgetpaper(superseded)/R_interpretation/performanceanalysis.R
1719 views
1
2
# ----------------------------------------------------------------------------------
3
# In this script the out-of-sample returns of the optimized portfolios is analyzed
4
#
5
# ----------------------------------------------------------------------------------
6
7
setwd("c:/Documents and Settings/Administrator/Desktop/risk budget programs")
8
9
# Optimized portfolio you want to analyse out-of-sample performance through (Component) Sharpe ratios
10
11
estyears = 8;
12
percriskcontribcriterion = "mES"
13
frequency = "quarterly" ;yearly = F;
14
15
# Load additional programs to interpret the data
16
17
library(zoo); library("PerformanceAnalytics"); source("R_interpretation/pfolioreturn.R");
18
source("R_Allocation/estimators.R"); library(zoo);
19
histVaR = function( series ){ return(-quantile(series,probs=0.05) ) }
20
histCVaR = function( series ){ series = as.numeric(series) ; q = as.numeric(histVaR(series)) ; return( -mean( series[series<(-q)] )) }
21
22
# Define optimization criteria
23
24
names = c( "EqualWeight" , "MinRisk" , "MinRisk_PositionLimit" , "MinRisk_RiskLimit" ,
25
"MinRiskConc" , "MinRiskConc_PositionLimit", "EqualRisk" ,
26
"MinRisk_ReturnTarget", "MinRiskConc_ReturnTarget" )
27
28
namelabels = c( "Equal Weight" , "Min CVaR" , "Min CVaR + Position Limit" , "Min CVaR + CVaR Alloc Limit" ,
29
"Min CVaR Conc" , "Min CVaR Conc + 40% Position Limit", "Min CVaR + ERC constraint" , "Min CVaR + Return Target" , "Min CVaR Conc + Return Target" )
30
31
criteria = paste( rep("weights/",8) , names , sep="")
32
33
# Load the data
34
35
firstyear = 1976 ; firstquarter = 1; lastyear = 2010; lastquarter = 2;
36
data = read.table( file= paste("data/","data.txt",sep="") ,header=T)
37
date = as.Date(data[,1],format="%Y-%m-%d")
38
39
nominalreturns = T;
40
if(nominalreturns){ monthlyR = zoo( data[,2:ncol(data)] , order.by = date ) }else{
41
monthlyR = zoo( data[,2:(ncol(data)-1)] , order.by = date ) - zoo( data[,ncol(data)] , order.by = date )
42
}
43
monthlyR = monthlyR[,1:4]
44
45
summarystats_assets = FALSE;
46
if(summarystats_assets){
47
apply( monthlyR , 2 , 'mean' )*100 ; apply( monthlyR , 2 , 'sd' )*100
48
apply( monthlyR , 2 , 'skew' ) ; apply( monthlyR , 2 , 'exkur' )
49
apply( monthlyR , 2 , 'histCVaR' ) ; cor(monthlyR)
50
}
51
52
53
# Define the out-of-sample periods
54
55
# Define rebalancing periods:
56
57
ep = endpoints(monthlyR,on='quarters')
58
# select those for estimation period
59
ep.start = ep[(1+estyears*4):(length(ep)-1)]+1
60
from = time(monthlyR)[ep.start]
61
from = seq( as.Date("1984-01-01"), as.Date("2010-04-01"), by="3 month")
62
ep.end = ep[(1+estyears*4):(length(ep)-1)]+3
63
to = time(monthlyR)[ep.end]
64
65
66
67
# Compute daily out of sample returns, accounting for compounding effects
68
69
Returns.rebalancing( R = monthlyR , criteria = criteria, from = from, to = to , folder="/oosreturns/" )
70
oosdates = time( window (monthlyR , start = from[1] , end = to[ length(to) ] ) )
71
72
load(paste(getwd(),"/","/oosreturns/", "simplereturns.Rdata" ,sep="") )
73
74
colnames(simplereturns) = names
75
date = time(simplereturns)
76
77
78
# Bear periods
79
sp500 = window (monthlyR , start = from[1] , end = to[ length(to) ] )[,2]
80
bear = c(1:length(sp500))[sp500<mean(sp500)]
81
bear = c(1:length(sp500))[sp500<(-0.12)]
82
m.bear.dates = list();
83
i=1;
84
for( b in bear){
85
m.bear.dates[[i]] = c( b-0.5, b+0.5)
86
i = i + 1;
87
}
88
89
# http://www.aheadofthecurve-thebook.com/charts.html
90
# Vertical yellow bars in most charts denote bear markets (declines in the S&P 500 Index of 12% or more).
91
# IMPORTANT: The leading edge (left side) of the vertical yellow bars are thus stock market peaks,
92
# and the trailing edge (right side) are stock market troughs.
93
94
#source( paste(getwd(),"/R_interpretation/findDrawdowns.R",sep="") )
95
out = table.Drawdowns(sp500,top=10)
96
start.bear = out$From[out$Depth<(-0.12)]
97
end.bear = out$Trough[out$Depth<(-0.12)]
98
start.bear.index = c(1:length(sp500))[ time(sp500) ]
99
m.bear.dates = list()
100
v.bear.dates = c()
101
for( i in 1:length(start.bear) ){
102
m.bear.dates[[i]] = c( as.yearmon(start.bear[i]) , as.yearmon(end.bear[i]) )
103
v.bear.dates = c( v.bear.dates , seq(start.bear[i],end.bear[i],"days") )
104
}
105
v.bear.dates = as.Date( v.bear.dates )
106
107
108
# Chart of relative performance strategies vs Equal-Weight
109
110
postscript( file="RelPerf_EW.eps" )
111
# zelf opslaan anders worden de cijfers niet gedraaid in de y-as
112
par( mfrow = c(2,1) , mar =c(2,5,2,2), cex.axis = 0.7 , cex.main=0.7 )
113
# EqualWeight, MinCVaR, MinCVaRConcentration
114
chart.RelativePerformance( simplereturns[,c(2,3,4)] , simplereturns[,c(1)] ,
115
main = "" , lty=c("solid","solid","solid") , ylab="Relative performance vs equal-weight", xlab="",
116
col=c("black","darkgray","darkgray") , las=1, lwd=c(2,2,5) ,
117
auto.grid = TRUE, minor.ticks = FALSE ,ylim=c(0.7,1.65),
118
period.areas = m.bear.dates , period.color="lightgray",
119
date.format.in = "%Y-%m-%d",date.format = "%b %Y")
120
legend("topleft", legend = c("Min CVaR","Min CVaR + 40% Position Limit", "Min CVaR + 40% Risk Allocation Limit"),
121
col=c("black","darkgray","darkgray"), lty=c("solid","solid","solid"), lwd=c(2,2,5) ,cex=0.7)
122
123
chart.RelativePerformance( simplereturns[,c(5,6,7)] , simplereturns[,c(1)] ,
124
main = "" , lty=c("solid","solid","solid") , ylab="Relative performance vs equal-weight",
125
col=c("black","darkgray","darkgray") , lwd=c(2,2,5), las=1 ,
126
auto.grid = TRUE, minor.ticks = FALSE , ylim=c(0.7,1.65),
127
period.areas = m.bear.dates , period.color="lightgray",
128
date.format.in = "%Y-%m-%d",date.format = "%b %Y")
129
130
legend("topleft", legend = c("Min CVaR Concentration","Min CVaR Concentration + 40% Position Limit", "Min CVaR + ERC constraint"),
131
col=c("black","darkgray","darkgray"), lty=c("solid","solid","solid"), lwd=c(2,2,5) ,cex=0.7)
132
dev.off()
133
134
135
# Table of summary statistics on out-of-sample returns
136
137
library(PerformanceAnalytics)
138
library(zoo)
139
oosreturns = zoo(simplereturns[,c(1:7)],order.by = seq.Date(as.Date(from[1])+31, as.Date(tail(to,1)) + 1, by ="month") - 1)
140
141
v.nobear.dates = as.Date(setdiff( time(oosreturns) , v.bear.dates ))
142
143
# Mean, Standard Deviation, CVaR
144
histVaR = function( series ){ return(-quantile(series,probs=0.05) ) }
145
histCVaR = function( series ){ series = as.numeric(series) ; q = as.numeric(histVaR(series)) ; return( -mean( series[series<(-q)] )) }
146
147
print("Full period") #median, skew; exkur; histVaR
148
apply( oosreturns , 2 , 'mean' )*100*12 ;
149
apply( oosreturns , 2 , 'sd' )*100*sqrt(12)
150
100*apply( oosreturns , 2 , 'histCVaR')
151
152
oosreturns_bear = oosreturns[ v.bear.dates ]
153
oosreturns_bull = oosreturns[ v.nobear.dates ]
154
155
print("Bear market")
156
apply( oosreturns_bear , 2 , 'mean' )*100*12;
157
apply( oosreturns_bear , 2 , 'sd' )*100*sqrt(12)
158
100*apply( oosreturns_bear , 2 , 'histCVaR')
159
160
print("Bull market")
161
apply( oosreturns_bull , 2 , 'mean' )*100*12 ;
162
apply( oosreturns_bull , 2 , 'sd' )*100*sqrt(12)
163
100*apply( oosreturns_bull , 2 , 'histCVaR')
164
165
for( i in 1:7 ){ # Print the drawdowns
166
print( namelabels[i] )
167
print( table.Drawdowns(oosreturns[,i],top=10) )
168
}
169
170
# Risk concentration
171
172
for( strat in 1:7 ){
173
criterion = criteria[strat];
174
print( criterion );
175
weightedR = c(); portfolioVaR = c();
176
weights = read.csv( file = paste( criterion,".csv",sep=""),header = TRUE, sep = ",", na.strings = "NA", dec = ".")
177
178
# Step 1: compute for each optimal weight the corresponding historical quantile
179
180
for (row in 1:length(from)){
181
# For the determination of the historical quantile all returns preceding the rebalancing period are taken
182
previousR = window(monthlyR, start = time(monthlyR)[1] , end = as.Date(from[row]-1)) ;
183
pfoosR = rowSums( matrix( rep( as.numeric(weights[row,]),nrow(previousR)) , nrow = nrow(previousR) )*previousR )
184
# The weighted returns need the returns of the rebalancing period
185
Rrebalperiod = window(monthlyR, start = as.Date(from[row]) , end = as.Date(to[row])) ;
186
weightedR = rbind( weightedR , matrix( rep( as.numeric(weights[row,]),nrow(Rrebalperiod)) , nrow = nrow(Rrebalperiod) )*Rrebalperiod );
187
portfolioVaR = c( portfolioVaR , histVaR( pfoosR ) ) ;
188
}
189
190
# Step 2: compute the mean squared weighted return over months with beyond VaR losses
191
192
series = rowSums(weightedR) ;
193
#out = mean(weightedR[series<(-portfolioVaR),]^2);
194
downsidelosses = weightedR[series<(-portfolioVaR),]
195
downsidelosses = weightedR[series<=-0.10,]
196
vES = rowSums(downsidelosses)
197
198
print("Total portfolio loss")
199
print( summary( apply( -downsidelosses , 1 , 'sum') ))
200
print("Max percentage loss")
201
print( summary( apply( downsidelosses/ apply( downsidelosses , 1 , 'sum') , 1 , 'max') ))
202
203
}
204
205
206
# Portfolio turnover per strategy:
207
208
turnover = c();
209
210
# Compute for each rebalancing period, the cumulative return:
211
212
cumR = c()
213
oosR = window (monthlyR , start = from[1] , end = to[ length(to) ] )
214
cRebalancing = length(from)
215
216
for( i in 1:cRebalancing ){
217
sel = seq( (i-1)*3+1 , i*3 )
218
cumR = rbind( cumR , apply((1+oosR[sel,]),2,'cumprod')[3,] )
219
}
220
221
# Load portfolio weights:
222
223
for( strat in 1:7 ){
224
criterion = criteria[strat];
225
wstart = read.csv( file = paste( criterion,".csv",sep=""),header = TRUE, sep = ",", na.strings = "NA", dec = ".")
226
wend = (wstart[1:cRebalancing,]*cumR)/rowSums( wstart[1:cRebalancing,]*cumR )
227
out = mean( abs( wstart[2:cRebalancing,]-wend[1:(cRebalancing-1),] ))
228
turnover = c( turnover , mean(out) )
229
}
230
231
print( rbind( namelabels[1:7] , turnover*100) );
232
233