Skip to content

merwanroudane/tca

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TCA — Transmission Channel Analysis in Python

TCA is a Python library for Transmission Channel Analysis of structural macro-econometric models. It is a careful Python port of the MATLAB reference toolbox accompanying

Wegner, Lieb, Smeekes & Wilms (2024). Transmission Channel Analysis in Dynamic Models. arXiv:2405.18987.

with first-class plotting and reporting helpers.


What is TCA?

For a structural shock $\varepsilon_{i,t}$ and a target variable $y_{j,t+h}$, the impulse response function (IRF) measures the total dynamic causal effect of the shock. TCA decomposes that total effect into effects flowing through user-defined transmission channels, where a channel is defined either:

  • graphically, as a subset of paths in the DAG induced by the systems-form representation $x = Bx + \Omega \varepsilon$, or
  • via potential outcomes, as an assignment vector that turns some intermediate dependencies on or off.

TCA is fully compatible with traditional impulse-response analysis: it needs only the structural identification of the shock of interest plus a transmission ordering (a permutation of the variables encoded in the transmission matrix $T$).


Installation

pip install tca-channels
# Optional pretty terminals + DAG layouts:
pip install "tca-channels[all]"

Editable install for development:

git clone https://github.com/merwanroudane/tca
cd tca
pip install -e .[dev]

The distribution name on PyPI is tca-channels, but the Python package is imported as tca:

import tca
from tca.models import SVAR

Pure-Python dependencies: numpy, scipy, pandas, matplotlib. Optional: rich (coloured tables), networkx (alternative DAG layout), statsmodels (alternative VAR estimators).


Library map

Module What lives there
tca.q Q Boolean condition algebra; make_condition, make_condition_y
tca.transmission transmission, transmission_BOmega, transmission_irfs, through, not_through
tca.systems make_B, make_Omega, make_systems_form, to_transmission_irfs
tca.models VAR, SVAR, LP, DSGE, Recursive, ExternalInstrument, InternalInstrument
tca.viz plot_decomposition, plot_compare_decompositions, plot_irf_grid, plot_dag, plot_heatmap
tca.tables decomposition_table, channel_share_table, render_rich, style_dataframe

Quick start

import numpy as np, pandas as pd
from tca.models import SVAR, Recursive
from tca import transmission, through, not_through
from tca.systems import make_systems_form, to_transmission_irfs
from tca.viz import plot_decomposition, plot_dag
from tca.tables import decomposition_table, render_rich

# 1) Estimate a structural VAR (recursive / Cholesky identification).
data = pd.DataFrame(np.random.RandomState(0).randn(200, 3),
                    columns=["x", "pi", "i"])
m = SVAR(data, p=2, identification=Recursive()).fit()

# 2) Choose a transmission ordering (here: x -> pi -> i).
order = m.define_order(["x", "pi", "i"])

# 3) Build channels:
direct   = m.not_through("pi", horizons=[0], order=["x", "pi", "i"])
indirect = m.through    ("pi", horizons=[0], order=["x", "pi", "i"])

# 4) Compute total IRFs and channel decompositions.
H = 12
irfs    = m.irfs(H)                                # structural IRFs
B, Om   = make_systems_form(m.Phi0, m.var.coeff_lags(), [], order, H)

eff_dir = transmission(from_=1, arr1=B, arr2=Om, q=direct,   method="BOmega", order=order)
eff_ind = transmission(from_=1, arr1=B, arr2=Om, q=indirect, method="BOmega", order=order)

# 5) Pretty table + decomposition plot.
df = decomposition_table(idx_outcome=3, irfs_total=irfs,
                         channel_effects=[eff_dir, eff_ind],
                         channel_names=["Direct", "Indirect (via π)"])
render_rich(df, title="Demand shock → interest rate")

plot_decomposition(idx_outcome=3, irfs_total=irfs,
                   channel_effects=[eff_dir, eff_ind],
                   channel_names=["Direct", "Indirect (via π)"],
                   ylabel="Response of i").show()

API at a glance

Boolean conditions

from tca import Q, make_condition

# Atomic variables follow systems-form ordering: x1 = first variable at horizon 0.
q = (Q(1) | Q(2)) & ~Q(3)
q = make_condition("(x1 | x2) & !x3")

Channel builders

from tca import through, not_through

order = [1, 2, 3]
contemporaneous = through(1, [0], order)            # paths through x_{1,0}
no_inflation    = not_through(2, range(0, 13), order)
combined        = through([1, 2], [0, 1], order)    # joint condition

Engine

from tca import transmission

# Systems-form method.
eff = transmission(from_=1, arr1=B, arr2=Omega, q=q, method="BOmega", order=order)

# IRF method (works with local projections).
eff = transmission(from_=1, arr1=irfs_T, arr2=ortho_T, q=q, method="irf", order=order)

eff is a 3-D array of shape (K, 1, H+1) when order is supplied.

Models

from tca.models import VAR, SVAR, LP, DSGE, Recursive, ExternalInstrument

VAR(data, p=4).fit_and_select(max_p=8, ic="aic")
SVAR(data, p=4, identification=Recursive()).fit()
SVAR(data, p=4, identification=ExternalInstrument(z, normalize_to=2)).fit()
LP(data, shock=z, max_horizon=20, n_lags=4).fit()

# DSGE: provide a *linearised* model in VARMA form, an ABCD state-space
# (Morris 2016 conversion is built in), or pre-extracted Dynare structs.
DSGE.from_varma(Phi0, As=[A1], Psis=[])
DSGE.from_state_space(A, B, C, D, Sigma_e=Sigma_e)
DSGE.from_dynare(M_, options_, oo_)

Visualisations

tca.viz provides four chart families:

  • plot_decomposition — stacked-bar decomposition of an IRF.
  • plot_compare_decompositions — side-by-side comparison of two decompositions.
  • plot_irf_grid — IRF panel with optional confidence bands.
  • plot_heatmap — heatmap of B / Omega / Phi.
  • plot_dag — DAG of the systems form across horizons.

A consistent TCA_PALETTE and set_style() helper keep plots publication-ready.


Tables

from tca.tables import decomposition_table, channel_share_table, render_rich, style_dataframe

df = decomposition_table(2, irfs_total, [eff_dir, eff_ind], ["Direct", "Indirect"])
render_rich(df, title="Demand shock → inflation")        # coloured terminal table
style_dataframe(df, cmap="RdBu_r")                       # notebook / HTML / LaTeX

render_rich requires the optional rich dependency and falls back to plain text otherwise.


Citing

If you use this library, please cite both the original framework and this implementation:

@article{wegner2024tca,
  title  = {Transmission Channel Analysis in Dynamic Models},
  author = {Wegner, Enrico and Lieb, Lenard and Smeekes, Stephan and Wilms, Ines},
  journal= {arXiv preprint arXiv:2405.18987},
  year   = {2024}
}

@misc{roudane2026tcapy,
  title  = {tca: Transmission Channel Analysis in Python},
  author = {Roudane, Merwan},
  year   = {2026},
  url    = {https://github.com/merwanroudane/tca}
}

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages