Installation

As this package is so far only available on Github you need to install the devtools package first:

install.packages("devtools")

Secondly, load devtools and install the ConnectednessApproach package as follows:

library(devtools)
install_github("GabauerDavid/ConnectednessApproach")

General statement

As this package should make the connectedness approach and its extensions available to programmers, practitioners and researchers with or without solid programming skills, the description will focus solely explain the intuition of the methods and won’t be written in an academic style and thus avoid technical explanations of the underlying formulas (another section will be dedicated to this in the future).

Furthermore, I would like to emphasize that this package is created in such a way that beginners as well as professional R programmers can use it to replicate papers, run their own analyses and extend the models and methods easily.

I tried to create the package as modular as possible as the connectedness approach can be seen as a multivariate time series tool such as impulse response functions and forecast error variance decomposition, which solely depends on an already estimated multivariate time series model.

Following, the static analysis of Diebold and Yilmaz (2009, 2012):

  1. Estimate a VAR(p) model
  2. Calculate the connectedness measures
  3. Use connectedness extensions

Empirical analysis

Let’s first load the package and the necessary dataset:

data("dy2012")
kable(head(dy2012))
SP500 R_10Y DJUBSCOM USDX
-9.891998 -10.081905 -9.797694 -12.971578
-9.353294 -10.090498 -11.475212 -13.237477
-9.314619 -10.103319 -15.317140 -9.749465
-8.997370 -10.090498 -12.044040 -10.853610
-8.855955 -9.426092 -12.928477 -11.788281
-10.282395 -8.936206 -12.821930 -11.308455

The compressed one-liner

The easiest and most compressed way to replicate the static analysis of the Diebold and Yilmaz (2012) paper is to use the eponymous core function of the ConnectednessApproach package:

dca = ConnectednessApproach(dy2012,
                            nlag=4,
                            nfore=10)
## Estimating model
## Computing connectedness measures
## The (generalized) VAR connectedness approach is implemented according to:
##  Diebold, F. X., & Yilmaz, K. (2012). Better to give than to receive: Predictive directional measurement of volatility spillovers. International Journal of Forecasting, 28(1), 57-66.
kable(dca$TABLE)
SP500 R_10Y DJUBSCOM USDX FROM
SP500 88.76 7.29 0.35 3.61 11.24
R_10Y 10.21 81.45 2.73 5.61 18.55
DJUBSCOM 0.47 3.70 93.69 2.14 6.31
USDX 5.69 7.03 1.55 85.73 14.27
TO 16.37 18.01 4.62 11.36 50.37
Inc.Own 105.13 99.46 98.31 97.10 cTCI/TCI
NET 5.13 -0.54 -1.69 -2.90 16.79/12.59
NPT 3.00 2.00 0.00 1.00

The one-liner’s argument

Even though the replication of DY2012 is done using the above formula it is of everyone’s interest to know what has been done. Thus, I would recommend to read through the manual of the function. There you will see that dy2012 needs to be a zoo object, a specific model needs to be selected which is by default VAR, the corrected TCI value of Chatziantoniou and Gabauer (2021) is available, a window size needs to be selected (where NULL is the static analysis and any positive integer result in dynamic connectedness measures), different types of connectedness approaches are available - Time, and finally a list of parameters for the employed connectedness approach needs to be chosen.

dca = ConnectednessApproach(dy2012,
                            nlag=4,
                            nfore=10,
                            model="VAR",
                            corrected=FALSE,
                            window.size=NULL,
                            connectedness="Time",
                            Connectedness_config = list(
                              TimeConnectedness=list(generalized=TRUE)))
