Path: blob/master/sandbox/Risk_budget_functions.R
1433 views
1PortfolioOptim = function( minriskcriterion = "mES" , MinMaxComp = F, percriskcontribcriterion = "mES" ,2R = NULL, mu = NULL , sigma = NULL, M3=NULL,M4=NULL, alpha = 0.05, alphariskbudget = 0.05,3lower = NULL , upper = NULL, Riskupper = NULL, Returnlower = NULL, RBlower = NULL , RBupper = NULL, precision = 1e-3 ,4controlDE = list( VTR = 0 , NP=200, trace = FALSE ) , heuristic=TRUE ){56# Description:7# This function produces the portfolio that minimimizes8# either the portfolio risk (when MinMaxComp = F) or the portfolio concentration (when MinMaxComp = T)9# subject to10# lower <= weights <= upper11# risk <= Riskupper12# expected return >= Returnlower13# RBlower <= percentage risk <= RBupper1415# Input:16# Either the multivariate return series is given or estimates of the mean, covariance, coskewness or cokurtosis17require(zoo); require(PerformanceAnalytics); require(DEoptim)1819if( !is.null(R) ){20R = clean.boudt2( R , alpha = alphariskbudget )[[1]];21T = nrow(R);N=ncol(R)22mu = matrix( as.vector(apply(R,2,'mean')),ncol=1);23sigma = cov(R);24M3 = PerformanceAnalytics:::M3.MM(R)25M4 = PerformanceAnalytics:::M4.MM(R)26}else{ N = length(mu) }2728if( is.null(lower) ){ lower = rep(0,N) } ; if( is.null(upper) ){ upper = rep(1,N) }29if( is.null(RBlower) ){ RBlower = rep(-Inf,N) } ; if( is.null(RBupper) ){ RBupper = rep(Inf,N) }30if( is.null(Riskupper) ){ Riskupper = Inf } ; if( is.null(Returnlower) ){ Returnlower = -Inf }3132switch( percriskcontribcriterion ,33StdDev = { percriskcontrib = function(w){ return( Portsd(w,mu=mu,sigma=sigma) ) }},34GVaR = { percriskcontrib = function(w){ return( PortgausVaR(w,alpha=alphariskbudget,mu=mu,sigma=sigma) ) }},35GES = { percriskcontrib = function(w){ return( PortgausES(w,mu=mu,alpha=alphariskbudget,sigma=sigma) ) }},36mVaR = { percriskcontrib = function(w){ return( PortMVaR(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4) ) }},37mES = { percriskcontrib = function(w){ return( operPortMES(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4) ) }}38) #end function that finds out which percentage risk contribution criterion to use39switch( minriskcriterion ,40StdDev = { prisk = function(w){ return( stddevfun(w,mu=mu,sigma=sigma) ) }},41GVaR = { prisk = function(w){ return( gausVaRfun(w,alpha=alpha,mu=mu,sigma=sigma) ) }},42GES = { prisk = function(w){ return( gausESfun(w,mu=mu,alpha=alpha,sigma=sigma) ) }},43mVaR = { prisk = function(w){ return( MVaRfun(w,mu=mu,alpha=alpha,sigma=sigma,M3=M3,M4=M4) )}},44mES = { prisk = function(w){ return( operMESfun(w,mu=mu,alpha=alpha,sigma=sigma,M3=M3,M4=M4)) }}45) #end function that finds out which risk function to minimize4647abspenalty = 1e6; relpenalty = 100*N;48if( heuristic ){49objective = function( w ){50w = w/sum(w)51cont = percriskcontrib( w ); percrisk = cont[[3]]; crisk = cont[[2]] ;52if(MinMaxComp){ out = max( crisk ) }else{ out = prisk(w) }53# add weight constraints54out_con = out + out*abspenalty*sum( 1*( w < lower )+1*( w > upper ) )55# add risk budget constraint56con1 = sum( (percrisk-RBupper)*( percrisk > RBupper ),na.rm=TRUE ) ; if( is.na(con1) ){ con1 = 0 } # because of Inf*057con2 = sum( (RBlower-percrisk)*( percrisk < RBlower ),na.rm=TRUE ); if( is.na(con2) ){ con2 = 0 }58out_con = out_con + out*relpenalty*(con1+con2)59# add minimum risk constraint60con = ( prisk(w) - Riskupper)*( prisk(w) > Riskupper ); if( is.na(con) ){ con = 0 }61out_con = out_con + out*relpenalty*con62# add minimum return constraint63# portfolio return and risk are in the same unit, but portfolio return is typically some orders of magnitude smaller64# say: as a very conservative choice: 10065preturn = sum( w*mu ) ;66con = ( Returnlower - preturn)*( preturn < Returnlower ); if( is.na(con) ){ con = 0 }67out_con = out_con + out*100*relpenalty*con68return(out_con)69}70minw = DEoptim( fn = objective , lower = lower , upper = upper , control = controlDE)71fvalues = minw$member$bestval72diff = as.vector( quantile(fvalues,0.10) - min(fvalues) )73print(c("diff",diff))74best = min( fvalues ) ; print(best)75bestsol = minw ;7677while( diff>1e-6 ){78pop = as.matrix(minw$member$pop)79pop[1,] = minw$optim$bestmem;80minw = DEoptim( fn = objective , lower = lower , upper = upper ,81control = list( itermax = 150, NP=as.numeric(nrow(pop)) , initialpop=pop,trace=F ) )82fvalues = minw$member$bestval83diff = best - min(fvalues) ;84if( diff > 0 ){ best = min( fvalues ) ; bestsol = minw ; print(best) }85}86minw = bestsol$optim$bestmem/sum(bestsol$optim$bestmem) ; #full investment constraint87}else{88objective = function( w ){89if(sum(w)==0){w=w+0.001}90w = w/sum(w)91cont = percriskcontrib( w ); percrisk = cont[[3]]; crisk = cont[[2]] ;92if(MinMaxComp){ out = max( crisk ) }else{ out = prisk(w) }93# add risk budget constraint94con1 = sum( (percrisk-RBupper)*( percrisk > RBupper ),na.rm=TRUE ) ; if( is.na(con1) ){ con1 = 0 } # because of Inf*095con2 = sum( (RBlower-percrisk)*( percrisk < RBlower ),na.rm=TRUE ); if( is.na(con2) ){ con2 = 0 }96out_con = out + out*relpenalty*(con1+con2)97# add minimum risk constraint98con = ( prisk(w) - Riskupper)*( prisk(w) > Riskupper ); if( is.na(con) ){ con = 0 }99out_con = out_con + out*relpenalty*con100return(out_con)101}102103if(Returnlower==-Inf){104inittheta = rep(1,N)/N105out = optim( par=inittheta, f = objective, lower = lower, upper = upper )106}else{107Amat = rbind(diag(x =1,nrow=N,ncol=N), diag(x =-1,nrow=N,ncol=N), rep(1,N), rep(-1,N),as.vector(mu))108inittheta = rep(0.001,N);109inittheta[mu==max(mu)] = 1; inittheta = 1-sum(inittheta[mu!=max(mu)] );110out = constrOptim( theta=inittheta, f = objective, grad=NULL,ui=Amat,111ci = c(rep(0,N),rep(-1,N),0.99999,-1.0001,Returnlower) )112}113114minw = out$par/sum(out$par)115}116cont = percriskcontrib( minw ); percrisk = cont[[3]]; crisk = cont[[2]] ;117# check118print( "out = list( minw , sum( minw*mu ) , prisk(minw) , percriskcontrib(minw)" )119out = list( minw , sum( minw*mu ) , prisk(minw) , percrisk , crisk )120print( out )121return(out)122}123124findportfolio.dynamic = function(R, from, to, names.input = NA, names.assets,125p = 0.95 , priskbudget = 0.95, mincriterion = "mES" , percriskcontribcriterion = "mES" ,126strategy , controlDE = list( VTR = 0 , NP=200 ) )127{ # @author Kris Boudt and Brian G. Peterson128129# Description:130#131# Performs a loop over the reallocation periods with estimation samples given by from:to132# It calls the function RBconportfolio to obtain the optimal weights of the strategy.133#134# @todo135#136# R matrix/zoo holding historical returns on risky assets137#138# names vector holding the names of the .csv files to be read139#140# from, to define the estimation sample141#142# criteria the criterion to be optimized143#144# columns.crit the columns of R in which the criteria are located145#146# percriskcontribcriterion risk measure used for the risk budget constraints147#148# strategy = c( "EqualRisk" , "EqualWeight" , "MinRisk" , "MinRiskConc" ,149# "MinRisk_PositionLimit" , "MinRisk_RiskLimit" , "MinRisk_ReturnTarget",150# "MinRiskConc_PositionLimit" , "MinRiskConc_RiskLimit" , "MinRiskConc_ReturnTarget")151152# Return:153# List with first element optimal weights per reallocation period and associated percentage CVaR contributions.154155# Create a matrix that will hold for each method and each vector the best weights156157cPeriods = length(from);158159out = matrix( rep(0, cPeriods*(cAssets)) , ncol= (cAssets) );160RCout = matrix( rep(0, cPeriods*(cAssets)) , ncol= (cAssets) );161# first cPeriods rows correspond to cCriteria[1] and so on162163# downside risk164alpha = 1 - p;165alphariskbudget = 1-priskbudget;166167# Estimation of the return mean vector, covariance, coskewness and cokurtosis matrix168169170if(strategy=="EqualRisk"){171lower = rep(0,cAssets); upper=rep(1,cAssets)172RBlower = rep(1/cAssets,cAssets) ; RBupper = rep(1/cAssets,cAssets) ;173}174175if(strategy=="EqualWeight"){176lower = rep(1/cAssets,cAssets); upper=rep(1/cAssets,cAssets)177RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;178}179180if(strategy=="MinRisk" | strategy=="MinRiskConc" | strategy=="MinRisk_ReturnTarget" | strategy=="MinRiskConc_ReturnTarget"){181lower = rep(0,cAssets); upper=rep(1,cAssets)182RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;183}184185MinMaxComp = F; mutarget = -Inf;186if( strategy=="MinRiskConc" | strategy=="MinRiskConc_PositionLimit" | strategy=="MinRiskConc_RiskLimit" | strategy=="MinRiskConc_ReturnTarget" ){187MinMaxComp = T;188}189190if(strategy=="MinRisk_PositionLimit" | strategy=="MinRiskConc_PositionLimit"){191lower = rep(0,cAssets); upper=rep(0.4,cAssets)192RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;193}194195if(strategy=="MinRisk_RiskLimit" | strategy=="MinRiskConc_RiskLimit"){196lower = rep(0,cAssets); upper=rep(1,cAssets)197RBlower = rep(-Inf,cAssets) ; RBupper = rep(0.40,cAssets) ;198}199200for( per in c(1:cPeriods) ){201202print("-----------New estimation period ends on observation------------------")203print( paste(to[per],"out of total number of obs equal to", max(to) ));204print("----------------------------------------------------------------")205206# Estimate GARCH model with data from inception207208inception.R = window(R, start = as.Date(from[1]) , end = as.Date(to[per]) );209210# Estimate comoments of innovations with rolling estimation windows211in.sample.R = window(R, start = as.Date(from[per]) , end = as.Date(to[per]) );212in.sample.R = checkData(in.sample.R, method="matrix");213214# Estimation of mean return215M = c();216library(TTR)217Tmean = 47 # monthly returns: 4 year exponentially weighted moving average218for( i in 1:cAssets ){219M = cbind( M , as.vector( EMA(x=inception.R[,i],n=Tmean) ) ) #2/(n+1)220}221M = zoo( M , order.by=time(inception.R) )222223# Center returns (shift by one observations since M[t,] is rolling mean t-Tmean+1,...,t; otherwise lookahead bias)224inception.R.cent = inception.R;225ZZ = matrix( rep(as.vector( apply( inception.R[1:Tmean, ] , 2 , 'mean' )),Tmean),byrow=T,nrow=Tmean);226inception.R.cent[1:Tmean,] = inception.R[1:Tmean, ] - ZZ;227if( nrow(inception.R)>(Tmean+1) ){228A = M[Tmean:(nrow(inception.R)-1),];229A = zoo( A , order.by = time(inception.R[(Tmean+1):nrow(inception.R), ])) ; #shift dates; otherwise zoo poses problem230inception.R.cent[(Tmean+1):nrow(inception.R), ] = inception.R[(Tmean+1):nrow(inception.R), ] - A}231232# Garch estimation233S = c();234for( i in 1:cAssets ){235gout = garchFit(formula ~ garch(1,1), data = inception.R.cent[,i],include.mean = F, cond.dist="QMLE", trace = FALSE )236if( as.vector(gout@fit$coef["alpha1"]) < 0.01 ){237sigmat = rep( sd( as.vector(inception.R.cent[,i])), length(inception.R.cent[,i]) );238}else{239sigmat = gout@sigma.t240}241S = cbind( S , sigmat)242}243S = zoo( S , order.by=time(inception.R.cent) )244245# Estimate correlation, coskewness and cokurtosis matrix locally using cleaned innovation series in three year estimation window246selectU = window(inception.R.cent, start = as.Date(from[per]) , end = as.Date(to[per]) )247selectU = selectU/window(S, start = as.Date(from[per]) , end = as.Date(to[per]) );248selectU = clean.boudt2(selectU , alpha = 0.05 )[[1]];249Rcor = cor(selectU)250D = diag( as.vector(tail(S,n=1) ),ncol=cAssets )251sigma = D%*%Rcor%*%D252253# we only need mean and conditional covariance matrix of last observation254mu = matrix(tail(M,n=1),ncol=1 ) ;255D = diag( as.vector(as.vector(tail(S,n=1) ) ),ncol=cAssets )256sigma = D%*%Rcor%*%D257in.sample.T = nrow(selectU);258# set volatility of all U to last observation, such that cov(rescaled U)=sigma259selectU = selectU*matrix( rep(as.vector(tail(S,n=1)),in.sample.T ) , ncol = cAssets , byrow = T )260M3 = PerformanceAnalytics:::M3.MM(selectU)261M4 = PerformanceAnalytics:::M4.MM(selectU)262263264mESfun = function(series){ return( operMES(series,alpha=alpha,2) ) }265266267if(strategy=="MinRisk_ReturnTarget" | strategy=="MinRiskConc_ReturnTarget"){268mutarget = mean( mu );269print( c("Minimum return requirement is" , mutarget) )270}271272if(strategy=="EqualWeight"){273sol1 = rep(1/cAssets,cAssets);274switch( percriskcontribcriterion ,275StdDev = { percriskcontrib = function(w){ cont = Portsd(w,mu=mu,sigma=sigma)[[3]] ; return( cont ) }},276GVaR = {percriskcontrib = function(w){ cont = PortgausVaR(w,alpha=alphariskbudget,mu=mu,sigma=sigma)[[3]] ; return( cont ) }},277GES = {percriskcontrib = function(w){ cont = PortgausES(w,mu=mu,alpha=alphariskbudget,sigma=sigma)[[3]] ; return( cont ) }},278mVaR = {percriskcontrib = function(w){ cont = PortMVaR(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4)[[3]] ; return( cont ) }},279mES = {percriskcontrib = function(w){ cont = operPortMES(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4)[[3]] ; return( cont ) }280}281)282sol2 = percriskcontrib( sol1 )283solution = list( sol1 , sol2 ) ;284}else{285solution = PortfolioOptim( minriskcriterion = "mES" , MinMaxComp = MinMaxComp, percriskcontribcriterion = "mES" ,286mu = mu , sigma = sigma, M3=M3 , M4=M4 , alpha = alpha , alphariskbudget = alphariskbudget ,287lower = lower , upper = upper , Riskupper = Inf , Returnlower= mutarget , RBlower = RBlower, RBupper = RBupper ,288controlDE = controlDE )289solution = list( solution[[1]] , solution[[4]] );290}291out[ per, ] = as.vector( solution[[1]] )292RCout[per, ] = as.vector( solution[[2]] )293294}#end loop over the rebalancing periods; indexed by per=1,...,cPeriods295296297# Output save298rownames(out) = rownames(RCout) = names.input; colnames(out) = colnames(RCout) = names.assets;299300EWweights = c( rep(1/cAssets,cAssets) )301EWweights = matrix ( rep(EWweights,cPeriods) , ncol=(cAssets) , byrow = TRUE )302rownames(EWweights) = names.input; colnames(EWweights) = names.assets;303304return( list( out, RCout) )305}306307clean.boudt2 =308function (R, alpha = 0.01, trim = 0.001)309{310# @author Kris Boudt and Brian Peterson311# Cleaning method as described in312# Boudt, Peterson and Croux. 2009. Estimation and decomposition of downside risk for portfolios with non-normal returns. Journal of Risk.313314stopifnot("package:robustbase" %in% search() || require("robustbase",315quietly = TRUE))316R = checkData(R, method = "zoo")317T = dim(R)[1]318date = c(1:T)319N = dim(R)[2]320MCD = covMcd(as.matrix(R), alpha = 1 - alpha)321# mu = as.matrix(MCD$raw.center)322mu = MCD$raw.center323sigma = MCD$raw.cov324invSigma = solve(sigma)325vd2t = c()326cleaneddata = R327outlierdate = c()328for (t in c(1:T)) {329d2t = as.matrix(R[t, ] - mu) %*% invSigma %*% t(as.matrix(R[t,] - mu))330vd2t = c(vd2t, d2t)331}332out = sort(vd2t, index.return = TRUE)333sortvd2t = out$x334sortt = out$ix335empirical.threshold = sortvd2t[floor((1 - alpha) * T)]336T.alpha = floor(T * (1 - alpha)) + 1337cleanedt = sortt[c(T.alpha:T)]338for (t in cleanedt) {339if (vd2t[t] > qchisq(1 - trim, N)) {340cleaneddata[t, ] = sqrt(max(empirical.threshold,341qchisq(1 - trim, N))/vd2t[t]) * R[t, ]342outlierdate = c(outlierdate, date[t])343}344}345return(list(cleaneddata, outlierdate))346}347348349Ipower = function(power,h)350{351352fullprod = 1;353354if( (power%%2)==0 ) #even number: number mod is zero355{356pstar = power/2;357for(j in c(1:pstar))358{359fullprod = fullprod*(2*j)360}361I = fullprod*dnorm(h);362363for(i in c(1:pstar) )364{365prod = 1;366for(j in c(1:i) )367{368prod = prod*(2*j)369}370I = I + (fullprod/prod)*(h^(2*i))*dnorm(h)371}372}373else{374pstar = (power-1)/2375for(j in c(0:pstar) )376{377fullprod = fullprod*( (2*j)+1 )378}379I = -fullprod*pnorm(h);380381for(i in c(0:pstar) )382{383prod = 1;384for(j in c(0:i) )385{386prod = prod*( (2*j) + 1 )387}388I = I + (fullprod/prod)*(h^( (2*i) + 1))*dnorm(h)389}390}391return(I)392}393394395# Definition of statistics needed to compute Gaussian and modified VaR and ES for the return series of portfolios396# and to compute the contributions to portfolio downside risk, made by the different positions in the portfolio.397#----------------------------------------------------------------------------------------------------------------398399400401m2 = function(w,sigma)402{403return(t(w)%*%sigma%*%w)404}405derm2 = function(w,sigma)406{407return(2*sigma%*%w)408}409m3 = function(w,M3)410{411return(t(w)%*%M3%*%(w%x%w))412}413derm3 = function(w,M3)414{415return(3*M3%*%(w%x%w))416}417m4 = function(w,M4)418{419return(t(w)%*%M4%*%(w%x%w%x%w))420}421derm4 = function(w,M4)422{423return(4*M4%*%(w%x%w%x%w))424}425426StdDevfun = function(w,sigma){ return( sqrt( t(w)%*%sigma%*%w )) }427428GVaRfun = function(w,alpha,mu,sigma){ return (- (t(w)%*%mu) - qnorm(alpha)*sqrt( t(w)%*%sigma%*%w ) ) }429430mVaRfun = function(w,alpha,mu,sigma,M3,M4){431pm4 = t(w)%*%M4%*%(w%x%w%x%w) ; pm3 = t(w)%*%M3%*%(w%x%w) ; pm2 = t(w)%*%sigma%*%w ;432skew = pm3 / pm2^(3/2);433exkurt = pm4 / pm2^(2) - 3; z = qnorm(alpha);434h = z + (1/6)*(z^2 -1)*skew435h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;436return (- (t(w)%*%mu) - h*sqrt( pm2 ) ) }437438resmVaRfun = function(w,alpha,mu,sigma,ressigma,M3,M4){439pm4 = t(w)%*%M4%*%(w%x%w%x%w) ; pm3 = t(w)%*%M3%*%(w%x%w) ; pm2 = t(w)%*%sigma%*%w ; respm2 = t(w)%*%resSigma%*%w ;440skew = pm3 / respm2^(3/2);441exkurt = pm4 / respm2^(2) - 3; z = qnorm(alpha);442h = z + (1/6)*(z^2 -1)*skew443h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;444return (- (t(w)%*%mu) - h*sqrt( pm2 ) ) }445446GESfun = function(w,alpha,mu,sigma,M3,M4){447return (- (t(w)%*%mu) + dnorm(qnorm(alpha))*sqrt(t(w)%*%sigma%*%w)/alpha ) }448449operMESfun = function(w,alpha,mu,sigma,M3,M4){450pm4 = t(w)%*%M4%*%(w%x%w%x%w) ; pm3 = t(w)%*%M3%*%(w%x%w) ; pm2 = t(w)%*%sigma%*%w ;451skew = pm3 / pm2^(3/2);452exkurt = pm4 / pm2^(2) - 3; z = qnorm(alpha);453h = z + (1/6)*(z^2 -1)*skew454h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;455E = dnorm(h)456E = E + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt457E = E + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;458E = E + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)459E = E/alpha460return (- (t(w)%*%mu) - sqrt(pm2)*min(-E,h) ) }461462precision = 4;463464Portmean = function(w,mu,precision=4)465{466return( list( round( t(w)%*%mu , precision) , round ( as.vector(w)*as.vector(mu) , precision ) , round( as.vector(w)*as.vector(mu)/t(w)%*%mu) , precision) )467}468469Portsd = function(w,sigma,precision=4)470{471pm2 = m2(w,sigma)472dpm2 = derm2(w,sigma)473dersd = (0.5*as.vector(dpm2))/sqrt(pm2);474contrib = dersd*as.vector(w)475return(list( round( sqrt(pm2) , precision ) , round( contrib , precision ) , round ( contrib/sqrt(pm2) , precision) ))476}477478479PortgausVaR = function(alpha,w,mu,sigma,precision=4){480location = t(w)%*%mu481pm2 = m2(w,sigma)482dpm2 = derm2(w,sigma)483VaR = - location - qnorm(alpha)*sqrt(pm2)484derVaR = - as.vector(mu)- qnorm(alpha)*(0.5*as.vector(dpm2))/sqrt(pm2);485contrib = derVaR*as.vector(w)486return(list( round( VaR , precision ) , round ( contrib , precision ) , round( contrib/VaR , precision) ))487}488489PortgausES = function(alpha,w,mu,sigma,precision=4){490location = t(w)%*%mu491pm2 = m2(w,sigma)492dpm2 = derm2(w,sigma)493ES = - location + dnorm(qnorm(alpha))*sqrt(pm2)/alpha494derES = - as.vector(mu) + (1/alpha)*dnorm(qnorm(alpha))*(0.5*as.vector(dpm2))/sqrt(pm2);495contrib = as.vector(w)*derES;496return(list( round( ES , precision ) , round( contrib , precision) , round( contrib/ES , precision) ))497}498499PortSkew = function(w,sigma,M3)500{501pm2 = m2(w,sigma)502pm3 = m3(w,M3)503skew = pm3 / pm2^(3/2);504return( skew )505}506507PortKurt = function(w,sigma,M4)508{509pm2 = m2(w,sigma)510pm4 = m4(w,M4)511kurt = pm4 / pm2^(2) ;512return( kurt )513}514515PortMVaR = function(alpha,w,mu,sigma,M3,M4,precision=4)516{517z = qnorm(alpha)518location = t(w)%*%mu519pm2 = m2(w,sigma)520dpm2 = as.vector( derm2(w,sigma) )521pm3 = m3(w,M3)522dpm3 = as.vector( derm3(w,M3) )523pm4 = m4(w,M4)524dpm4 = as.vector( derm4(w,M4) )525526skew = pm3 / pm2^(3/2);527exkurt = pm4 / pm2^(2) - 3;528529derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)530derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)531532h = z + (1/6)*(z^2 -1)*skew533h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;534535MVaR = - location - h*sqrt(pm2)536537derGausVaR = - as.vector(mu)- qnorm(alpha)*(0.5*as.vector(dpm2))/sqrt(pm2);538derMVaR = derGausVaR + (0.5*dpm2/sqrt(pm2))*( -(1/6)*(z^2 -1)*skew - (1/24)*(z^3 - 3*z)*exkurt + (1/36)*(2*z^3 - 5*z)*skew^2 )539derMVaR = derMVaR + sqrt(pm2)*( -(1/6)*(z^2 -1)*derskew - (1/24)*(z^3 - 3*z)*derexkurt + (1/36)*(2*z^3 - 5*z)*2*skew*derskew )540contrib = as.vector(w)*as.vector(derMVaR)541return(list( round( MVaR , precision) , round( contrib , precision ), round (contrib/MVaR , precision ) ) )542}543544derIpower = function(power,h)545{546547fullprod = 1;548549if( (power%%2)==0 ) #even number: number mod is zero550{551pstar = power/2;552for(j in c(1:pstar))553{554fullprod = fullprod*(2*j)555}556I = -fullprod*h*dnorm(h);557558for(i in c(1:pstar) )559{560prod = 1;561for(j in c(1:i) )562{563prod = prod*(2*j)564}565I = I + (fullprod/prod)*(h^(2*i-1))*(2*i-h^2)*dnorm(h)566}567}else{568pstar = (power-1)/2569for(j in c(0:pstar) )570{571fullprod = fullprod*( (2*j)+1 )572}573I = -fullprod*dnorm(h);574575for(i in c(0:pstar) )576{577prod = 1;578for(j in c(0:i) )579{580prod = prod*( (2*j) + 1 )581}582I = I + (fullprod/prod)*(h^(2*i)*(2*i+1-h^2) )*dnorm(h)583}584}585return(I)586}587588589PortMES = function(alpha,w,mu,sigma,M3,M4,precision=4)590{591z = qnorm(alpha)592location = t(w)%*%mu593pm2 = m2(w,sigma)594dpm2 = as.vector( derm2(w,sigma) )595pm3 = m3(w,M3)596dpm3 = as.vector( derm3(w,M3) )597pm4 = m4(w,M4)598dpm4 = as.vector( derm4(w,M4) )599600skew = pm3 / pm2^(3/2);601exkurt = pm4 / pm2^(2) - 3;602603derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)604derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)605606h = z + (1/6)*(z^2 -1)*skew607h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;608609derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew610611E = dnorm(h)612E = E + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt613E = E + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;614E = E + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)615E = E/alpha616MES = - location + sqrt(pm2)*E617618derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E619derE = (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*derexkurt620derE = derE + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*derskew621derE = derE + (1/36)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*skew*derskew622X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt623X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew624X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2625derE = derE+derh*X # X is a scalar626derE = derE/alpha627derMES = derMES + sqrt(pm2)*derE628contrib = as.vector(w)*as.vector(derMES)629return(list( round( MES , precision ) , round( contrib , precision ), round( contrib/MES, precision )) )630}631632633operPortMES = function(alpha,w,mu,sigma,M3,M4,precision=4)634{635z = qnorm(alpha)636location = t(w)%*%mu637pm2 = m2(w,sigma)638dpm2 = as.vector( derm2(w,sigma) )639pm3 = m3(w,M3)640dpm3 = as.vector( derm3(w,M3) )641pm4 = m4(w,M4)642dpm4 = as.vector( derm4(w,M4) )643644skew = pm3 / pm2^(3/2);645exkurt = pm4 / pm2^(2) - 3;646647derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)648derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)649650h = z + (1/6)*(z^2 -1)*skew651h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;652I1 = Ipower(1,h); I2 = Ipower(2,h); I3 = Ipower(3,h); I4 = Ipower(4,h); I6 = Ipower(6,h);653654derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew655656E = dnorm(h)657E = E + (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*exkurt658E = E + (1/6)*( I3 - 3*I1 )*skew;659E = E + (1/72)*( I6 -15*I4+ 45*I2 - 15*dnorm(h) )*(skew^2)660E = E/alpha661662MES = - location - sqrt(pm2)*min(-E,h)663664if(-E<=h){665derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E666derE = (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*derexkurt667derE = derE + (1/6)*( I3 - 3*I1 )*derskew668derE = derE + (1/36)*( I6 -15*I4 + 45*I2 - 15*dnorm(h) )*skew*derskew669X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt670X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew671X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2672derE = derE+derh*X # X is a scalar673derE = derE/alpha674derMES = derMES + sqrt(pm2)*derE }else{675derMES = -mu - 0.5*(dpm2/sqrt(pm2))*h - sqrt(pm2)*derh ; }676contrib = as.vector(w)*as.vector(derMES)677return(list( round( MES, precision) , round( contrib , precision ) , round(contrib/MES,precision) ) )678}679680681centeredmoment = function(series,power)682{683location = mean(series);684out = sum( (series-location)^power )/length(series);685return(out);686}687688operMES = function(series,alpha,r)689{690z = qnorm(alpha)691location = mean(series);692m2 = centeredmoment(series,2)693m3 = centeredmoment(series,3)694m4 = centeredmoment(series,4)695skew = m3 / m2^(3/2);696exkurt = m4 / m2^(2) - 3;697698h = z + (1/6)*(z^2 -1)*skew699if(r==2){ h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2};700701MES = dnorm(h)702MES = MES + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt703MES = MES + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;704MES = MES + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)705MES = - location - (sqrt(m2))*min( -MES/alpha , h )706return(MES)707}708709TwoVarPlot <- function(xvar, y1var, y2var, labels, noincs = 5,marks=c(1,2), legpos, leglabs, title)710{711# https://stat.ethz.ch/pipermail/r-help/2000-September/008182.html712713# plots an x y1 y2 using left and right axes for the different y's714# rescales y2 to fit in the same space as y1715716# noincs - no of divisions in the axis labels717# marks - type of marker for each y718# legpos - legend position719# leglabs - legend labels720721# rescale to fit on same axis722scaledy2var <- (y2var - min(y2var)) / (max(y2var) - min(y2var))723scaledy2var <- (scaledy2var * (max(y1var) - min(y1var))) + min(y1var)724725# plot it up and add the points726plot(xvar, y1var, xlab=labels[1], ylab="", axes=F, pch=marks[1],main=title,type="l")727lines(xvar, scaledy2var, lty=3 )728729# make up some labels and positions730y1labs <- round(seq(min(y1var), max(y1var), length=noincs),2)731732# convert these to the y2 axis scaling733y2labs <- (y1labs - min(y1var)) / (max(y1var) - min(y1var))734y2labs <- (y2labs * (max(y2var) - min(y2var))) + min(y2var)735y2labs <- round(y2labs, 2)736737axis(1)738axis(2, at=y1labs, labels=y1labs)739axis(4, at=y1labs, labels=y2labs)740mtext(labels[3], side=4, line=2)741mtext(labels[2], side=2, line=2)742box()743744legend( legend=leglabs, lty = c(1,3), bty="o", x=legpos)745}746747748749750