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):
- Estimate a VAR(p) model
- Calculate the connectedness measures
- 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:
= ConnectednessApproach(dy2012,
dca 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.
= ConnectednessApproach(dy2012,
dca 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
= VAR(dy2012, configuration=list(nlag=4))
fit # 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 |
= TimeConnectedness(fit$B, fit$Q, nfore=10)
dca 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:
= colnames(dy2012)
NAMES = 4
nlag = ncol(dy2012)
k = vars::VAR(dy2012, p=nlag)
fit = t(matrix(unlist(coefficients(fit)), ncol=4))[,1:(k*nlag)]
B = summary(fit)$covres
Q 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 |
= TimeConnectedness(B, Q, nfore=10)
dca 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:
= MTS::VAR(as.matrix(dy2012), p=4, output=FALSE)
fit = fit$Phi
B = fit$Sigma
Q 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 |
= fit$coef/fit$secoef # can be compared with those of vars
tval = TimeConnectedness(B, Q, nfore=10)
dca 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:
= MTS::VAR(as.matrix(dy2012), p=4, output=FALSE)
fit = 0.10 # should be at least significant on the 10% level
pval = MTS::refVAR(fit, thres=qnorm(1-pval/2)) fit
## 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
= fit$Phi
B = fit$Sigma
Q colnames(Q) = rownames(Q) = NAMES
= TimeConnectedness(B, Q, nfore=10)
dca 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.
= ConnectednessApproach(dy2012,
dca 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.