## Estimating model
## Computing connectedness measures
## The (generalized) VAR connectedness approach is implemented according to:
##  Diebold, F. X., & Yilmaz, K. (2012). Better to give than to receive: Predictive directional measurement of volatility spillovers. International Journal of Forecasting, 28(1), 57-66.
kable(dca$TABLE)
SP500 R_10Y DJUBSCOM USDX FROM
SP500 88.76 7.29 0.35 3.61 11.24
R_10Y 10.21 81.45 2.73 5.61 18.55
DJUBSCOM 0.47 3.70 93.69 2.14 6.31
USDX 5.69 7.03 1.55 85.73 14.27
TO 16.37 18.01 4.62 11.36 50.37
Inc.Own 105.13 99.46 98.31 97.10 cTCI/TCI
NET 5.13 -0.54 -1.69 -2.90 16.79/12.59
NPT 3.00 2.00 0.00 1.00

A bit more flexibility

Another option is - as described above - to estimate the VAR first and then calculate the connectedness measures

fit = VAR(dy2012, configuration=list(nlag=4))
# Error variance-covariance
kable(fit$Q)
SP500.2010-01-29 R_10Y.2010-01-29 DJUBSCOM.2010-01-29 USDX.2010-01-29
SP500 0.6897966 0.1974423 0.0749659 0.1244823
R_10Y 0.1974423 0.8822770 0.0663860 0.1888625
DJUBSCOM 0.0749659 0.0663860 1.4183829 0.0638352
USDX 0.1244823 0.1888625 0.0638352 0.7175651
dca = TimeConnectedness(fit$B, fit$Q, nfore=10)
kable(dca$TABLE)
SP500 R_10Y DJUBSCOM USDX FROM
SP500 88.76 7.29 0.35 3.61 11.24
R_10Y 10.21 81.45 2.73 5.61 18.55
DJUBSCOM 0.47 3.70 93.69 2.14 6.31
USDX 5.69 7.03 1.55 85.73 14.27
TO 16.37 18.01 4.62 11.36 50.37
Inc.Own 105.13 99.46 98.31 97.10 cTCI/TCI
NET 5.13 -0.54 -1.69 -2.90 16.79/12.59
NPT 3.00 2.00 0.00 1.00

Using third-party packages

For all those who would like to provide more detailed insights of the VAR model or extend the connectedness approach this section might be of interest - keep in mind that all my estimators come without confidence intervals of the parameters (mainly caused by the fact that this increases the computational burdensome drastically and also as the connectedness literature is not making use of those). Thus, if you are interested in the dynamics of the predefined network and also of the significance of the VAR parameters you might have to use other packages such as vars or MTS - obviously some transformations are necessary.

For example, we might want to compute the connectedness measures using the vars package:

NAMES = colnames(dy2012)
nlag = 4
k = ncol(dy2012)
fit = vars::VAR(dy2012, p=nlag)
B = t(matrix(unlist(coefficients(fit)), ncol=4))[,1:(k*nlag)]
Q = summary(fit)$covres
colnames(Q) = rownames(Q) = NAMES
kable(Q)
SP500 R_10Y DJUBSCOM USDX
SP500 0.6940608 0.1986628 0.0754293 0.1252519
R_10Y 0.1986628 0.8877311 0.0667964 0.1900300
DJUBSCOM 0.0754293 0.0667964 1.4271511 0.0642298
USDX 0.1252519 0.1900300 0.0642298 0.7220010
dca = TimeConnectedness(B, Q, nfore=10)
kable(dca$TABLE)
SP500 R_10Y DJUBSCOM USDX FROM
SP500 88.76 7.29 0.35 3.61 11.24
R_10Y 10.21 81.45 2.73 5.61 18.55
DJUBSCOM 0.47 3.70 93.69 2.14 6.31
USDX 5.69 7.03 1.55 85.73 14.27
TO 16.37 18.01 4.62 11.36 50.37
Inc.Own 105.13 99.46 98.31 97.10 cTCI/TCI
NET 5.13 -0.54 -1.69 -2.90 16.79/12.59
NPT 3.00 2.00 0.00 1.00

Or using the MTS package:

