Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
braverock
GitHub Repository: braverock/portfolioanalytics
Path: blob/master/sandbox/symposium2013/R/table.RiskStats.R
1433 views
1
# Additional and re-organized tables for WB presentations
2
3
table.RiskStats <-
4
function (R, ci = 0.95, scale = NA, Rf = 0, MAR = .1/12, p= 0.95, digits = 4)
5
{# @author Peter Carl
6
# Risk Statistics: Statistics and Stylized Facts
7
8
y = checkData(R, method = "zoo")
9
if(!is.null(dim(Rf)))
10
Rf = checkData(Rf, method = "zoo")
11
# Set up dimensions and labels
12
columns = ncol(y)
13
rows = nrow(y)
14
columnnames = colnames(y)
15
rownames = rownames(y)
16
17
if(is.na(scale)) {
18
freq = periodicity(y)
19
switch(freq$scale,
20
minute = {stop("Data periodicity too high")},
21
hourly = {stop("Data periodicity too high")},
22
daily = {scale = 252},
23
weekly = {scale = 52},
24
monthly = {scale = 12},
25
quarterly = {scale = 4},
26
yearly = {scale = 1}
27
)
28
}
29
30
# for each column, do the following:
31
for(column in 1:columns) {
32
x = na.omit(y[,column,drop=FALSE])
33
# for each column, make sure that R and Rf are for the same dates
34
if(!is.null(dim(Rf))){ # if Rf is a column
35
z = merge(x,Rf)
36
zz = na.omit(z)
37
x = zz[,1,drop=FALSE]
38
Rf.subset = zz[,2,drop=FALSE]
39
}
40
else { # unless Rf is a single number
41
Rf.subset = Rf
42
}
43
44
z = c(
45
Return.annualized(x, scale = scale),
46
StdDev.annualized(x, scale = scale),
47
SharpeRatio.annualized(x, scale = scale, Rf = Rf),
48
DownsideDeviation(x,MAR=0)*sqrt(scale),# Add annualization to this function
49
SortinoRatio(x)*sqrt(scale), # New function adds annualization
50
PerformanceAnalytics:::AverageDrawdown(x),
51
maxDrawdown(x),
52
SterlingRatio(x),
53
VaR(x, p=p,method="historical"),
54
ES(x, p=p,method="historical"),
55
skewness(x),
56
kurtosis(x),
57
VaR(x, p=p),
58
ES(x, p=p),
59
SharpeRatio(x, p=p, Rf=Rf, FUN="ES", annualize=TRUE),
60
length(x)
61
)
62
znames = c(
63
"Annualized Return",
64
"Annualized Std Dev",
65
"Annualized Sharpe Ratio",
66
"Annualized Downside Deviation",
67
"Annualized Sortino Ratio",
68
"Average Drawdown",
69
"Maximum Drawdown",
70
"Sterling Ratio (10%)",
71
paste("Historical VaR (",base::round(p*100,1),"%)",sep=""),
72
paste("Historical ETL (",base::round(p*100,1),"%)",sep=""),
73
"Skewness",
74
"Excess Kurtosis",
75
paste("Modified VaR (",base::round(p*100,1),"%)",sep=""),
76
paste("Modified ETL (",base::round(p*100,1),"%)",sep=""),
77
paste("Annualized Modified Sharpe Ratio (ETL ", base::round(p*100,1),"%)",sep=""),
78
"# Obs"
79
)
80
if(column == 1) {
81
resultingtable = data.frame(Value = z, row.names = znames)
82
}
83
else {
84
nextcolumn = data.frame(Value = z, row.names = znames)
85
resultingtable = cbind(resultingtable, nextcolumn)
86
}
87
}
88
colnames(resultingtable) = columnnames
89
ans = base::round(resultingtable, digits)
90
ans
91
}
92
93
table.PerfStats <-
94
function (R, scale = NA, Rf = 0, digits = 4)
95
{# @author Peter Carl
96
# Performance Statistics: Statistics and Stylized Facts
97
98
y = checkData(R)
99
if(!is.null(dim(Rf)))
100
Rf = checkData(Rf)
101
# Set up dimensions and labels
102
columns = ncol(y)
103
rows = nrow(y)
104
columnnames = colnames(y)
105
rownames = rownames(y)
106
107
if(is.na(scale)) {
108
freq = periodicity(y)
109
switch(freq$scale,
110
minute = {stop("Data periodicity too high")},
111
hourly = {stop("Data periodicity too high")},
112
daily = {scale = 252},
113
weekly = {scale = 52},
114
monthly = {scale = 12},
115
quarterly = {scale = 4},
116
yearly = {scale = 1}
117
)
118
}
119
120
# for each column, do the following:
121
for(column in 1:columns) {
122
x = na.omit(y[,column,drop=FALSE])
123
# for each column, make sure that R and Rf are for the same dates
124
if(!is.null(dim(Rf))){ # if Rf is a column
125
z = merge(x,Rf)
126
zz = na.omit(z)
127
x = zz[,1,drop=FALSE]
128
Rf.subset = zz[,2,drop=FALSE]
129
}
130
else { # unless Rf is a single number
131
Rf.subset = Rf
132
}
133
134
z = c(
135
Return.cumulative(x),
136
Return.annualized(x, scale = scale),
137
StdDev.annualized(x, scale = scale),
138
length(subset(x, x>0)),
139
length(subset(x, x<=0)),
140
length(subset(x, x>0))/length(x),
141
mean(subset(x, x>0)),
142
mean(subset(x, x<=0)),
143
mean(x),
144
AverageDrawdown(x),
145
AverageRecovery(x)
146
)
147
znames = c(
148
"Cumulative Return",
149
"Annualized Return",
150
"Annualized Std Dev",
151
"# Positive Months",
152
"# Negative Months",
153
"% Positive Months",
154
"Average Positive Month",
155
"Average Negative Month",
156
"Average Month",
157
"Average Drawdown",
158
"Average Months to Recovery"
159
)
160
if(column == 1) {
161
resultingtable = data.frame(Value = z, row.names = znames)
162
}
163
else {
164
nextcolumn = data.frame(Value = z, row.names = znames)
165
resultingtable = cbind(resultingtable, nextcolumn)
166
}
167
}
168
colnames(resultingtable) = columnnames
169
ans = base::round(resultingtable, digits)
170
ans
171
}
172
173
table.RiskContribution <- function(R, p, ..., weights=NULL, scale=NA, geometric = TRUE) {
174
175
R = na.omit(R)
176
if(is.null(weights)) {
177
message("no weights passed in, assuming equal weighted portfolio")
178
weights = rep(1/dim(R)[[2]], dim(R)[[2]])
179
}
180
if (is.na(scale)) {
181
freq = periodicity(R)
182
switch(freq$scale, minute = {
183
stop("Data periodicity too high")
184
}, hourly = {
185
stop("Data periodicity too high")
186
}, daily = {
187
scale = 252
188
}, weekly = {
189
scale = 52
190
}, monthly = {
191
scale = 12
192
}, quarterly = {
193
scale = 4
194
}, yearly = {
195
scale = 1
196
})
197
}
198
199
# Returns
200
# ret.col = colMeans(R)*weights
201
ret.col = Return.annualized(R, geometric=geometric)*weights
202
percret.col = ret.col/sum(ret.col)
203
result = cbind(t(ret.col), t(percret.col))
204
# Standard Deviation
205
sd.cols = StdDev(R, weights=weights, invert=TRUE, portfolio_method="component", p=(1-1/12))
206
result = cbind(sd.cols$contribution*sqrt(scale), sd.cols$pct_contrib_StdDev, result)
207
# VaR?
208
var.cols = VaR(R, weights=weights, method="gaussian", portfolio_method="component", p=(1-1/12))
209
result = cbind(var.cols$contribution, var.cols$pct_contrib_VaR, result)
210
211
mvar.cols = VaR(R, weights=weights, method="gaussian", portfolio_method="component", p=(1-1/12))
212
result = cbind(mvar.cols$contribution, mvar.cols$pct_contrib_VaR, result)
213
214
# ES
215
es.cols = ES(R, weights=weights, method="gaussian", portfolio_method="component", p=(1-1/12))
216
result = cbind(es.cols$contribution, es.cols$pct_contrib_ES, result)
217
218
mes.cols = ES(R, weights=weights, method="modified", portfolio_method="component", p=(1-1/12))
219
result = cbind(weights, mes.cols$contribution, mes.cols$pct_contrib_MES, result)
220
total = colSums(result)
221
222
result = rbind(result, colSums(result))
223
rownames(result) = c(colnames(R),"Total")
224
# colnames(result) = c("Weights", "Contribution to mETL", "Percentage Contribution to mETL", "Contribution to gETL", "Percentage Contribution to gETL", "Contribution to Annualized StdDev", "Percentage Contribution to StdDev", "Contribution to Annualized E(R)", "Percentage Contribution to E(R)")
225
226
colnames(result) = c("Weights", "Contribution to mETL", "%Contribution to mETL", "Contribution to gETL", "%Contribution to gETL", "Contribution to mVaR", "%Contribution to mVaR", "Contribution to gVaR", "%Contribution to gVaR", "Contribution to Annualized StdDev", "%Contribution to StdDev", "Contribution to Annualized E(R)", "%Contribution to E(R)")
227
return(result)
228
229
}
230
231