Asymptotic Moments & Covariance Analysis¶
In business cycle analysis, comparing model-implied theoretical moments against empirical data (such as relative volatilities, contemporaneous correlations, and autocorrelations with GDP) is central to evaluating model performance.
Theoretical Derivation¶
Consider the stationary first-order decision rule:
where \(y_t\) denotes deviations from steady state.
1. Conditional Covariance Matrix (\(\Gamma_0\))¶
The covariance of the contemporaneous shock impact is:
2. Unconditional Covariance Matrix (\(\Gamma\))¶
Applying the covariance operator to both sides of the VAR(1) system:
Under covariance stationarity, \(\text{Cov}(y_t) = \text{Cov}(y_{t-1}) = \Gamma\). Thus, \(\Gamma\) satisfies the discrete Lyapunov equation:
Dyno solves this discrete Lyapunov equation efficiently using doubled Schur/Kronecker algebraic methods.
Computing Moments in Dyno¶
Call solution.moments() directly on a PerturbationSolution:
from dyno import DynoModel
model = DynoModel("examples/modfiles/RBC.mod")
solution = model.solve()
# Returns (Gamma_0, Gamma)
Gamma_0, Gamma = solution.moments()
Inspecting Standard Deviations & Correlations¶
Convert the unconditional covariance matrix \(\Gamma\) into standard deviations and correlation matrices:
import numpy as np
import pandas as pd
var_names = solution.symbols["endogenous"]
# Variance is the diagonal of Gamma
variances = np.diag(Gamma)
std_devs = np.sqrt(variances)
# Standard deviations DataFrame
df_volatility = pd.DataFrame({
"Variable": var_names,
"Std Dev (%)": std_devs * 100
}).set_index("Variable")
print("Theoretical Volatilities:")
print(df_volatility)
# Correlation matrix
diag_inv = np.diag(1.0 / std_devs)
corr_matrix = diag_inv @ Gamma @ diag_inv
df_corr = pd.DataFrame(corr_matrix, index=var_names, columns=var_names)
print("\nCorrelation Matrix:")
print(df_corr[["y", "c", "i", "n", "w"]].loc[["y", "c", "i", "n", "w"]])
Standalone moments Function¶
You can also compute moments directly given arbitrary state-space matrices \((X, Y, \Sigma)\):