fit = MTS::VAR(as.matrix(dy2012), p=4, output=FALSE)
B = fit$Phi
Q = fit$Sigma
colnames(Q) = rownames(Q) = NAMES
# Error variance-covariance
kable(Q)
SP500 R_10Y DJUBSCOM USDX
SP500 0.6897966 0.1974423 0.0749659 0.1244823
R_10Y 0.1974423 0.8822770 0.0663860 0.1888625
DJUBSCOM 0.0749659 0.0663860 1.4183829 0.0638352
USDX 0.1244823 0.1888625 0.0638352 0.7175651
tval = fit$coef/fit$secoef # can be compared with those of vars
dca = TimeConnectedness(B, Q, nfore=10)
kable(dca$TABLE)
SP500 R_10Y DJUBSCOM USDX FROM
SP500 88.76 7.29 0.35 3.61 11.24
R_10Y 10.21 81.45 2.73 5.61 18.55
DJUBSCOM 0.47 3.70 93.69 2.14 6.31
USDX 5.69 7.03 1.55 85.73 14.27
TO 16.37 18.01 4.62 11.36 50.37
Inc.Own 105.13 99.46 98.31 97.10 cTCI/TCI
NET 5.13 -0.54 -1.69 -2.90 16.79/12.59
NPT 3.00 2.00 0.00 1.00

This option leaves quite a lot of space for new ways how to analyze your data. For instance, MTS has a function which sets coefficients to zero if they are not significant on a specific level. Let’s give this idea some room as some coefficients are not significant as we have seen in the vars summary:

fit = MTS::VAR(as.matrix(dy2012), p=4, output=FALSE)
pval = 0.10 # should be at least significant on the 10% level
fit = MTS::refVAR(fit, thres=qnorm(1-pval/2))
## Constant term: 
## Estimates:  -1.403504 -1.095043 -1.63876 -3.063451 
## Std.Error:  0.1994229 0.2369673 0.3349057 0.2716654 
## AR coefficient matrix 
## AR( 1 )-matrix 
##        [,1]   [,2]   [,3]   [,4]
## [1,] 0.1808 0.0000 0.0000 0.0000
## [2,] 0.0679 0.1654 0.0542 0.0000
## [3,] 0.0000 0.0982 0.1865 0.0000
## [4,] 0.0591 0.0000 0.0320 0.0679
## standard error 
##        [,1]   [,2]   [,3]   [,4]
## [1,] 0.0187 0.0000 0.0000 0.0000
## [2,] 0.0203 0.0193 0.0148 0.0000
## [3,] 0.0000 0.0223 0.0187 0.0000
## [4,] 0.0151 0.0000 0.0110 0.0192
## AR( 2 )-matrix 
##       [,1]  [,2]   [,3]  [,4]
## [1,] 0.274 0.000 0.0000 0.000
## [2,] 0.000 0.183 0.0261 0.000
## [3,] 0.000 0.000 0.2095 0.000
## [4,] 0.000 0.000 0.0000 0.209
## standard error 
##        [,1]   [,2]   [,3]   [,4]
## [1,] 0.0186 0.0000 0.0000 0.0000
## [2,] 0.0000 0.0188 0.0148 0.0000
## [3,] 0.0000 0.0000 0.0187 0.0000
## [4,] 0.0000 0.0000 0.0000 0.0185
## AR( 3 )-matrix 
##         [,1]   [,2]    [,3]  [,4]
## [1,]  0.2066 0.0282 -0.0232 0.000
## [2,]  0.0424 0.1303 -0.0434 0.000
## [3,] -0.0821 0.0000  0.1884 0.000
## [4,]  0.0000 0.0291  0.0000 0.183
## standard error 
##        [,1]   [,2]   [,3]   [,4]
## [1,] 0.0192 0.0160 0.0108 0.0000
## [2,] 0.0204 0.0194 0.0148 0.0000
## [3,] 0.0207 0.0000 0.0187 0.0000
## [4,] 0.0000 0.0163 0.0000 0.0191
## AR( 4 )-matrix 
##       [,1]   [,2]   [,3]   [,4]
## [1,] 0.164 0.0290 0.0000 0.0000
## [2,] 0.000 0.2076 0.0374 0.0000
## [3,] 0.000 0.0477 0.1562 0.0501
## [4,] 0.000 0.0431 0.0000 0.1166
## standard error 
##        [,1]   [,2]   [,3]   [,4]
## [1,] 0.0194 0.0161 0.0000 0.0000
## [2,] 0.0000 0.0186 0.0148 0.0000
## [3,] 0.0000 0.0229 0.0187 0.0254
## [4,] 0.0000 0.0164 0.0000 0.0193
##   
## Residuals cov-mtx: 
##            [,1]       [,2]       [,3]       [,4]
## [1,] 0.69087780 0.19759251 0.07567774 0.12458630
## [2,] 0.19759251 0.88372401 0.06709083 0.18961072
## [3,] 0.07567774 0.06709083 1.42360917 0.06366757
## [4,] 0.12458630 0.18961072 0.06366757 0.71973326
##   
## det(SSE) =  0.5388654 
## AIC =  -0.5944713 
## BIC =  -0.5238867 
## HQ  =  -0.5689794
B = fit$Phi
Q = fit$Sigma
colnames(Q) = rownames(Q) = NAMES
dca = TimeConnectedness(B, Q, nfore=10)
kable(dca$TABLE)
SP500 R_10Y DJUBSCOM USDX FROM
SP500 88.79 7.84 0.38 2.99 11.21
R_10Y 9.99 81.90 2.91 5.20 18.10
DJUBSCOM 0.66 3.55 94.58 1.21 5.42
USDX 5.29 7.89 1.28 85.54 14.46
TO 15.94 19.29 4.56 9.41 49.19
Inc.Own 104.73 101.19 99.14 94.94 cTCI/TCI
NET 4.73 1.19 -0.86 -5.06 16.40/12.30
NPT 3.00 2.00 1.00 0.00

