Skip to main content

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.

Metadata

Release files for tca-channels 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tca-channels 0.1.0
File Size Uploaded Provenance
tca_channels-0.1.0.tar.gz 36.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tca-channels 0.1.0
File Interpreter ABI Platform
tca_channels-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 72.4 kB

Release files / tca_channels-0.1.0.tar.gz

Download URL tca_channels-0.1.0.tar.gz
Size 36.6 kB
Tags Source
SHA-256 checksum
How to use checksums
419df2636e04daee9f6fe737ded115e513315057f8a2d7a61792e54e4c6728d6
BLAKE2b-256 checksum
How to use checksums
5664f645fe9e5ca9581c4b49e78a6139d072c3f1efa279550efc5d5e38762243
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.0

Release files / tca_channels-0.1.0-py3-none-any.whl

Download URL tca_channels-0.1.0-py3-none-any.whl
Size 35.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0d307d578a64602a63221873da2d6228a3f80de1b529f2a8e511bf438339251b
BLAKE2b-256 checksum
How to use checksums
cc48abd063f2c5a96f8e09240805eb3ee1a14c4ccf4c8b5affebd8a42861d279
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.0

Security for tca-channels 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page