Path: blob/master/sandbox/paper_analysis/R_Allocation/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 = NULL , optimize_method = "DEoptim+L-BFGS-B", penalty = NULL ){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);18require( DEoptim )1920if( !is.null(R) ){21R = clean.boudt2( R , alpha = alphariskbudget )[[1]];22T = nrow(R);N=ncol(R)23mu = matrix( as.vector(apply(R,2,'mean')),ncol=1);24sigma = cov(R);25M3 = PerformanceAnalytics:::M3.MM(R)26M4 = PerformanceAnalytics:::M4.MM(R)27}else{ N = length(mu) }2829if( is.null(lower) ){ lower = rep(0,N) } ; if( is.null(upper) ){ upper = rep(1,N) }30if( is.null(RBlower) ){ RBlower = rep(-Inf,N) } ; if( is.null(RBupper) ){ RBupper = rep(Inf,N) }31if( is.null(Riskupper) ){ Riskupper = Inf } ; if( is.null(Returnlower) ){ Returnlower = -Inf }3233switch( percriskcontribcriterion ,34StdDev = { percriskcontrib = function(w){ return( Portsd(w,sigma=sigma, precision=9) ) }},35GVaR = { percriskcontrib = function(w){ return( PortgausVaR(w,alpha=alphariskbudget,mu=mu,sigma=sigma, precision=9) ) }},36GES = { percriskcontrib = function(w){ return( PortgausES(w,mu=mu,alpha=alphariskbudget,sigma=sigma, precision=9) ) }},37mVaR = { percriskcontrib = function(w){ return( PortMVaR(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4, precision=9) ) }},38mES = { percriskcontrib = function(w){ return( operPortMES(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4) ) }}39) #end function that finds out which percentage risk contribution criterion to use40switch( minriskcriterion ,41StdDev = { prisk = function(w){ return( StdDevfun(w,sigma=sigma) ) } ; },42GVaR = { prisk = function(w){ return( GVaRfun(w,alpha=alpha,mu=mu,sigma=sigma) ) }},43GES = { prisk = function(w){ return( GESfun(w,mu=mu,alpha=alpha,sigma=sigma) ) }},44mVaR = { prisk = function(w){ return( MVaRfun(w,mu=mu,alpha=alpha,sigma=sigma,M3=M3,M4=M4) )}},45mES = { prisk = function(w){ return( operMESfun(w,mu=mu,alpha=alpha,sigma=sigma,M3=M3,M4=M4)) };46derprisk = function(w){ return( deroperPortMES(w,mu=mu,alpha=alpha,sigma=sigma,M3=M3,M4=M4)) }47}48) #end function that finds out which risk function to minimize4950if( is.null(penalty) ){51abspenalty = 1e6; relpenalty = 100*N52}else{53abspenalty = relpenalty = penalty;54};5556if( optimize_method == "quadprog" & minriskcriterion == "StdDev" ){57require(quadprog)58dvec = matrix( rep(0,N) , ncol=1 )59# only risky assets60sumweights = 1;61Amat = rep(1,N);62bvec = sumweights;63# No short selling64minweight = 0 ;65# first round (afterwards, we impose minassetweight on assets with non-zero weight [heuristic]66Amat = rbind( Amat , diag(x =1,nrow=N,ncol=N) , diag(x =-1,nrow=N,ncol=N));67# you need to allow for an epsilon to make it feasible in the second stage68bvec = matrix( c( bvec , rep(minweight,N), -upper ),ncol=1)69minw = solve.QP( Dmat = sigma , dvec = dvec , Amat = t(Amat) , bvec = bvec , meq =1 )$solution70}7172if( optimize_method == "DEoptim" | optimize_method == "DEoptim+L-BFGS-B" ){73objective = function( w ){74if( sum(w) < 1e-4 ){75w <- w + 1e-276}77w = w/sum(w)78cont = percriskcontrib( w ); percrisk = cont[[3]]; crisk = cont[[2]] ;79if(MinMaxComp){ out = max( crisk ) }else{ out = prisk(w) }80# add weight constraints81out_con = out;82if( any(lower !=0) | any(upper!=1) ){83out_con = out_con + out*abspenalty*sum( 1*( w < lower )+1*( w > upper ) ) # can happen because of the standardization84}85# add risk budget constraint86if( any(RBupper < Inf ) ){87con1 = sum( (percrisk-RBupper)[RBupper < Inf]*( percrisk > RBupper )[RBupper < Inf] ,na.rm=TRUE ) ;88out_con = out_con + out*relpenalty*con189}90if( any(RBlower > -Inf ) ){91con2 = sum( (RBlower-percrisk)[RBlower > -Inf]*( percrisk < RBlower )[RBlower > -Inf] ,na.rm=TRUE ) ;92out_con = out_con + out*relpenalty*con293}94# add minimum risk constraint95if( Riskupper < Inf ){96con = ( prisk(w) - Riskupper)*( prisk(w) > Riskupper );97out_con = out_con + out*relpenalty*con98}99# add minimum return constraint100# portfolio return and risk are in the same unit, but portfolio return is typically some orders of magnitude smaller101# say: as a very conservative choice: 100102preturn = sum( w*mu ) ;103if( Returnlower > -Inf ){104con = ( Returnlower - preturn)*( preturn < Returnlower ); if( is.na(con) ){ con = 0 }105out_con = out_con + out*100*relpenalty*con106}107#der = derprisk(w)[w>0.01]108#der = abs(der -mean( der ) )109#if( sum( der )>0.01 ){110# out_con = out_con + out/sum( der )* max( der )}111return(out_con)112}113set.seed(1234)114if( is.null(controlDE) ){115# initial population is generated with random_portfolios function116require('PortfolioAnalytics')117eps = 0.01118rpconstraint<-constraint(assets=length(lower), min_sum=(1-eps), max_sum=(1+eps),119min=lower, max=upper, weight_seq=generatesequence())120rp<- random_portfolios(rpconstraints=rpconstraint,permutations=200)121controlDE <- list(reltol=1e-6,steptol=150, itermax = 5000,trace = 100,122strategy=6, c=.4,123NP=as.numeric(nrow(rp)),initialpop=rp)124}125# print(controlDE)126minw = DEoptim( fn = objective , lower = lower , upper = upper , control = controlDE)127fvalues = minw$member$bestval128#diff = as.vector( quantile(fvalues,0.10) - min(fvalues) )129#print(c("diff",diff))130best = min( fvalues ) ; print(best)131bestsol = minw ;132minw = bestsol$optim$bestmem/sum(bestsol$optim$bestmem) ; #full investment constraint133print( bestsol$optim$iter )134}135136137if( optimize_method == "DEoptim+L-BFGS-B" ){138print(minw) ; print( objective(minw) ) ;139print("local improvement")140out = optim( par=minw, f = objective, lower = lower, upper = upper, method="L-BFGS-B" )141minw = out$par/sum(out$par)142print(minw) ; print( objective(minw) )143}144145if( optimize_method == "L-BFGS-B" ){146objective = function( w ){147if(sum(w)==0){w=w+0.001}148w = w/sum(w)149cont = percriskcontrib( w ); percrisk = cont[[3]]; crisk = cont[[2]] ;150if(MinMaxComp){ out = max( crisk ) }else{ out = prisk(w) }151# add risk budget constraint152if( max(RBupper) != Inf ){ con1 = sum( (percrisk-RBupper)*( percrisk > RBupper ),na.rm=TRUE )}else{ con1 = 0 }153if( min(RBlower) != -Inf ){con2 = sum( (RBlower-percrisk)*( percrisk < RBlower ),na.rm=TRUE )}else{ con2 = 0 }154con = con1 + con2; if( is.na(con) ){ con = 0 }155out_con = out + out*relpenalty*con156# add minimum risk constraint157if( Riskupper != Inf ){ con = ( prisk(w) - Riskupper)*( prisk(w) > Riskupper )}else{ con = 0 };158if( is.na(con) ){ con = 0 }159out_con = out_con + out*relpenalty*con160return(out_con)161}162163if(Returnlower==-Inf){164inittheta = rep(1,N)/N165out = optim( par=inittheta, f = objective, lower = lower, upper = upper )166}else{167Amat = rbind(diag(x =1,nrow=N,ncol=N), diag(x =-1,nrow=N,ncol=N), rep(1,N), rep(-1,N),as.vector(mu))168inittheta = rep(0.001,N);169inittheta[mu==max(mu)] = 1; inittheta = 1-sum(inittheta[mu!=max(mu)] );170out = constrOptim( theta=inittheta, f = objective, grad=NULL,ui=Amat,171ci = c(rep(0,N),rep(-1,N),0.99999,-1.0001,Returnlower) )172}173174minw = out$par/sum(out$par)175}176cont = percriskcontrib( minw ); percrisk = cont[[3]]; crisk = cont[[2]] ;177# check178print( "out = list( minw , sum( minw*mu ) , prisk(minw) , percriskcontrib(minw)" )179out = list( minw , sum( minw*mu ) , prisk(minw) , percrisk , crisk )180print( out )181return(out)182}183184findportfolio.dynamic = function(R, mulist , sigmalist, M3list , M4list , from, to, names.input = NA, names.assets,185p = 0.95 , priskbudget = 0.95, mincriterion = "mES" , percriskcontribcriterion = "mES" ,186strategy , controlDE = NULL , optimize_method = "DEoptim+L-BFGS-B" )187{ # @author Kris Boudt and Brian G. Peterson188189# Description:190#191# Performs a loop over the reallocation periods with estimation samples given by from:to192# It calls the function RBconportfolio to obtain the optimal weights of the strategy.193#194# @todo195#196# R matrix/zoo holding historical returns on risky assets197#198# names vector holding the names of the .csv files to be read199#200# from, to define the estimation sample201#202# criteria the criterion to be optimized203#204# columns.crit the columns of R in which the criteria are located205#206# percriskcontribcriterion risk measure used for the risk budget constraints207#208# strategy = c( "EqualRisk" , "EqualWeight" , "MinRisk" , "MinRiskConc" ,209# "MinRisk_PositionLimit" , "MinRisk_RiskLimit" , "MinRisk_ReturnTarget",210# "MinRiskConc_PositionLimit" , "MinRiskConc_RiskLimit" , "MinRiskConc_ReturnTarget")211212# Return:213# List with first element optimal weights per reallocation period and associated percentage CVaR contributions.214215# Create a matrix that will hold for each method and each vector the best weights216217cPeriods = length(from);218219out = matrix( rep(0, cPeriods*(cAssets)) , ncol= (cAssets) );220RCout = matrix( rep(0, cPeriods*(cAssets)) , ncol= (cAssets) );221RiskReturnout = matrix( rep(0, cPeriods*2 ) , ncol= 2 );222223# first cPeriods rows correspond to cCriteria[1] and so on224225# downside risk226alpha = 1 - p;227alphariskbudget = 1-priskbudget;228229# Estimation of the return mean vector, covariance, coskewness and cokurtosis matrix230231232if(strategy=="EqualRisk"){233lower = rep(0,cAssets); upper=rep(1,cAssets)234RBlower = rep(1/cAssets,cAssets) ; RBupper = rep(1/cAssets,cAssets) ;235}236237if(strategy=="EqualWeight"){238lower = rep(1/cAssets,cAssets); upper=rep(1/cAssets,cAssets)239RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;240}241242if(strategy=="MinRisk" | strategy=="MinRiskConc" | strategy=="MinRisk_ReturnTarget" | strategy=="MinRiskConc_ReturnTarget"){243lower = rep(0,cAssets); upper=rep(1,cAssets)244RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;245}246247MinMaxComp = F; mutarget = -Inf;248if( strategy=="MinRiskConc" | strategy=="MinRiskConc_PositionLimit" | strategy=="MinRiskConc_RiskLimit" | strategy=="MinRiskConc_ReturnTarget" ){249MinMaxComp = T;250}251252if(strategy=="MinRisk_PositionLimit" | strategy=="MinRiskConc_PositionLimit"){253lower = rep(0,cAssets); upper=rep(0.4,cAssets)254RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;255}256257if(strategy=="MinRisk_RiskLimit" | strategy=="MinRiskConc_RiskLimit"){258lower = rep(0,cAssets); upper=rep(1,cAssets)259RBlower = rep(-Inf,cAssets) ; RBupper = rep(0.40,cAssets) ;260}261262# initial population is generated with random_portfolios function263if(is.null(controlDE) & optimize_method != "quadprog" ){264require('PortfolioAnalytics')265eps = 0.025266rpconstraint<-constraint(assets=length(lower), min_sum=(1-eps), max_sum=(1+eps),267min=lower, max=upper, weight_seq=generatesequence())268rp<- random_portfolios(rpconstraints=rpconstraint,permutations=controlDE$NP)269controlDE = list(reltol=1e-6,steptol=150, itermax = 5000,trace = 500, strategy=6, c=.4,270NP=as.numeric(nrow(rp)),initialpop=rp)271}272for( per in c(1:cPeriods) ){273274print("-----------New estimation period ends on observation------------------")275print( paste(to[per],"out of total number of obs equal to", max(to) ));276print("----------------------------------------------------------------")277278mu = 100*mulist[[per]] ;279sigma = (100^2)*sigmalist[[per]] ;280M3 = (100^3)*M3list[[per]] ;281M4 = (100^4)*M4list[[per]] ;282283284mESfun = function(series){ return( operMES(series,alpha=alpha,2) ) }285286287if(strategy=="MinRisk_ReturnTarget" | strategy=="MinRiskConc_ReturnTarget"){288mutarget = mean( mu );289print( c("Minimum return requirement is" , mutarget) )290}291292if(strategy=="EqualWeight"){293sol1 = rep(1/cAssets,cAssets);294switch( percriskcontribcriterion ,295StdDev = { percriskcontrib = function(w){ cont = Portsd(w,sigma=sigma) ; return( cont ) }},296GVaR = {percriskcontrib = function(w){ cont = PortgausVaR(w,alpha=alphariskbudget,mu=mu,sigma=sigma) ; return( cont ) }},297GES = {percriskcontrib = function(w){ cont = PortgausES(w,mu=mu,alpha=alphariskbudget,sigma=sigma) ; return( cont ) }},298mVaR = {percriskcontrib = function(w){ cont = PortMVaR(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4) ; return( cont ) }},299mES = {percriskcontrib = function(w){ cont = operPortMES(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4) ; return( cont ) }300}301)302sol2 = percriskcontrib( sol1 )303solution = list( sol1 , sol2[[3]] , sol2[[1]] , mean(mu) ) ;304}else{305if( per > 1 & optimize_method != "quadprog" ){306controlDE$initialpop = rbind( rp , out[1:(per-1),] )307controlDE$NP = as.numeric( nrow(controlDE$initialpop) )308}309#controlDE = list(reltol=1e-6,steptol=150, itermax = 5000,trace = 500, strategy=6, c=.4,310# NP=as.numeric(nrow(rp)),initialpop=rp)311solution = PortfolioOptim( minriskcriterion = mincriterion, MinMaxComp = MinMaxComp,312percriskcontribcriterion = percriskcontribcriterion ,313mu = mu , sigma = sigma, M3=M3 , M4=M4 , alpha = alpha , alphariskbudget = alphariskbudget ,314lower = lower , upper = upper , Riskupper = Inf , Returnlower= mutarget , RBlower = RBlower, RBupper = RBupper ,315controlDE = controlDE , optimize_method = optimize_method )316# [[1]] : weights ; [[2]] : expected portfolio return ; [[3]] : portfolio CVaR317# [[4]] : percentage CVaR ; [[5]] : component CVaR318solution = list( solution[[1]] , solution[[4]] , solution[[3]]/100 , solution[[2]]/100 );319}320out[ per, ] = as.vector( solution[[1]] )321RCout[per, ] = as.vector( solution[[2]] )322RiskReturnout[per,] = c( as.numeric(solution[[3]]) , as.numeric(solution[[4]]) )323324}#end loop over the rebalancing periods; indexed by per=1,...,cPeriods325326# Output save327rownames(out) = rownames(RCout) = rownames(RiskReturnout) = names.input;328colnames(out) = colnames(RCout) = names.assets;329colnames(RiskReturnout) = c( "risk" , "expreturn" )330331EWweights = c( rep(1/cAssets,cAssets) )332EWweights = matrix ( rep(EWweights,cPeriods) , ncol=(cAssets) , byrow = TRUE )333rownames(EWweights) = names.input; colnames(EWweights) = names.assets;334335return( list( out, RCout, RiskReturnout) )336}337338clean.boudt2 =339function (R, alpha = 0.01, trim = 0.001)340{341# @author Kris Boudt and Brian Peterson342# Cleaning method as described in343# Boudt, Peterson and Croux. 2009. Estimation and decomposition of downside risk for portfolios with non-normal returns. Journal of Risk.344345stopifnot("package:robustbase" %in% search() || require("robustbase",346quietly = TRUE))347R = checkData(R, method = "zoo")348T = dim(R)[1]349date = c(1:T)350N = dim(R)[2]351MCD = covMcd(as.matrix(R), alpha = 1 - alpha)352# mu = as.matrix(MCD$raw.center)353mu = MCD$raw.center354sigma = MCD$raw.cov355invSigma = solve(sigma)356vd2t = c()357cleaneddata = R358outlierdate = c()359for (t in c(1:T)) {360d2t = as.matrix(R[t, ] - mu) %*% invSigma %*% t(as.matrix(R[t,] - mu))361vd2t = c(vd2t, d2t)362}363out = sort(vd2t, index.return = TRUE)364sortvd2t = out$x365sortt = out$ix366empirical.threshold = sortvd2t[floor((1 - alpha) * T)]367T.alpha = floor(T * (1 - alpha)) + 1368cleanedt = sortt[c(T.alpha:T)]369for (t in cleanedt) {370if (vd2t[t] > qchisq(1 - trim, N)) {371cleaneddata[t, ] = sqrt(max(empirical.threshold,372qchisq(1 - trim, N))/vd2t[t]) * R[t, ]373outlierdate = c(outlierdate, date[t])374}375}376return(list(cleaneddata, outlierdate))377}378379380Ipower = function(power,h)381{382383fullprod = 1;384385if( (power%%2)==0 ) #even number: number mod is zero386{387pstar = power/2;388for(j in c(1:pstar))389{390fullprod = fullprod*(2*j)391}392I = fullprod*dnorm(h);393394for(i in c(1:pstar) )395{396prod = 1;397for(j in c(1:i) )398{399prod = prod*(2*j)400}401I = I + (fullprod/prod)*(h^(2*i))*dnorm(h)402}403}404else{405pstar = (power-1)/2406for(j in c(0:pstar) )407{408fullprod = fullprod*( (2*j)+1 )409}410I = -fullprod*pnorm(h);411412for(i in c(0:pstar) )413{414prod = 1;415for(j in c(0:i) )416{417prod = prod*( (2*j) + 1 )418}419I = I + (fullprod/prod)*(h^( (2*i) + 1))*dnorm(h)420}421}422return(I)423}424425426# Definition of statistics needed to compute Gaussian and modified VaR and ES for the return series of portfolios427# and to compute the contributions to portfolio downside risk, made by the different positions in the portfolio.428#----------------------------------------------------------------------------------------------------------------429430431432m2 = function(w,sigma)433{434return(t(w)%*%sigma%*%w)435}436derm2 = function(w,sigma)437{438return(2*sigma%*%w)439}440m3 = function(w,M3)441{442return(t(w)%*%M3%*%(w%x%w))443}444derm3 = function(w,M3)445{446return(3*M3%*%(w%x%w))447}448m4 = function(w,M4)449{450return(t(w)%*%M4%*%(w%x%w%x%w))451}452derm4 = function(w,M4)453{454return(4*M4%*%(w%x%w%x%w))455}456457StdDevfun = function(w,sigma){ return( sqrt( t(w)%*%sigma%*%w )) }458459GVaRfun = function(w,alpha,mu,sigma){ return (- (t(w)%*%mu) - qnorm(alpha)*sqrt( t(w)%*%sigma%*%w ) ) }460461mVaRfun = function(w,alpha,mu,sigma,M3,M4){462pm4 = t(w)%*%M4%*%(w%x%w%x%w) ; pm3 = t(w)%*%M3%*%(w%x%w) ; pm2 = t(w)%*%sigma%*%w ;463skew = pm3 / pm2^(3/2);464exkurt = pm4 / pm2^(2) - 3; z = qnorm(alpha);465h = z + (1/6)*(z^2 -1)*skew466h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;467return (- (t(w)%*%mu) - h*sqrt( pm2 ) ) }468469resmVaRfun = function(w,alpha,mu,sigma,ressigma,M3,M4){470pm4 = 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 ;471skew = pm3 / respm2^(3/2);472exkurt = pm4 / respm2^(2) - 3; z = qnorm(alpha);473h = z + (1/6)*(z^2 -1)*skew474h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;475return (- (t(w)%*%mu) - h*sqrt( pm2 ) ) }476477GESfun = function(w,alpha,mu,sigma,M3,M4){478return (- (t(w)%*%mu) + dnorm(qnorm(alpha))*sqrt(t(w)%*%sigma%*%w)/alpha ) }479480operMESfun = function(w,alpha,mu,sigma,M3,M4){481pm4 = t(w)%*%M4%*%(w%x%w%x%w) ; pm3 = t(w)%*%M3%*%(w%x%w) ; pm2 = t(w)%*%sigma%*%w ;482skew = pm3 / pm2^(3/2);483exkurt = pm4 / pm2^(2) - 3; z = qnorm(alpha);484h = z + (1/6)*(z^2 -1)*skew485h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;486E = dnorm(h)487E = E + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt488E = E + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;489E = E + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)490E = E/alpha491return (- (t(w)%*%mu) - sqrt(pm2)*min(-E,h) )492}493494495Portmean = function(w,mu,precision=4)496{497return( 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) )498}499500Portsd = function(w,sigma,precision=4)501{502pm2 = m2(w,sigma)503dpm2 = derm2(w,sigma)504dersd = (0.5*as.vector(dpm2))/sqrt(pm2);505contrib = dersd*as.vector(w)506return(list( round( sqrt(pm2) , precision ) , round( contrib , precision ) , round ( contrib/sqrt(pm2) , precision) ))507}508509510PortgausVaR = function(alpha,w,mu,sigma,precision=4){511location = t(w)%*%mu512pm2 = m2(w,sigma)513dpm2 = derm2(w,sigma)514VaR = - location - qnorm(alpha)*sqrt(pm2)515derVaR = - as.vector(mu)- qnorm(alpha)*(0.5*as.vector(dpm2))/sqrt(pm2);516contrib = derVaR*as.vector(w)517return(list( round( VaR , precision ) , round ( contrib , precision ) , round( contrib/VaR , precision) ))518}519520PortgausES = function(alpha,w,mu,sigma,precision=4){521location = t(w)%*%mu522pm2 = m2(w,sigma)523dpm2 = derm2(w,sigma)524ES = - location + dnorm(qnorm(alpha))*sqrt(pm2)/alpha525derES = - as.vector(mu) + (1/alpha)*dnorm(qnorm(alpha))*(0.5*as.vector(dpm2))/sqrt(pm2);526contrib = as.vector(w)*derES;527return(list( round( ES , precision ) , round( contrib , precision) , round( contrib/ES , precision) ))528}529530PortSkew = function(w,sigma,M3)531{532pm2 = m2(w,sigma)533pm3 = m3(w,M3)534skew = pm3 / pm2^(3/2);535return( skew )536}537538PortKurt = function(w,sigma,M4)539{540pm2 = m2(w,sigma)541pm4 = m4(w,M4)542kurt = pm4 / pm2^(2) ;543return( kurt )544}545546PortMVaR = function(alpha,w,mu,sigma,M3,M4,precision=4)547{548z = qnorm(alpha)549location = t(w)%*%mu550pm2 = m2(w,sigma)551dpm2 = as.vector( derm2(w,sigma) )552pm3 = m3(w,M3)553dpm3 = as.vector( derm3(w,M3) )554pm4 = m4(w,M4)555dpm4 = as.vector( derm4(w,M4) )556557skew = pm3 / pm2^(3/2);558exkurt = pm4 / pm2^(2) - 3;559560derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)561derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)562563h = z + (1/6)*(z^2 -1)*skew564h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;565566MVaR = - location - h*sqrt(pm2)567568derGausVaR = - as.vector(mu)- qnorm(alpha)*(0.5*as.vector(dpm2))/sqrt(pm2);569derMVaR = 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 )570derMVaR = 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 )571contrib = as.vector(w)*as.vector(derMVaR)572return(list( round( MVaR , precision) , round( contrib , precision ), round (contrib/MVaR , precision ) ) )573}574575derIpower = function(power,h)576{577578fullprod = 1;579580if( (power%%2)==0 ) #even number: number mod is zero581{582pstar = power/2;583for(j in c(1:pstar))584{585fullprod = fullprod*(2*j)586}587I = -fullprod*h*dnorm(h);588589for(i in c(1:pstar) )590{591prod = 1;592for(j in c(1:i) )593{594prod = prod*(2*j)595}596I = I + (fullprod/prod)*(h^(2*i-1))*(2*i-h^2)*dnorm(h)597}598}else{599pstar = (power-1)/2600for(j in c(0:pstar) )601{602fullprod = fullprod*( (2*j)+1 )603}604I = -fullprod*dnorm(h);605606for(i in c(0:pstar) )607{608prod = 1;609for(j in c(0:i) )610{611prod = prod*( (2*j) + 1 )612}613I = I + (fullprod/prod)*(h^(2*i)*(2*i+1-h^2) )*dnorm(h)614}615}616return(I)617}618619620PortMES = function(alpha,w,mu,sigma,M3,M4,precision=4)621{622z = qnorm(alpha)623location = t(w)%*%mu624pm2 = m2(w,sigma)625dpm2 = as.vector( derm2(w,sigma) )626pm3 = m3(w,M3)627dpm3 = as.vector( derm3(w,M3) )628pm4 = m4(w,M4)629dpm4 = as.vector( derm4(w,M4) )630631skew = pm3 / pm2^(3/2);632exkurt = pm4 / pm2^(2) - 3;633634derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)635derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)636637h = z + (1/6)*(z^2 -1)*skew638h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;639640derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew641642E = dnorm(h)643E = E + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt644E = E + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;645E = E + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)646E = E/alpha647MES = - location + sqrt(pm2)*E648649derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E650derE = (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*derexkurt651derE = derE + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*derskew652derE = derE + (1/36)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*skew*derskew653X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt654X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew655X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2656derE = derE+derh*X # X is a scalar657derE = derE/alpha658derMES = derMES + sqrt(pm2)*derE659contrib = as.vector(w)*as.vector(derMES)660return(list( round( MES , precision ) , round( contrib , precision ), round( contrib/MES, precision )) )661}662663derMES = function(alpha,w,mu,sigma,M3,M4,precision=4)664{665z = qnorm(alpha)666location = t(w)%*%mu667pm2 = m2(w,sigma)668dpm2 = as.vector( derm2(w,sigma) )669pm3 = m3(w,M3)670dpm3 = as.vector( derm3(w,M3) )671pm4 = m4(w,M4)672dpm4 = as.vector( derm4(w,M4) )673674skew = pm3 / pm2^(3/2);675exkurt = pm4 / pm2^(2) - 3;676677derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)678derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)679680h = z + (1/6)*(z^2 -1)*skew681h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;682683derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew684685E = dnorm(h)686E = E + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt687E = E + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;688E = E + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)689E = E/alpha690MES = - location + sqrt(pm2)*E691692derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E693derE = (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*derexkurt694derE = derE + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*derskew695derE = derE + (1/36)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*skew*derskew696X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt697X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew698X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2699derE = derE+derh*X # X is a scalar700derE = derE/alpha701derMES = derMES + sqrt(pm2)*derE702return(derMES)703}704705706operPortMES = function(alpha,w,mu,sigma,M3,M4)707{708z = qnorm(alpha)709location = t(w)%*%mu710pm2 = m2(w,sigma)711dpm2 = as.vector( derm2(w,sigma) )712pm3 = m3(w,M3)713dpm3 = as.vector( derm3(w,M3) )714pm4 = m4(w,M4)715dpm4 = as.vector( derm4(w,M4) )716717skew = pm3 / pm2^(3/2);718exkurt = pm4 / pm2^(2) - 3;719720derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)721derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)722723h = z + (1/6)*(z^2 -1)*skew724h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;725I1 = Ipower(1,h); I2 = Ipower(2,h); I3 = Ipower(3,h); I4 = Ipower(4,h); I6 = Ipower(6,h);726727derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew728729E = dnorm(h)730E = E + (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*exkurt731E = E + (1/6)*( I3 - 3*I1 )*skew;732E = E + (1/72)*( I6 -15*I4+ 45*I2 - 15*dnorm(h) )*(skew^2)733E = E/alpha734735MES = - location - sqrt(pm2)*min(-E,h)736737if(-E<=h){738derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E739derE = (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*derexkurt740derE = derE + (1/6)*( I3 - 3*I1 )*derskew741derE = derE + (1/36)*( I6 -15*I4 + 45*I2 - 15*dnorm(h) )*skew*derskew742X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt743X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew744X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2745derE = derE+derh*X # X is a scalar746derE = derE/alpha747derMES = derMES + sqrt(pm2)*derE748}else{749derMES = -mu - 0.5*(dpm2/sqrt(pm2))*h - sqrt(pm2)*derh ;750}751contrib = as.vector(w)*as.vector(derMES)752return(list( MES , contrib , contrib/MES ) )753}754755deroperPortMES = function(alpha,w,mu,sigma,M3,M4)756{757z = qnorm(alpha)758location = t(w)%*%mu759pm2 = m2(w,sigma)760dpm2 = as.vector( derm2(w,sigma) )761pm3 = m3(w,M3)762dpm3 = as.vector( derm3(w,M3) )763pm4 = m4(w,M4)764dpm4 = as.vector( derm4(w,M4) )765766skew = pm3 / pm2^(3/2);767exkurt = pm4 / pm2^(2) - 3;768769derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)770derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)771772h = z + (1/6)*(z^2 -1)*skew773h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;774I1 = Ipower(1,h); I2 = Ipower(2,h); I3 = Ipower(3,h); I4 = Ipower(4,h); I6 = Ipower(6,h);775776derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew777778E = dnorm(h)779E = E + (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*exkurt780E = E + (1/6)*( I3 - 3*I1 )*skew;781E = E + (1/72)*( I6 -15*I4+ 45*I2 - 15*dnorm(h) )*(skew^2)782E = E/alpha783784MES = - location - sqrt(pm2)*min(-E,h)785786if(-E<=h){787derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E788derE = (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*derexkurt789derE = derE + (1/6)*( I3 - 3*I1 )*derskew790derE = derE + (1/36)*( I6 -15*I4 + 45*I2 - 15*dnorm(h) )*skew*derskew791X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt792X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew793X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2794derE = derE+derh*X # X is a scalar795derE = derE/alpha796derMES = derMES + sqrt(pm2)*derE797}else{798derMES = -mu - 0.5*(dpm2/sqrt(pm2))*h - sqrt(pm2)*derh ;799}800return( derMES )801}802803centeredmoment = function(series,power)804{805location = mean(series);806out = sum( (series-location)^power )/length(series);807return(out);808}809810operMES = function(series,alpha,r)811{812z = qnorm(alpha)813location = mean(series);814m2 = centeredmoment(series,2)815m3 = centeredmoment(series,3)816m4 = centeredmoment(series,4)817skew = m3 / m2^(3/2);818exkurt = m4 / m2^(2) - 3;819820h = z + (1/6)*(z^2 -1)*skew821if(r==2){ h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2};822823MES = dnorm(h)824MES = MES + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt825MES = MES + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;826MES = MES + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)827MES = - location - (sqrt(m2))*min( -MES/alpha , h )828return(MES)829}830831TwoVarPlot <- function(xvar, y1var, y2var, labels, noincs = 5,marks=c(1,2), legpos, leglabs, title)832{833# https://stat.ethz.ch/pipermail/r-help/2000-September/008182.html834835# plots an x y1 y2 using left and right axes for the different y's836# rescales y2 to fit in the same space as y1837838# noincs - no of divisions in the axis labels839# marks - type of marker for each y840# legpos - legend position841# leglabs - legend labels842843# rescale to fit on same axis844scaledy2var <- (y2var - min(y2var)) / (max(y2var) - min(y2var))845scaledy2var <- (scaledy2var * (max(y1var) - min(y1var))) + min(y1var)846847# plot it up and add the points848plot(xvar, y1var, xlab=labels[1], ylab="", axes=F, pch=marks[1],main=title,type="l")849lines(xvar, scaledy2var, lty=3 )850851# make up some labels and positions852y1labs <- round(seq(min(y1var), max(y1var), length=noincs),2)853854# convert these to the y2 axis scaling855y2labs <- (y1labs - min(y1var)) / (max(y1var) - min(y1var))856y2labs <- (y2labs * (max(y2var) - min(y2var))) + min(y2var)857y2labs <- round(y2labs, 2)858859axis(1)860axis(2, at=y1labs, labels=y1labs)861axis(4, at=y1labs, labels=y2labs)862mtext(labels[3], side=4, line=2)863mtext(labels[2], side=2, line=2)864box()865866legend( legend=leglabs, lty = c(1,3), bty="o", x=legpos)867}868869870871872