Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
braverock
GitHub Repository: braverock/portfolioanalytics
Path: blob/master/sandbox/TAA.R
1433 views
1
2
TAA = function( R , minreturn = 0.05,
3
lowerweights = NA, upperweights = NA, alpha = 0.05,clean = F,
4
lowerESriskbudgetweights = -Inf, upperESriskbudgetweights = +Inf ,
5
nrestarts = 60, nrounds = 10 , nsteps = 500 ,increment = 0.01)
6
{
7
# Author: Kris Boudt
8
# This function uses the threshold accepting algorithm in Gilli, Kellezi and Hysi (Journal of Risk, 2006)
9
# to find the portfolio with highes ES sharpe ratio and that respect the ES risk budget constraints
10
11
T = nrow(R); N=ncol(R);
12
if( is.na(lowerweights) ){ lowerweights = rep(0.0,N) } # no short sales
13
if( is.na(upperweights) ){ upperweights = rep(0.3,N) } # no concentration
14
15
if(clean){ R = cleaning(R,alpha=alpha,trim=1e-3)[[1]] };
16
mu = apply(R,2,'mean' )
17
sigma = cov(R)
18
invSigma = solve(sigma)
19
M3 = matrix(rep(0,N^3),nrow=N,ncol=N^2)
20
M4 = matrix(rep(0,N^4),nrow=N,ncol=N^3)
21
for(t in c(1:T)){
22
centret = as.numeric(matrix(R[t,]-as.vector(mu),nrow=N,ncol=1))
23
M3 = M3 + ( centret%*%t(centret) )%x%t(centret)
24
M4 = M4 + ( centret%*%t(centret) )%x%t(centret)%x%t(centret)
25
}
26
M3 = 1/T*M3;
27
M4 = 1/T*M4;
28
29
# Define function to be minimized
30
NegSRMES = function( w )
31
{
32
largevalue = 100;
33
MES = operPortMES(alpha,w,mu,sigma,M3,M4)
34
MESi = MES[[1]];
35
portreturni = sum( w*mu)
36
return( -portreturni/MESi )
37
}
38
39
# Define functions that will generate random solutions that respect the constraints
40
ransol.h = function(N)
41
{
42
w = rep(0,N); vassets = c(1:N);
43
while( sum(w) <1 ){
44
i = vassets[ceiling( runif(1,0.01,length(vassets)) ) ];
45
w[i] = round( min( runif( 1 , lower[i] , upper[i] ) , 1-sum(w) ) , digits= 2);
46
vassets = setdiff( vassets , i) ;
47
if(length(vassets)==1){w[vassets[1]] = 1-sum(w) ; }
48
}
49
return(w)
50
}
51
52
ransol = function(N)
53
{
54
viol = T;
55
while( viol ){
56
neww = ransol.h(N);
57
MES = operPortMES(alpha,neww,mu,sigma,M3,M4)
58
MESi = MES[[1]];
59
portreturni = sum( neww*mu*12 )
60
percentcontrib = MES[[3]]
61
viol= ( any( (percentcontrib > upperESriskbudgetweights) | (percentcontrib < lowerESriskbudgetweights) ) | (portreturni<minreturn) )
62
}
63
return(neww)
64
}
65
66
# Function that generates neigbors
67
# This can take some time because the neigborhood is constrained not only by the weight constraints but also by the ES risk budget constraints
68
69
neighbor = function( w )
70
{
71
viol = T;
72
while( viol ){
73
# exchange incr between two positions, ensures that if initial value satisfies budget constraint, it will remain satisfied
74
partners = ceiling( runif(2,0,N) );
75
# ceiling( runif(2*npartners,0,N) );
76
neww = w ; neww[partners ] = neww[partners]+ increment*c(+1,-1) ;
77
viol = ( any( neww < lower ) | any( neww > upper) )
78
if(!viol){
79
MES = operPortMES(alpha,neww,mu,sigma,M3,M4)
80
MESi = MES[[1]];
81
portreturni = sum( w*mu*12 )
82
percentcontrib = MES[[3]]
83
viol= ( any( (percentcontrib > upperESriskbudgetweights) | (percentcontrib < lowerESriskbudgetweights) ) | (portreturni<minreturn) )
84
}
85
}
86
return(neww)
87
}
88
89
initw = ransol( N);
90
91
# Generation of threshold sequence (Algorithm 3 in Gilli, Kellezi and Hysi (Journal of Risk, 2006) )
92
vdelta = rep(0,nsteps)
93
for( i in 1:nsteps){
94
neww = neighbor(initw);
95
vdelta[i] = abs( NegSRMES(initw) - NegSRMES(neww) );
96
}
97
qthreshold = quantile( x = vdelta , probs = seq(0.01,1,0.01) ) ;
98
plot(seq(0.01,1,0.01) , qthreshold , main = "Quantile function of Delta used for setting threshold" )
99
100
bestw = initw ; bestf = NegSRMES( initw );
101
102
for( k in 1:nrestarts ){
103
print( c("restart",k,"out of", nrestarts) );
104
initw = ransol( N) ; localbestw = initw ; initf = localbestf = NegSRMES( initw );
105
for( r in 1:nrounds ){
106
# the threshold tau > 0 : "if we want to escape local minima, the algorithm must accept uphill moves"
107
# the threshold is gradually reduced to zero in a deterministic way
108
taur = round( 0.8*( nrounds - r )/nrounds , digits=2 )*100;
109
for( i in 1:nsteps ){
110
neww = neighbor(initw); newf = NegSRMES(neww);
111
delta = newf-initf ;
112
if( (delta < qthreshold[ taur +1 ]) ){ localbestw = initw ; localbestf = newf; }
113
}
114
}
115
if( localbestf < bestf ){ bestw = localbestw ; bestf = localbestf ; }
116
}
117
118
return( bestw )
119
}
120
121
###############################################################################
122
# R (http://r-project.org/) Numeric Methods for Optimization of Portfolios
123
#
124
# Copyright (c) 2004-2014 Kris Boudt, Peter Carl and Brian G. Peterson
125
#
126
# This library is distributed under the terms of the GNU Public License (GPL)
127
# for full details see the file COPYING
128
#
129
# $Id$
130
#
131
###############################################################################
132
# $Log: not supported by cvs2svn $
133
###############################################################################
134
135