The same can be done with the popular bvarsv package which includes a TVP-VAR model (Del Negro and Primiceri, 2015). (Will be included in a later version - takes a long time to estimate).

Dynamic Connectedness Measures

Finally, we are coming to the part most of you are waiting for. As more experienced programmers will know that the a for loop will do the trick, I will directly come to the easier way how to get the dynamic connectedness plot. You have to set a rolling-window size.

dca = ConnectednessApproach(dy2012,
                            nlag=4,
                            nfore=10,
                            window.size=200)
## Estimating model
## Computing connectedness measures
## The (generalized) VAR connectedness approach is implemented according to:
##  Diebold, F. X., & Yilmaz, K. (2012). Better to give than to receive: Predictive directional measurement of volatility spillovers. International Journal of Forecasting, 28(1), 57-66.
kable(dca$TABLE)
SP500 R_10Y DJUBSCOM USDX FROM
SP500 83.03 7.41 4.05 5.51 16.97
R_10Y 9.05 80.55 4.00 6.40 19.45
DJUBSCOM 4.42 3.92 87.79 3.86 12.21
USDX 6.62 7.56 3.28 82.54 17.46
TO 20.09 18.89 11.33 15.77 66.08
Inc.Own 103.12 99.44 99.12 98.31 cTCI/TCI
NET 3.12 -0.56 -0.88 -1.69 22.03/16.52
NPT 3.00 1.00 1.00 1.00

Now some might say that something is wrong here as the connectedness table is now different to the previous ones and most importantly to the one in the paper… and yeah you are right but for me this table summarizes the dynamics ‘better’ than the other one.

Why?

Short answer: Sometimes the static connectedness table is telling us a different story than the dynamic connectedness plots and this is from my perspective not optimal. Also intuitively it is slightly contradictory as either you assume that the network dynamics are constant or time-varying. If you already observe that some time-variation is going on why are you explaining the result of a model that neglects those time-variations. So you need to ask yourself why you explain a static connectedness table and later on the dynamic connectedness measures which might deliver a contradicting story. I also want to point out that I am not critizising Diebold or Yilmaz. This is research. You come up with an idea - a briliant one in this case - and sometimes there are certain flaws. Research is only about overcoming those flaws so there will never ever be the one single model that is perfect from the very beginning. Also computational or conceptual mistakes as those in Primiceri (2005) are not problematic from my perspective as after all he introduced as to a new era of TVP-VAR models. And honestly mistakes are happening to everyone of us including me. But enough of my research philosophy.

