Path: blob/master/sandbox/riskbudgetpaper(superseded)/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); 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, precision=9) ) }},34GVaR = { percriskcontrib = function(w){ return( PortgausVaR(w,alpha=alphariskbudget,mu=mu,sigma=sigma, precision=9) ) }},35GES = { percriskcontrib = function(w){ return( PortgausES(w,mu=mu,alpha=alphariskbudget,sigma=sigma, precision=9) ) }},36mVaR = { percriskcontrib = function(w){ return( PortMVaR(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4, precision=9) ) }},37mES = { percriskcontrib = function(w){ return( operPortMES(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4, precision=9) ) }}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 minimize4647if( is.null(penalty) ){48abspenalty = 1e6; relpenalty = 100*N49}else{50abspenalty = relpenalty = penalty;51};52if( optimize_method == "DEoptim" | optimize_method == "DEoptim+L-BFGS-B" ){53objective = function( w ){54w = w/sum(w)55cont = percriskcontrib( w ); percrisk = cont[[3]]; crisk = cont[[2]] ;56if(MinMaxComp){ out = max( crisk ) }else{ out = prisk(w) }57# add weight constraints58out_con = out + out*abspenalty*sum( 1*( w < lower )+1*( w > upper ) )59# add risk budget constraint60con1 = sum( (percrisk-RBupper)*( percrisk > RBupper ),na.rm=TRUE ) ; if( is.na(con1) ){ con1 = 0 } # because of Inf*061con2 = sum( (RBlower-percrisk)*( percrisk < RBlower ),na.rm=TRUE ); if( is.na(con2) ){ con2 = 0 }62out_con = out_con + out*relpenalty*(con1+con2)63# add minimum risk constraint64con = ( prisk(w) - Riskupper)*( prisk(w) > Riskupper ); if( is.na(con) ){ con = 0 }65out_con = out_con + out*relpenalty*con66# add minimum return constraint67# portfolio return and risk are in the same unit, but portfolio return is typically some orders of magnitude smaller68# say: as a very conservative choice: 10069preturn = sum( w*mu ) ;70con = ( Returnlower - preturn)*( preturn < Returnlower ); if( is.na(con) ){ con = 0 }71out_con = out_con + out*100*relpenalty*con72return(out_con)73}7475if( is.null(controlDE) ){76# initial population is generated with random_portfolios function77require('PortfolioAnalytics')78eps = 0.0179rpconstraint<-constraint(assets=length(lower), min_sum=(1-eps), max_sum=(1+eps),80min=lower, max=upper, weight_seq=generatesequence())81rp<- random_portfolios(rpconstraints=rpconstraint,permutations=200)82controlDE = list( NP=as.numeric(nrow(rp)) , initialpop=rp,trace=F )83}84# print(controlDE)85minw = DEoptim( fn = objective , lower = lower , upper = upper , control = controlDE)86fvalues = minw$member$bestval87diff = as.vector( quantile(fvalues,0.10) - min(fvalues) )88print(c("diff",diff))89best = min( fvalues ) ; print(best)90bestsol = minw ;9192while( diff>1e-6 ){93pop = as.matrix(minw$member$pop)94pop[1,] = minw$optim$bestmem;95minw = DEoptim( fn = objective , lower = lower , upper = upper ,96control = list( itermax = 150, NP=as.numeric(nrow(pop)) , initialpop=pop,trace=F ) )97fvalues = minw$member$bestval98diff = best - min(fvalues) ;99if( diff > 0 ){ best = min( fvalues ) ; bestsol = minw ; print(best) }100}101minw = bestsol$optim$bestmem/sum(bestsol$optim$bestmem) ; #full investment constraint102}103104105if( optimize_method == "DEoptim+L-BFGS-B" ){106print(minw) ; print( objective(minw) )107print("local improvement")108out = optim( par=minw, f = objective, lower = lower, upper = upper, method="L-BFGS-B" )109minw = out$par/sum(out$par)110print(minw) ; print( objective(minw) )111}112113if( optimize_method == "L-BFGS-B" ){114objective = function( w ){115if(sum(w)==0){w=w+0.001}116w = w/sum(w)117cont = percriskcontrib( w ); percrisk = cont[[3]]; crisk = cont[[2]] ;118if(MinMaxComp){ out = max( crisk ) }else{ out = prisk(w) }119# add risk budget constraint120con1 = sum( (percrisk-RBupper)*( percrisk > RBupper ),na.rm=TRUE ) ; if( is.na(con1) ){ con1 = 0 } # because of Inf*0121con2 = sum( (RBlower-percrisk)*( percrisk < RBlower ),na.rm=TRUE ); if( is.na(con2) ){ con2 = 0 }122out_con = out + out*relpenalty*(con1+con2)123# add minimum risk constraint124con = ( prisk(w) - Riskupper)*( prisk(w) > Riskupper ); if( is.na(con) ){ con = 0 }125out_con = out_con + out*relpenalty*con126return(out_con)127}128129if(Returnlower==-Inf){130inittheta = rep(1,N)/N131out = optim( par=inittheta, f = objective, lower = lower, upper = upper )132}else{133Amat = rbind(diag(x =1,nrow=N,ncol=N), diag(x =-1,nrow=N,ncol=N), rep(1,N), rep(-1,N),as.vector(mu))134inittheta = rep(0.001,N);135inittheta[mu==max(mu)] = 1; inittheta = 1-sum(inittheta[mu!=max(mu)] );136out = constrOptim( theta=inittheta, f = objective, grad=NULL,ui=Amat,137ci = c(rep(0,N),rep(-1,N),0.99999,-1.0001,Returnlower) )138}139140minw = out$par/sum(out$par)141}142cont = percriskcontrib( minw ); percrisk = cont[[3]]; crisk = cont[[2]] ;143# check144print( "out = list( minw , sum( minw*mu ) , prisk(minw) , percriskcontrib(minw)" )145out = list( minw , sum( minw*mu ) , prisk(minw) , percrisk , crisk )146print( out )147return(out)148}149150findportfolio.dynamic = function(R, from, to, names.input = NA, names.assets,151p = 0.95 , priskbudget = 0.95, mincriterion = "mES" , percriskcontribcriterion = "mES" ,152strategy , controlDE = list( VTR = 0 , NP=200 , itermax = 200,trace=F ), optimize_method = "DEoptim+L-BFGS-B" )153{ # @author Kris Boudt and Brian G. Peterson154155# Description:156#157# Performs a loop over the reallocation periods with estimation samples given by from:to158# It calls the function RBconportfolio to obtain the optimal weights of the strategy.159#160# @todo161#162# R matrix/zoo holding historical returns on risky assets163#164# names vector holding the names of the .csv files to be read165#166# from, to define the estimation sample167#168# criteria the criterion to be optimized169#170# columns.crit the columns of R in which the criteria are located171#172# percriskcontribcriterion risk measure used for the risk budget constraints173#174# strategy = c( "EqualRisk" , "EqualWeight" , "MinRisk" , "MinRiskConc" ,175# "MinRisk_PositionLimit" , "MinRisk_RiskLimit" , "MinRisk_ReturnTarget",176# "MinRiskConc_PositionLimit" , "MinRiskConc_RiskLimit" , "MinRiskConc_ReturnTarget")177178# Return:179# List with first element optimal weights per reallocation period and associated percentage CVaR contributions.180181# Create a matrix that will hold for each method and each vector the best weights182183cPeriods = length(from);184185out = matrix( rep(0, cPeriods*(cAssets)) , ncol= (cAssets) );186RCout = matrix( rep(0, cPeriods*(cAssets)) , ncol= (cAssets) );187RiskReturnout = matrix( rep(0, cPeriods*2 ) , ncol= 2 );188189# first cPeriods rows correspond to cCriteria[1] and so on190191# downside risk192alpha = 1 - p;193alphariskbudget = 1-priskbudget;194195# Estimation of the return mean vector, covariance, coskewness and cokurtosis matrix196197198if(strategy=="EqualRisk"){199lower = rep(0,cAssets); upper=rep(1,cAssets)200RBlower = rep(1/cAssets,cAssets) ; RBupper = rep(1/cAssets,cAssets) ;201}202203if(strategy=="EqualWeight"){204lower = rep(1/cAssets,cAssets); upper=rep(1/cAssets,cAssets)205RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;206}207208if(strategy=="MinRisk" | strategy=="MinRiskConc" | strategy=="MinRisk_ReturnTarget" | strategy=="MinRiskConc_ReturnTarget"){209lower = rep(0,cAssets); upper=rep(1,cAssets)210RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;211}212213MinMaxComp = F; mutarget = -Inf;214if( strategy=="MinRiskConc" | strategy=="MinRiskConc_PositionLimit" | strategy=="MinRiskConc_RiskLimit" | strategy=="MinRiskConc_ReturnTarget" ){215MinMaxComp = T;216}217218if(strategy=="MinRisk_PositionLimit" | strategy=="MinRiskConc_PositionLimit"){219lower = rep(0,cAssets); upper=rep(0.4,cAssets)220RBlower = rep(-Inf,cAssets) ; RBupper = rep(Inf,cAssets) ;221}222223if(strategy=="MinRisk_RiskLimit" | strategy=="MinRiskConc_RiskLimit"){224lower = rep(0,cAssets); upper=rep(1,cAssets)225RBlower = rep(-Inf,cAssets) ; RBupper = rep(0.40,cAssets) ;226}227228# initial population is generated with random_portfolios function229require('PortfolioAnalytics')230eps = 0.01231rpconstraint<-constraint(assets=length(lower), min_sum=(1-eps), max_sum=(1+eps),232min=lower, max=upper, weight_seq=generatesequence())233rp<- random_portfolios(rpconstraints=rpconstraint,permutations=controlDE$NP)234controlDE = list( NP=as.numeric(nrow(rp)) , initialpop=rp,trace=F )235236for( per in c(1:cPeriods) ){237238print("-----------New estimation period ends on observation------------------")239print( paste(to[per],"out of total number of obs equal to", max(to) ));240print("----------------------------------------------------------------")241242# Estimate GARCH model with data from inception243244inception.R = window(R, start = as.Date(from[1]) , end = as.Date(to[per]) );245246# Estimate comoments of innovations with rolling estimation windows247in.sample.R = window(R, start = as.Date(from[per]) , end = as.Date(to[per]) );248in.sample.R = checkData(in.sample.R, method="matrix");249250# Estimation of mean return251M = c();252library(TTR)253Tmean = 47 # monthly returns: 4 year exponentially weighted moving average254for( i in 1:cAssets ){255M = cbind( M , as.vector( EMA(x=inception.R[,i],n=Tmean) ) ) #2/(n+1)256}257M = zoo( M , order.by=time(inception.R) )258259# Center returns (shift by one observations since M[t,] is rolling mean t-Tmean+1,...,t; otherwise lookahead bias)260inception.R.cent = inception.R;261ZZ = matrix( rep(as.vector( apply( inception.R[1:Tmean, ] , 2 , 'mean' )),Tmean),byrow=T,nrow=Tmean);262inception.R.cent[1:Tmean,] = inception.R[1:Tmean, ] - ZZ;263if( nrow(inception.R)>(Tmean+1) ){264A = M[Tmean:(nrow(inception.R)-1),];265A = zoo( A , order.by = time(inception.R[(Tmean+1):nrow(inception.R), ])) ; #shift dates; otherwise zoo poses problem266inception.R.cent[(Tmean+1):nrow(inception.R), ] = inception.R[(Tmean+1):nrow(inception.R), ] - A}267268# Garch estimation269S = c();270for( i in 1:cAssets ){271gout = garchFit(formula ~ garch(1,1), data = inception.R.cent[,i],include.mean = F, cond.dist="QMLE", trace = FALSE )272if( as.vector(gout@fit$coef["alpha1"]) < 0.01 ){273sigmat = rep( sd( as.vector(inception.R.cent[,i])), length(inception.R.cent[,i]) );274}else{275sigmat = gout@sigma.t276}277S = cbind( S , sigmat)278}279S = zoo( S , order.by=time(inception.R.cent) )280281# Estimate correlation, coskewness and cokurtosis matrix locally using cleaned innovation series in three year estimation window282selectU = window(inception.R.cent, start = as.Date(from[per]) , end = as.Date(to[per]) )283selectU = selectU/window(S, start = as.Date(from[per]) , end = as.Date(to[per]) );284selectU = clean.boudt2(selectU , alpha = 0.05 )[[1]];285Rcor = cor(selectU)286D = diag( as.vector(tail(S,n=1) ),ncol=cAssets )287sigma = D%*%Rcor%*%D288289# we only need mean and conditional covariance matrix of last observation290mu = matrix(tail(M,n=1),ncol=1 ) ;291D = diag( as.vector(as.vector(tail(S,n=1) ) ),ncol=cAssets )292sigma = D%*%Rcor%*%D293in.sample.T = nrow(selectU);294# set volatility of all U to last observation, such that cov(rescaled U)=sigma295selectU = selectU*matrix( rep(as.vector(tail(S,n=1)),in.sample.T ) , ncol = cAssets , byrow = T )296M3 = PerformanceAnalytics:::M3.MM(selectU)297M4 = PerformanceAnalytics:::M4.MM(selectU)298299300mESfun = function(series){ return( operMES(series,alpha=alpha,2) ) }301302303if(strategy=="MinRisk_ReturnTarget" | strategy=="MinRiskConc_ReturnTarget"){304mutarget = mean( mu );305print( c("Minimum return requirement is" , mutarget) )306}307308if(strategy=="EqualWeight"){309sol1 = rep(1/cAssets,cAssets);310switch( percriskcontribcriterion ,311StdDev = { percriskcontrib = function(w){ cont = Portsd(w,mu=mu,sigma=sigma) ; return( cont ) }},312GVaR = {percriskcontrib = function(w){ cont = PortgausVaR(w,alpha=alphariskbudget,mu=mu,sigma=sigma) ; return( cont ) }},313GES = {percriskcontrib = function(w){ cont = PortgausES(w,mu=mu,alpha=alphariskbudget,sigma=sigma) ; return( cont ) }},314mVaR = {percriskcontrib = function(w){ cont = PortMVaR(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4) ; return( cont ) }},315mES = {percriskcontrib = function(w){ cont = operPortMES(w,mu=mu,alpha=alphariskbudget,sigma=sigma,M3=M3,M4=M4) ; return( cont ) }316}317)318sol2 = percriskcontrib( sol1 )319solution = list( sol1 , sol2[[3]] , sol2[[1]] , mean(mu) ) ;320}else{321solution = PortfolioOptim( minriskcriterion = "mES" , MinMaxComp = MinMaxComp, percriskcontribcriterion = "mES" ,322mu = mu , sigma = sigma, M3=M3 , M4=M4 , alpha = alpha , alphariskbudget = alphariskbudget ,323lower = lower , upper = upper , Riskupper = Inf , Returnlower= mutarget , RBlower = RBlower, RBupper = RBupper ,324controlDE = controlDE , optimize_method = optimize_method )325# [[1]] : weights ; [[2]] : expected portfolio return ; [[3]] : portfolio CVaR326# [[4]] : percentage CVaR ; [[5]] : component CVaR327solution = list( solution[[1]] , solution[[4]] , solution[[3]] , solution[[2]] );328}329out[ per, ] = as.vector( solution[[1]] )330RCout[per, ] = as.vector( solution[[2]] )331RiskReturnout[per,] = c( as.numeric(solution[[3]]) , as.numeric(solution[[4]]) )332333}#end loop over the rebalancing periods; indexed by per=1,...,cPeriods334335# Output save336rownames(out) = rownames(RCout) = rownames(RiskReturnout) = names.input;337colnames(out) = colnames(RCout) = names.assets;338colnames(RiskReturnout) = c( "risk" , "expreturn" )339340EWweights = c( rep(1/cAssets,cAssets) )341EWweights = matrix ( rep(EWweights,cPeriods) , ncol=(cAssets) , byrow = TRUE )342rownames(EWweights) = names.input; colnames(EWweights) = names.assets;343344return( list( out, RCout, RiskReturnout) )345}346347clean.boudt2 =348function (R, alpha = 0.01, trim = 0.001)349{350# @author Kris Boudt and Brian Peterson351# Cleaning method as described in352# Boudt, Peterson and Croux. 2009. Estimation and decomposition of downside risk for portfolios with non-normal returns. Journal of Risk.353354stopifnot("package:robustbase" %in% search() || require("robustbase",355quietly = TRUE))356R = checkData(R, method = "zoo")357T = dim(R)[1]358date = c(1:T)359N = dim(R)[2]360MCD = covMcd(as.matrix(R), alpha = 1 - alpha)361# mu = as.matrix(MCD$raw.center)362mu = MCD$raw.center363sigma = MCD$raw.cov364invSigma = solve(sigma)365vd2t = c()366cleaneddata = R367outlierdate = c()368for (t in c(1:T)) {369d2t = as.matrix(R[t, ] - mu) %*% invSigma %*% t(as.matrix(R[t,] - mu))370vd2t = c(vd2t, d2t)371}372out = sort(vd2t, index.return = TRUE)373sortvd2t = out$x374sortt = out$ix375empirical.threshold = sortvd2t[floor((1 - alpha) * T)]376T.alpha = floor(T * (1 - alpha)) + 1377cleanedt = sortt[c(T.alpha:T)]378for (t in cleanedt) {379if (vd2t[t] > qchisq(1 - trim, N)) {380cleaneddata[t, ] = sqrt(max(empirical.threshold,381qchisq(1 - trim, N))/vd2t[t]) * R[t, ]382outlierdate = c(outlierdate, date[t])383}384}385return(list(cleaneddata, outlierdate))386}387388389Ipower = function(power,h)390{391392fullprod = 1;393394if( (power%%2)==0 ) #even number: number mod is zero395{396pstar = power/2;397for(j in c(1:pstar))398{399fullprod = fullprod*(2*j)400}401I = fullprod*dnorm(h);402403for(i in c(1:pstar) )404{405prod = 1;406for(j in c(1:i) )407{408prod = prod*(2*j)409}410I = I + (fullprod/prod)*(h^(2*i))*dnorm(h)411}412}413else{414pstar = (power-1)/2415for(j in c(0:pstar) )416{417fullprod = fullprod*( (2*j)+1 )418}419I = -fullprod*pnorm(h);420421for(i in c(0:pstar) )422{423prod = 1;424for(j in c(0:i) )425{426prod = prod*( (2*j) + 1 )427}428I = I + (fullprod/prod)*(h^( (2*i) + 1))*dnorm(h)429}430}431return(I)432}433434435# Definition of statistics needed to compute Gaussian and modified VaR and ES for the return series of portfolios436# and to compute the contributions to portfolio downside risk, made by the different positions in the portfolio.437#----------------------------------------------------------------------------------------------------------------438439440441m2 = function(w,sigma)442{443return(t(w)%*%sigma%*%w)444}445derm2 = function(w,sigma)446{447return(2*sigma%*%w)448}449m3 = function(w,M3)450{451return(t(w)%*%M3%*%(w%x%w))452}453derm3 = function(w,M3)454{455return(3*M3%*%(w%x%w))456}457m4 = function(w,M4)458{459return(t(w)%*%M4%*%(w%x%w%x%w))460}461derm4 = function(w,M4)462{463return(4*M4%*%(w%x%w%x%w))464}465466StdDevfun = function(w,sigma){ return( sqrt( t(w)%*%sigma%*%w )) }467468GVaRfun = function(w,alpha,mu,sigma){ return (- (t(w)%*%mu) - qnorm(alpha)*sqrt( t(w)%*%sigma%*%w ) ) }469470mVaRfun = function(w,alpha,mu,sigma,M3,M4){471pm4 = t(w)%*%M4%*%(w%x%w%x%w) ; pm3 = t(w)%*%M3%*%(w%x%w) ; pm2 = t(w)%*%sigma%*%w ;472skew = pm3 / pm2^(3/2);473exkurt = pm4 / pm2^(2) - 3; z = qnorm(alpha);474h = z + (1/6)*(z^2 -1)*skew475h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;476return (- (t(w)%*%mu) - h*sqrt( pm2 ) ) }477478resmVaRfun = function(w,alpha,mu,sigma,ressigma,M3,M4){479pm4 = 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 ;480skew = pm3 / respm2^(3/2);481exkurt = pm4 / respm2^(2) - 3; z = qnorm(alpha);482h = z + (1/6)*(z^2 -1)*skew483h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;484return (- (t(w)%*%mu) - h*sqrt( pm2 ) ) }485486GESfun = function(w,alpha,mu,sigma,M3,M4){487return (- (t(w)%*%mu) + dnorm(qnorm(alpha))*sqrt(t(w)%*%sigma%*%w)/alpha ) }488489operMESfun = function(w,alpha,mu,sigma,M3,M4){490pm4 = t(w)%*%M4%*%(w%x%w%x%w) ; pm3 = t(w)%*%M3%*%(w%x%w) ; pm2 = t(w)%*%sigma%*%w ;491skew = pm3 / pm2^(3/2);492exkurt = pm4 / pm2^(2) - 3; z = qnorm(alpha);493h = z + (1/6)*(z^2 -1)*skew494h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;495E = dnorm(h)496E = E + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt497E = E + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;498E = E + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)499E = E/alpha500return (- (t(w)%*%mu) - sqrt(pm2)*min(-E,h) ) }501502503Portmean = function(w,mu,precision=4)504{505return( 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) )506}507508Portsd = function(w,sigma,precision=4)509{510pm2 = m2(w,sigma)511dpm2 = derm2(w,sigma)512dersd = (0.5*as.vector(dpm2))/sqrt(pm2);513contrib = dersd*as.vector(w)514return(list( round( sqrt(pm2) , precision ) , round( contrib , precision ) , round ( contrib/sqrt(pm2) , precision) ))515}516517518PortgausVaR = function(alpha,w,mu,sigma,precision=4){519location = t(w)%*%mu520pm2 = m2(w,sigma)521dpm2 = derm2(w,sigma)522VaR = - location - qnorm(alpha)*sqrt(pm2)523derVaR = - as.vector(mu)- qnorm(alpha)*(0.5*as.vector(dpm2))/sqrt(pm2);524contrib = derVaR*as.vector(w)525return(list( round( VaR , precision ) , round ( contrib , precision ) , round( contrib/VaR , precision) ))526}527528PortgausES = function(alpha,w,mu,sigma,precision=4){529location = t(w)%*%mu530pm2 = m2(w,sigma)531dpm2 = derm2(w,sigma)532ES = - location + dnorm(qnorm(alpha))*sqrt(pm2)/alpha533derES = - as.vector(mu) + (1/alpha)*dnorm(qnorm(alpha))*(0.5*as.vector(dpm2))/sqrt(pm2);534contrib = as.vector(w)*derES;535return(list( round( ES , precision ) , round( contrib , precision) , round( contrib/ES , precision) ))536}537538PortSkew = function(w,sigma,M3)539{540pm2 = m2(w,sigma)541pm3 = m3(w,M3)542skew = pm3 / pm2^(3/2);543return( skew )544}545546PortKurt = function(w,sigma,M4)547{548pm2 = m2(w,sigma)549pm4 = m4(w,M4)550kurt = pm4 / pm2^(2) ;551return( kurt )552}553554PortMVaR = function(alpha,w,mu,sigma,M3,M4,precision=4)555{556z = qnorm(alpha)557location = t(w)%*%mu558pm2 = m2(w,sigma)559dpm2 = as.vector( derm2(w,sigma) )560pm3 = m3(w,M3)561dpm3 = as.vector( derm3(w,M3) )562pm4 = m4(w,M4)563dpm4 = as.vector( derm4(w,M4) )564565skew = pm3 / pm2^(3/2);566exkurt = pm4 / pm2^(2) - 3;567568derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)569derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)570571h = z + (1/6)*(z^2 -1)*skew572h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;573574MVaR = - location - h*sqrt(pm2)575576derGausVaR = - as.vector(mu)- qnorm(alpha)*(0.5*as.vector(dpm2))/sqrt(pm2);577derMVaR = 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 )578derMVaR = 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 )579contrib = as.vector(w)*as.vector(derMVaR)580return(list( round( MVaR , precision) , round( contrib , precision ), round (contrib/MVaR , precision ) ) )581}582583derIpower = function(power,h)584{585586fullprod = 1;587588if( (power%%2)==0 ) #even number: number mod is zero589{590pstar = power/2;591for(j in c(1:pstar))592{593fullprod = fullprod*(2*j)594}595I = -fullprod*h*dnorm(h);596597for(i in c(1:pstar) )598{599prod = 1;600for(j in c(1:i) )601{602prod = prod*(2*j)603}604I = I + (fullprod/prod)*(h^(2*i-1))*(2*i-h^2)*dnorm(h)605}606}else{607pstar = (power-1)/2608for(j in c(0:pstar) )609{610fullprod = fullprod*( (2*j)+1 )611}612I = -fullprod*dnorm(h);613614for(i in c(0:pstar) )615{616prod = 1;617for(j in c(0:i) )618{619prod = prod*( (2*j) + 1 )620}621I = I + (fullprod/prod)*(h^(2*i)*(2*i+1-h^2) )*dnorm(h)622}623}624return(I)625}626627628PortMES = function(alpha,w,mu,sigma,M3,M4,precision=4)629{630z = qnorm(alpha)631location = t(w)%*%mu632pm2 = m2(w,sigma)633dpm2 = as.vector( derm2(w,sigma) )634pm3 = m3(w,M3)635dpm3 = as.vector( derm3(w,M3) )636pm4 = m4(w,M4)637dpm4 = as.vector( derm4(w,M4) )638639skew = pm3 / pm2^(3/2);640exkurt = pm4 / pm2^(2) - 3;641642derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)643derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)644645h = z + (1/6)*(z^2 -1)*skew646h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;647648derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew649650E = dnorm(h)651E = E + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt652E = E + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;653E = E + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)654E = E/alpha655MES = - location + sqrt(pm2)*E656657derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E658derE = (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*derexkurt659derE = derE + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*derskew660derE = derE + (1/36)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*skew*derskew661X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt662X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew663X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2664derE = derE+derh*X # X is a scalar665derE = derE/alpha666derMES = derMES + sqrt(pm2)*derE667contrib = as.vector(w)*as.vector(derMES)668return(list( round( MES , precision ) , round( contrib , precision ), round( contrib/MES, precision )) )669}670671672operPortMES = function(alpha,w,mu,sigma,M3,M4,precision=4)673{674z = qnorm(alpha)675location = t(w)%*%mu676pm2 = m2(w,sigma)677dpm2 = as.vector( derm2(w,sigma) )678pm3 = m3(w,M3)679dpm3 = as.vector( derm3(w,M3) )680pm4 = m4(w,M4)681dpm4 = as.vector( derm4(w,M4) )682683skew = pm3 / pm2^(3/2);684exkurt = pm4 / pm2^(2) - 3;685686derskew = ( 2*(pm2^(3/2))*dpm3 - 3*pm3*sqrt(pm2)*dpm2 )/(2*pm2^3)687derexkurt = ( (pm2)*dpm4 - 2*pm4*dpm2 )/(pm2^3)688689h = z + (1/6)*(z^2 -1)*skew690h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2;691I1 = Ipower(1,h); I2 = Ipower(2,h); I3 = Ipower(3,h); I4 = Ipower(4,h); I6 = Ipower(6,h);692693derh = (1/6)*(z^2 -1)*derskew + (1/24)*(z^3 - 3*z)*derexkurt - (1/18)*(2*z^3 - 5*z)*skew*derskew694695E = dnorm(h)696E = E + (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*exkurt697E = E + (1/6)*( I3 - 3*I1 )*skew;698E = E + (1/72)*( I6 -15*I4+ 45*I2 - 15*dnorm(h) )*(skew^2)699E = E/alpha700701MES = - location - sqrt(pm2)*min(-E,h)702703if(-E<=h){704derMES = -mu + 0.5*(dpm2/sqrt(pm2))*E705derE = (1/24)*( I4 - 6*I2 + 3*dnorm(h) )*derexkurt706derE = derE + (1/6)*( I3 - 3*I1 )*derskew707derE = derE + (1/36)*( I6 -15*I4 + 45*I2 - 15*dnorm(h) )*skew*derskew708X = -h*dnorm(h) + (1/24)*( derIpower(4,h) - 6*derIpower(2,h) -3*h*dnorm(h) )*exkurt709X = X + (1/6)*( derIpower(3,h) - 3*derIpower(1,h) )*skew710X = X + (1/72)*( derIpower(6,h) - 15*derIpower(4,h) + 45*derIpower(2,h) + 15*h*dnorm(h) )*skew^2711derE = derE+derh*X # X is a scalar712derE = derE/alpha713derMES = derMES + sqrt(pm2)*derE }else{714derMES = -mu - 0.5*(dpm2/sqrt(pm2))*h - sqrt(pm2)*derh ; }715contrib = as.vector(w)*as.vector(derMES)716return(list( round( MES, precision) , round( contrib , precision ) , round(contrib/MES,precision) ) )717}718719720centeredmoment = function(series,power)721{722location = mean(series);723out = sum( (series-location)^power )/length(series);724return(out);725}726727operMES = function(series,alpha,r)728{729z = qnorm(alpha)730location = mean(series);731m2 = centeredmoment(series,2)732m3 = centeredmoment(series,3)733m4 = centeredmoment(series,4)734skew = m3 / m2^(3/2);735exkurt = m4 / m2^(2) - 3;736737h = z + (1/6)*(z^2 -1)*skew738if(r==2){ h = h + (1/24)*(z^3 - 3*z)*exkurt - (1/36)*(2*z^3 - 5*z)*skew^2};739740MES = dnorm(h)741MES = MES + (1/24)*( Ipower(4,h) - 6*Ipower(2,h) + 3*dnorm(h) )*exkurt742MES = MES + (1/6)*( Ipower(3,h) - 3*Ipower(1,h) )*skew;743MES = MES + (1/72)*( Ipower(6,h) -15*Ipower(4,h)+ 45*Ipower(2,h) - 15*dnorm(h) )*(skew^2)744MES = - location - (sqrt(m2))*min( -MES/alpha , h )745return(MES)746}747748TwoVarPlot <- function(xvar, y1var, y2var, labels, noincs = 5,marks=c(1,2), legpos, leglabs, title)749{750# https://stat.ethz.ch/pipermail/r-help/2000-September/008182.html751752# plots an x y1 y2 using left and right axes for the different y's753# rescales y2 to fit in the same space as y1754755# noincs - no of divisions in the axis labels756# marks - type of marker for each y757# legpos - legend position758# leglabs - legend labels759760# rescale to fit on same axis761scaledy2var <- (y2var - min(y2var)) / (max(y2var) - min(y2var))762scaledy2var <- (scaledy2var * (max(y1var) - min(y1var))) + min(y1var)763764# plot it up and add the points765plot(xvar, y1var, xlab=labels[1], ylab="", axes=F, pch=marks[1],main=title,type="l")766lines(xvar, scaledy2var, lty=3 )767768# make up some labels and positions769y1labs <- round(seq(min(y1var), max(y1var), length=noincs),2)770771# convert these to the y2 axis scaling772y2labs <- (y1labs - min(y1var)) / (max(y1var) - min(y1var))773y2labs <- (y2labs * (max(y2var) - min(y2var))) + min(y2var)774y2labs <- round(y2labs, 2)775776axis(1)777axis(2, at=y1labs, labels=y1labs)778axis(4, at=y1labs, labels=y2labs)779mtext(labels[3], side=4, line=2)780mtext(labels[2], side=2, line=2)781box()782783legend( legend=leglabs, lty = c(1,3), bty="o", x=legpos)784}785786787788789