Nothing
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General
# Public License along with this library; if not, write to the
# Free Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
################################################################################
# FUNCTION: DESCRIPTION:
# .tailDependenceCoeffs Returns Lower and Upper Tail Dependence Coeffs
# FUNCTION: MIXED GUMBEL-SURVIVALGUMBEL-NORMAL COPULA:
# .rgsgnormCopula Generates G-SG-NORM copula random variates
# .dgsgnormCopula Computes G-SG-NORM copula density
# FUNCTION: MIXED G-SG-NORM COPULA FIT:
# .gsgnormCopulaFit Estimates the parameters of the G-SG-NORM copula
# FUNCTION: NON-PARAMETRIC TAIL DEPENDECY ESTIMATOR:
# .cfgTDE Estimates non-parametrically tail dependence
# FUNCTION: COPULA FIT WITH NORM, NIG OR GHT MARGINALS:
# .empiricalDependencyFit Estimates tail dependence with empirical marginals
# .normDependencyFit Estimates tail dependence with normal marginals
# .gldDependencyFit Estimates tail dependence with GLD marginals
# .ghtDependencyFit Estimates tail dependence with GHT marginals
################################################################################
.tailDependenceCoeffs <-
function(x, method = c("nig", "norm", "ght"),
trace = FALSE, doplot = TRUE)
{
# A function implemented by Diethelm Wuertz
# Description:
# Returns a list with lower and upper bivariate tail depenence matrixes
# Example:
# x <- 100 * LPP2005.RET[, 1:6]; .tailDependenceCoeffs(x)
# Notes:
# Tested only for NIG marginal distributions.
# FUNCTION:
# Check Settings:
method <- match.arg(method)
# Compute Coeffs with desired Marginals:
fun <- paste(".", method, "DependencyFit", sep = "")
funFit <- match.fun(fun)
coeffs <- funFit(x, doplot = doplot, trace = trace)
# Return Value:
coeffs
}
################################################################################
.rgsgnormCopula <-
function(n = 1000, alpha = c(2, 2), rho = 0, weights = c(1/3, 1/3))
{
# A function implemented by Diethelm Wuertz
# Description:
# Computes RVs from a mixed Gumbel-SurvivalGumbel-Normal Copula
# Arguments:
# n - an integer value, the number of random variates to be
# generated.
# alpha - a numeric vector with two entries. The first denotes
# the parameter value of alpha for the Gumbel copula, and
# the second for the Survival Gumbel Copula.
# rho - a numeric value denoting the correlation parameter for
# the normal copula.
# weights - a numeric vector with two entries. The first denotes
# the weight of the Gumbel copula, and the second the weight
# of the Survival Gumbel Copula. The weight for the normal
# copula is evaluated by 1 - sum(weights).
# Example:
# .rgsgnormCopula(20)
# FUNCTION:
# Checking:
stopifnot(any(weights >= 0))
stopifnot(sum(weights) <= 1)
# Upper Gumbel = 1 , Lower Gumbel = 2, t = 3:
weights <- c(weights, 1-sum(weights))
N <- round(n*weights[1:2])
N <- c(N, n-sum(N))
# Random Variates:
r <- rbind(
if (N[1] > 0) fCopulae::rgumbelCopula(N[1], alpha[1]),
if (N[2] > 0) 1-fCopulae::rgumbelCopula(N[2], alpha[2]),
if (N[3] > 0) fCopulae::rellipticalCopula(N[3], rho, type = "norm") )
index <- sample(1:n)
ans <- r[index, ]
N <- c(n, N)
names(N) <- c("n", "n1", "n2", "n3")
attr(ans, "control") < -N
# Return Value:
ans
}
# ------------------------------------------------------------------------------
.dgsgnormCopula <-
function(u = 0.5, v = u, alpha = c(2, 2), rho = 0, weights = c(1/3, 1/3),
output = c("vector", "list"))
{
# A function implemented by Diethelm Wuertz
# Description:
# Computes mixed Gumbel-SurvivalGumbel-Normal Copula density
# Example:
# .perspPlot(.dgsgnormCopula(u=grid2d()$x, v=grid2d()$y, output = "list"))
# FUNCTION:
# Settings:
if (is.list(u)) {
v = u[[2]]
u = u[[1]]
}
if (is.matrix(u)) {
v = u[, 1]
u = u[, 2]
}
# Match Arguments:
output = match.arg(output)
# Mixed Copula:
weights <- c(weights, 1-sum(weights))
dCopula1 <- fCopulae::dgumbelCopula(u, v, alpha[1])
dCopula2 <- fCopulae::dgumbelCopula(1-u, 1-v, alpha[2])
dCopula3 <- fCopulae::dellipticalCopula(u, v, rho, type = "norm")
c.uv <- weights[1]*dCopula1 + weights[2]*dCopula2 + weights[3]*dCopula3
attr(c.uv, "control") <- c(alpha = alpha, rho = rho, weights = weights)
if (output == "list") {
N = sqrt(length(u))
x = u[1:N]
y = matrix(v, ncol = N)[1, ]
c.uv = list(x = x, y = y, z = matrix(c.uv, ncol = N))
}
# Return Value:
c.uv
}
# ------------------------------------------------------------------------------
.gsgnormCopulaFit <-
function(u, v = NULL, trace = FALSE)
{
# A function implemented by Diethelm Wuertz
# Description:
# Fits parameters for a mixed GSG copula
# FUNCTION:
# Settings:
U <- u
V <- v
if (is.list(u)) {
U = u[[1]]
V = u[[2]]
}
if (is.matrix(u)) {
U = u[, 1]
V = u[, 2]
}
# From weights to gamma ...
# G-SG-NORM: W1*Gumbel + W2*SurvivalGumbul + W3*NORM
# with W3 = 1-W2-W3
# Transformation: Use Weights W1 and W3
# gamma = c(gamma1, gamma2)
# 0 < gamma1 = W1/(1-W3) < 1
# 0 < gamma2 = 1-W3 < 1
# W3 = 1-gamma2
# W1 = gamma1*gamma2
# W2 = gamma2*(1-gamma1)
# Note, this transformation has the advantage, that gamma1
# and gamma2 are independent from each other.
# Estimate Copula:
start = c(alpha1 = 1.5, alpha2 = 1.5, rho = 0, gamma1 = 1/2, gamma2 = 1/2)
fun = function(x, U, V, trace)
{
alpha = x[1:2]
rho = x[3]
gamma = x[4:5]
weights = c(
weights1 = gamma[[1]]*gamma[[2]],
weights2 = gamma[[2]]*(1-gamma[[1]]))
density = .dgsgnormCopula(u = U, v = V, alpha, rho, weights = weights)
density = density[!is.na(density)]
f = -mean( log(density) )
if (trace) {
params = round(c(x[1:3],
weights[1], weights[2], 1-weights[1]-weights[2]), 4)
names(params) = c("alpha1", "alpha2", "rho",
"gumbel", "survival", "norm")
cat("\n Objective Function Value: ", -f)
cat("\n Parameter Estimates: ", params, "\n")
}
f
}
# Fit:
fit = nlminb(
start = start, objective = fun,
lower = c( 1, 1, -0.999, 0, 0),
upper = c(Inf, Inf, 0.999, 1, 1), U = U, V = V, trace = trace)
# Fitted Parameters:
param = fit$par
# Named Parameters:
alpha1 = param[1]
alpha2 = param[2]
rho = param[3]
gamma1 = param[4]
gamma2 = param[5]
# Weights:
weights3 = 1-gamma2
weights1 = gamma1*gamma2
weights2 = gamma2*(1-gamma1)
# Tail Coefficients
upperLambda = (weights1*(2 - 2^(1/alpha1)))[[1]]
lowerLambda = (weights2*(2 - 2^(1/alpha2)))[[1]]
params = c(param[1:3], param[5]*param[4], param[5]*(1-param[4]), 1-param[5])
names(params) = c("alpha1", "alpha2", "rho", "gumbel", "survival", "norm")
Lambda = c(lower = lowerLambda, upper = upperLambda)
# Return Value:
list(param = params, lambda = Lambda, fitted = fit$par)
}
################################################################################
.cfgTDE <-
function(x, y)
{
# A function implemented by Diethelm Wuertz
# Description:
# Estimates non-parametrically tail dependency coefficient
# FUNCTION:
# Upper Tail:
lambda = NULL
n = length(x)
for(i in 1:n){
lambda = c(lambda,
log(sqrt(log(1/x[i])*log(1/y[i]))/log(1/max(x[i],y[i])^2)))
}
upper <- 2 - 2*exp(sum(lambda/n))
# Lower Tail:
x = 1-x
y = 1-y
lambda = NULL
n = length(x)
for(i in 1:n){
lambda = c(lambda,
log(sqrt(log(1/x[i])*log(1/y[i]))/log(1/max(x[i],y[i])^2)))
}
lower <- 2 - 2*exp(sum(lambda/n))
# Return Value:
c(lower = lower, upper = upper)
}
################################################################################
.empiricalDependencyFit <-
function(x, doplot = TRUE, trace = FALSE)
{
# A function implemented by Diethelm Wuertz
# Description:
# Estimates tail dependency coefficients with Normal marginals
# Arguments:
# x - a multivariate 'timeSeries' object
# FUNCTION:
# Settings:
N = ncol(x)
lowerLambda = upperLambda = 0*diag(N)
assetsNames = colnames(x)
P = NULL
for (i in 1:(N-1)) {
# First asset:
r1 = as.vector(x[, i])
fit1 = nFit(r1)
estim1 = fit1@fit$estimate
p1 = pnorm(r1, estim1[1], estim1[2])
Main1 = assetsNames[i]
P = cbind(P, p1)
for (j in (i+1):N)
{
# Second asset:
r2 = as.vector(x[, j])
fit2 = nFit(r2)
estim2 = fit2@fit$estimate
p2 = pnorm(r2, estim2[1], estim2[2])
Main2 = assetsNames[j]
# Optional Plot:
if (doplot)
{
# Plot Distribution:
MainR = paste("Distribution:", Main1, "-", Main2)
plot(r1, r2, pch = 19, main = MainR)
grid()
# Plot Copula:
MainP = paste("Copula:", Main1, "-", Main2)
plot(p1, p2, pch = 19, main = MainP)
grid()
}
# Fit GSG copula parameters:
fit = .gsgnormCopulaFit(u = p1, v = p2, trace = trace)
if (trace)
cat(assetsNames[c(i,j)], round(fit$lambda, 3), "\n")
# Compose lambda Matrix:
lowerLambda[i, j] = lowerLambda[j, i] = fit$lambda[1]
upperLambda[i, j] = upperLambda[j, i] = fit$lambda[2]
}
}
# Result:
colnames(lowerLambda) = rownames(lowerLambda) = assetsNames
colnames(upperLambda) = rownames(upperLambda) = assetsNames
ans = list(lower = lowerLambda, upper = upperLambda)
# Return Value:
ans
}
# ------------------------------------------------------------------------------
.normDependencyFit <-
function(x, doplot = TRUE, trace = FALSE)
{
# A function implemented by Diethelm Wuertz
# Description:
# Estimates tail dependency coefficients with Normal marginals
# Arguments:
# x - a multivariate 'timeSeries' object
# FUNCTION:
# Settings:
N = ncol(x)
lowerLambda = upperLambda = 0*diag(N)
assetsNames = colnames(x)
P = NULL
for (i in 1:(N-1)) {
# First asset:
r1 = as.vector(x[, i])
fit1 = nFit(r1)
estim1 = fit1@fit$estimate
p1 = pnorm(r1, estim1[1], estim1[2])
Main1 = assetsNames[i]
P = cbind(P, p1)
for (j in (i+1):N)
{
# Second asset:
r2 = as.vector(x[, j])
fit2 = nFit(r2)
estim2 = fit2@fit$estimate
p2 = pnorm(r2, estim2[1], estim2[2])
Main2 = assetsNames[j]
# Optional Plot:
if (doplot)
{
# Plot Distribution:
MainR = paste("Distribution:", Main1, "-", Main2)
plot(r1, r2, pch = 19, main = MainR)
grid()
# Plot Copula:
MainP = paste("Copula:", Main1, "-", Main2)
plot(p1, p2, pch = 19, main = MainP)
grid()
}
# Fit GSG copula parameters:
fit = .gsgnormCopulaFit(u = p1, v = p2, trace = trace)
if (trace)
cat(assetsNames[c(i,j)], round(fit$lambda, 3), "\n")
# Compose lambda Matrix:
lowerLambda[i, j] = lowerLambda[j, i] = fit$lambda[1]
upperLambda[i, j] = upperLambda[j, i] = fit$lambda[2]
}
}
# Result:
colnames(lowerLambda) = rownames(lowerLambda) = assetsNames
colnames(upperLambda) = rownames(upperLambda) = assetsNames
ans = list(lower = lowerLambda, upper = upperLambda)
# Return Value:
ans
}
# ------------------------------------------------------------------------------
.gldDependencyFit <-
function(x, doplot = TRUE, trace = FALSE)
{
# A function implemented by Diethelm Wuertz
# Description:
# Estimates tail dependency coefficients with NIG marginals
# Arguments:
# x - a multivariate 'timeSeries' object
# FUNCTION:
# Settings:
N <- ncol(x)
lowerLambda <- upperLambda <- 0*diag(N)
assetsNames <- colnames(x)
P <- NULL
for (i in 1:(N-1)) {
# First asset:
r1 <- as.vector(x[, i])
fit1 <- gldFit(r1, doplot = FALSE, trace = trace)
estim1 <- fit1@fit$estimate
p1 <- pgld(r1, estim1[1], estim1[2], estim1[3], estim1[4])
Main1 <- assetsNames[i]
P <- cbind(P, p1)
for (j in (i+1):N) {
# Second asset:
r2 <- as.vector(x[, j])
fit2 <- gldFit(r2, doplot = FALSE, trace = trace)
estim2 = fit2@fit$estimate
p2 <- pgld(r2, estim2[1], estim2[2], estim2[3], estim2[4])
Main2 <- assetsNames[j]
# Optional Plot:
if (doplot) {
## MainR = paste("Distribution:", Main1, "-", Main2)
## plot(r1, r2, pch = 19, main = MainR)
## grid()
MainP <- paste("Copula:", Main1, "-", Main2)
plot(p1, p2, pch = 19, main = MainP, xlab = "", ylab = "", cex=0.5)
grid()
}
# Fit GSG copula parameters:
fit <- .gsgnormCopulaFit(u = p1, v = p2, trace = trace)
if (trace) cat(assetsNames[c(i,j)], round(fit$lambda, 3), "\n")
# Compose lambda Matrix:
lowerLambda[i, j] <- lowerLambda[j, i] <- fit$lambda[1]
upperLambda[i, j] <- upperLambda[j, i] <- fit$lambda[2]
}
}
# Result:
colnames(lowerLambda) <- rownames(lowerLambda) <- assetsNames
colnames(upperLambda) <- rownames(upperLambda) <- assetsNames
ans = list(lower = lowerLambda, upper = upperLambda)
# Return Value:
ans
}
# ------------------------------------------------------------------------------
.ghtDependencyFit <-
function(x, doplot = TRUE, trace = FALSE)
{
# A function implemented by Diethelm Wuertz
# Description:
# Estimates tail dependency coefficients with GH Student-t marginals
# Arguments:
# x - a multivariate 'timeSeries' object
# FUNCTION:
# Settings:
N = ncol(x)
lowerLambda = upperLambda = 0*diag(N)
assetsNames = colnames(x)
P = NULL
for (i in 1:(N-1)) {
# First asset:
r1 = as.vector(x[, i])
fit1 = ghtFit(r1, doplot = FALSE, trace = trace)
estim1 = fit1@fit$estimate
p1 = pght(r1, estim1[1], estim1[2], estim1[3], estim1[4])
Main1 = assetsNames[i]
P = cbind(P, p1)
for (j in (i+1):N) {
# Second asset:
r2 = as.vector(x[, j])
fit2 = ghtFit(r2, doplot = FALSE, trace = trace)
estim2 = fit2@fit$estimate
p2 = pght(r2, estim2[1], estim2[2], estim2[3], estim2[4])
Main2 = assetsNames[j]
# Optional Plot:
if (doplot) {
MainR = paste("Distribution:", Main1, "-", Main2)
plot(r1, r2, pch = 19, main = MainR)
grid()
MainP = paste("Copula:", Main1, "-", Main2)
plot(p1, p2, pch = 19, main = MainP)
grid()
}
# Fit GSG copula parameters:
fit = .gsgnormCopulaFit(u = p1, v = p2, trace = trace)
if (trace)
cat(assetsNames[c(i,j)], round(fit$lambda, 3), "\n")
# Compose lambda Matrix:
lowerLambda[i, j] = lowerLambda[j, i] = fit$lambda[1]
upperLambda[i, j] = upperLambda[j, i] = fit$lambda[2]
}
}
# Result:
colnames(lowerLambda) = rownames(lowerLambda) = assetsNames
colnames(upperLambda) = rownames(upperLambda) = assetsNames
ans = list(lower = lowerLambda, upper = upperLambda)
# Return Value:
ans
}
################################################################################
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.