Let’s focus again on how we get the dynamic connectedness plots. You can either plot the variables that are stored in dca yourself or use some plot functions. So let’s plot the original connectedness plots first:

The total connectedness index (\(TCI\)) illustrates the average impact a shock in one series has on all others.

PlotTCI(dca, ylim=c(0,40))

On the one side, the total directional connectedness TO others, \(TO_i\), represents the impact series i has on all other series

PlotTO(dca, ylim=c(0,60))

while the total directional connectedness FROM, \(FROM_i\), others demonstrates the impact all series have on series i.

PlotFROM(dca, ylim=c(0,60))

Interestingly, the average of all TO or all FROM values is equal to the TCI.

The difference between the total directional connectedness TO and FROM others results in the net total directional connectedness, \(NET_i\), which illustrates the net influence on the predefined network. If \(NET_i>0\) (\(NET_i<0\)), we know that the impact series \(i\) has on all others is larger (smaller) than the impact all others have on series \(i\). Thus, series \(i\) is considered as a net transmitter (receiver) of shocks and hence driving (driven by) the network.

PlotNET(dca, ylim=c(-30,30))

On the bilateral level, the net pairwise directional connectedness measure, \(NPSO_{ij}\), is of major interest. If \(NPSO_{ij}>0\) (\(NPSO_{ij}<0\)) it means that series \(i\) has a larger (smaller) impact on series \(j\) than series \(j\) has on series \(i\).

PlotNPDC(dca, ylim=c(-20,20))

What other connectedness plots are available:

Furthermore, the pairwise connectedness index (\(PCI\)) illustrates the TCI on a bilateral level. Thus, the \(PCI\) is equal to the \(TCI\) if a network with only two series is considered. As the calculation of the TCI between two series might lead to bias results - as only two series are considered even though more might have an impact on each series - computing the PCI based upon a large network is not only more efficient than calculating the TCI of multiple small networks, it also leads to a more accurate result caused by the unbiased coefficient estimates of the VAR model.

PlotPCI(dca)
## The pairwise connectedness index is implemented according to:
##  Gabauer, D. (2021). Dynamic measures of asymmetric & pairwise connectedness within an optimal currency area: Evidence from the ERM I system. Journal of Multinational Financial Management, 60, 100680.

Another interesting plot is the net pairwise transmission plot which illustrates how many series series \(i\) dominates. If the network consists of \(k\) series, one series can at maximum dominate \(k-1\) series. This plot summarizes the net transmission mechanism of each series.

PlotNPT(dca)

The package also includes the net influence index which is identical to the net pairwise directional connectedness plots, however, highlights the changes in percentage and not in levels.

PlotINF(dca, ylim=c(0,100))
## The influence connectedness index is implemented according to:
##  Gabauer, D. (2021). Dynamic measures of asymmetric & pairwise connectedness within an optimal currency area: Evidence from the ERM I system. Journal of Multinational Financial Management, 60, 100680.

Finally, network plots which represents the NPDC and PCI are provided as well:

PlotNetwork(dca, method="NPDC")

PlotNetwork(dca, method="PCI")

Is this all the package can do?

No! There is even more this package can be used for. This package does not only allow to estimate the standard VAR, it also estimates quantile, LASSO, Ridge, ElasticNet and time-varying parameter VAR models. In addition to the Diebold and Yilmaz (2009,2012) orthorgonalized and generalized connectedness approaches, the frequency connectedness, joint connectedness and extended joint connectedness approaches can be utilized. Besides the pairwise connectedness, net influence, and net pairwise transmission plot, it is also possible to calculate decomposed - external and internal connectedness – and partial connectedness measures – exclusive and inclusive – as well as conditional and aggregated connectedness measures. Those topics will be discussed in upcoming chapters.