API Functions

This page documents all functions in MacroEconometricModels.jl, organized by module.


Data Management

Validation and Cleaning

MacroEconometricModels.diagnoseFunction
diagnose(d::AbstractMacroData) -> DataDiagnostic

Scan data for NaN, Inf, constant columns, and very short series.

Examples

d = TimeSeriesData(randn(100, 3))
diag = diagnose(d)
diag.is_clean  # true if no issues
source
MacroEconometricModels.fixFunction
fix(d::TimeSeriesData; method=:listwise) -> TimeSeriesData

Fix data issues and return a clean copy.

Methods

  • :listwise — drop rows with any NaN or Inf (default)
  • :interpolate — linear interpolation for interior NaN, forward-fill edges
  • :mean — replace NaN with column mean of finite values

Inf values are always replaced with NaN first (then handled by the chosen method). Constant columns are dropped with a warning.

Examples

d = TimeSeriesData([1.0 NaN; 2.0 3.0; 3.0 4.0])
d_clean = fix(d; method=:listwise)  # drops row 1
source
fix(d::PanelData; method=:listwise) -> PanelData

Fix data issues and return a clean copy.

Methods

  • :listwise — drop rows with any NaN or Inf (default)
  • :interpolate — linear interpolation within each group
  • :mean — replace NaN with within-group column mean

Inf values are replaced with NaN first. Constant columns are dropped with a warning.

source
fix(d::CrossSectionData; method=:listwise) -> CrossSectionData

Fix data issues and return a clean copy.

Methods

  • :listwise — drop rows with any NaN or Inf (default)
  • :mean — replace NaN with column mean of finite values
  • :interpolate — same as :mean (no time ordering in cross-section data)

Inf values are replaced with NaN first. Constant columns are dropped with a warning.

source
MacroEconometricModels.validate_for_modelFunction
validate_for_model(d::AbstractMacroData, model_type::Symbol)

Check that data is compatible with the specified model type. Throws ArgumentError on mismatch.

Model types requiring multivariate data (n_vars ≥ 2)

:var, :vecm, :bvar, :factors, :dynamic_factors, :gdfm

Model types requiring univariate data (n_vars == 1)

:arima, :ar, :ma, :arma, :arch, :garch, :egarch, :gjr_garch, :sv, :hp_filter, :hamilton_filter, :beveridge_nelson, :baxter_king, :boosted_hp, :adf, :kpss, :pp, :za, :ngperron

Model types accepting any dimensionality

:lp, :lp_iv, :smooth_lp, :state_lp, :propensity_lp, :gmm

Examples

d = TimeSeriesData(randn(100, 3))
validate_for_model(d, :var)    # OK
validate_for_model(d, :arima)  # throws ArgumentError
source

FRED Transformations

MacroEconometricModels.apply_tcodeFunction
apply_tcode(y::AbstractVector{<:Real}, tcode::Int) -> Vector{Float64}

Apply FRED transformation code to a univariate series.

Codes 4–7 require strictly positive data. The output vector is shorter than the input for difference-based codes:

  • tcode 1: same length
  • tcode 2, 4, 5: length T-1
  • tcode 3, 6, 7: length T-2

Examples

y = [100.0, 102.0, 105.0, 103.0, 108.0]
apply_tcode(y, 5)  # log first differences (approx growth rates)
source
apply_tcode(d::TimeSeriesData, tcodes::Vector{Int}) -> TimeSeriesData

Apply per-variable FRED transformation codes. Rows are trimmed consistently (to the shortest transformed series).

Examples

d = TimeSeriesData(rand(200, 3) .+ 1; varnames=["GDP","CPI","FFR"])
d2 = apply_tcode(d, [5, 5, 1])  # log-diff GDP and CPI, leave FFR in levels
source
apply_tcode(d::TimeSeriesData, tcode::Int) -> TimeSeriesData

Apply the same FRED transformation code to all variables.

source
apply_tcode(d::TimeSeriesData) -> TimeSeriesData

Convenience method: apply the transformation codes stored in d.tcode. Equivalent to apply_tcode(d, d.tcode).

Examples

d = load_example(:fred_md)  # tcode already set
d_transformed = apply_tcode(d)
source
apply_tcode(d::PanelData, tcodes::Vector{Int}) -> PanelData

Apply per-variable FRED transformation codes to a PanelData container, processing each group independently. Each group is trimmed to its own common length after transformation, then reassembled.

Examples

pd = xtset(df, :id, :t)
pd2 = apply_tcode(pd, [5, 5, 1])  # log-diff first two vars, leave third in levels
source
apply_tcode(d::PanelData, tcode::Int) -> PanelData

Apply the same FRED transformation code to all variables in a PanelData container.

source
MacroEconometricModels.inverse_tcodeFunction
inverse_tcode(y::AbstractVector{<:Real}, tcode::Int;
              x_prev::Union{AbstractVector{<:Real},Nothing}=nothing) -> Vector{Float64}

Undo a FRED transformation to recover the original series.

For difference-based codes (2, 3, 5, 6, 7), x_prev must supply the initial values needed for reconstruction:

  • tcode 2: x_prev = [x₀] (1 value)
  • tcode 3: x_prev = [x₀, x₁] (2 values, original levels)
  • tcode 5: x_prev = [x₀] (1 value, original level)
  • tcode 6: x_prev = [x₀, x₁] (2 values, original levels)
  • tcode 7: x_prev = [x₀, x₁] (2 values, original levels)

Examples

y = [100.0, 102.0, 105.0]
yd = apply_tcode(y, 2)                        # [2.0, 3.0]
inverse_tcode(yd, 2; x_prev=[100.0])          # [102.0, 105.0]
source

Filtering

MacroEconometricModels.apply_filterFunction
apply_filter(d::TimeSeriesData, specs::AbstractVector; component=:cycle, kwargs...)

Apply per-variable filter specifications to a TimeSeriesData container.

Each element of specs can be:

  • Symbol — filter name (:hp, :hamilton, :bn, :bk, :boosted_hp)
  • AbstractFilterResult — a pre-computed filter result
  • Tuple{filter, Symbol} — filter with per-variable component override (e.g., (:hp, :trend))
  • nothing — pass-through (no filtering for this variable)

The output is trimmed to the intersection of valid ranges across all variables.

Arguments

  • d::TimeSeriesData — input data
  • specs::AbstractVector — per-variable filter specifications (length must equal n_vars)

Keyword Arguments

  • component::Symbol=:cycle — default component to extract (:cycle or :trend)
  • Additional kwargs are forwarded to filter functions

Returns

A new TimeSeriesData with filtered data, trimmed to the common valid range.

Examples

d = TimeSeriesData(cumsum(randn(200, 3), dims=1); varnames=["GDP","CPI","FFR"])

# Per-variable: HP cycle for GDP, Hamilton cycle for CPI, pass-through FFR
d2 = apply_filter(d, [:hp, :hamilton, nothing])

# Per-variable component overrides via tuples
d3 = apply_filter(d, [(:hp, :trend), (:hamilton, :cycle), nothing])
source
apply_filter(d::TimeSeriesData, spec::Union{Symbol, AbstractFilterResult};
             component=:cycle, vars=nothing, kwargs...)

Apply a single filter to all variables (or a subset specified by vars).

Variables not in vars are passed through unchanged.

Arguments

  • d::TimeSeriesData — input data
  • spec — filter symbol (:hp, :hamilton, :bn, :bk, :boosted_hp) or pre-computed result

Keyword Arguments

  • component::Symbol=:cycle — component to extract (:cycle or :trend)
  • vars::Union{Nothing, Vector{String}, Vector{Int}} — variables to filter (default: all)
  • Additional kwargs are forwarded to filter functions

Examples

d = TimeSeriesData(cumsum(randn(200, 3), dims=1); varnames=["GDP","CPI","FFR"])

# HP cycle for all variables
d_hp = apply_filter(d, :hp)

# HP trend for selected variables only
d_sel = apply_filter(d, :hp; vars=["GDP", "CPI"], component=:trend)
source
apply_filter(d::PanelData, spec; component=:cycle, vars=nothing, kwargs...)

Apply filters to a PanelData container group-by-group.

Each group is extracted via group_data, filtered, and the results are reassembled into a new PanelData. Each group is trimmed independently to its own common valid range (groups may have different resulting lengths if unbalanced).

Arguments

  • d::PanelData — input panel data
  • spec — filter specification: a single Symbol, AbstractFilterResult, or AbstractVector of per-variable specs (same formats as TimeSeriesData)

Keyword Arguments

  • component::Symbol=:cycle — component to extract
  • vars — variables to filter (others pass-through)
  • Additional kwargs forwarded to filter functions

Examples

pd = xtset(df, :id, :t)
pd_hp = apply_filter(pd, :hp; component=:cycle)
pd_sel = apply_filter(pd, :hp; vars=["GDP"], component=:trend)
source

Summary Statistics

MacroEconometricModels.describe_dataFunction
describe_data(d::AbstractMacroData) -> DataSummary

Compute per-variable summary statistics (N, Mean, Std, Min, P25, Median, P75, Max, Skewness, Kurtosis). NaN values are excluded from all computations.

For PanelData, also prints panel dimensions via panel_summary.

Examples

d = TimeSeriesData(randn(200, 3); varnames=["GDP","CPI","FFR"], frequency=Quarterly)
describe_data(d)
source

Panel Data

MacroEconometricModels.xtsetFunction
xtset(df::DataFrame, group_col::Symbol, time_col::Symbol;
      varnames=nothing, frequency=Other, tcode=nothing,
      cohort=nothing) -> PanelData{Float64}

Construct a PanelData container from a DataFrame, analogous to Stata's xtset.

Extracts all numeric columns (excluding group_col, time_col, and cohort), sorts by (group, time), validates no duplicate (group, time) pairs, and detects whether the panel is balanced.

Arguments

  • df::DataFrame — input data
  • group_col::Symbol — column name identifying groups (entities)
  • time_col::Symbol — column name identifying time periods

Keyword Arguments

  • varnames::Union{Vector{String},Nothing} — override variable names (default: column names)
  • frequency::Frequency — data frequency (default: Other)
  • tcode::Union{Vector{Int},Nothing} — transformation codes per variable
  • cohort::Union{Symbol,Nothing} — column name identifying cohort membership (default: nothing)

Examples

using DataFrames
df = DataFrame(id=repeat(1:3, inner=50), t=repeat(1:50, 3),
               x=randn(150), y=randn(150))
pd = xtset(df, :id, :t)
source
MacroEconometricModels.group_dataFunction
group_data(d::PanelData, g) -> TimeSeriesData

Extract data for a single group as a TimeSeriesData container.

g can be an integer group index or a string group name.

Examples

pd = xtset(df, :id, :t)
g1 = group_data(pd, 1)       # by index
g1 = group_data(pd, "1")     # by name
source
MacroEconometricModels.panel_summaryFunction
panel_summary(d::PanelData)

Display a summary table of the panel structure: number of groups, observations per group (min, mean, max), and balance status.

Examples

pd = xtset(df, :id, :t)
panel_summary(pd)
source

Data Accessors and Conversion

StatsAPI.nobsMethod
StatsAPI.nobs(d::AbstractMacroData)

Return the number of observations.

source
MacroEconometricModels.descFunction
desc(d::AbstractMacroData) -> String

Return the dataset description. Returns "" if no description has been set.

Examples

d = TimeSeriesData(randn(100, 3); desc="US macro quarterly data")
desc(d)  # "US macro quarterly data"
source
MacroEconometricModels.vardescFunction
vardesc(d::AbstractMacroData) -> Dict{String,String}

Return the dictionary of per-variable descriptions.

Examples

d = TimeSeriesData(randn(100, 2); varnames=["GDP","CPI"],
    vardesc=Dict("GDP" => "Real GDP growth", "CPI" => "Consumer prices"))
vardesc(d)  # Dict("GDP" => "Real GDP growth", "CPI" => "Consumer prices")
source
vardesc(d::AbstractMacroData, name::String) -> String

Return the description for variable name. Throws ArgumentError if no description exists for that variable.

Examples

vardesc(d, "GDP")  # "Real GDP growth"
source
MacroEconometricModels.rename_vars!Function
rename_vars!(d::AbstractMacroData, old => new)
rename_vars!(d::AbstractMacroData, names::Vector{String})

Rename variables in a data container. With a Pair, renames a single variable. With a Vector{String}, replaces all variable names. Also updates vardesc keys.

source
MacroEconometricModels.set_desc!Function
set_desc!(d::AbstractMacroData, text::String)

Set the dataset description.

Examples

d = TimeSeriesData(randn(100, 3))
set_desc!(d, "US macroeconomic quarterly data 1959-2024")
desc(d)  # "US macroeconomic quarterly data 1959-2024"
source
MacroEconometricModels.set_vardesc!Function
set_vardesc!(d::AbstractMacroData, name::String, text::String)

Set the description for a single variable. The variable must exist in the data.

Examples

d = TimeSeriesData(randn(100, 2); varnames=["GDP", "CPI"])
set_vardesc!(d, "GDP", "Real Gross Domestic Product, seasonally adjusted")
set_vardesc!(d, "CPI", "Consumer Price Index for All Urban Consumers")
vardesc(d, "GDP")  # "Real Gross Domestic Product, seasonally adjusted"
source
set_vardesc!(d::AbstractMacroData, descriptions::Dict{String,String})

Set descriptions for multiple variables at once. All keys must be valid variable names.

Examples

set_vardesc!(d, Dict("GDP" => "Real GDP", "CPI" => "Consumer prices"))
source
MacroEconometricModels.set_dates!Function
set_dates!(d::TimeSeriesData, dates::Vector{String})

Set the date labels for a TimeSeriesData container. Length must match T_obs, or pass an empty vector to clear dates.

Examples

d = TimeSeriesData(randn(4, 2))
set_dates!(d, ["2020Q1", "2020Q2", "2020Q3", "2020Q4"])
dates(d)  # ["2020Q1", "2020Q2", "2020Q3", "2020Q4"]
source
MacroEconometricModels.to_matrixFunction
to_matrix(d::TimeSeriesData) -> Matrix

Return the raw data matrix from a TimeSeriesData container.

source
to_matrix(d::PanelData) -> Matrix

Return the raw stacked data matrix from a PanelData container.

source
to_matrix(d::CrossSectionData) -> Matrix

Return the raw data matrix from a CrossSectionData container.

source
MacroEconometricModels.to_vectorFunction
to_vector(d::TimeSeriesData) -> Vector

Return the data as a vector (requires exactly 1 variable).

source
to_vector(d::TimeSeriesData, var::Int) -> Vector

Return a single column by index.

source
to_vector(d::TimeSeriesData, var::String) -> Vector

Return a single column by name.

source
MacroEconometricModels.load_exampleFunction
load_example(name::Symbol) -> AbstractMacroData

Load a built-in example dataset.

Available Datasets

  • :fred_md — FRED-MD Monthly Database, January 2026 vintage (126 variables × 804 months) → TimeSeriesData
  • :fred_qd — FRED-QD Quarterly Database, January 2026 vintage (245 variables × 268 quarters) → TimeSeriesData
  • :pwt — Penn World Table 10.01, 38 OECD countries (42 variables × 74 years, 1950–2023) → PanelData
  • :ddcg — Acemoglu et al. (2019) Democracy-GDP Panel (2 variables × 9,384 obs, 184 countries × 51 years) → PanelData
  • :mpdta — Callaway & Sant'Anna (2021) Minimum Wage Panel (3 variables × 2,500 obs, 500 counties × 5 years) → PanelData

For time series datasets, the returned TimeSeriesData includes variable names, transformation codes, frequency, per-variable descriptions (via vardesc), dataset description (via desc), and bibliographic references (via refs).

For panel datasets, the returned PanelData includes country identifiers as groups, year identifiers as time index, variable descriptions, and references.

Examples

# Load FRED-MD
md = load_example(:fred_md)
nobs(md)       # 804
nvars(md)      # 126
desc(md)       # "FRED-MD Monthly Database, January 2026 Vintage (McCracken & Ng 2016)"
vardesc(md, "INDPRO")  # "IP Index"
refs(md)       # McCracken & Ng (2016)

# Apply recommended transformations
md_transformed = apply_tcode(md, md.tcode)

# Load FRED-QD
qd = load_example(:fred_qd)

# Load Penn World Table (panel data)
pwt = load_example(:pwt)
nobs(pwt)         # 2812 (38 countries × 74 years)
nvars(pwt)        # 42
ngroups(pwt)      # 38
groups(pwt)       # ["AUS", "AUT", ..., "USA"]
isbalanced(pwt)   # true
g = group_data(pwt, "USA")  # extract single country as TimeSeriesData
refs(pwt)         # Feenstra, Inklaar & Timmer (2015)
source

Time Series Filters

MacroEconometricModels.hp_filterFunction
hp_filter(y::AbstractVector; lambda=1600.0) -> HPFilterResult

Apply the Hodrick-Prescott filter to decompose time series y into trend and cycle.

Solves the optimization problem:

\[\min_\tau \sum_{t=1}^T (y_t - \tau_t)^2 + \lambda \sum_{t=2}^{T-1} (\tau_{t+1} - 2\tau_t + \tau_{t-1})^2\]

Implementation uses a sparse pentadiagonal Cholesky factorization for O(T) cost.

Arguments

  • y::AbstractVector: Time series data (length ≥ 3)

Keywords

  • lambda::Real=1600.0: Smoothing parameter. Common values: 6.25 (annual), 1600 (quarterly, default), 129600 (monthly)

Returns

  • HPFilterResult{T} with fields trend, cycle, lambda, T_obs

Examples

y = cumsum(randn(200))
result = hp_filter(y)
result = hp_filter(y; lambda=6.25)  # annual data

References

  • Hodrick, R. J., & Prescott, E. C. (1997). JMCB 29(1): 1–16.
source
MacroEconometricModels.hamilton_filterFunction
hamilton_filter(y::AbstractVector; h=8, p=4) -> HamiltonFilterResult

Apply the Hamilton (2018) regression filter for trend-cycle decomposition.

Regresses $y_{t+h}$ on $[1, y_t, y_{t-1}, \ldots, y_{t-p+1}]$ by OLS. The residuals form the cyclical component and the fitted values form the trend.

The filter loses h + p - 1 observations at the start of the sample.

Arguments

  • y::AbstractVector: Time series data

Keywords

  • h::Int=8: Forecast horizon (default 8 for quarterly data = 2 years)
  • p::Int=4: Number of lags in the regression (default 4 for quarterly data)

Returns

  • HamiltonFilterResult{T} with fields trend, cycle, beta, h, p, T_obs, valid_range

Examples

y = cumsum(randn(200))
result = hamilton_filter(y)                 # quarterly defaults
result = hamilton_filter(y; h=24, p=12)     # monthly data (2-year horizon)

References

  • Hamilton, J. D. (2018). REStat 100(5): 831–843.
source
MacroEconometricModels.beveridge_nelsonFunction
beveridge_nelson(y::AbstractVector; method=:arima, p=:auto, q=:auto, max_terms=500, cycle_order=2) -> BeveridgeNelsonResult

Compute the Beveridge-Nelson decomposition of time series y.

Assumes y is I(1) and decomposes it into:

\[y_t = \tau_t + c_t\]

where $\tau_t$ is a random walk with drift (permanent component) and $c_t$ is a stationary transitory component.

Methods

  • :arima (default): Classic BN via ARIMA representation (Beveridge & Nelson, 1981)
  • :statespace: Correlated UC model via MLE + Kalman smoother (Morley, Nelson & Zivot, 2003)

Arguments

  • y::AbstractVector: Time series data (assumed I(1), length ≥ 10)

Keywords

  • method::Symbol=:arima: Decomposition method
  • p: AR order for ARMA model of Δy (method=:arima). :auto uses auto_arima
  • q: MA order for ARMA model of Δy (method=:arima). :auto uses auto_arima
  • max_terms::Int=500: Maximum ψ-weights for MA(∞) truncation (method=:arima)
  • cycle_order::Int=2: AR order for cyclical component (method=:statespace, 1 or 2)

Returns

  • BeveridgeNelsonResult{T} with fields permanent, transitory, drift, long_run_multiplier, arima_order, T_obs

Examples

# Classic ARIMA-based BN decomposition
y = cumsum(randn(200)) + 0.3 * sin.(2π * (1:200) / 20)
result = beveridge_nelson(y)
result = beveridge_nelson(y; p=2, q=1)  # manual ARMA order

# Morley (2002) correlated UC model
result = beveridge_nelson(y; method=:statespace)
result = beveridge_nelson(y; method=:statespace, cycle_order=1)

References

  • Beveridge, S., & Nelson, C. R. (1981). JME 7(2): 151–174.
  • Morley, J. C., Nelson, C. R., & Zivot, E. (2003). REStat 85(2): 235–243.
source
MacroEconometricModels.baxter_kingFunction
baxter_king(y::AbstractVector; pl=6, pu=32, K=12) -> BaxterKingResult

Apply the Baxter-King band-pass filter to isolate business cycle frequencies.

Computes symmetric moving average weights that approximate the ideal band-pass filter for periods between pl and pu. The filter is constrained to sum to zero (removing stochastic trends).

Loses K observations at each end of the sample (2K total).

Arguments

  • y::AbstractVector: Time series data (length > 2K)

Keywords

  • pl::Int=6: Minimum period of oscillation to pass (quarterly: 6 = 1.5 years)
  • pu::Int=32: Maximum period of oscillation to pass (quarterly: 32 = 8 years)
  • K::Int=12: Truncation length (number of leads/lags in the moving average)

Returns

  • BaxterKingResult{T} with fields cycle, trend, weights, pl, pu, K, T_obs, valid_range

Examples

y = cumsum(randn(200))
result = baxter_king(y)                    # quarterly defaults (6-32 quarters)
result = baxter_king(y; pl=2, pu=8, K=6)  # annual data (2-8 years)

References

  • Baxter, M., & King, R. G. (1999). REStat 81(4): 575–593.
source
MacroEconometricModels.boosted_hpFunction
boosted_hp(y::AbstractVector; lambda=1600.0, stopping=:BIC, max_iter=100, sig_p=0.05) -> BoostedHPResult

Apply the boosted HP filter (Phillips & Shi 2021) for improved trend estimation.

Iteratively re-filters the cyclical component of the standard HP filter. At each iteration, the cycle is decomposed again and the newly estimated "trend of the cycle" is added back to the overall trend.

Stopping criteria

  • :ADF — Stop when the ADF test rejects the null of a unit root in the cycle at significance level sig_p (recommended for detecting stationarity)
  • :BIC — Stop when the Phillips-Shi information criterion increases (balances variance reduction against effective degrees of freedom)
  • :fixed — Run all max_iter iterations

Arguments

  • y::AbstractVector: Time series data (length ≥ 3)

Keywords

  • lambda::Real=1600.0: HP smoothing parameter
  • stopping::Symbol=:BIC: Stopping criterion (:ADF, :BIC, or :fixed)
  • max_iter::Int=100: Maximum number of boosting iterations
  • sig_p::Real=0.05: Significance level for ADF stopping criterion

Returns

  • BoostedHPResult{T} with fields trend, cycle, lambda, iterations, stopping, bic_path, adf_pvalues, T_obs

Examples

y = cumsum(randn(200))
result = boosted_hp(y)                              # BIC stopping (default)
result = boosted_hp(y; stopping=:ADF, sig_p=0.05)   # ADF stopping
result = boosted_hp(y; stopping=:fixed, max_iter=5)  # fixed iterations

References

  • Phillips, P. C. B., & Shi, Z. (2021). IER 62(2): 521–570.
  • Mei, Z., Phillips, P. C. B., & Shi, Z. (2024). JAE 39(7): 1260–1281.
source
MacroEconometricModels.trendFunction
trend(result::AbstractFilterResult) -> Vector

Return the trend component from a filter result. For BeveridgeNelsonResult, returns the permanent component.

source
MacroEconometricModels.cycleFunction
cycle(result::AbstractFilterResult) -> Vector

Return the cyclical component from a filter result. For BeveridgeNelsonResult, returns the transitory component.

source

ARIMA Models

Estimation

MacroEconometricModels.estimate_arFunction
estimate_ar(y, p; method=:ols, include_intercept=true) -> ARModel

Estimate AR(p) model: yₜ = c + φ₁yₜ₋₁ + ... + φₚyₜ₋ₚ + εₜ

Arguments

  • y: Time series vector
  • p: AR order (must be ≥ 1)
  • method: Estimation method (:ols or :mle)
  • include_intercept: Whether to include constant term

Returns

ARModel with estimated coefficients and diagnostics.

Example

y = randn(200)
model = estimate_ar(y, 2)
println(model.phi)  # AR coefficients
source
MacroEconometricModels.estimate_maFunction
estimate_ma(y, q; method=:css_mle, include_intercept=true, max_iter=500) -> MAModel

Estimate MA(q) model: yₜ = c + εₜ + θ₁εₜ₋₁ + ... + θqεₜ₋q

Arguments

  • y: Time series vector
  • q: MA order (must be ≥ 1)
  • method: Estimation method (:css, :mle, or :css_mle)
  • include_intercept: Whether to include constant term
  • max_iter: Maximum optimization iterations

Returns

MAModel with estimated coefficients and diagnostics.

Example

y = randn(200)
model = estimate_ma(y, 1)
println(model.theta)  # MA coefficient
source
MacroEconometricModels.estimate_armaFunction
estimate_arma(y, p, q; method=:css_mle, include_intercept=true, max_iter=500) -> ARMAModel

Estimate ARMA(p,q) model: yₜ = c + φ₁yₜ₋₁ + ... + φₚyₜ₋ₚ + εₜ + θ₁εₜ₋₁ + ... + θqεₜ₋q

Arguments

  • y: Time series vector
  • p: AR order
  • q: MA order
  • method: Estimation method (:css, :mle, or :css_mle)
  • include_intercept: Whether to include constant term
  • max_iter: Maximum optimization iterations

Returns

ARMAModel with estimated coefficients and diagnostics.

Example

y = randn(200)
model = estimate_arma(y, 1, 1)
println("AR: ", model.phi, " MA: ", model.theta)
source
MacroEconometricModels.estimate_arimaFunction
estimate_arima(y, p, d, q; method=:css_mle, include_intercept=true, max_iter=500) -> ARIMAModel

Estimate ARIMA(p,d,q) model by differencing d times and fitting ARMA(p,q).

Arguments

  • y: Time series vector
  • p: AR order
  • d: Integration order (number of differences)
  • q: MA order
  • method: Estimation method (:css, :mle, or :css_mle)
  • include_intercept: Whether to include constant term (on differenced series)
  • max_iter: Maximum optimization iterations

Returns

ARIMAModel with estimated coefficients and diagnostics.

Example

y = cumsum(randn(200))  # Random walk
model = estimate_arima(y, 1, 1, 0)  # ARIMA(1,1,0)
println(model.phi)
source

Forecasting

MacroEconometricModels._compute_psi_weightsMethod
_compute_psi_weights(phi, theta, h) -> Vector{T}

Compute ψ-weights for the MA(∞) representation of an ARMA process.

The ARMA(p,q) process can be written as: yₜ = μ + Σⱼ₌₀^∞ ψⱼ εₜ₋ⱼ

where ψ₀ = 1 and ψⱼ follows the recursion: ψⱼ = φ₁ψⱼ₋₁ + ... + φₚψⱼ₋ₚ + θⱼ

Returns ψ₁, ψ₂, ..., ψₕ.

source
MacroEconometricModels._forecast_armaMethod
_forecast_arma(y, resid, c, phi, theta, sigma2, h, conf_level) -> ARIMAForecast

Unified point forecast + CI computation for any ARMA(p,q) model. AR models pass theta=T[], MA models pass phi=T[].

source
MacroEconometricModels._integrate_seMethod
_integrate_se(se_diff, d) -> Vector{T}

Approximate standard errors after integration.

For d-fold integration, the variance grows roughly as h^d. This is a conservative approximation.

source
MacroEconometricModels.forecastMethod
forecast(model::ARIMAModel, h; conf_level=0.95) -> ARIMAForecast

Compute h-step ahead forecasts with confidence intervals for ARIMA model. Forecasts are computed on the differenced series and then integrated back to the original scale.

source
StatsAPI.predictMethod
predict(model::AbstractARIMAModel, h::Int) -> Vector{T}

Return h-step ahead point forecasts (without confidence intervals).

source

Order Selection

MacroEconometricModels.select_arima_orderFunction
select_arima_order(y, max_p, max_q; criterion=:bic, d=0, method=:css_mle, include_intercept=true)

Automatically select ARMA/ARIMA order via grid search over information criteria.

Searches over p ∈ 0:maxp and q ∈ 0:maxq, fits each model, and selects the order that minimizes the specified information criterion.

Arguments

  • y: Time series vector
  • max_p: Maximum AR order to consider
  • max_q: Maximum MA order to consider
  • criterion: Selection criterion (:aic or :bic, default :bic)
  • d: Integration order for ARIMA (default 0 = ARMA)
  • method: Estimation method (:css, :mle, or :css_mle)
  • include_intercept: Whether to include constant term

Returns

ARIMAOrderSelection with best orders, IC matrices, and fitted models.

Example

y = randn(200)
result = select_arima_order(y, 3, 3; criterion=:bic)
println("Best order: p=$(result.best_p_bic), q=$(result.best_q_bic)")
best_model = result.best_model_bic
source
MacroEconometricModels.auto_arimaFunction
auto_arima(y; max_p=5, max_q=5, max_d=2, criterion=:bic, method=:css_mle, stepwise=true)

Automatically select and fit the best ARIMA model.

Performs order selection over p, d, and q using the specified criterion. For integration order d, uses unit root test heuristics.

Arguments

  • y: Time series vector
  • max_p: Maximum AR order (default 5)
  • max_q: Maximum MA order (default 5)
  • max_d: Maximum integration order (default 2)
  • criterion: Selection criterion (:aic or :bic)
  • method: Estimation method
  • stepwise: If true (default), use Hyndman-Khandakar (2008) stepwise search. If false, use exhaustive grid search over all (p,q) combinations.

Returns

Best fitted ARIMAModel or ARMAModel.

Example

y = cumsum(randn(200))
model = auto_arima(y)
println(model)

References

  • Hyndman, R. J., & Khandakar, Y. (2008). Automatic time series forecasting: the forecast package for R. Journal of Statistical Software 27(3): 1–22.
source

ARIMA Accessors

ARIMA StatsAPI Interface


Cross-Sectional Models

Estimation

MacroEconometricModels.estimate_regFunction
estimate_reg(y, X; cov_type=:hc1, weights=nothing, varnames=nothing, clusters=nothing) -> RegModel{T}

Estimate a linear regression model via OLS or WLS.

OLS: beta = (X'X)^{-1} X'y WLS: beta = (X'WX)^{-1} X'Wy where W = diag(weights)

Arguments

  • y::AbstractVector{T} — dependent variable (n x 1)
  • X::AbstractMatrix{T} — regressor matrix (n x k), should include a constant column
  • cov_type::Symbol — covariance estimator: :ols, :hc0, :hc1 (default), :hc2, :hc3, :cluster
  • weights::Union{Nothing,AbstractVector} — WLS weights (nothing for OLS)
  • varnames::Union{Nothing,Vector{String}} — coefficient names (auto-generated if nothing)
  • clusters::Union{Nothing,AbstractVector} — cluster assignments (required for :cluster)

Returns

RegModel{T} with estimated coefficients, robust covariance matrix, fit statistics.

Examples

using MacroEconometricModels
n = 200
X = hcat(ones(n), randn(n, 2))
beta_true = [1.0, 2.0, -0.5]
y = X * beta_true + 0.5 * randn(n)
m = estimate_reg(y, X)
report(m)

References

  • Greene, W. H. (2018). Econometric Analysis. 8th ed. Pearson.
  • White, H. (1980). Econometrica 48(4), 817-838.
source
MacroEconometricModels.estimate_ivFunction
estimate_iv(y, X, Z; endogenous, cov_type=:hc1, varnames=nothing) -> RegModel{T}

Estimate a linear regression model via instrumental variables / two-stage least squares (IV/2SLS).

Algorithm

  1. Project regressors onto instrument space: Xhat = PZ * X where P_Z = Z(Z'Z)^{-1}Z'
  2. Second stage: beta = (Xhat'X)^{-1} Xhat'y
  3. Residuals from ORIGINAL X: e = y - Xbeta (not X_hatbeta)
  4. Covariance uses X_hat for the bread and original residuals for the meat

Arguments

  • y::AbstractVector{T} — dependent variable (n x 1)
  • X::AbstractMatrix{T} — regressor matrix (n x k), includes exogenous regressors and intercept
  • Z::AbstractMatrix{T} — instrument matrix (n x m), includes exogenous regressors and excluded instruments
  • endogenous::Vector{Int} — column indices of endogenous regressors in X
  • cov_type::Symbol — covariance estimator: :ols, :hc0, :hc1 (default), :hc2, :hc3
  • varnames::Union{Nothing,Vector{String}} — coefficient names (auto-generated if nothing)

Returns

RegModel{T} with method=:iv, including first-stage F-statistic and Sargan test.

Diagnostics

  • first_stage_f: minimum first-stage F across endogenous variables (>10 suggests strong instruments)
  • sargan_stat/sargan_pval: overidentification test (nothing if exactly identified)

Examples

using MacroEconometricModels
n = 500
z1, z2 = randn(n), randn(n)
x_endog = 0.5 * z1 + 0.3 * z2 + randn(n)
u = randn(n)
x_endog .+= 0.5 * u  # endogeneity
y = 1.0 .+ 2.0 * x_endog + u
X = hcat(ones(n), x_endog)
Z = hcat(ones(n), z1, z2)
m = estimate_iv(y, X, Z; endogenous=[2])
report(m)

References

  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press, ch. 5.
  • Stock, J. H. & Yogo, M. (2005). Identification and Inference for Econometric Models. Cambridge University Press, ch. 5.
source
MacroEconometricModels.estimate_logitFunction
estimate_logit(y, X; cov_type=:ols, varnames=nothing, clusters=nothing, maxiter=100, tol=1e-8) -> LogitModel{T}

Estimate a binary logistic regression model via maximum likelihood (IRLS/Fisher scoring).

Algorithm

Uses iteratively reweighted least squares with the canonical logit link mu = 1/(1+exp(-X*beta)). Converges when the change in log-likelihood is below tol * (|loglik| + 1).

Arguments

  • y::AbstractVector{T} — binary dependent variable (0/1), n x 1
  • X::AbstractMatrix{T} — regressor matrix (n x k), should include a constant column
  • cov_type::Symbol — covariance estimator: :ols (information matrix), :hc0, :hc1, :hc2, :hc3, :cluster
  • varnames::Union{Nothing,Vector{String}} — coefficient names (auto-generated if nothing)
  • clusters::Union{Nothing,AbstractVector} — cluster assignments (required for :cluster)
  • maxiter::Int — maximum IRLS iterations (default 100)
  • tol — convergence tolerance (default 1e-8)

Returns

LogitModel{T} with estimated coefficients, McFadden pseudo-R-squared, deviance residuals.

Examples

using MacroEconometricModels, Random
rng = MersenneTwister(42)
n = 500
X = hcat(ones(n), randn(rng, n, 2))
beta_true = [0.0, 1.5, -1.0]
p = 1 ./ (1 .+ exp.(-X * beta_true))
y = Float64.(rand(rng, n) .< p)
m = estimate_logit(y, X; varnames=["const", "x1", "x2"])
report(m)

References

  • McCullagh, P. & Nelder, J. A. (1989). Generalized Linear Models. Chapman & Hall.
  • Agresti, A. (2002). Categorical Data Analysis. 2nd ed. Wiley.
source
MacroEconometricModels.estimate_probitFunction
estimate_probit(y, X; cov_type=:ols, varnames=nothing, clusters=nothing, maxiter=100, tol=1e-8) -> ProbitModel{T}

Estimate a binary probit regression model via maximum likelihood (IRLS/Fisher scoring).

Algorithm

Uses iteratively reweighted least squares with the probit link mu = Phi(X*beta), where Phi is the standard normal CDF. Converges when the change in log-likelihood is below tol * (|loglik| + 1).

Arguments

  • y::AbstractVector{T} — binary dependent variable (0/1), n x 1
  • X::AbstractMatrix{T} — regressor matrix (n x k), should include a constant column
  • cov_type::Symbol — covariance estimator: :ols (information matrix), :hc0, :hc1, :hc2, :hc3, :cluster
  • varnames::Union{Nothing,Vector{String}} — coefficient names (auto-generated if nothing)
  • clusters::Union{Nothing,AbstractVector} — cluster assignments (required for :cluster)
  • maxiter::Int — maximum IRLS iterations (default 100)
  • tol — convergence tolerance (default 1e-8)

Returns

ProbitModel{T} with estimated coefficients, McFadden pseudo-R-squared, deviance residuals.

Examples

using MacroEconometricModels, Random
rng = MersenneTwister(42)
n = 500
X = hcat(ones(n), randn(rng, n, 2))
beta_true = [0.0, 1.0, -0.8]
using Distributions
p = cdf.(Normal(), X * beta_true)
y = Float64.(rand(rng, n) .< p)
m = estimate_probit(y, X; varnames=["const", "x1", "x2"])
report(m)

References

  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press, ch. 15.
  • Cameron, A. C. & Trivedi, P. K. (2005). Microeconometrics. Cambridge University Press, ch. 14.
source

Marginal Effects and Odds Ratios

MacroEconometricModels.marginal_effectsFunction
marginal_effects(m::LogitModel{T}; type=:ame, at=nothing, conf_level=0.95) -> MarginalEffects{T}

Compute marginal effects from a logistic regression model with delta-method SEs.

Types

  • :ame — Average Marginal Effects: (1/N) sumi f(Xi beta) * beta_j
  • :mem — Marginal Effects at the Mean: f(Xbar beta) * betaj
  • :mer — Marginal Effects at Representative values: f(x0 beta) * betaj

where f(eta) = logistic PDF = p(1-p) and p = 1/(1+exp(-eta)).

Arguments

  • m::LogitModel{T} — estimated logit model
  • type::Symbol — :ame (default), :mem, or :mer
  • at::Union{Nothing,Dict} — for :mer, Dict mapping column index => value
  • conf_level::Real — confidence level (default 0.95)

Returns

MarginalEffects{T} with effects, delta-method SEs, z-stats, p-values, and CIs.

Examples

m = estimate_logit(y, X)
me_ame = marginal_effects(m)                          # AME
me_mem = marginal_effects(m; type=:mem)                # MEM
me_mer = marginal_effects(m; type=:mer, at=Dict(2=>0.0))  # MER at x2=0

References

  • Cameron, A. C. & Trivedi, P. K. (2005). Microeconometrics. Cambridge University Press, ch. 14.
  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press.
source
marginal_effects(m::ProbitModel{T}; type=:ame, at=nothing, conf_level=0.95) -> MarginalEffects{T}

Compute marginal effects from a probit regression model with delta-method SEs.

Types

  • :ame — Average Marginal Effects: (1/N) sumi phi(Xi beta) * beta_j
  • :mem — Marginal Effects at the Mean: phi(Xbar beta) * betaj
  • :mer — Marginal Effects at Representative values: phi(x0 beta) * betaj

where phi(eta) = standard normal PDF.

Arguments

  • m::ProbitModel{T} — estimated probit model
  • type::Symbol — :ame (default), :mem, or :mer
  • at::Union{Nothing,Dict} — for :mer, Dict mapping column index => value
  • conf_level::Real — confidence level (default 0.95)

Returns

MarginalEffects{T} with effects, delta-method SEs, z-stats, p-values, and CIs.

Examples

m = estimate_probit(y, X)
me_ame = marginal_effects(m)                          # AME
me_mem = marginal_effects(m; type=:mem)                # MEM
me_mer = marginal_effects(m; type=:mer, at=Dict(2=>0.0))  # MER at x2=0

References

  • Cameron, A. C. & Trivedi, P. K. (2005). Microeconometrics. Cambridge University Press, ch. 14.
source
marginal_effects(m::OrderedLogitModel{T}) -> NamedTuple

Compute average marginal effects (AME) for an ordered logit model.

Returns a K x J matrix of AMEs where element (k,j) is the average marginal effect of variable k on P(y = j).

Formula: dP(y=j)/dxk = [f(alpha{j-1} - x'beta) - f(alphaj - x'beta)] * betak where f is the logistic PDF, alpha0 = -Inf, alphaJ = +Inf.

Key property: AMEs sum to zero across categories for each variable.

Returns

Named tuple with fields:

  • effects::Matrix{T} – K x J matrix of AMEs
  • varnames::Vector{String} – variable names
  • categories::Vector – category labels

References

  • Cameron, A. C. & Trivedi, P. K. (2005). Microeconometrics. Cambridge University Press, ch. 15.
  • Greene, W. H. (2012). Econometric Analysis. 7th ed. Prentice Hall.
source
marginal_effects(m::OrderedProbitModel{T}) -> NamedTuple

Compute average marginal effects (AME) for an ordered probit model.

Same structure as marginal_effects(::OrderedLogitModel) but using the standard normal PDF.

References

  • Cameron, A. C. & Trivedi, P. K. (2005). Microeconometrics. Cambridge University Press, ch. 15.
  • Greene, W. H. (2012). Econometric Analysis. 7th ed. Prentice Hall.
source
marginal_effects(m::MultinomialLogitModel{T}) -> NamedTuple

Compute average marginal effects (AME) for a multinomial logit model.

Returns a K x J matrix of AMEs where element (k,j) is the average marginal effect of variable k on P(y = j).

Formula: dP(y=j)/dxk = pj * (beta{j,k} - summ pm * beta{m,k}) where beta for the base category = 0.

Key property: AMEs sum to zero across categories for each variable.

Returns

Named tuple with fields:

  • effects::Matrix{T} – K x J matrix of AMEs
  • varnames::Vector{String} – variable names
  • categories::Vector – category labels

References

  • Cameron, A. C. & Trivedi, P. K. (2005). Microeconometrics. Cambridge University Press, ch. 15.
  • Train, K. E. (2009). Discrete Choice Methods with Simulation. 2nd ed. Cambridge Univ. Press.
source
marginal_effects(m::PanelLogitModel{T}; conf_level=0.95, n_quadrature=12) -> MarginalEffects{T}

Compute average marginal effects from a panel logit model with delta-method SEs.

Formulas by model type

  • Pooled: AMEj = (1/n) sumi Lambda(xi'beta)(1-Lambda(xi'beta)) * beta_j
  • FE (conditional): AMEj = (1/n) sumi Lambda(xi'beta)(1-Lambda(xi'beta)) * beta_j (evaluated at observed X without entity effects)
  • RE: AMEj = (1/n) sumi integral Lambda(xi'beta + sigmausqrt(2)u)(1-Lambda(...)) * beta_j * w(u) du (integrated over random effect using Gauss-Hermite quadrature)
  • CRE: Same as RE but only reports AMEs for original variables (not group-mean augmented ones)

Arguments

  • m::PanelLogitModel{T} – estimated panel logit model
  • conf_level::Real – confidence level for CIs (default 0.95)
  • n_quadrature::Int – number of Gauss-Hermite quadrature points for RE/CRE (default 12)

Returns

MarginalEffects{T} with AMEs, delta-method SEs, z-stats, p-values, and CIs.

References

  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press.
  • Cameron, A. C. & Trivedi, P. K. (2005). Microeconometrics. Cambridge University Press.
source
marginal_effects(m::PanelProbitModel{T}; conf_level=0.95, n_quadrature=12) -> MarginalEffects{T}

Compute average marginal effects from a panel probit model with delta-method SEs.

Formulas by model type

  • Pooled: AMEj = (1/n) sumi phi(xi'beta) * betaj
  • RE: AMEj = (1/n) sumi integral phi(xi'beta + sigmausqrt(2)u) * beta_j * w(u) du
  • CRE: Same as RE but only reports AMEs for original variables

Arguments

  • m::PanelProbitModel{T} – estimated panel probit model
  • conf_level::Real – confidence level for CIs (default 0.95)
  • n_quadrature::Int – Gauss-Hermite quadrature points for RE/CRE (default 12)

Returns

MarginalEffects{T} with AMEs, delta-method SEs, z-stats, p-values, and CIs.

source
MacroEconometricModels.odds_ratioFunction
odds_ratio(m::LogitModel{T}; conf_level=0.95) -> NamedTuple

Compute odds ratios from a logistic regression model with delta-method CIs.

ORj = exp(betaj). Standard error via delta method: SE(OR) = OR * SE(beta). Confidence intervals on log scale: exp(beta +/- z * SE(beta)).

Arguments

  • m::LogitModel{T} — estimated logit model
  • conf_level::Real — confidence level (default 0.95)

Returns

Named tuple with fields:

  • or::Vector{T} — odds ratios exp(beta)
  • se::Vector{T} — delta-method standard errors
  • ci_lower::Vector{T} — lower CI bounds
  • ci_upper::Vector{T} — upper CI bounds
  • varnames::Vector{String} — variable names

Examples

m = estimate_logit(y, X)
result = odds_ratio(m)
result.or       # odds ratios
result.ci_lower # lower 95% CI

References

  • Agresti, A. (2002). Categorical Data Analysis. 2nd ed. Wiley, ch. 5.
source

Diagnostics

MacroEconometricModels.vifFunction
vif(m::RegModel{T}) -> Vector{T}

Compute Variance Inflation Factors for each non-intercept regressor.

VIFj = 1 / (1 - R^2j), where R^2j is the R-squared from regressing xj on all other regressors (excluding the intercept column). A VIF > 10 indicates severe multicollinearity (Belsley, Kuh & Welsch 1980).

Arguments

  • m::RegModel{T} — estimated OLS/WLS model

Returns

Vector{T} of VIF values, one per non-intercept regressor. The order matches m.varnames with the intercept column removed.

Examples

m = estimate_reg(y, X; varnames=["const", "x1", "x2"])
v = vif(m)  # VIF for x1, x2

References

  • Belsley, D. A., Kuh, E. & Welsch, R. E. (1980). Regression Diagnostics. Wiley.
  • Greene, W. H. (2018). Econometric Analysis. 8th ed. Pearson, ch. 4.
source
MacroEconometricModels.classification_tableFunction
classification_table(m::Union{LogitModel{T},ProbitModel{T}}; threshold=0.5) -> Dict{String,Any}

Compute a classification table (confusion matrix) and summary metrics for a binary response model.

Arguments

  • m — estimated LogitModel or ProbitModel
  • threshold::Real — classification threshold (default 0.5)

Returns

Dict with keys:

  • "confusion" — 2x2 confusion matrix [[TN, FP], [FN, TP]]
  • "accuracy" — (TP + TN) / N
  • "sensitivity" — TP / (TP + FN) (true positive rate / recall)
  • "specificity" — TN / (TN + FP) (true negative rate)
  • "precision" — TP / (TP + FP) (positive predictive value)
  • "f1_score" — 2 * precision * recall / (precision + recall)
  • "n" — number of observations
  • "threshold" — classification threshold used

Examples

m = estimate_logit(y, X)
ct = classification_table(m)
ct["accuracy"]    # overall accuracy
ct["confusion"]   # 2x2 confusion matrix

References

  • Agresti, A. (2002). Categorical Data Analysis. 2nd ed. Wiley.
source

Ordered and Multinomial Models

MacroEconometricModels.estimate_ologitFunction
estimate_ologit(y, X; cov_type=:ols, varnames=nothing, clusters=nothing, maxiter=200, tol=1e-8) -> OrderedLogitModel{T}

Estimate an ordered logistic regression model via maximum likelihood (Newton-Raphson).

Model

Cumulative link model: P(y <= j | x) = Logistic(alpha_j - x' beta). X should NOT include an intercept column – it is absorbed into cutpoints.

Arguments

  • y::AbstractVector – ordinal dependent variable (will be remapped to 1:J)
  • X::AbstractMatrix{T} – regressor matrix (n x K, no intercept)
  • cov_type::Symbol – covariance estimator: :ols (MLE), :hc1 (sandwich)
  • varnames::Union{Nothing,Vector{String}} – coefficient names (auto-generated if nothing)
  • clusters::Union{Nothing,AbstractVector} – cluster assignments (for :cluster)
  • maxiter::Int – maximum Newton-Raphson iterations (default 200)
  • tol – convergence tolerance (default 1e-8)

Returns

OrderedLogitModel{T} with estimated coefficients, cutpoints, and joint vcov.

Examples

using MacroEconometricModels, Random, Distributions
rng = MersenneTwister(42)
n = 1000
X = randn(rng, n, 2)
xb = X * [1.0, -0.5]
p = 1 ./ (1 .+ exp.(-([0.0 1.5]' .- xb)))
u = rand(rng, n)
y = [u[i] < p[1,i] ? 1 : u[i] < p[2,i] ? 2 : 3 for i in 1:n]
m = estimate_ologit(y, X; varnames=["x1", "x2"])
report(m)

References

  • McCullagh, P. (1980). JRSS B 42(2), 109-142.
  • Agresti, A. (2010). Analysis of Ordinal Categorical Data. 2nd ed. Wiley.
source
MacroEconometricModels.estimate_oprobitFunction
estimate_oprobit(y, X; cov_type=:ols, varnames=nothing, clusters=nothing, maxiter=200, tol=1e-8) -> OrderedProbitModel{T}

Estimate an ordered probit regression model via maximum likelihood (Newton-Raphson).

Model

Cumulative link model: P(y <= j | x) = Phi(alpha_j - x' beta). X should NOT include an intercept column – it is absorbed into cutpoints.

Arguments

Same as estimate_ologit.

Returns

OrderedProbitModel{T} with estimated coefficients, cutpoints, and joint vcov.

Examples

using MacroEconometricModels, Random, Distributions
rng = MersenneTwister(42)
n = 1000
X = randn(rng, n, 2)
xb = X * [0.8, -0.5]
d = Normal()
p = cdf.(d, [0.0 1.0]' .- xb)
u = rand(rng, n)
y = [u[i] < p[1,i] ? 1 : u[i] < p[2,i] ? 2 : 3 for i in 1:n]
m = estimate_oprobit(y, X; varnames=["x1", "x2"])
report(m)

References

  • McCullagh, P. (1980). JRSS B 42(2), 109-142.
  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press.
source
MacroEconometricModels.estimate_mlogitFunction
estimate_mlogit(y, X; cov_type=:ols, varnames=nothing, clusters=nothing, maxiter=200, tol=1e-8) -> MultinomialLogitModel{T}

Estimate a multinomial logistic regression model via maximum likelihood (Newton-Raphson).

Model

Multinomial logit: P(y = j | x) = exp(x' betaj) / sumk exp(x' betak), with beta1 = 0 (base category).

Arguments

  • y::AbstractVector – categorical dependent variable (will be remapped to 1:J)
  • X::AbstractMatrix{T} – regressor matrix (n x K)
  • cov_type::Symbol – covariance estimator: :ols (MLE), :hc0, :hc1 (sandwich), :cluster
  • varnames::Union{Nothing,Vector{String}} – coefficient names (auto-generated if nothing)
  • clusters::Union{Nothing,AbstractVector} – cluster assignments (for :cluster)
  • maxiter::Int – maximum Newton-Raphson iterations (default 200)
  • tol – convergence tolerance (default 1e-8)

Returns

MultinomialLogitModel{T} with estimated coefficients and joint vcov.

Examples

using MacroEconometricModels, Random
rng = MersenneTwister(42)
n = 1000
X = [ones(n) randn(rng, n, 2)]
beta_true = [0.5 -0.3; 1.0 -0.5; -0.5 0.8]  # K=3 x (J-1)=2
V = X * beta_true
P = exp.(V) ./ (1 .+ sum(exp.(V), dims=2))
# ... generate y from probabilities
m = estimate_mlogit(y, X; varnames=["const", "x1", "x2"])
report(m)

References

  • McFadden, D. (1974). Conditional logit analysis of qualitative choice behavior.
  • Train, K. E. (2009). Discrete Choice Methods with Simulation. 2nd ed. Cambridge Univ. Press.
source
MacroEconometricModels.brant_testFunction
brant_test(m::OrderedLogitModel{T}) -> NamedTuple

Brant test of the proportional odds (parallel regression) assumption for an ordered logit model.

For each cutpoint j = 1,...,J-1, fits a binary logit (y <= j vs y > j). Under H0 (proportional odds), all binary logit coefficients should be equal.

Algorithm

  1. Fit J-1 binary logits splitting at each cutpoint
  2. Compute Wald statistic comparing each binary logit's beta to the pooled ordered logit estimate
  3. Overall test: chi-squared with K*(J-2) degrees of freedom
  4. Per-variable tests: chi-squared with (J-2) df each

Returns

Named tuple with fields:

  • statistic::T – overall Wald test statistic
  • pvalue::T – overall p-value (chi-squared)
  • df::Int – degrees of freedom K*(J-2)
  • per_variable::Vector{T} – per-variable p-values (length K)
  • binary_coefs::Matrix{T} – K x (J-1) matrix of binary logit coefficients

References

  • Brant, R. (1990). Assessing proportionality in the proportional odds model for ordinal logistic regression. Biometrics 46, 1171-1178.
source
MacroEconometricModels.hausman_iiaFunction
hausman_iia(m::MultinomialLogitModel{T}; omit_category::Int) -> NamedTuple

Hausman-McFadden test of the Independence of Irrelevant Alternatives (IIA) assumption for a multinomial logit model.

Re-estimates the model excluding observations where y = omit_category, then compares coefficients for the remaining categories with the full model using a Hausman-type statistic.

Arguments

  • m::MultinomialLogitModel{T} – estimated full multinomial logit model
  • omit_category::Int – category to omit (1-based index into m.categories)

Returns

Named tuple with fields:

  • statistic::T – Hausman test statistic
  • pvalue::T – p-value (chi-squared)
  • df::Int – degrees of freedom
  • omitted_category – the omitted category label

References

  • Hausman, J. & McFadden, D. (1984). Specification Tests for the Multinomial Logit Model. Econometrica 52(5), 1219-1240.
source

VAR Estimation

Frequentist Estimation

MacroEconometricModels.estimate_varFunction
estimate_var(Y::AbstractMatrix{T}, p::Int; check_stability::Bool=true) -> VARModel{T}

Estimate VAR(p) via OLS: Yₜ = c + A₁Yₜ₋₁ + ... + AₚYₜ₋ₚ + uₜ.

Arguments

  • Y: Data matrix (T × n)
  • p: Number of lags
  • check_stability: If true (default), warns if estimated VAR is non-stationary

Returns

VARModel with estimated coefficients, residuals, covariance matrix, and information criteria.

source

Estimate VAR from DataFrame. Use vars to select columns.

source
StatsAPI.predictFunction
StatsAPI.predict(m::RegModel{T}, X_new::AbstractMatrix) -> Vector{T}

Predict fitted values for new data from a linear regression model.

Returns X_new * beta.

Arguments

  • m::RegModel{T} — estimated OLS/WLS/IV model
  • X_new::AbstractMatrix — new regressor matrix (n_new x k)

Returns

Vector{T} of predicted values.

Examples

m = estimate_reg(y, X)
y_hat = predict(m, X_test)
source
StatsAPI.predict(m::LogitModel{T}, X_new::AbstractMatrix) -> Vector{T}

Predict probabilities for new data from a logistic regression model.

Returns 1 / (1 + exp(-X_new * beta)).

Arguments

  • m::LogitModel{T} — estimated logit model
  • X_new::AbstractMatrix — new regressor matrix (n_new x k)

Returns

Vector{T} of predicted probabilities in (0, 1).

Examples

m = estimate_logit(y, X)
p_hat = predict(m, X_test)
source
StatsAPI.predict(m::ProbitModel{T}, X_new::AbstractMatrix) -> Vector{T}

Predict probabilities for new data from a probit regression model.

Returns Phi(X_new * beta), where Phi is the standard normal CDF.

Arguments

  • m::ProbitModel{T} — estimated probit model
  • X_new::AbstractMatrix — new regressor matrix (n_new x k)

Returns

Vector{T} of predicted probabilities in (0, 1).

Examples

m = estimate_probit(y, X)
p_hat = predict(m, X_test)
source
StatsAPI.predict(m::OrderedLogitModel{T}, X_new::AbstractMatrix) -> Matrix{T}

Predict category probabilities for new data from an ordered logit model.

Returns an n_new x J probability matrix where each row sums to 1.

source
StatsAPI.predict(m::OrderedProbitModel{T}, X_new::AbstractMatrix) -> Matrix{T}

Predict category probabilities for new data from an ordered probit model.

Returns an n_new x J probability matrix where each row sums to 1.

source
StatsAPI.predict(m::MultinomialLogitModel{T}, X_new::AbstractMatrix) -> Matrix{T}

Predict category probabilities for new data from a multinomial logit model.

Returns an n_new x J probability matrix where each row sums to 1.

source

In-sample fitted values.

source

Out-of-sample forecasts for steps periods.

source

Predicted values: F * Λ'.

source

Predicted values: F * Λ'.

source

Predicted values (common component).

source
predict(model::AbstractARIMAModel, h::Int) -> Vector{T}

Return h-step ahead point forecasts (without confidence intervals).

source

Conditional variance series $\hat{\sigma}^2_t$.

source

Conditional variance series $\hat{\sigma}^2_t$.

source

Conditional variance series $\hat{\sigma}^2_t$.

source

Conditional variance series $\hat{\sigma}^2_t$.

source

Posterior mean volatility series $\hat{\sigma}^2_t$.

source
StatsAPI.confintMethod

Confidence intervals for RegModel coefficients (t-distribution).

source

Confidence intervals for LogitModel coefficients (normal distribution).

source

Confidence intervals for ProbitModel coefficients (normal distribution).

source

Confidence intervals at given level (default 95%).

source

Confidence intervals for PanelRegModel coefficients (t-distribution).

source

Confidence intervals for PanelIVModel coefficients (t-distribution).

source

Confidence intervals for PanelLogitModel coefficients (normal distribution).

source

Confidence intervals for PanelProbitModel coefficients (normal distribution).

source

Bayesian Estimation

MacroEconometricModels.estimate_bvarFunction
estimate_bvar(Y, p; n_draws=1000, sampler=:direct, burnin=0, thin=1,
              prior=:normal, hyper=nothing) -> BVARPosterior

Estimate Bayesian VAR via conjugate Normal-Inverse-Wishart posterior.

Model

Y = X B + E,    E ~ MN(0, Σ, I_T)
Prior: Σ ~ IW(ν₀, S₀),  vec(B)|Σ ~ N(b₀, Σ ⊗ V₀)

Samplers

  • :direct (default) — i.i.d. draws from analytical posterior. burnin and thin are ignored.
  • :gibbs — Standard two-block Gibbs sampler. burnin defaults to 200 if not specified.

Arguments

  • Y::AbstractMatrix: T × n data matrix
  • p::Int: Number of lags

Keyword Arguments

  • n_draws::Int=1000: Number of posterior draws to keep
  • sampler::Symbol=:direct: Sampling algorithm (:direct or :gibbs)
  • burnin::Int=0: Burnin period (only for :gibbs; defaults to 200 when sampler=:gibbs and burnin=0)
  • thin::Int=1: Thinning interval (only for :gibbs)
  • prior::Symbol=:normal: Prior type (:normal or :minnesota)
  • hyper::Union{Nothing,MinnesotaHyperparameters}=nothing: Minnesota hyperparameters. When prior=:minnesota and hyper=nothing, tau is automatically optimized via marginal likelihood maximization (Giannone, Lenza & Primiceri 2015). Pass an explicit MinnesotaHyperparameters(...) to use fixed values instead.

Returns

BVARPosterior{T} containing coefficient and covariance draws.

Example

Y = randn(200, 3)
post = estimate_bvar(Y, 2; n_draws=1000)
post_mn = estimate_bvar(Y, 2; prior=:minnesota, n_draws=500)
source

VAR/BVAR Forecasting

MacroEconometricModels._estimate_favar_bayesianMethod
_estimate_favar_bayesian(X, Y_key, r, p, n_draws, burnin, pvn, Y_key_indices, aug_varnames) -> BayesianFAVAR

Bayesian FAVAR via Gibbs sampling (Bernanke, Boivin & Eliasz 2005, Section IV).

Algorithm:

  1. Initialize factors via PCA
  2. Gibbs sampler iterates:
    • Draw (B, Σ) | F, Y_key from the VAR posterior
    • Draw Λ | F, X equation-by-equation
    • Draw F | Λ, B, Σ, X, Y_key via regression posterior
  3. Store post-burnin draws
source
MacroEconometricModels._remove_double_countingMethod
_remove_double_counting(F_raw, Y_key) -> Matrix{T}

Remove the component of Fraw that is spanned by Ykey (BBE 2005 Step 2).

For each factor column, regress it on Y_key via OLS and keep the residual. This yields "slow-moving" factors that are orthogonal to the key variables.

source
MacroEconometricModels.estimate_bvarMethod
estimate_bvar(Y, p; n_draws=1000, sampler=:direct, burnin=0, thin=1,
              prior=:normal, hyper=nothing) -> BVARPosterior

Estimate Bayesian VAR via conjugate Normal-Inverse-Wishart posterior.

Model

Y = X B + E,    E ~ MN(0, Σ, I_T)
Prior: Σ ~ IW(ν₀, S₀),  vec(B)|Σ ~ N(b₀, Σ ⊗ V₀)

Samplers

  • :direct (default) — i.i.d. draws from analytical posterior. burnin and thin are ignored.
  • :gibbs — Standard two-block Gibbs sampler. burnin defaults to 200 if not specified.

Arguments

  • Y::AbstractMatrix: T × n data matrix
  • p::Int: Number of lags

Keyword Arguments

  • n_draws::Int=1000: Number of posterior draws to keep
  • sampler::Symbol=:direct: Sampling algorithm (:direct or :gibbs)
  • burnin::Int=0: Burnin period (only for :gibbs; defaults to 200 when sampler=:gibbs and burnin=0)
  • thin::Int=1: Thinning interval (only for :gibbs)
  • prior::Symbol=:normal: Prior type (:normal or :minnesota)
  • hyper::Union{Nothing,MinnesotaHyperparameters}=nothing: Minnesota hyperparameters. When prior=:minnesota and hyper=nothing, tau is automatically optimized via marginal likelihood maximization (Giannone, Lenza & Primiceri 2015). Pass an explicit MinnesotaHyperparameters(...) to use fixed values instead.

Returns

BVARPosterior{T} containing coefficient and covariance draws.

Example

Y = randn(200, 3)
post = estimate_bvar(Y, 2; n_draws=1000)
post_mn = estimate_bvar(Y, 2; prior=:minnesota, n_draws=500)
source
MacroEconometricModels.estimate_favarMethod
estimate_favar(X, Y_key, r, p; method=:two_step, panel_varnames=nothing) -> FAVARModel
estimate_favar(X, key_indices::Vector{Int}, r, p; ...) -> FAVARModel

Estimate a Factor-Augmented VAR (Bernanke, Boivin & Eliasz, 2005).

Two-Step Algorithm (BBE 2005)

  1. Extract r factors from panel X via PCA (estimate_factors)
  2. Remove double-counting: regress each factor on Y_key, use residuals as slow-moving factors F_tilde
  3. Estimate VAR(p) on augmented system [F_tilde, Y_key]

Arguments

  • X: Panel data matrix (T x N) — large cross-section of macroeconomic variables
  • Y_key: Key observed variables (T x n_key) or column indices into X
  • r: Number of latent factors to extract
  • p: VAR lag order

Keyword Arguments

  • method::Symbol=:two_step: Estimation method (currently only :two_step)
  • panel_varnames::Union{Nothing, Vector{String}}=nothing: Names for the N panel variables
  • n_draws::Int=5000: Number of posterior draws (for Bayesian, reserved for future use)
  • burnin::Int=1000: Burn-in draws (for Bayesian, reserved for future use)

Returns

FAVARModel{T} with estimated VAR on [Ftilde, Ykey], factor loadings, and panel variable metadata for panel-wide IRF mapping.

Example

X = randn(200, 50)    # 200 obs, 50 variables
Y_key = X[:, [1, 5]]  # 2 key variables
favar = estimate_favar(X, Y_key, 3, 2)

# Or using column indices:
favar = estimate_favar(X, [1, 5], 3, 2)

# IRFs (via to_var delegation):
irf_result = irf(favar, 20)

# Panel-wide IRFs (all 50 variables):
panel_irfs = favar_panel_irf(favar, irf_result)
source
MacroEconometricModels.estimate_favarMethod
estimate_favar(X, key_indices::Vector{Int}, r, p; kwargs...) -> FAVARModel or BayesianFAVAR

Estimate FAVAR where key variables are specified as column indices of X.

source
MacroEconometricModels.estimate_pvarMethod
estimate_pvar(d::PanelData{T}, p::Int; kwargs...) -> PVARModel{T}

Estimate Panel VAR(p) via GMM.

Arguments

  • d::PanelData{T} — balanced panel data (use xtset to construct)
  • p::Int — number of lags

Keyword Arguments

  • dependent_vars::Union{Vector{String},Nothing}=nothing — endogenous variable names (default: all)
  • predet_vars::Vector{String}=String[] — predetermined variable names
  • exog_vars::Vector{String}=String[] — strictly exogenous variable names
  • transformation::Symbol=:fd:fd (first-difference) or :fod (forward orthogonal deviations)
  • steps::Symbol=:twostep:onestep, :twostep, or :mstep (iterated)
  • system_instruments::Bool=false — if true, use System GMM (Blundell-Bond)
  • system_constant::Bool=true — include constant in level equation (System GMM)
  • min_lag_endo::Int=2 — minimum instrument lag for endogenous variables
  • max_lag_endo::Int=99 — maximum instrument lag (99 = all available)
  • collapse::Bool=false — collapse instruments to limit proliferation
  • pca_instruments::Bool=false — apply PCA reduction to instruments
  • pca_max_components::Int=0 — max PCA components (0 = auto)
  • max_iter::Int=100 — max iterations for iterated GMM

Returns

  • PVARModel{T} with coefficient estimates, robust standard errors, and GMM internals

References

  • Arellano, M. & Bond, S. (1991). Review of Economic Studies 58(2), 277-297.
  • Blundell, R. & Bond, S. (1998). Journal of Econometrics 87(1), 115-143.
  • Windmeijer, F. (2005). Journal of Econometrics 126(1), 25-51.

Examples

pd = xtset(df, :id, :time)
model = estimate_pvar(pd, 2; steps=:twostep)
model = estimate_pvar(pd, 1; system_instruments=true, steps=:twostep)
source
MacroEconometricModels.estimate_pvar_feolsMethod
estimate_pvar_feols(d::PanelData{T}, p::Int; kwargs...) -> PVARModel{T}

Estimate Panel VAR(p) via Fixed Effects OLS (within estimator).

Simpler than GMM but subject to Nickell (1981) bias when T is small relative to N. Uses within-group demeaning to remove fixed effects, then pooled OLS with cluster-robust standard errors.

Arguments

  • d::PanelData{T} — panel data
  • p::Int — number of lags

Keyword Arguments

  • dependent_vars::Union{Vector{String},Nothing}=nothing — endogenous variable names
  • predet_vars::Vector{String}=String[] — predetermined variable names
  • exog_vars::Vector{String}=String[] — strictly exogenous variable names

Examples

pd = xtset(df, :id, :time)
model = estimate_pvar_feols(pd, 2)
source
MacroEconometricModels.estimate_varMethod
estimate_var(Y::AbstractMatrix{T}, p::Int; check_stability::Bool=true) -> VARModel{T}

Estimate VAR(p) via OLS: Yₜ = c + A₁Yₜ₋₁ + ... + AₚYₜ₋ₚ + uₜ.

Arguments

  • Y: Data matrix (T × n)
  • p: Number of lags
  • check_stability: If true (default), warns if estimated VAR is non-stationary

Returns

VARModel with estimated coefficients, residuals, covariance matrix, and information criteria.

source
MacroEconometricModels.extract_chain_parametersMethod
extract_chain_parameters(post::BVARPosterior) -> (b_vecs, sigmas)

Extract coefficient vectors and covariance matrices from posterior draws. Returns matrices compatible with downstream parameters_to_model calls.

  • b_vecs: n_draws × (k*n) matrix of vectorized coefficients
  • sigmas: n_draws × (n*n) matrix of vectorized covariance matrices
source
MacroEconometricModels.forecastMethod
forecast(post::BVARPosterior, h; reps=nothing, conf_level=0.95, point_estimate=:mean) -> BVARForecast{T}

Forecast from Bayesian VAR using posterior draws.

For each posterior draw, iterates the VAR recursion forward h steps. Returns posterior mean forecast with credible intervals from the distribution of forecast paths across draws.

Arguments

  • post: BVAR posterior
  • h: Forecast horizon

Keyword Arguments

  • reps: Number of posterior draws to use (default: all)
  • conf_level: Credible interval level (default: 0.95)
  • point_estimate: :mean (default) or :median for central tendency

Returns

BVARForecast{T} with posterior mean forecast and credible intervals.

Example

post = estimate_bvar(Y, 4; n_draws=1000)
fc = forecast(post, 12)
source
MacroEconometricModels.forecastMethod
forecast(model::VARModel, h; ci_method=:bootstrap, reps=500, conf_level=0.95) -> VARForecast{T}

Forecast from VAR model for h steps ahead with optional bootstrap CIs.

Iterates the VAR recursion forward using the estimated coefficients and the last p observations as initial conditions.

Arguments

  • model: Estimated VAR model
  • h: Forecast horizon (number of steps ahead)
  • ci_method: :bootstrap (default) or :none
  • reps: Number of bootstrap replications (default 500)
  • conf_level: Confidence level for intervals (default 0.95)

Returns

VARForecast{T} with point forecasts and CIs.

Example

model = estimate_var(Y, 4)
fc = forecast(model, 12)  # 12-step ahead forecast with bootstrap CIs
source

Forecast Accessors

MacroEconometricModels.point_forecastFunction
point_forecast(f::AbstractForecastResult)

Return the point forecast values (Vector or Matrix).

Most subtypes store the point forecast in a .forecast field; this default accessor returns that field. Overrides exist for VECMForecast (.levels) and FactorForecast (.observables).

source
MacroEconometricModels.lower_boundFunction
lower_bound(f::AbstractForecastResult)

Return the lower confidence interval bound.

Most subtypes store this in .ci_lower; an override exists for FactorForecast (.observables_lower).

source
MacroEconometricModels.upper_boundFunction
upper_bound(f::AbstractForecastResult)

Return the upper confidence interval bound.

Most subtypes store this in .ci_upper; an override exists for FactorForecast (.observables_upper).

source

Prior Specification

MacroEconometricModels.gen_dummy_obsMethod
gen_dummy_obs(Y, p, hyper) -> (Y_dummy, X_dummy)

Generate Minnesota prior dummy observations. Hyperparameters: tau (tightness), decay, lambda (sum-of-coef), mu (co-persistence), omega.

source

VECM Estimation

MacroEconometricModels.estimate_vecmFunction
estimate_vecm(Y, p; rank=:auto, deterministic=:constant, method=:johansen, significance=0.05)

Estimate a Vector Error Correction Model.

Arguments

  • Y: Data matrix (T × n) in levels
  • p: Underlying VAR order (VECM has p-1 lagged differences)
  • rank: Cointegrating rank; :auto (default) selects via Johansen trace test, or specify an integer
  • deterministic: :none, :constant (default), or :trend
  • method: :johansen (default) or :engle_granger (bivariate, rank=1 only)
  • significance: Significance level for automatic rank selection (default 0.05)

Returns

VECMModel with estimated α, β, Γ matrices, residuals, and diagnostics.

Example

Y = cumsum(randn(200, 3), dims=1)
Y[:, 2] = Y[:, 1] + 0.1 * randn(200)
m = estimate_vecm(Y, 2)
source
MacroEconometricModels.to_varFunction
to_var(vecm::VECMModel) -> VARModel

Convert VECM to VAR in levels representation.

The VECM: ΔYₜ = ΠYₜ₋₁ + Σᵢ ΓᵢΔYₜ₋ᵢ + μ + uₜ maps to VAR: Yₜ = c + A₁Yₜ₋₁ + ... + AₚYₜ₋ₚ + uₜ

with:

  • A₁ = Π + Iₙ + Γ₁
  • Aᵢ = Γᵢ - Γᵢ₋₁ for i = 2, ..., p-1
  • Aₚ = -Γₚ₋₁
source
to_var(favar::FAVARModel) -> VARModel

Convert a FAVAR to a standard VARModel for use with irf, fevd, historical_decomposition, and other structural analysis methods.

This follows the same delegation pattern as to_var(vecm::VECMModel).

source
MacroEconometricModels.granger_causality_vecmFunction
granger_causality_vecm(vecm, cause, effect) -> VECMGrangerResult

Test Granger causality from variable cause to variable effect in a VECM.

Three tests are computed:

  1. Short-run: Wald test on Γ coefficients of the cause variable in the effect equation
  2. Long-run: Wald test on α coefficients in the effect equation (error correction channel)
  3. Strong: Joint test of both short-run and long-run

Arguments

  • vecm: Estimated VECMModel
  • cause: Index of the causing variable
  • effect: Index of the effect variable

Returns

VECMGrangerResult with test statistics, p-values, and degrees of freedom.

source

VECM Analysis and Forecasting

MacroEconometricModels.irfMethod
irf(vecm::VECMModel, horizon; kwargs...) -> ImpulseResponse

Compute IRFs for a VECM by converting to VAR representation. All identification methods (Cholesky, sign, narrative, etc.) are supported.

source
MacroEconometricModels.forecastMethod
forecast(vecm::VECMModel, h; ci_method=:none, reps=500, conf_level=0.95) -> VECMForecast

Forecast from a VECM by iterating the VECM equations in levels.

Unlike VAR forecasting, this preserves the cointegrating relationships in the forecast path.

Arguments

  • vecm: Estimated VECM
  • h: Forecast horizon
  • ci_method: :none (default), :bootstrap, or :simulation
  • reps: Number of bootstrap/simulation replications (default 500)
  • conf_level: Confidence level (default 0.95)

Returns

VECMForecast with level and difference forecasts, plus CIs if requested.

source

Structural Identification

MacroEconometricModels.compute_QMethod
compute_Q(model, method, horizon, check_func, narrative_check;
          max_draws=100, transition_var=nothing, regime_indicator=nothing)

Compute identification matrix Q for structural VAR analysis.

Methods

  • :cholesky — Cholesky decomposition (recursive ordering)
  • :sign — Sign restrictions (requires check_func)
  • :narrative — Narrative restrictions (requires check_func and narrative_check)
  • :long_run — Long-run restrictions (Blanchard-Quah)
  • :fastica — FastICA (Hyvärinen 1999)
  • :jade — JADE (Cardoso 1999)
  • :sobi — SOBI (Belouchrani et al. 1997)
  • :dcov — Distance covariance ICA (Matteson & Tsay 2017)
  • :hsic — HSIC independence ICA (Gretton et al. 2005)
  • :student_t — Student-t ML (Lanne et al. 2017)
  • :mixture_normal — Mixture of normals ML (Lanne et al. 2017)
  • :pml — Pseudo-ML (Gouriéroux et al. 2017)
  • :skew_normal — Skew-normal ML (Lanne & Luoto 2020)
  • :nongaussian_ml — Unified non-Gaussian ML dispatcher (default: Student-t)
  • :markov_switching — Markov-switching heteroskedasticity (Lütkepohl & Netšunajev 2017)
  • :garch — GARCH-based heteroskedasticity (Normandin & Phaneuf 2004)
  • :smooth_transition — Smooth-transition heteroskedasticity (requires transition_var)
  • :external_volatility — External volatility regimes (requires regime_indicator)

Keyword Arguments

  • max_draws::Int=100: Maximum draws for sign/narrative identification
  • transition_var::Union{Nothing,AbstractVector}=nothing: Transition variable for :smooth_transition
  • regime_indicator::Union{Nothing,AbstractVector{Int}}=nothing: Regime indicator for :external_volatility
source
MacroEconometricModels.compute_irfMethod
compute_irf(model, Q, horizon) -> Array{T,3}

Compute IRFs for rotation matrix Q. Returns (horizon × n × n) array. IRF[h, i, j] = response of variable i to shock j at horizon h-1.

source
MacroEconometricModels.identify_signMethod
identify_sign(model, horizon, check_func; max_draws=1000, store_all=false)

Find Q satisfying sign restrictions via random draws.

With store_all=false (default), returns (Q, irf) — the first valid rotation. With store_all=true, returns a SignIdentifiedSet containing ALL accepted rotations and their IRFs (Baumeister & Hamilton, 2015).

source
MacroEconometricModels.irf_boundsMethod
irf_bounds(s::SignIdentifiedSet{T}; quantiles=[0.16, 0.84]) -> (lower, upper)

Compute pointwise bounds (or quantile bands) over the identified set.

source

Arias et al. (2018) Sign/Zero Restrictions

MacroEconometricModels.identify_ariasFunction
identify_arias(model, restrictions, horizon; n_draws=1000, n_rotations=1000, compute_weights=true) -> AriasSVARResult

Identify SVAR using Arias et al. (2018) with zero and sign restrictions.

Uses importance sampling with draw-dependent weights (Proposition 4) for zero+sign restriction combinations. For pure sign restrictions, draws uniformly from O(n) with unit weights.

Keywords

  • n_draws::Int=1000: Target number of accepted draws
  • n_rotations::Int=1000: Maximum attempts per target draw
  • compute_weights::Bool=true: Compute importance weights (set false for faster exploratory analysis)
source
MacroEconometricModels.identify_arias_bayesianFunction
identify_arias_bayesian(post::BVARPosterior, restrictions, horizon; data=nothing, n_rotations=100, quantiles=[0.16,0.5,0.84], compute_weights=true)

Apply Arias identification to each posterior draw. Returns IRF quantiles, mean, acceptance rates.

Creates the _AriasSVARSetup once (W matrices fixed across all posterior draws) for consistency.

source

Sign-Identified Set

MacroEconometricModels.irf_boundsFunction
irf_bounds(s::SignIdentifiedSet{T}; quantiles=[0.16, 0.84]) -> (lower, upper)

Compute pointwise bounds (or quantile bands) over the identified set.

source

Mountford-Uhlig (2009) Penalty Function

MacroEconometricModels.identify_uhligFunction
identify_uhlig(model::VARModel{T}, restrictions::SVARRestrictions, horizon::Int;
    n_starts=50, n_refine=10, max_iter_coarse=500, max_iter_fine=2000,
    tol_coarse=1e-4, tol_fine=1e-8) -> UhligSVARResult{T}

Identify SVAR using Mountford & Uhlig (2009) penalty function approach.

Uses Nelder-Mead optimization over spherical coordinates to find the rotation matrix $Q$ that best satisfies sign restrictions, with zero restrictions enforced as hard constraints via null-space projection.

Algorithm

  1. Precompute MA coefficients and Cholesky factor $L$
  2. Phase 1 (coarse): n_starts Nelder-Mead runs from random $\theta_0 \in [0, 2\pi]$
  3. Phase 2 (refinement): n_refine local re-optimizations from best solution
  4. Build final $Q$, compute IRFs, check convergence

Keywords

  • n_starts::Int=50: Number of random starting points (Phase 1)
  • n_refine::Int=10: Number of local refinements (Phase 2)
  • max_iter_coarse::Int=500: Max iterations per Phase 1 run
  • max_iter_fine::Int=2000: Max iterations per Phase 2 run
  • tol_coarse::T=1e-4: Convergence tolerance for Phase 1
  • tol_fine::T=1e-8: Convergence tolerance for Phase 2

Returns

UhligSVARResult{T} with optimal rotation matrix, IRFs, penalty values, and convergence indicator.

Example

model = estimate_var(Y, 2)
restrictions = SVARRestrictions(3;
    zeros = [zero_restriction(3, 1)],
    signs = [sign_restriction(1, 1, :positive),
             sign_restriction(2, 1, :positive)]
)
result = identify_uhlig(model, restrictions, 20)

Reference: Mountford & Uhlig (2009)

source

Innovation Accounting

Impulse Response Functions

MacroEconometricModels.cumulative_irfMethod
cumulative_irf(irf_result::BayesianImpulseResponse{T}) -> BayesianImpulseResponse{T}

Compute cumulative Bayesian impulse response: Σₛ₌₀ʰ IRF_s.

When raw posterior draws are available, cumulates each draw first then extracts quantiles — the statistically correct approach.

source
MacroEconometricModels.cumulative_irfMethod
cumulative_irf(irf_result::ImpulseResponse{T}) -> ImpulseResponse{T}

Compute cumulative impulse response for VAR models: Σₛ₌₀ʰ IRF_s.

When raw bootstrap/simulation draws are available, cumulates each draw first then extracts quantiles — the statistically correct approach since quantiles are NOT additive: Qα(A+B) ≠ Qα(A) + Q_α(B).

source
MacroEconometricModels.irfMethod
irf(post::BVARPosterior, horizon; method=:cholesky, quantiles=[0.16, 0.5, 0.84], point_estimate=:mean, ...)

Compute Bayesian IRFs from posterior draws with posterior quantiles. Uses posterior mean as central tendency by default (pass point_estimate=:median for median).

Methods

:cholesky, :sign, :narrative, :long_run, :fastica, :jade, :sobi, :dcov, :hsic, :student_t, :mixture_normal, :pml, :skew_normal, :nongaussian_ml, :markov_switching, :garch, :smooth_transition, :external_volatility

Note: :smooth_transition requires transition_var kwarg. :external_volatility requires regime_indicator kwarg.

Uses process_posterior_samples and compute_posterior_quantiles from bayesian_utils.jl.

source
MacroEconometricModels.irfMethod
irf(model, horizon; method=:cholesky, ci_type=:none, reps=200, conf_level=0.95, ...)

Compute IRFs with optional confidence intervals.

Methods

:cholesky, :sign, :narrative, :long_run, :fastica, :jade, :sobi, :dcov, :hsic, :student_t, :mixture_normal, :pml, :skew_normal, :nongaussian_ml, :markov_switching, :garch, :smooth_transition, :external_volatility

Note: :smooth_transition requires transition_var kwarg. :external_volatility requires regime_indicator kwarg.

CI types

:none, :bootstrap, :theoretical

source
MacroEconometricModels.lp_irfMethod
lp_irf(Y::AbstractMatrix, shock_var::Int, horizon::Int; kwargs...) -> LPImpulseResponse

Convenience function: estimate LP and extract IRF in one call.

source
MacroEconometricModels.lp_irfMethod
lp_irf(model::LPModel{T}; conf_level::Real=0.95) -> LPImpulseResponse{T}

Extract impulse response function with confidence intervals from LP model.

source

Forecast Error Variance Decomposition

MacroEconometricModels.fevdMethod
fevd(model, horizon; method=:cholesky, ...) -> FEVD

Compute FEVD showing proportion of h-step forecast error variance attributable to each shock.

Methods

:cholesky, :sign, :narrative, :long_run, :fastica, :jade, :sobi, :dcov, :hsic, :student_t, :mixture_normal, :pml, :skew_normal, :nongaussian_ml, :markov_switching, :garch, :smooth_transition, :external_volatility

Note: :smooth_transition requires transition_var kwarg. :external_volatility requires regime_indicator kwarg.

source

Historical Decomposition

MacroEconometricModels.contributionMethod
contribution(hd::BayesianHistoricalDecomposition, var, shock; stat=:mean) -> Vector

Get contribution time series for specific variable and shock (Bayesian).

Arguments

  • hd: Bayesian historical decomposition result
  • var: Variable index (Int) or name (String)
  • shock: Shock index (Int) or name (String)
  • stat: :mean or quantile index (Int)
source
MacroEconometricModels.contributionMethod
contribution(hd::HistoricalDecomposition, var, shock) -> Vector

Get contribution time series for specific variable and shock.

Arguments

  • hd: Historical decomposition result
  • var: Variable index (Int) or name (String)
  • shock: Shock index (Int) or name (String)

Example

contrib_y1_s1 = contribution(hd, 1, 1)  # Contribution of shock 1 to variable 1
contrib_y1_s1 = contribution(hd, "Var 1", "Shock 1")
source
MacroEconometricModels.historical_decompositionFunction
historical_decomposition(post::BVARPosterior, horizon; data=..., ...) -> BayesianHistoricalDecomposition

Compute Bayesian historical decomposition from posterior draws with posterior quantiles.

Arguments

  • post::BVARPosterior: Posterior draws from estimate_bvar
  • horizon::Int: Maximum horizon for MA coefficients

Keyword Arguments

  • data::AbstractMatrix: Override data matrix (defaults to post.data)
  • method::Symbol=:cholesky: Identification method
  • quantiles::Vector{<:Real}=[0.16, 0.5, 0.84]: Posterior quantile levels
  • check_func=nothing: Sign restriction check function
  • narrative_check=nothing: Narrative restriction check function
  • transition_var=nothing: Transition variable (for method=:smooth_transition)
  • regime_indicator=nothing: Regime indicator (for method=:external_volatility)

Methods

:cholesky, :sign, :narrative, :long_run, :fastica, :jade, :sobi, :dcov, :hsic, :student_t, :mixture_normal, :pml, :skew_normal, :nongaussian_ml, :markov_switching, :garch, :smooth_transition, :external_volatility

Note: :smooth_transition requires transition_var kwarg. :external_volatility requires regime_indicator kwarg.

Returns

BayesianHistoricalDecomposition with posterior quantiles and means.

Example

post = estimate_bvar(Y, 2; n_draws=500)
hd = historical_decomposition(post, 198)
source
MacroEconometricModels.historical_decompositionMethod
historical_decomposition(slp::StructuralLP{T}, T_hd::Int) -> HistoricalDecomposition{T}

Compute historical decomposition from structural LP.

Uses LP-estimated IRFs as the structural MA coefficients Θ_h and the structural shocks from the underlying VAR identification.

Arguments

  • slp: Structural LP result
  • T_hd: Number of time periods for decomposition (≤ T_eff of underlying VAR)

Returns

HistoricalDecomposition{T} with contributions, initial conditions, and actual data.

source
MacroEconometricModels.historical_decompositionMethod
historical_decomposition(model::VARModel, restrictions::SVARRestrictions, horizon; ...) -> BayesianHistoricalDecomposition

Compute historical decomposition using Arias et al. (2018) identification with importance weights.

Arguments

  • model::VARModel: Estimated VAR model
  • restrictions::SVARRestrictions: Zero and sign restrictions
  • horizon::Int: Maximum horizon for MA coefficients

Keyword Arguments

  • n_draws::Int=1000: Number of accepted draws
  • n_rotations::Int=1000: Maximum rotation attempts per draw
  • quantiles::Vector{<:Real}=[0.16, 0.5, 0.84]: Quantile levels for weighted quantiles

Returns

BayesianHistoricalDecomposition with weighted posterior quantiles and means.

Example

r = SVARRestrictions(3; signs=[sign_restriction(1, 1, :positive)])
hd = historical_decomposition(model, r, 198; n_draws=500)
source
MacroEconometricModels.historical_decompositionMethod
historical_decomposition(model::VARModel, horizon; method=:cholesky, ...) -> HistoricalDecomposition

Compute historical decomposition for a VAR model.

Decomposes observed data into contributions from each structural shock plus initial conditions.

Arguments

  • model::VARModel: Estimated VAR model
  • horizon::Int: Maximum horizon for MA coefficient computation (typically T_eff)

Keyword Arguments

  • method::Symbol=:cholesky: Identification method
  • check_func=nothing: Sign restriction check function (for method=:sign or :narrative)
  • narrative_check=nothing: Narrative restriction check function (for method=:narrative)
  • max_draws::Int=1000: Maximum draws for sign/narrative identification
  • transition_var=nothing: Transition variable (for method=:smooth_transition)
  • regime_indicator=nothing: Regime indicator (for method=:external_volatility)

Methods

:cholesky, :sign, :narrative, :long_run, :fastica, :jade, :sobi, :dcov, :hsic, :student_t, :mixture_normal, :pml, :skew_normal, :nongaussian_ml, :markov_switching, :garch, :smooth_transition, :external_volatility

Note: :smooth_transition requires transition_var kwarg. :external_volatility requires regime_indicator kwarg.

Returns

HistoricalDecomposition containing:

  • contributions: Shock contributions (Teff × nvars × n_shocks)
  • initial_conditions: Initial condition effects (Teff × nvars)
  • actual: Actual data values
  • shocks: Structural shocks

Example

model = estimate_var(Y, 2)
hd = historical_decomposition(model, size(Y, 1) - 2)
verify_decomposition(hd)  # Check decomposition identity
source
MacroEconometricModels.verify_decompositionMethod
verify_decomposition(hd::HistoricalDecomposition; tol=1e-10) -> Bool

Verify that contributions + initial_conditions ≈ actual.

Example

hd = historical_decomposition(model, horizon)
@assert verify_decomposition(hd) "Decomposition identity failed"
source

Summary Tables

MacroEconometricModels.point_estimateMethod
point_estimate(result::AbstractAnalysisResult)

Get the point estimate from an analysis result.

Returns the main values/estimates (IRF values, FEVD proportions, HD contributions).

source
MacroEconometricModels.reportMethod
report(model::VARModel)

Print comprehensive VAR model summary including specification, per-equation coefficient estimates with standard errors and significance, information criteria, residual covariance, and stationarity check.

source
MacroEconometricModels.reportMethod
report(vecm::VECMModel)

Print comprehensive VECM summary including cointegrating vectors, adjustment coefficients, short-run dynamics, and diagnostics.

source

Local Projections

Core LP Estimation and Covariance

MacroEconometricModels._lp_robust_vcovMethod
_lp_robust_vcov(X_h, U_h, cov_estimator, h)

Horizon-aware robust variance-covariance for LP regressions.

LP residuals at horizon h have MA(h-1) serial correlation (Jordà 2005), so the Newey-West bandwidth must be at least h+1. When automatic bandwidth selection (bandwidth == 0) yields a smaller value, this function enforces the floor max(m̂_NW, h+1).

For non-NW estimators (White, Driscoll-Kraay), falls through to the standard compute_block_robust_vcov.

source
MacroEconometricModels.build_control_columns!Method
build_control_columns!(X_h::AbstractMatrix{T}, Y::AbstractMatrix{T},
                       t_start::Int, t_end::Int, lags::Int, start_col::Int) where T

Fill control (lagged Y) columns into regressor matrix X_h. Returns the next available column index.

source
MacroEconometricModels.construct_lp_matricesMethod
construct_lp_matrices(Y::AbstractMatrix{T}, shock_var::Int, h::Int, lags::Int;
                      response_vars::Vector{Int}=collect(1:size(Y,2))) where T

Construct regressor and response matrices for LP regression at horizon h.

Returns: (Yh, Xh, valid_idx)

source
MacroEconometricModels.estimate_lpMethod
estimate_lp(Y::AbstractMatrix{T}, shock_var::Int, horizon::Int;
            lags::Int=4, response_vars::Vector{Int}=collect(1:size(Y,2)),
            cov_type::Symbol=:newey_west, bandwidth::Int=0,
            conf_level::Real=0.95) -> LPModel{T}

Estimate Local Projection impulse response functions (Jordà 2005).

The LP regression for horizon h: y{t+h} = αh + βh * shockt + Γh * controlst + ε_{t+h}

source
MacroEconometricModels.extract_shock_irfMethod
extract_shock_irf(B::Vector{Matrix{T}}, vcov::Vector{Matrix{T}},
                  response_vars::Vector{Int}, shock_coef_idx::Int;
                  conf_level::Real=0.95) where T

Generic IRF extraction from coefficient and covariance vectors. Works for LPModel, LPIVModel, PropensityLPModel.

source
MacroEconometricModels.structural_lpMethod
structural_lp(Y::AbstractMatrix{T}, horizon::Int;
              method=:cholesky, lags=4, var_lags=nothing,
              cov_type=:newey_west, conf_level=0.95,
              ci_type=:none, reps=200,
              check_func=nothing, narrative_check=nothing,
              max_draws=1000,
              transition_var=nothing, regime_indicator=nothing) -> StructuralLP{T}

Estimate structural LP impulse responses using VAR-based identification with LP estimation.

Algorithm:

  1. Estimate VAR(p) → obtain Σ and residuals
  2. Compute rotation matrix Q via chosen identification method
  3. Compute structural shocks εt = Q'L⁻¹ut
  4. For each shock j, run LP with εj as regressor and Yeff as responses
  5. Stack into 3D IRF array: irfs[h, i, j]

Arguments

  • Y: T × n data matrix
  • horizon: Maximum IRF horizon H

Keyword Arguments

  • method: Identification method
  • lags: Number of LP control lags (default: 4)
  • var_lags: VAR lag order for identification (default: same as lags)
  • cov_type: HAC estimator (:newey_west, :white)
  • conf_level: Confidence level for CIs (default: 0.95)
  • ci_type: CI method (:none, :bootstrap)
  • reps: Number of bootstrap replications
  • check_func: Sign restriction check function (for :sign/:narrative)
  • narrative_check: Narrative check function (for :narrative)
  • max_draws: Maximum draws for sign/narrative identification
  • transition_var: Transition variable (for :smooth_transition)
  • regime_indicator: Regime indicator (for :external_volatility)

Methods

:cholesky, :sign, :narrative, :long_run, :fastica, :jade, :sobi, :dcov, :hsic, :student_t, :mixture_normal, :pml, :skew_normal, :nongaussian_ml, :markov_switching, :garch, :smooth_transition, :external_volatility

Note: :smooth_transition requires transition_var kwarg. :external_volatility requires regime_indicator kwarg.

Returns

StructuralLP{T} with 3D IRFs, structural shocks, VAR model, and individual LP models.

References

Plagborg-Møller, M. & Wolf, C. K. (2021). "Local Projections and VARs Estimate the Same Impulse Responses." Econometrica, 89(2), 955–980.

source

LP-IV (Stock & Watson 2018)

MacroEconometricModels.estimate_lp_ivMethod
estimate_lp_iv(Y::AbstractMatrix{T}, shock_var::Int, instruments::AbstractMatrix{T},
               horizon::Int; lags::Int=4, response_vars::Vector{Int}=collect(1:size(Y,2)),
               cov_type::Symbol=:newey_west, bandwidth::Int=0) -> LPIVModel{T}

Estimate LP with Instrumental Variables (Stock & Watson 2018) using 2SLS.

source
MacroEconometricModels.first_stage_regressionMethod
first_stage_regression(endog::AbstractVector{T}, instruments::AbstractMatrix{T},
                       controls::AbstractMatrix{T}; h::Int=0) -> NamedTuple

First-stage regression for 2SLS with HAC-robust F-statistic for instrument relevance.

At LP horizon h > 0, residuals have MA(h-1) autocorrelation by construction (Jordà 2005), so the F-statistic uses Newey-West HAC variance with bandwidth ≥ h+1.

source
MacroEconometricModels.tsls_regressionMethod
tsls_regression(Y::AbstractMatrix{T}, endog::AbstractVector{T},
                endog_fitted::AbstractVector{T}, controls::AbstractMatrix{T};
                cov_estimator::AbstractCovarianceEstimator=NeweyWestEstimator()) -> NamedTuple

Second-stage regression using fitted values from first stage.

source

Smooth LP (Barnichon & Brownlees 2019)

MacroEconometricModels.bspline_basisMethod
bspline_basis(horizons::AbstractVector{Int}, degree::Int, n_interior_knots::Int;
              T::Type{<:AbstractFloat}=Float64) -> BSplineBasis{T}

Construct B-spline basis matrix for given horizons.

source
MacroEconometricModels.cross_validate_lambdaMethod
cross_validate_lambda(Y::AbstractMatrix{T}, shock_var::Int, horizon::Int;
                      lambda_grid::Vector{T}=T.(10.0 .^ (-4:0.5:2)),
                      k_folds::Int=5, kwargs...) -> T

Select optimal λ via k-fold cross-validation.

source
MacroEconometricModels.estimate_smooth_lpMethod
estimate_smooth_lp(Y::AbstractMatrix{T}, shock_var::Int, horizon::Int;
                   degree::Int=3, n_knots::Int=4, lambda::T=T(0.0),
                   lags::Int=4, response_vars::Vector{Int}=collect(1:size(Y,2)),
                   cov_type::Symbol=:newey_west, bandwidth::Int=0) -> SmoothLPModel{T}

Estimate Smooth LP with B-spline parameterization (Barnichon & Brownlees 2019).

source

State-Dependent LP (Auerbach & Gorodnichenko 2013)

MacroEconometricModels.estimate_state_lpMethod
estimate_state_lp(Y::AbstractMatrix{T}, shock_var::Int, state_var::AbstractVector{T},
                  horizon::Int; gamma::Union{T,Symbol}=:estimate, ...) -> StateLPModel{T}

Estimate state-dependent LP (Auerbach & Gorodnichenko 2013).

source

Propensity Score LP (Angrist et al. 2018)

MacroEconometricModels.doubly_robust_lpMethod
doubly_robust_lp(Y::AbstractMatrix{T}, treatment::AbstractVector{Bool},
                 covariates::AbstractMatrix{T}, horizon::Int; ...) -> PropensityLPModel{T}

Doubly robust LP estimator combining IPW and regression adjustment.

source
MacroEconometricModels.estimate_propensity_lpMethod
estimate_propensity_lp(Y::AbstractMatrix{T}, treatment::AbstractVector{Bool},
                       covariates::AbstractMatrix{T}, horizon::Int; ...) -> PropensityLPModel{T}

Estimate LP with Inverse Propensity Weighting (Angrist et al. 2018).

source
MacroEconometricModels.inverse_propensity_weightsMethod
inverse_propensity_weights(treatment::AbstractVector{Bool}, propensity::AbstractVector{T};
                           trimming::Tuple{T,T}=(T(0.01), T(0.99)), normalize::Bool=true) -> Vector{T}

Compute IPW weights with optional trimming.

source

LP Forecasting

MacroEconometricModels.forecastMethod
forecast(lp::LPModel{T}, shock_path::AbstractVector{<:Real};
         ci_method=:analytical, conf_level=0.95, n_boot=500) -> LPForecast{T}

Compute direct multi-step LP forecasts given a shock trajectory.

For each horizon h=1,...,H, the forecast uses the LP regression coefficients: ŷ{T+h} = αh + βh·shockh + Γh·controlsT

where controls_T are the last lags observations of Y.

Arguments

  • lp: Estimated LP model
  • shock_path: Vector of length H with assumed future shock values

Keyword Arguments

  • ci_method: :analytical (default), :bootstrap, or :none
  • conf_level: Confidence level (default: 0.95)
  • n_boot: Number of bootstrap replications (default: 500)

Returns

LPForecast{T} with point forecasts, CIs, and standard errors.

source
MacroEconometricModels.forecastMethod
forecast(slp::StructuralLP{T}, shock_idx::Int, shock_path::AbstractVector{<:Real};
         ci_method=:analytical, conf_level=0.95, n_boot=500) -> LPForecast{T}

Compute direct multi-step forecast from a structural LP model using a specific orthogonalized shock.

Arguments

  • slp: Structural LP model
  • shock_idx: Index of the structural shock to use (1:n)
  • shock_path: Vector of length H with assumed shock values

Keyword Arguments

  • ci_method: :analytical (default), :bootstrap, or :none
  • conf_level: Confidence level (default: 0.95)
  • n_boot: Number of bootstrap replications (default: 500)
source

LP-FEVD (Gorodnichenko & Lee 2019)

MacroEconometricModels._lp_fevd_bootstrapMethod

Bootstrap bias correction and CIs for LP-FEVD.

  1. Fit bivariate VAR(L) on (z, y) with HQIC lag selection
  2. Compute 'true' FEVD from VAR (theoretical benchmark)
  3. Simulate B samples from VAR, compute LP-FEVD for each
  4. Bias = mean(bootstrap FEVD) - true FEVD
  5. Bias-corrected = raw - bias
  6. CIs from centered bootstrap distribution (Kilian 1998)
source
MacroEconometricModels._lp_fevd_lpa_hMethod
_lp_fevd_lpa_h(lp_model, shock, resp_idx, h) -> T

LP-A FEVD: ŝh = (Σ{i=0}^{h} β̂₀^{i,LP}² σ̂z²) / Var(f̂{t+h|t-1}). Uses IRF coefficients directly — no R² regression needed.

source
MacroEconometricModels._lp_fevd_lpb_hMethod
_lp_fevd_lpb_h(f_hat, shock, lp_model, resp_idx, t_start, h) -> T

LP-B FEVD: ŝh = numerator / (numerator + Var(ṽ{t+h|t-1})), where ṽ is the residual from the R²-regression (Eq. 6).

source
MacroEconometricModels.fevdMethod
fevd(slp::StructuralLP{T}, horizon::Int; kwargs...) -> LPFEVD{T}

Compute LP-based FEVD for structural LP results. Dispatches to lp_fevd.

See lp_fevd for full documentation.

source
MacroEconometricModels.lp_fevdMethod
lp_fevd(slp::StructuralLP{T}, horizon::Int; kwargs...) -> LPFEVD{T}

Compute LP-based FEVD using the R²-based estimator of Gorodnichenko & Lee (2019).

At each horizon h, the share of variable i's forecast error variance due to shock j is estimated by regressing LP forecast error residuals on structural shock leads z{t+h}, z{t+h-1}, ..., z_t and computing R².

Arguments

  • slp: Structural LP result from structural_lp()
  • horizon: Maximum FEVD horizon (capped at IRF horizon)

Keyword Arguments

  • method: Estimator (:r2, :lpa, :lpb). Default: :r2
  • bias_correct: Apply VAR-based bootstrap bias correction. Default: true
  • n_boot: Number of bootstrap replications. Default: 500
  • conf_level: Confidence level for CIs. Default: 0.95
  • var_lags: VAR lag order for bias correction (default: HQIC-selected)

Returns

LPFEVD{T} with raw proportions, bias-corrected values, SEs, and CIs.

Reference

Gorodnichenko, Y. & Lee, B. (2019). "Forecast Error Variance Decompositions with Local Projections." JBES, 38(4), 921–933.

source

Factor Models

Static Factor Model

MacroEconometricModels._estimate_restricted_emMethod
_estimate_restricted_em(X, r, blocks, standardize; max_iter=500, tol=1e-6) -> FactorModel

Estimate block-restricted factor model via EM algorithm.

Each factor loads only on its assigned block of variables. The restriction mask R enforces zero loadings outside each block.

Algorithm

  1. Validate block structure (count, overlap, range, minimum size)
  2. Build N × r restriction mask R from block assignments
  3. Initialize Λ via block-wise PCA (first eigenvector per block)
  4. EM iteration:
    • E-step: F = X Λ (Λ'Λ)⁻¹ (posterior mean of factors given loadings)
    • M-step: Λ_new = (F'F)⁻¹ F'X, masked by R (zero out restricted entries)
  5. Convergence when max absolute change in Λ < tol
source
MacroEconometricModels.estimate_factorsMethod
estimate_factors(X, r; standardize=true, blocks=nothing) -> FactorModel

Estimate static factor model Xt = Λ Ft + e_t via Principal Component Analysis, or via block-restricted EM when blocks is provided.

Arguments

  • X: Data matrix (T × N), observations × variables
  • r: Number of factors to extract

Keyword Arguments

  • standardize::Bool=true: Standardize data before estimation
  • blocks::Union{Nothing, Dict{Symbol, Vector{Int}}}=nothing: Block restriction map. When provided, each key is a block (factor) name and the value is a vector of variable indices that load on that factor. Variables not in a block have zero loadings on that factor. The number of blocks must equal r.

Returns

FactorModel containing factors, loadings, eigenvalues, and explained variance. When blocks is provided, block_names is set on the returned model.

Example

X = randn(200, 50)  # 200 observations, 50 variables
fm = estimate_factors(X, 3)  # Extract 3 factors via PCA
r2(fm)  # R² for each variable

# Block-restricted estimation
blocks = Dict(:real => [1,2,3,4,5], :nominal => [6,7,8,9,10])
fm_restricted = estimate_factors(X, 2; blocks=blocks)
source
MacroEconometricModels.forecastMethod
forecast(model::FactorModel, h; p=1, ci_method=:theoretical, conf_level=0.95, n_boot=1000)

Forecast factors and observables h steps ahead from a static factor model.

Internally fits a VAR(p) on the extracted factors, then uses the VAR dynamics to produce multi-step forecasts and confidence intervals.

Arguments

  • model: Estimated static factor model
  • h: Forecast horizon

Keyword Arguments

  • p::Int=1: VAR lag order for factor dynamics
  • ci_method::Symbol=:theoretical: CI method — :none, :theoretical, or :bootstrap
  • conf_level::Real=0.95: Confidence level for intervals
  • n_boot::Int=1000: Number of bootstrap replications (if ci_method=:bootstrap)

Returns

FactorForecast with factor and observable forecasts (and CIs if requested).

source
MacroEconometricModels.ic_criteriaMethod
ic_criteria(X, max_factors; standardize=true)

Compute Bai-Ng (2002) information criteria IC1, IC2, IC3 for selecting the number of factors.

Arguments

  • X: Data matrix (T × N)
  • max_factors: Maximum number of factors to consider

Returns

Named tuple with IC values and optimal factor counts:

  • IC1, IC2, IC3: Information criteria vectors
  • r_IC1, r_IC2, r_IC3: Optimal factor counts

Example

result = ic_criteria(X, 10)
println("Optimal factors: IC1=", result.r_IC1, ", IC2=", result.r_IC2, ", IC3=", result.r_IC3)
source
MacroEconometricModels.scree_plot_dataMethod
scree_plot_data(m::FactorModel)

Return data for scree plot: factor indices, explained variance, cumulative variance.

Example

data = scree_plot_data(fm)
# Plot: data.factors vs data.explained_variance
source

Dynamic Factor Model

MacroEconometricModels.companion_matrix_factorsMethod
companion_matrix_factors(model::DynamicFactorModel)

Construct companion matrix for factor VAR dynamics.

The companion form converts VAR(p) to VAR(1): [Ft; F{t-1}; ...] = C [F{t-1}; F{t-2}; ...] + [η_t; 0; ...]

source
MacroEconometricModels.estimate_dynamic_factorsMethod
estimate_dynamic_factors(X, r, p; method=:twostep, standardize=true, max_iter=100, tol=1e-6)

Estimate dynamic factor model with VAR(p) factor dynamics.

Arguments

  • X: Data matrix (T × N)
  • r: Number of factors
  • p: Number of lags in factor VAR

Keyword Arguments

  • method::Symbol=:twostep: Estimation method (:twostep or :em)
  • standardize::Bool=true: Standardize data
  • max_iter::Int=100: Maximum EM iterations (if method=:em)
  • tol::Float64=1e-6: Convergence tolerance (if method=:em)
  • diagonal_idio::Bool=true: Assume diagonal idiosyncratic covariance

Returns

DynamicFactorModel with factors, loadings, VAR coefficients, and diagnostics.

Example

dfm = estimate_dynamic_factors(X, 3, 2)  # 3 factors, VAR(2)
forecast(dfm, 12)  # 12-step ahead forecast
source
MacroEconometricModels.forecastMethod
forecast(model::DynamicFactorModel, h; ci_method=:theoretical, conf_level=0.95, n_boot=1000, ci=false, ci_level=0.95)

Forecast factors and observables h steps ahead.

Arguments

  • model: Estimated dynamic factor model
  • h: Forecast horizon

Keyword Arguments

  • ci_method::Symbol=:theoretical: CI method — :none, :theoretical, :bootstrap, or :simulation
  • conf_level::Real=0.95: Confidence level for intervals
  • n_boot::Int=1000: Bootstrap replications (for :bootstrap and :simulation)
  • ci::Bool=false: Legacy keyword — ci=true maps to ci_method=:simulation
  • ci_level::Real=0.95: Legacy keyword — maps to conf_level

Returns

FactorForecast with factor and observable forecasts (and CIs if requested).

Example

fc = forecast(dfm, 12; ci_method=:theoretical)
fc.observables       # h×N matrix of forecasts
fc.observables_lower # h×N lower CI bounds
source
MacroEconometricModels.ic_criteria_dynamicMethod
ic_criteria_dynamic(X, max_r, max_p; standardize=true, method=:twostep)

Select (r, p) via AIC/BIC grid search over factor and lag combinations.

Returns

Named tuple with AIC/BIC matrices and optimal (r, p) combinations.

source

Generalized Dynamic Factor Model

MacroEconometricModels.estimate_gdfmMethod
estimate_gdfm(X, q; standardize=true, bandwidth=0, kernel=:bartlett, r=0) -> GeneralizedDynamicFactorModel

Estimate Generalized Dynamic Factor Model using spectral methods.

Arguments

  • X: Data matrix (T × N)
  • q: Number of dynamic factors

Keyword Arguments

  • standardize::Bool=true: Standardize data
  • bandwidth::Int=0: Kernel bandwidth (0 = automatic selection)
  • kernel::Symbol=:bartlett: Kernel for spectral smoothing (:bartlett, :parzen, :tukey)
  • r::Int=0: Number of static factors (0 = same as q)

Returns

GeneralizedDynamicFactorModel with common/idiosyncratic components and spectral loadings.

Example

gdfm = estimate_gdfm(X, 3)
common_variance_share(gdfm)  # Fraction of variance explained by common component
source
MacroEconometricModels.forecastMethod
forecast(model::GeneralizedDynamicFactorModel, h; method=:ar, ci_method=:theoretical, conf_level=0.95, n_boot=1000)

Forecast h steps ahead using AR extrapolation of factors.

Arguments

  • model: Estimated GDFM
  • h: Forecast horizon

Keyword Arguments

  • method::Symbol=:ar: Forecasting method (currently only :ar supported)
  • ci_method::Symbol=:theoretical: CI method — :none, :theoretical, or :bootstrap
  • conf_level::Real=0.95: Confidence level for intervals
  • n_boot::Int=1000: Bootstrap replications (for :bootstrap)

Returns

FactorForecast with factor and observable forecasts (and CIs if requested).

source
MacroEconometricModels.ic_criteria_gdfmMethod
ic_criteria_gdfm(X, max_q; standardize=true, bandwidth=0, kernel=:bartlett)

Information criteria for selecting number of dynamic factors.

Uses eigenvalue ratio test and cumulative variance threshold.

Returns

Named tuple with:

  • eigenvalue_ratios: Ratios of consecutive eigenvalues
  • cumulative_variance: Cumulative variance explained
  • q_ratio: Optimal q from eigenvalue ratio
  • q_variance: Optimal q from 90% variance threshold
source

Panel VAR

Estimation

MacroEconometricModels.estimate_pvarFunction
estimate_pvar(d::PanelData{T}, p::Int; kwargs...) -> PVARModel{T}

Estimate Panel VAR(p) via GMM.

Arguments

  • d::PanelData{T} — balanced panel data (use xtset to construct)
  • p::Int — number of lags

Keyword Arguments

  • dependent_vars::Union{Vector{String},Nothing}=nothing — endogenous variable names (default: all)
  • predet_vars::Vector{String}=String[] — predetermined variable names
  • exog_vars::Vector{String}=String[] — strictly exogenous variable names
  • transformation::Symbol=:fd:fd (first-difference) or :fod (forward orthogonal deviations)
  • steps::Symbol=:twostep:onestep, :twostep, or :mstep (iterated)
  • system_instruments::Bool=false — if true, use System GMM (Blundell-Bond)
  • system_constant::Bool=true — include constant in level equation (System GMM)
  • min_lag_endo::Int=2 — minimum instrument lag for endogenous variables
  • max_lag_endo::Int=99 — maximum instrument lag (99 = all available)
  • collapse::Bool=false — collapse instruments to limit proliferation
  • pca_instruments::Bool=false — apply PCA reduction to instruments
  • pca_max_components::Int=0 — max PCA components (0 = auto)
  • max_iter::Int=100 — max iterations for iterated GMM

Returns

  • PVARModel{T} with coefficient estimates, robust standard errors, and GMM internals

References

  • Arellano, M. & Bond, S. (1991). Review of Economic Studies 58(2), 277-297.
  • Blundell, R. & Bond, S. (1998). Journal of Econometrics 87(1), 115-143.
  • Windmeijer, F. (2005). Journal of Econometrics 126(1), 25-51.

Examples

pd = xtset(df, :id, :time)
model = estimate_pvar(pd, 2; steps=:twostep)
model = estimate_pvar(pd, 1; system_instruments=true, steps=:twostep)
source
MacroEconometricModels.estimate_pvar_feolsFunction
estimate_pvar_feols(d::PanelData{T}, p::Int; kwargs...) -> PVARModel{T}

Estimate Panel VAR(p) via Fixed Effects OLS (within estimator).

Simpler than GMM but subject to Nickell (1981) bias when T is small relative to N. Uses within-group demeaning to remove fixed effects, then pooled OLS with cluster-robust standard errors.

Arguments

  • d::PanelData{T} — panel data
  • p::Int — number of lags

Keyword Arguments

  • dependent_vars::Union{Vector{String},Nothing}=nothing — endogenous variable names
  • predet_vars::Vector{String}=String[] — predetermined variable names
  • exog_vars::Vector{String}=String[] — strictly exogenous variable names

Examples

pd = xtset(df, :id, :time)
model = estimate_pvar_feols(pd, 2)
source

Structural Analysis

MacroEconometricModels.pvar_oirfFunction
pvar_oirf(model::PVARModel{T}, H::Int) -> Array{T, 3}

Orthogonalized impulse response functions via Cholesky decomposition.

Ψh = Φh P where P = chol(Σ) is the lower Cholesky factor.

Returns H+1 × m × m array: oirf[h+1, response, shock].

Arguments

  • model::PVARModel — estimated PVAR
  • H::Int — maximum horizon

Examples

oirf = pvar_oirf(model, 10)
oirf[1, :, :]  # impact response (h=0)
source
MacroEconometricModels.pvar_girfFunction
pvar_girf(model::PVARModel{T}, H::Int) -> Array{T, 3}

Generalized impulse response functions (Pesaran & Shin, 1998).

GIRFh(j) = Φh Σ ej / √σjj

where ej is the j-th unit vector and σjj = Σ[j,j].

Returns H+1 × m × m array: girf[h+1, response, shock].

source
MacroEconometricModels.pvar_fevdFunction
pvar_fevd(model::PVARModel{T}, H::Int) -> Array{T, 3}

Forecast error variance decomposition based on OIRF.

Ω[l, k, h] = Σ{j=0}^{h} (Ψj[l,k])² / MSE_h[l,l]

where MSEh = Σ{j=0}^{h} Φj Σ Φj'.

Returns H+1 × m × m array: fevd[h+1, variable, shock]. Each row sums to 1.

Examples

fv = pvar_fevd(model, 10)
sum(fv[11, 1, :])  # ≈ 1.0 (all shocks for var 1 at h=10)
source
MacroEconometricModels.pvar_stabilityFunction
pvar_stability(model::PVARModel{T}) -> PVARStability{T}

Check stability of the PVAR by computing eigenvalues of the companion matrix. The system is stable if all eigenvalue moduli are strictly less than 1.

Examples

stab = pvar_stability(model)
stab.is_stable  # true if all |λ| < 1
stab.moduli     # sorted eigenvalue moduli
source

Bootstrap

MacroEconometricModels.pvar_bootstrap_irfFunction
pvar_bootstrap_irf(model::PVARModel{T}, H::Int;
                    irf_type::Symbol=:oirf, n_draws::Int=500,
                    ci::Real=0.95, rng::AbstractRNG=Random.default_rng()) -> NamedTuple

Group-level block bootstrap for PVAR impulse response confidence intervals.

Resamples N groups with replacement → re-estimates PVAR → computes IRF → collects pointwise quantiles.

Arguments

  • model::PVARModel — estimated PVAR
  • H::Int — maximum IRF horizon

Keywords

  • irf_type::Symbol=:oirf:oirf or :girf
  • n_draws::Int=500 — number of bootstrap replications
  • ci::Real=0.95 — confidence level
  • rng::AbstractRNG — random number generator

Returns

NamedTuple with:

  • irf::Array{T,3} — point estimate (H+1 × m × m)
  • lower::Array{T,3} — lower CI bound
  • upper::Array{T,3} — upper CI bound
  • draws::Array{T,4} — all bootstrap draws (n_draws × H+1 × m × m)
source

Specification Tests

MacroEconometricModels.pvar_hansen_jFunction
pvar_hansen_j(model::PVARModel{T}) -> PVARTestResult{T}

Hansen (1982) J-test for overidentifying restrictions.

J = (Σi Zi' ei)' W (Σi Zi' ei) ~ χ²(q - k)

where q = number of instruments, k = number of parameters per equation.

H0: All moment conditions are valid. H1: Some moment conditions are invalid.

Examples

j = pvar_hansen_j(model)
j.pvalue > 0.05  # fail to reject → instruments valid
source
MacroEconometricModels.pvar_mmscFunction
pvar_mmsc(model::PVARModel{T}; hq_criterion::Real=2.1) -> NamedTuple

Andrews-Lu (2001) Model and Moment Selection Criteria based on Hansen J-statistic.

MMSCBIC = J - (c - b) × log(n) MMSCAIC = J - (c - b) × 2 MMSC_HQIC = J - Q(c - b) × log(log(n))

Lower values are preferred.

Returns

NamedTuple (bic, aic, hqic) of MMSC values.

Examples

mmsc = pvar_mmsc(model)
mmsc.bic   # MMSC-BIC value
source
MacroEconometricModels.pvar_lag_selectionFunction
pvar_lag_selection(d::PanelData{T}, max_p::Int; kwargs...) -> NamedTuple

Select optimal PVAR lag order by estimating models for p = 1, ..., max_p and comparing Andrews-Lu MMSC criteria.

Returns

NamedTuple with:

  • table::Matrix — comparison table (max_p × 4: p, BIC, AIC, HQIC)
  • best_bic::Int, best_aic::Int, best_hqic::Int — optimal lag orders
  • models::Vector{PVARModel} — estimated models

Examples

sel = pvar_lag_selection(pd, 4)
sel.best_bic  # optimal lag by BIC
source

GMM Utilities

MacroEconometricModels.linear_gmm_solveFunction
linear_gmm_solve(S_ZX::Matrix{T}, S_Zy::AbstractVecOrMat{T},
                  W::Matrix{T}) -> Vector{T}

Solve linear GMM analytically: E[Z'(y - Xβ)] = 0.

Given pre-aggregated cross-products SZX = Σi Zi'Xi and SZy = Σi Zi'yi:

β = (S_ZX' W S_ZX)⁻¹ S_ZX' W S_Zy

Arguments

  • S_ZX — q × k aggregated instrument-regressor cross-product
  • S_Zy — q × 1 (or q-vector) aggregated instrument-response cross-product
  • W — q × q weighting matrix

Returns

  • Parameter vector β (length k)
source
MacroEconometricModels.gmm_sandwich_vcovFunction
gmm_sandwich_vcov(S_ZX::Matrix{T}, W::Matrix{T},
                   D_e::Matrix{T}) -> Matrix{T}

Robust sandwich covariance for one-step GMM:

V = (S_ZX' W S_ZX)⁻¹ S_ZX' W D_e W S_ZX (S_ZX' W S_ZX)⁻¹

where De = Σi (Zi ei)(Zi ei)' is the robust moment covariance.

Arguments

  • S_ZX — q × k aggregated instrument-regressor cross-product
  • W — q × q weighting matrix
  • D_e — q × q robust moment covariance

Returns

  • k × k covariance matrix
source
MacroEconometricModels.andrews_lu_mmscFunction
andrews_lu_mmsc(j_stat::T, n_instruments::Int, n_params::Int,
                 n_obs::Int; hq_criterion::Real=2.1) -> NamedTuple

Andrews-Lu (2001) Model and Moment Selection Criteria based on Hansen J-statistic.

MMSC_BIC  = J - (c - b) × log(n)
MMSC_AIC  = J - (c - b) × 2
MMSC_HQIC = J - Q(c - b) × log(log(n))

where c = moment conditions, b = parameters, n = observations. Lower values indicate better model specification.

Arguments

  • j_stat — Hansen J-test statistic
  • n_instruments — number of moment conditions (c)
  • n_params — number of parameters (b)
  • n_obs — number of observations (n)
  • hq_criterion — penalty parameter Q for HQIC (default 2.1)

Returns

NamedTuple (bic, aic, hqic).

References

  • Andrews, D. & Lu, B. (2001). Journal of Econometrics 101(1), 123-164.
source

Difference-in-Differences

Estimation

MacroEconometricModels.estimate_didFunction
estimate_did(pd::PanelData{T}, outcome::Union{String,Symbol},
             treatment::Union{String,Symbol};
             method::Symbol=:twfe,
             leads::Int=0, horizon::Int=5,
             covariates::Vector{String}=String[],
             control_group::Symbol=:never_treated,
             cluster::Symbol=:unit,
             conf_level::Real=0.95) where {T}

Estimate a Difference-in-Differences model.

Arguments

  • pd: Panel data with outcome and treatment timing columns
  • outcome: Name of outcome variable
  • treatment: Name of treatment timing variable (contains period of first treatment; 0 or NaN for never-treated units)
  • method: Estimation method
    • :twfe – Two-Way Fixed Effects event-study regression (default)
    • :callaway_santanna – Callaway & Sant'Anna (2021) group-time ATT
    • :sun_abraham – Sun & Abraham (2021) interaction-weighted estimator
    • :bjs – Borusyak, Jaravel & Spiess (2024) imputation estimator
    • :did_multiplegt – de Chaisemartin & D'Haultfoeuille (2020)

Keyword Arguments

  • leads: Number of pre-treatment periods to estimate (default: 0)
  • horizon: Post-treatment horizon (default: 5)
  • covariates: Additional control variable names
  • control_group: :never_treated (default) or :not_yet_treated
  • cluster: SE clustering: :unit (default), :time, :twoway
  • conf_level: Confidence level (default: 0.95)
  • n_boot: Number of bootstrap replications for :did_multiplegt (default: 200)
  • base_period: :varying (default, R did default) or :universal. For :callaway_santanna only. :varying uses adjacent-period comparisons for pre-treatment cells; :universal always uses g-1 as base period

Returns

DIDResult{T} – unified result type for all methods.

Examples

# TWFE event study
did = estimate_did(pd, :gdp, :reform_year; method=:twfe, leads=3, horizon=5)
report(did)

# Callaway-Sant'Anna
did_cs = estimate_did(pd, :gdp, :reform_year; method=:callaway_santanna, leads=3, horizon=5)
plot_result(did_cs)

References

  • Callaway, B. & Sant'Anna, P. H. C. (2021). JoE 225(2), 200-230.
source
MacroEconometricModels.estimate_event_study_lpFunction
estimate_event_study_lp(pd::PanelData{T}, outcome::Union{String,Symbol},
                        treatment::Union{String,Symbol}, H::Int;
                        leads::Int=3, lags::Int=4,
                        covariates::Vector{String}=String[],
                        cluster::Symbol=:unit,
                        conf_level::Real=0.95) where {T}

Estimate event study impulse responses using local projections with panel FE.

Uses the switching indicator ΔD_{it} (= 1 only at the treatment onset period) and time-only FE. Already-treated observations are excluded from the sample.

Arguments

  • pd: Panel data
  • outcome: Outcome variable name
  • treatment: Treatment variable (binary 0/1 or timing column)
  • H: Maximum post-treatment horizon
  • leads: Number of pre-treatment leads to estimate (for pre-trends)
  • lags: Number of outcome lags as controls
  • covariates: Additional control variable names
  • cluster: Clustering level (:unit, :time, :twoway)
  • conf_level: Confidence level (default: 0.95)

Returns

EventStudyLP{T} with dynamic treatment effect coefficients.

References

  • Jordà, Ò. (2005). AER 95(1), 161-182.
  • Acemoglu, D. et al. (2019). JPE 127(1), 47-100.
source
MacroEconometricModels.estimate_lp_didFunction
estimate_lp_did(pd::PanelData{T}, outcome, treatment, H; kwargs...) -> LPDiDResult{T}

LP-DiD estimator with full feature parity to the Stata lpdid package v1.0.2.

Uses the switching indicator (ΔD_{it}) as treatment, clean control samples (CCS), and time-only fixed effects (long differencing absorbs unit FE).

Arguments

  • pd — panel data
  • outcome — outcome variable (name or symbol)
  • treatment — treatment variable (binary 0/1 or timing column)
  • H — maximum horizon

Keyword Arguments

  • pre_window::Int=3 — pre-treatment event-time window
  • post_window::Int=H — post-treatment event-time window
  • ylags::Int=0 — number of outcome lags as controls
  • dylags::Int=0 — number of ΔY lags as controls
  • covariates::Vector{String}=String[] — additional covariates
  • nonabsorbing::Union{Nothing,Int}=nothing — stabilization window L for non-absorbing treatment
  • notyet::Bool=false — restrict controls to not-yet-treated
  • nevertreated::Bool=false — restrict controls to never-treated
  • firsttreat::Bool=false — use only first treatment event per unit
  • oneoff::Bool=false — one-off treatment (requires nonabsorbing)
  • pmd::Union{Nothing,Symbol,Int}=nothing — pre-mean differencing (:max or integer k)
  • reweight::Bool=false — IPW reweighting for equally weighted ATE
  • nocomp::Bool=false — restrict to observations in CCS at all horizons
  • cluster::Symbol=:unit — clustering level (:unit, :time, :twoway)
  • conf_level::Real=0.95 — confidence level
  • only_pooled::Bool=false — skip event study, compute pooled only
  • only_event::Bool=false — skip pooled estimates
  • post_pooled::Union{Nothing,Tuple{Int,Int}}=nothing — pooled post-treatment window (start, end)
  • pre_pooled::Union{Nothing,Tuple{Int,Int}}=nothing — pooled pre-treatment window (start, end)

References

  • Dube, A., Girardi, D., Jordà, Ò. & Taylor, A.M. (2025). JAE.
  • Acemoglu, D. et al. (2019). JPE 127(1), 47-100.
source

Diagnostics

MacroEconometricModels.bacon_decompositionFunction
bacon_decomposition(pd::PanelData{T}, outcome::Union{String,Symbol},
                    treatment::Union{String,Symbol}) where {T}

Decompose the TWFE DiD estimator into a weighted average of all 2x2 DiD comparisons.

Each weight reflects the subsample size and variance of treatment within the comparison.

Returns

BaconDecomposition{T} with estimates, weights, and comparison types.

Reference

Goodman-Bacon, A. (2021). "Difference-in-Differences with Variation in Treatment Timing." JoE 225(2), 254-277.

source
MacroEconometricModels.pretrend_testFunction
pretrend_test(result::DIDResult{T}) where {T}
pretrend_test(result::EventStudyLP{T}) where {T}

Joint F-test for parallel trends: H0: beta{-K} = beta{-K+1} = ... = beta_{-1} = 0.

Tests whether pre-treatment event-time coefficients are jointly zero. High p-value -> no evidence against parallel trends.

Returns

PretrendTestResult{T} with F-statistic and p-value.

source
MacroEconometricModels.negative_weight_checkFunction
negative_weight_check(pd::PanelData{T}, treatment::Union{String,Symbol}) where {T}

de Chaisemartin & D'Haultfoeuille (2020) negative weight diagnostic.

Checks whether the TWFE estimator assigns negative weights to some group-time cells. Negative weights can cause the overall DiD estimate to have the opposite sign of all underlying ATT(g,t).

Returns

NegativeWeightResult{T}.

Reference

de Chaisemartin, C. & D'Haultfoeuille, X. (2020). AER 110(9), 2964-2996.

source

Sensitivity Analysis

MacroEconometricModels.honest_didFunction
honest_did(result::DIDResult{T}; Mbar::Real=1.0, conf_level::Real=0.95) where {T}

HonestDiD sensitivity analysis for a Difference-in-Differences result.

Constructs robust confidence intervals that account for bounded violations of the parallel trends assumption under the relative magnitudes restriction (Rambachan & Roth 2023).

Arguments

  • result::DIDResult{T} — DiD estimation result (from estimate_did or callaway_santanna)
  • Mbar::Real=1.0 — maximum violation bound (relative magnitudes parameter)
  • conf_level::Real=0.95 — confidence level for the robust CIs

Returns

HonestDiDResult{T} with robust CIs, breakdown value, and post-treatment estimates.

Example

did = estimate_did(pd, :y, :treat)
h = honest_did(did; Mbar=1.0)
h.breakdown_value  # smallest Mbar that overturns significance
source
honest_did(result::EventStudyLP{T}; Mbar::Real=1.0, conf_level::Real=0.95) where {T}

HonestDiD sensitivity analysis for an Event Study LP result.

Constructs robust confidence intervals that account for bounded violations of the parallel trends assumption under the relative magnitudes restriction (Rambachan & Roth 2023).

Arguments

  • result::EventStudyLP{T} — event study LP result (from event_study_lp or lp_did)
  • Mbar::Real=1.0 — maximum violation bound (relative magnitudes parameter)
  • conf_level::Real=0.95 — confidence level for the robust CIs

Returns

HonestDiDResult{T} with robust CIs, breakdown value, and post-treatment estimates.

Example

eslp = event_study_lp(pd, :y, :treat, 5; leads=3, lags=2)
h = honest_did(eslp; Mbar=0.5)
h.robust_ci_lower  # lower bounds accounting for trend violations
source

GMM Estimation

MacroEconometricModels.andrews_lu_mmscMethod
andrews_lu_mmsc(j_stat::T, n_instruments::Int, n_params::Int,
                 n_obs::Int; hq_criterion::Real=2.1) -> NamedTuple

Andrews-Lu (2001) Model and Moment Selection Criteria based on Hansen J-statistic.

MMSC_BIC  = J - (c - b) × log(n)
MMSC_AIC  = J - (c - b) × 2
MMSC_HQIC = J - Q(c - b) × log(log(n))

where c = moment conditions, b = parameters, n = observations. Lower values indicate better model specification.

Arguments

  • j_stat — Hansen J-test statistic
  • n_instruments — number of moment conditions (c)
  • n_params — number of parameters (b)
  • n_obs — number of observations (n)
  • hq_criterion — penalty parameter Q for HQIC (default 2.1)

Returns

NamedTuple (bic, aic, hqic).

References

  • Andrews, D. & Lu, B. (2001). Journal of Econometrics 101(1), 123-164.
source
MacroEconometricModels.estimate_gmmMethod
estimate_gmm(moment_fn::Function, theta0::AbstractVector{T}, data;
             weighting::Symbol=:two_step, max_iter::Int=100,
             tol::T=T(1e-8), hac::Bool=true, bandwidth::Int=0,
             bounds::Union{Nothing,ParameterTransform}=nothing) -> GMMModel{T}

Estimate parameters via Generalized Method of Moments.

Minimizes: Q(θ) = g(θ)'W g(θ) where g(θ) = (1/n) Σᵢ gᵢ(θ)

Arguments:

  • moment_fn: Function (theta, data) -> Matrix of moment conditions (n × q)
  • theta0: Initial parameter guess
  • data: Data passed to moment function
  • weighting: Weighting method (:identity, :optimal, :two_step, :iterated)
  • max_iter: Maximum iterations for optimization and/or iterated GMM
  • tol: Convergence tolerance
  • hac: Use HAC correction for optimal weighting
  • bandwidth: HAC bandwidth (0 = automatic)
  • bounds: Parameter bounds via ParameterTransform (default: nothing = unconstrained). When provided, optimization is performed in unconstrained space via bijective transforms, and standard errors are corrected via the delta method.

Returns:

  • GMMModel with estimates, covariance, and J-test results
source
MacroEconometricModels.estimate_lp_gmmMethod
estimate_lp_gmm(Y::AbstractMatrix{T}, shock_var::Int, horizon::Int;
                lags::Int=4, weighting::Symbol=:two_step) -> Vector{GMMModel{T}}

Estimate Local Projection via GMM.

Returns a GMMModel for each horizon.

source
MacroEconometricModels.gmm_objectiveMethod
gmm_objective(theta::AbstractVector{T}, moment_fn::Function, data,
              W::AbstractMatrix{T}) -> T

Compute GMM objective: Q(θ) = g(θ)'W g(θ)

where g(θ) = (1/n) Σᵢ gᵢ(θ,data)

Arguments:

  • theta: Parameter vector
  • moment_fn: Function (theta, data) -> Matrix of moment conditions (n × q)
  • data: Data passed to moment function
  • W: Weighting matrix (q × q)

Returns:

  • GMM objective value
source
MacroEconometricModels.gmm_sandwich_vcovMethod
gmm_sandwich_vcov(S_ZX::Matrix{T}, W::Matrix{T},
                   D_e::Matrix{T}) -> Matrix{T}

Robust sandwich covariance for one-step GMM:

V = (S_ZX' W S_ZX)⁻¹ S_ZX' W D_e W S_ZX (S_ZX' W S_ZX)⁻¹

where De = Σi (Zi ei)(Zi ei)' is the robust moment covariance.

Arguments

  • S_ZX — q × k aggregated instrument-regressor cross-product
  • W — q × q weighting matrix
  • D_e — q × q robust moment covariance

Returns

  • k × k covariance matrix
source
MacroEconometricModels.j_testMethod
j_test(model::GMMModel{T}) -> NamedTuple

Hansen's J-test for overidentifying restrictions.

H0: All moment conditions are valid (E[g(θ₀)] = 0) H1: Some moment conditions are violated

Returns:

  • J_stat: Test statistic
  • p_value: p-value from chi-squared distribution
  • df: Degrees of freedom (nmoments - nparams)
  • reject_05: Whether to reject at 5% level
source
MacroEconometricModels.linear_gmm_solveMethod
linear_gmm_solve(S_ZX::Matrix{T}, S_Zy::AbstractVecOrMat{T},
                  W::Matrix{T}) -> Vector{T}

Solve linear GMM analytically: E[Z'(y - Xβ)] = 0.

Given pre-aggregated cross-products SZX = Σi Zi'Xi and SZy = Σi Zi'yi:

β = (S_ZX' W S_ZX)⁻¹ S_ZX' W S_Zy

Arguments

  • S_ZX — q × k aggregated instrument-regressor cross-product
  • S_Zy — q × 1 (or q-vector) aggregated instrument-response cross-product
  • W — q × q weighting matrix

Returns

  • Parameter vector β (length k)
source
MacroEconometricModels.lp_gmm_momentsMethod
lp_gmm_moments(Y::AbstractMatrix{T}, shock_var::Int, h::Int, theta,
               lags::Int) -> Matrix{T}

Construct moment conditions for LP estimated via GMM.

Moments: E[Zt * ε{t+h}] = 0 where ε{t+h} = y{t+h} - θ' * X_t and Z includes all exogenous variables.

This is useful when you need to impose cross-equation restrictions.

source
MacroEconometricModels.minimize_gmmMethod
minimize_gmm(moment_fn::Function, theta0::AbstractVector{T}, data,
             W::AbstractMatrix{T}; max_iter::Int=100, tol::T=T(1e-8)) -> NamedTuple

Minimize GMM objective using Optim.jl (LBFGS with NelderMead fallback).

Returns:

  • theta: Minimizer
  • objective: Final objective value
  • converged: Convergence flag
  • iterations: Number of iterations
source
MacroEconometricModels.numerical_gradientMethod
numerical_gradient(f::Function, x::AbstractVector{T}; eps::T=T(1e-7)) -> Matrix{T}

Compute numerical gradient (Jacobian) of function f at point x using central differences.

Arguments:

  • f: Function that takes vector x and returns vector (moment conditions)
  • x: Point at which to evaluate gradient
  • eps: Step size for finite differences

Returns:

  • Jacobian matrix (nmoments × nparams)
source
MacroEconometricModels.optimal_weighting_matrixMethod
optimal_weighting_matrix(moment_fn::Function, theta::AbstractVector{T}, data;
                         hac::Bool=true, bandwidth::Int=0) -> Matrix{T}

Compute optimal GMM weighting matrix: W = inv(Var(g)).

For i.i.d. data: W = inv((1/n) Σᵢ gᵢ gᵢ') For time series: Uses HAC estimation with Newey-West kernel.

Arguments:

  • moment_fn: Moment function
  • theta: Current parameter estimate
  • data: Data
  • hac: Use HAC correction for serial correlation
  • bandwidth: HAC bandwidth (0 = automatic)

Returns:

  • Optimal weighting matrix (q × q)
source

Simulated Method of Moments

MacroEconometricModels._moment_covarianceMethod
_moment_covariance(data, moments_fn; hac, bandwidth) -> Matrix{T}

Internal: Compute long-run covariance of per-observation moment contributions. Shared by smm_weighting_matrix (inverted) and smm_data_covariance (raw).

source
MacroEconometricModels.autocovariance_momentsMethod
autocovariance_moments(data::AbstractMatrix{T}; lags::Int=1) -> Vector{T}

Compute standard DSGE moment vector from data matrix.

Returns: [upper-triangle variance-covariance elements; diagonal autocovariances at each lag]

For k variables, lags L: k*(k+1)/2 + k*L moments total.

Arguments

  • data –- T_obs x k data matrix
  • lags –- number of autocovariance lags (default: 1)
source
MacroEconometricModels.estimate_smmMethod
estimate_smm(simulator_fn, moments_fn, theta0, data;
             sim_ratio=5, burn=100, weighting=:two_step,
             bounds=nothing, hac=true, bandwidth=0,
             max_iter=1000, tol=1e-8,
             rng=Random.default_rng()) -> SMMModel{T}

Estimate parameters via Simulated Method of Moments.

Minimizes Q(theta) = (m_data - m_sim(theta))' W (m_data - m_sim(theta)) where m_data are data moments and m_sim(theta) are simulated moments.

Arguments

  • simulator_fn(theta, T_periods, burn; rng) –- simulates T_periods obs after discarding burn
  • moments_fn(data) -> Vector{T} –- computes moment vector from any T x k data matrix
  • theta0 –- initial parameter guess
  • data –- observed data matrix (T x k)

Keywords

  • sim_ratio::Int=5 –- tau = simulation periods / data periods
  • burn::Int=100 –- burn-in periods for simulator
  • weighting::Symbol=:two_step –- :identity or :two_step
  • bounds::Union{Nothing,ParameterTransform}=nothing –- parameter bounds
  • hac::Bool=true –- HAC for weighting matrix
  • bandwidth::Int=0 –- HAC bandwidth (0 = automatic)
  • max_iter::Int=1000 –- max optimizer iterations
  • tol=1e-8 –- convergence tolerance
  • rng –- random number generator (copied inside objective for deterministic simulation)

References

  • Ruge-Murcia (2012), Lee & Ingram (1991)
source
MacroEconometricModels.j_testMethod
j_test(m::SMMModel{T}) -> NamedTuple

Hansen's J-test for overidentifying restrictions on an SMM model.

H0: All moment conditions are valid (E[g(theta_0)] = 0) H1: Some moment conditions are violated

Returns:

  • J_stat: Test statistic
  • p_value: p-value from chi-squared distribution
  • df: Degrees of freedom (nmoments - nparams)
  • reject_05: Whether to reject at 5% level
source
MacroEconometricModels.smm_data_covarianceMethod
smm_data_covariance(data::AbstractMatrix{T}, moments_fn::Function;
                      hac::Bool=true, bandwidth::Int=0) -> Matrix{T}

Compute long-run covariance Ω of data moment contributions for sandwich SE formula.

source
MacroEconometricModels.smm_weighting_matrixMethod
smm_weighting_matrix(data::AbstractMatrix{T}, moments_fn::Function;
                      hac::Bool=true, bandwidth::Int=0) -> Matrix{T}

Compute optimal SMM weighting matrix from data moment contributions. Centers the per-observation moment contributions and applies HAC with Bartlett kernel.

Arguments

  • data — T_obs × k data matrix
  • moments_fn — function computing moment vector from data
  • hac — use HAC correction (default: true)
  • bandwidth — HAC bandwidth, 0 = automatic: floor(4*(n/100)^(2/9))
source

Parameter Transforms

MacroEconometricModels.transform_jacobianFunction
transform_jacobian(pt::ParameterTransform, phi::AbstractVector) -> Matrix

Diagonal Jacobian ∂θ/∂φ of the inverse transform (unconstrained → constrained). Used for delta method SE correction.

source

Unit Root and Cointegration Tests

MacroEconometricModels.adf_testMethod
adf_test(y; lags=:aic, max_lags=nothing, regression=:constant) -> ADFResult

Augmented Dickey-Fuller test for unit root.

Tests H₀: y has a unit root (non-stationary) against H₁: y is stationary.

Arguments

  • y: Time series vector
  • lags: Number of augmenting lags, or :aic/:bic/:hqic for automatic selection
  • max_lags: Maximum lags for automatic selection (default: floor(12*(T/100)^0.25))
  • regression: Deterministic terms - :none, :constant (default), or :trend

Returns

ADFResult containing test statistic, p-value, critical values, etc.

Example

y = cumsum(randn(200))  # Random walk (has unit root)
result = adf_test(y)
result.pvalue > 0.05  # Should fail to reject H₀

References

  • Dickey, D. A., & Fuller, W. A. (1979). Distribution of the estimators for autoregressive time series with a unit root. JASA, 74(366), 427-431.
  • MacKinnon, J. G. (2010). Critical values for cointegration tests. Queen's Economics Department Working Paper No. 1227.
source
MacroEconometricModels.kpss_testMethod
kpss_test(y; regression=:constant, bandwidth=:auto) -> KPSSResult

Kwiatkowski-Phillips-Schmidt-Shin test for stationarity.

Tests H₀: y is stationary against H₁: y has a unit root.

Arguments

  • y: Time series vector
  • regression: :constant (level stationarity) or :trend (trend stationarity)
  • bandwidth: Bartlett kernel bandwidth, or :auto for Newey-West selection

Returns

KPSSResult containing test statistic, p-value, critical values, etc.

Example

y = randn(200)  # Stationary series
result = kpss_test(y)
result.pvalue > 0.05  # Should fail to reject H₀ (stationarity)

References

  • Kwiatkowski, D., Phillips, P. C., Schmidt, P., & Shin, Y. (1992). Testing the null hypothesis of stationarity against the alternative of a unit root. Journal of Econometrics, 54(1-3), 159-178.
source
MacroEconometricModels.pp_testMethod
pp_test(y; regression=:constant, bandwidth=:auto) -> PPResult

Phillips-Perron test for unit root with non-parametric correction.

Tests H₀: y has a unit root against H₁: y is stationary.

Arguments

  • y: Time series vector
  • regression: :none, :constant (default), or :trend
  • bandwidth: Newey-West bandwidth, or :auto for automatic selection

Returns

PPResult containing test statistic (Zt), p-value, critical values, etc.

Example

y = cumsum(randn(200))  # Random walk
result = pp_test(y)
result.pvalue > 0.05  # Should fail to reject H₀

References

  • Phillips, P. C., & Perron, P. (1988). Testing for a unit root in time series regression. Biometrika, 75(2), 335-346.
source
MacroEconometricModels._za_ao_at_breakMethod

AO (additive outlier) model for a single break candidate.

Step 1: Detrend y via OLS on deterministics with break dummies → residuals e. Step 2: ADF regression on e with pulse dummy D(TB)_t = 1{t == tb} and its lags.

Returns (tstatonelag, lags_used).

source
MacroEconometricModels._za_io_at_breakMethod

IO (innovational outlier) model for a single break candidate.

Regression: Δyt = μ + β·t + θ·DUt(tb) [+ δ·DTt(tb)] + γ·y{t-1} + Σδj·Δy{t-j} + et where DUt = 1{t >= tb} and DT_t = max(0, t - tb + 1).

Returns (tstatongamma, lagsused).

source
MacroEconometricModels.za_testMethod
za_test(y; regression=:both, trim=0.15, lags=:aic, max_lags=nothing, outlier=:io) -> ZAResult

Zivot-Andrews test for unit root with endogenous structural break.

Tests H₀: y has a unit root without break against H₁: y is stationary with break.

Arguments

  • y: Time series vector
  • regression: Type of break - :constant (intercept), :trend (slope), or :both
  • trim: Trimming fraction for break search (default 0.15)
  • lags: Number of augmenting lags, or :aic/:bic for automatic selection
  • max_lags: Maximum lags for selection
  • outlier: Outlier model - :io (innovational outlier) or :ao (additive outlier)

Returns

ZAResult containing minimum t-statistic, break point, p-value, etc.

Example

# Series with structural break
y = vcat(randn(100), randn(100) .+ 2)
result = za_test(y; regression=:constant)

# Additive outlier model
result_ao = za_test(y; regression=:constant, outlier=:ao)

References

  • Zivot, E., & Andrews, D. W. K. (1992). Further evidence on the great crash, the oil-price shock, and the unit-root hypothesis. JBES, 10(3), 251-270.
source
MacroEconometricModels.ngperron_testMethod
ngperron_test(y; regression=:constant) -> NgPerronResult

Ng-Perron unit root tests with GLS detrending (MZα, MZt, MSB, MPT).

Tests H₀: y has a unit root against H₁: y is stationary. These tests have better size properties than ADF/PP in small samples.

Arguments

  • y: Time series vector
  • regression: :constant (default) or :trend

Returns

NgPerronResult containing MZα, MZt, MSB, MPT statistics and critical values.

Example

y = cumsum(randn(100))
result = ngperron_test(y)
# Check if MZt rejects at 5%
result.MZt < result.critical_values[:MZt][5]

References

  • Ng, S., & Perron, P. (2001). Lag length selection and the construction of unit root tests with good size and power. Econometrica, 69(6), 1519-1554.
source
MacroEconometricModels.johansen_testMethod
johansen_test(Y, p; deterministic=:constant) -> JohansenResult

Johansen cointegration test for VAR system.

Tests for the number of cointegrating relationships among variables using trace and maximum eigenvalue tests.

Arguments

  • Y: Data matrix (T × n)
  • p: Number of lags in the VECM representation
  • deterministic: Specification for deterministic terms
    • :none - No deterministic terms
    • :constant - Constant in cointegrating relation (default)
    • :trend - Linear trend in levels

Returns

JohansenResult containing trace and max-eigenvalue statistics, cointegrating vectors, adjustment coefficients, and estimated rank.

Example

# Generate cointegrated system
n, T = 3, 200
Y = randn(T, n)
Y[:, 2] = Y[:, 1] + 0.1 * randn(T)  # Y2 cointegrated with Y1

result = johansen_test(Y, 2)
result.rank  # Should detect 1 or 2 cointegrating relations

References

  • Johansen, S. (1991). Estimation and hypothesis testing of cointegration vectors in Gaussian vector autoregressive models. Econometrica, 59(6), 1551-1580.
  • Osterwald-Lenum, M. (1992). A note with quantiles of the asymptotic distribution of the ML cointegration rank test statistics. Oxford BEJM.
source
MacroEconometricModels.fourier_adf_testMethod
fourier_adf_test(y; regression=:constant, fmax=3, lags=:aic, max_lags=nothing, trim=0.15) -> FourierADFResult

Fourier ADF unit root test with flexible Fourier form (Enders & Lee 2012).

Tests H0: unit root against H1: stationary with smooth structural breaks captured by low-frequency Fourier components.

Arguments

  • y: Time series vector
  • regression: :constant or :trend
  • fmax: Maximum Fourier frequency (default 3, max 5)
  • lags: Number of augmenting lags, or :aic/:bic for automatic selection
  • max_lags: Maximum lags for IC selection (default: floor(12*(T/100)^0.25))
  • trim: Trimming fraction (default 0.15)

References

  • Enders, W., & Lee, J. (2012). A unit root test using a Fourier series to approximate smooth breaks. Oxford Bulletin of Economics and Statistics, 74(4), 574-599.
source
MacroEconometricModels.fourier_kpss_testMethod
fourier_kpss_test(y; regression=:constant, fmax=3, bandwidth=nothing) -> FourierKPSSResult

Fourier KPSS stationarity test (Becker, Enders & Lee 2006).

Tests H0: stationary (with Fourier terms) against H1: unit root.

Arguments

  • y: Time series vector
  • regression: :constant or :trend
  • fmax: Maximum Fourier frequency (default 3, max 3 for KPSS tables)
  • bandwidth: Bartlett kernel bandwidth (default: Newey-West)

References

  • Becker, R., Enders, W., & Lee, J. (2006). A stationarity test in the presence of an unknown number of smooth breaks. Journal of Time Series Analysis, 27(3), 381-409.
source
MacroEconometricModels.dfgls_testMethod
dfgls_test(y; regression=:constant, lags=:aic, max_lags=nothing) -> DFGLSResult

DF-GLS unit root test (Elliott, Rothenberg & Stock 1996).

Tests H₀: unit root against H₁: stationary using GLS-detrended data. Reports DF-GLS τ statistic, ERS Pt statistic, and MGLS statistics.

Arguments

  • y: Time series vector
  • regression: :constant or :trend
  • lags: Number of lags, or :aic/:bic for automatic selection
  • max_lags: Maximum lags for IC selection

References

  • Elliott, G., Rothenberg, T. J., & Stock, J. H. (1996). Efficient tests for an autoregressive unit root. Econometrica, 64(4), 813-836.
  • Ng, S., & Perron, P. (2001). Lag length selection and the construction of unit root tests with good size and power. Econometrica, 69(6), 1519-1554.
source
MacroEconometricModels.lm_unitroot_testMethod
lm_unitroot_test(y; breaks=0, regression=:level, lags=:aic, max_lags=nothing, trim=0.15) -> LMUnitRootResult

LM unit root test (Schmidt-Phillips 1992; Lee-Strazicich 2003, 2013).

Tests H₀: unit root (with breaks under H₀) against H₁: stationary.

Arguments

  • y: Time series vector
  • breaks: Number of structural breaks (0, 1, or 2)
  • regression: :level for intercept break, :both for intercept + trend break
  • lags: Number of augmenting lags, or :aic/:bic
  • max_lags: Maximum lags for IC selection
  • trim: Trimming fraction (default 0.15)

References

  • Schmidt, P., & Phillips, P. C. B. (1992). LM tests for a unit root in the presence of deterministic trends. Oxford Bulletin of Economics and Statistics, 54(3), 257-287.
  • Lee, J., & Strazicich, M. C. (2003). Minimum Lagrange multiplier unit root test with two structural breaks. Review of Economics and Statistics, 85(4), 1082-1089.
  • Lee, J., & Strazicich, M. C. (2013). Minimum LM unit root test with one structural break. Economics Bulletin, 33(4), 2483-2492.
source
MacroEconometricModels.adf_2break_testMethod
adf_2break_test(y; model=:level, lags=:aic, max_lags=nothing, trim=0.10) -> ADF2BreakResult

ADF unit root test with two structural breaks (Narayan & Popp 2010).

Tests H₀: unit root with two breaks against H₁: stationary with two breaks.

Arguments

  • y: Time series vector
  • model: :level (level shifts only) or :both (level + trend shifts)
  • lags: Number of augmenting lags, or :aic/:bic
  • max_lags: Maximum lags for IC selection
  • trim: Trimming fraction (default 0.10)

References

  • Narayan, P. K., & Popp, S. (2010). A new unit root test with two structural breaks in level and slope at unknown time. Journal of Applied Statistics, 22(2), 206-233.
source
MacroEconometricModels.gregory_hansen_testMethod
gregory_hansen_test(Y; model=:C, lags=:aic, max_lags=nothing, trim=0.15) -> GregoryHansenResult

Gregory-Hansen cointegration test with structural break (Gregory & Hansen 1996).

Tests H₀: no cointegration against H₁: cointegration with a structural break.

Arguments

  • Y: T×n matrix where Y[:,1] is the dependent variable and Y[:,2:end] are regressors
  • model: :C (level shift), :CT (level + trend shift), :CS (regime shift)
  • lags: Number of augmenting lags for ADF, or :aic/:bic
  • max_lags: Maximum lags for IC selection
  • trim: Trimming fraction (default 0.15)

References

  • Gregory, A. W., & Hansen, B. E. (1996). Residual-based tests for cointegration in models with regime shifts. Journal of Econometrics, 70(1), 99-126.
source
MacroEconometricModels.is_stationaryMethod
is_stationary(model::VARModel) -> VARStationarityResult

Check if estimated VAR model is stationary.

A VAR(p) is stationary if and only if all eigenvalues of the companion matrix have modulus strictly less than 1.

Returns

VARStationarityResult with:

  • is_stationary: Boolean indicating stationarity
  • eigenvalues: Complex eigenvalues of companion matrix
  • max_modulus: Maximum eigenvalue modulus
  • companion_matrix: The (np × np) companion form matrix

Example

model = estimate_var(Y, 2)
result = is_stationary(model)
if !result.is_stationary
    println("Warning: VAR is non-stationary, max modulus = ", result.max_modulus)
end
source
MacroEconometricModels.test_all_variablesMethod
test_all_variables(Y; test=:adf, kwargs...) -> Vector

Apply unit root test to each column of Y.

Arguments

  • Y: Data matrix (T × n)
  • test: Test to apply (:adf, :kpss, :pp, :za, :ngperron)
  • kwargs...: Additional arguments passed to the test

Returns

Vector of test results, one per variable.

Example

Y = randn(200, 3)
Y[:, 1] = cumsum(Y[:, 1])  # Make first column non-stationary
results = test_all_variables(Y; test=:adf)
[r.pvalue for r in results]  # P-values for each variable
source
MacroEconometricModels.unit_root_summaryMethod
unit_root_summary(y; tests=[:adf, :kpss, :pp], kwargs...) -> NamedTuple

Run multiple unit root tests and return summary with PrettyTables output.

Arguments

  • y: Time series vector
  • tests: Vector of test symbols to run (default: [:adf, :kpss, :pp])
  • kwargs...: Additional arguments passed to individual tests

Returns

NamedTuple with test results, conclusion, and summary table.

Example

y = cumsum(randn(200))
summary = unit_root_summary(y)
summary.conclusion  # Overall conclusion
source

Model Comparison Tests

MacroEconometricModels.lr_testFunction
lr_test(m1, m2) -> LRTestResult

Likelihood ratio test for nested models.

Computes LR = -2(ℓR - ℓU) where the restricted model has fewer parameters. Under H₀ (restricted model is correct), LR ~ χ²(df) where df = dofU - dofR.

Works for any two models implementing loglikelihood, dof, and nobs from StatsAPI. Automatically determines which model is restricted by comparing degrees of freedom.

Arguments

  • m1, m2: Two fitted models (order does not matter)

Returns

LRTestResult with test statistic, p-value, and model details.

Example

ar2 = estimate_ar(y, 2; method=:mle)
ar4 = estimate_ar(y, 4; method=:mle)
result = lr_test(ar2, ar4)
source
MacroEconometricModels.lm_testFunction
lm_test(m1, m2) -> LMTestResult

Lagrange multiplier (score) test for nested models.

Evaluates the score of the unrestricted log-likelihood at the restricted parameter estimates. Under H₀, LM = s'(-H)⁻¹s ~ χ²(df) where df = dofU - dofR.

Automatically determines restricted/unrestricted by comparing dof. Dispatches to model-family specific implementations for ARIMA, VAR, and volatility models.

Supported model pairs

  • AbstractARIMAModel × AbstractARIMAModel (same differencing order d)
  • VARModel × VARModel (different lag orders, same data)
  • ARCHModel × ARCHModel, GARCHModel × GARCHModel
  • ARCHModel × GARCHModel (cross-type nesting)
  • EGARCHModel × EGARCHModel, GJRGARCHModel × GJRGARCHModel

Arguments

  • m1, m2: Two fitted models from the same family (order does not matter)

Returns

LMTestResult with test statistic, p-value, and score norm diagnostic.

Example

ar2 = estimate_ar(y, 2; method=:mle)
ar4 = estimate_ar(y, 4; method=:mle)
result = lm_test(ar2, ar4)
source

Granger Causality Tests

MacroEconometricModels.granger_testFunction
granger_test(model::VARModel, cause::Int, effect::Int) -> GrangerCausalityResult

Test whether variable cause Granger-causes variable effect in a VAR model.

H₀: A₁[effect, cause] = A₂[effect, cause] = ... = Aₚ[effect, cause] = 0 H₁: At least one lag coefficient is nonzero

Uses a Wald χ² test with df = p (number of lags).

Arguments

  • model: Estimated VARModel
  • cause: Index of the causing variable (1-based)
  • effect: Index of the effect variable (1-based)

Returns

GrangerCausalityResult with Wald statistic, p-value, and test details.

Example

Y = randn(200, 3)
m = estimate_var(Y, 2)
g = granger_test(m, 1, 2)  # does variable 1 Granger-cause variable 2?
source
granger_test(model::VARModel, cause::Vector{Int}, effect::Int) -> GrangerCausalityResult

Test whether a group of variables cause jointly Granger-cause variable effect.

H₀: All lag coefficients from cause variables to the effect equation are zero H₁: At least one lag coefficient is nonzero

Uses a Wald χ² test with df = p × length(cause).

Arguments

  • model: Estimated VARModel
  • cause: Indices of the causing variables (1-based)
  • effect: Index of the effect variable (1-based)

Returns

GrangerCausalityResult with Wald statistic, p-value, and test details.

Example

Y = randn(200, 4)
m = estimate_var(Y, 2)
g = granger_test(m, [1, 2], 3)  # do variables 1 and 2 jointly Granger-cause variable 3?
source
MacroEconometricModels.granger_test_allFunction
granger_test_all(model::VARModel) -> Matrix{Union{GrangerCausalityResult, Nothing}}

Compute pairwise Granger causality tests for all variable pairs in a VAR model.

Returns an n×n matrix where entry [i,j] tests whether variable j Granger-causes variable i. Diagonal entries are nothing.

Arguments

  • model: Estimated VARModel

Returns

n×n matrix of GrangerCausalityResult (or nothing on diagonal).

Example

Y = randn(200, 3)
m = estimate_var(Y, 2)
results = granger_test_all(m)
results[2, 1]  # does variable 1 Granger-cause variable 2?
source

Volatility Models

ARCH Estimation and Diagnostics

MacroEconometricModels.estimate_archFunction
estimate_arch(y, q; method=:mle) -> ARCHModel

Estimate ARCH(q) model via Maximum Likelihood.

σ²ₜ = ω + α₁ε²ₜ₋₁ + ... + αqε²ₜ₋q

Uses two-stage optimization: NelderMead initialization → LBFGS refinement.

Arguments

  • y: Time series vector
  • q: ARCH order (≥ 1)
  • method: Estimation method (currently only :mle)

Returns

ARCHModel with estimated parameters and conditional variances.

Example

y = randn(500)
model = estimate_arch(y, 1)
println("ω = ", model.omega, ", α₁ = ", model.alpha[1])
source
MacroEconometricModels.arch_lm_testFunction
arch_lm_test(y_or_model, q=5)

ARCH-LM test for conditional heteroskedasticity (Engle 1982).

H₀: No ARCH effects (α₁ = ... = αq = 0) H₁: ARCH(q) effects present

Test statistic: T·R² from regression of ε²ₜ on ε²ₜ₋₁,...,ε²ₜ₋q, distributed χ²(q).

Arguments

  • y_or_model: Raw data vector or AbstractVolatilityModel (uses standardized residuals)
  • q: Number of lags (default 5)

Returns

Named tuple (statistic, pvalue, q).

Example

result = arch_lm_test(randn(500), 5)
println("p-value: ", result.pvalue)
source
MacroEconometricModels.ljung_box_squaredFunction
ljung_box_squared(z_or_model, K=10)

Ljung-Box test on squared (standardized) residuals.

H₀: No serial correlation in z²ₜ H₁: Serial correlation present in z²ₜ

Test statistic: Q = n(n+2) Σₖ ρ̂²ₖ/(n-k), distributed χ²(K).

Arguments

  • z_or_model: Standardized residuals vector or AbstractVolatilityModel
  • K: Number of lags (default 10)

Returns

Named tuple (statistic, pvalue, K).

source

GARCH Estimation and Diagnostics

MacroEconometricModels.estimate_garchFunction
estimate_garch(y, p=1, q=1; method=:mle) -> GARCHModel

Estimate GARCH(p,q) model via Maximum Likelihood (Bollerslev 1986).

σ²ₜ = ω + α₁ε²ₜ₋₁ + ... + αqε²ₜ₋q + β₁σ²ₜ₋₁ + ... + βpσ²ₜ₋p

Arguments

  • y: Time series vector
  • p: GARCH order (default 1)
  • q: ARCH order (default 1)
  • method: Estimation method (currently only :mle)

Example

model = estimate_garch(y, 1, 1)
println("Persistence: ", persistence(model))
source
MacroEconometricModels.estimate_egarchFunction
estimate_egarch(y, p=1, q=1; method=:mle) -> EGARCHModel

Estimate EGARCH(p,q) model via Maximum Likelihood (Nelson 1991).

log(σ²ₜ) = ω + Σαᵢ(|zₜ₋ᵢ| - E|z|) + Σγᵢzₜ₋ᵢ + Σβⱼlog(σ²ₜ₋ⱼ)

The γ parameters capture leverage effects (typically γ < 0 for equities).

Arguments

  • y: Time series vector
  • p: GARCH order (default 1)
  • q: ARCH order (default 1)
  • method: Estimation method (currently only :mle)

Example

model = estimate_egarch(y, 1, 1)
println("Leverage: ", model.gamma[1])
source
MacroEconometricModels.estimate_gjr_garchFunction
estimate_gjr_garch(y, p=1, q=1; method=:mle) -> GJRGARCHModel

Estimate GJR-GARCH(p,q) model via Maximum Likelihood (Glosten, Jagannathan & Runkle 1993).

σ²ₜ = ω + Σ(αᵢ + γᵢI(εₜ₋ᵢ<0))ε²ₜ₋ᵢ + Σβⱼσ²ₜ₋ⱼ

γᵢ > 0 captures the asymmetric (leverage) effect.

Arguments

  • y: Time series vector
  • p: GARCH order (default 1)
  • q: ARCH order (default 1)
  • method: Estimation method (currently only :mle)

Example

model = estimate_gjr_garch(y, 1, 1)
println("Asymmetry: ", model.gamma[1])
source
MacroEconometricModels.news_impact_curveFunction
news_impact_curve(m; range=(-3,3), n_points=200)

Compute the news impact curve: how a shock εₜ₋₁ maps to σ²ₜ, holding all else at unconditional values.

Returns named tuple (shocks, variance) where both are vectors of length n_points.

Supported models

  • GARCHModel: Symmetric parabola
  • GJRGARCHModel: Asymmetric parabola (steeper for negative shocks)
  • EGARCHModel: Asymmetric exponential curve
source

Stochastic Volatility

MacroEconometricModels.estimate_svFunction
estimate_sv(y; n_samples=2000, burnin=1000,
            dist=:normal, leverage=false,
            quantile_levels=[0.025, 0.5, 0.975]) -> SVModel

Estimate a Stochastic Volatility model via Kim-Shephard-Chib (1998) Gibbs sampler with Omori et al. (2007) 10-component mixture approximation.

Model

yₜ = exp(hₜ/2) εₜ,       εₜ ~ N(0,1)
hₜ = μ + φ(hₜ₋₁ - μ) + σ_η ηₜ,  ηₜ ~ N(0,1)

Arguments

  • y: Time series vector
  • n_samples: Number of posterior samples to keep (default 2000)
  • burnin: Number of burn-in iterations to discard (default 1000)
  • dist: Error distribution (:normal or :studentt)
  • leverage: Whether to include leverage effect (correlated innovations)
  • quantile_levels: Quantile levels for volatility posterior

Example

y = randn(200) .* exp.(cumsum(0.1 .* randn(200)) ./ 2)
model = estimate_sv(y; n_samples=1000)
println("φ = ", mean(model.phi_post))
source

Volatility Forecasting

MacroEconometricModels.forecastMethod
forecast(m::ARCHModel, h; conf_level=0.95, n_sim=10000) -> VolatilityForecast

Forecast conditional variance from an ARCH(q) model.

For h > q, the forecast converges to the unconditional variance. Confidence intervals are computed via simulation.

Arguments

  • m: Fitted ARCHModel
  • h: Forecast horizon
  • conf_level: Confidence level for intervals (default 0.95)
  • n_sim: Number of simulation paths for CIs (default 10000)
source
MacroEconometricModels.forecastMethod
forecast(m::EGARCHModel, h; conf_level=0.95, n_sim=10000) -> VolatilityForecast

Forecast conditional variance from an EGARCH(p,q) model via simulation.

source
MacroEconometricModels.forecastMethod
forecast(m::GARCHModel, h; conf_level=0.95, n_sim=10000) -> VolatilityForecast

Forecast conditional variance from a GARCH(p,q) model.

Uses analytical iteration for point forecasts and simulation for CIs. Point forecasts converge to unconditional variance as h → ∞.

source
MacroEconometricModels.forecastMethod
forecast(m::GJRGARCHModel, h; conf_level=0.95, n_sim=10000) -> VolatilityForecast

Forecast conditional variance from a GJR-GARCH(p,q) model via simulation.

source
MacroEconometricModels.forecastMethod
forecast(m::SVModel, h; conf_level=0.95) -> VolatilityForecast

Posterior predictive forecast of volatility from an SV model.

For each posterior draw (μ, φ, ση), simulates the log-volatility path forward h{T+1}, ..., h_{T+h} and returns quantiles of exp(hₜ).

Arguments

  • m: Fitted SVModel
  • h: Forecast horizon
  • conf_level: Confidence level for intervals (default 0.95)
source

Volatility Accessors

Volatility StatsAPI Interface

StatsAPI.coefMethod

Coefficient vector [μ, ω, α₁, …, αq, γ₁, …, γq, β₁, …, βp].

source
StatsAPI.coefMethod

Coefficient vector [μ, ω, α₁, …, αq, γ₁, …, γq, β₁, …, βp].

source
StatsAPI.stderrorMethod
StatsAPI.stderror(m::ARCHModel{T}) -> Vector{T}

MLE standard errors for ARCH model via numerical Hessian. Returns SE vector matching coef(m) = [μ, ω, α₁, ..., αq].

source
StatsAPI.stderror(m::GARCHModel{T}) -> Vector{T}

MLE standard errors for GARCH model via numerical Hessian + delta method. Returns SE vector matching coef(m) = [μ, ω, α₁..αq, β₁..βp].

source
StatsAPI.stderror(m::EGARCHModel{T}) -> Vector{T}

MLE standard errors for EGARCH model via numerical Hessian. EGARCH params are unconstrained — no delta method needed. Returns SE vector matching coef(m) = [μ, ω, α₁..αq, γ₁..γq, β₁..βp].

source
StatsAPI.stderror(m::GJRGARCHModel{T}) -> Vector{T}

MLE standard errors for GJR-GARCH model via numerical Hessian + delta method. Returns SE vector matching coef(m) = [μ, ω, α₁..αq, γ₁..γq, β₁..βp].

source

Nowcasting

Estimation

MacroEconometricModels.nowcast_dfmFunction
nowcast_dfm(Y, nM, nQ; r=2, p=1, idio=:ar1, blocks=nothing,
            max_iter=100, thresh=1e-4) -> NowcastDFM{T}

Estimate a dynamic factor model on mixed-frequency data with missing values.

The first nM columns of Y are monthly variables; the next nQ columns are quarterly variables (observed every 3rd month, NaN otherwise).

Arguments

  • Y::AbstractMatrix — T_obs × N data matrix (NaN for missing)
  • nM::Int — number of monthly variables
  • nQ::Int — number of quarterly variables

Keyword Arguments

  • r::Int=2 — number of factors
  • p::Int=1 — VAR lags in factor dynamics
  • idio::Symbol=:ar1 — idiosyncratic component (:ar1 or :iid)
  • blocks::Union{Matrix{Int},Nothing}=nothing — block structure (N × n_blocks)
  • max_iter::Int=100 — maximum EM iterations
  • thresh::Real=1e-4 — convergence threshold (relative log-likelihood change)

Returns

NowcastDFM{T} with smoothed data, factors, and state-space parameters.

References

  • Bańbura, M. & Modugno, M. (2014). Maximum Likelihood Estimation of Factor Models on Datasets with Arbitrary Pattern of Missing Data.
source
MacroEconometricModels.nowcast_bvarFunction
nowcast_bvar(Y, nM, nQ; lags=5, thresh=1e-6, max_iter=200,
            lambda0=0.2, theta0=1.0, miu0=1.0, alpha0=2.0) -> NowcastBVAR{T}

Estimate a large BVAR for mixed-frequency nowcasting.

The first nM columns are monthly variables; the next nQ columns are quarterly (observed every 3rd month). The BVAR is estimated on the complete (non-NaN) portion, then the Kalman smoother fills the ragged edge.

Arguments

  • Y::AbstractMatrix — T_obs × N data matrix (NaN for missing)
  • nM::Int — number of monthly variables
  • nQ::Int — number of quarterly variables

Keyword Arguments

  • lags::Int=5 — number of lags
  • thresh::Real=1e-6 — optimization convergence threshold
  • max_iter::Int=200 — max optimization iterations
  • lambda0::Real=0.2 — initial overall shrinkage
  • theta0::Real=1.0 — initial cross-variable shrinkage
  • miu0::Real=1.0 — initial sum-of-coefficients weight
  • alpha0::Real=2.0 — initial co-persistence weight

Returns

NowcastBVAR{T} with smoothed data and posterior parameters.

References

  • Cimadomo, J., Giannone, D., Lenza, M., Monti, F. & Sokol, A. (2022). Nowcasting with Large Bayesian Vector Autoregressions.
source
MacroEconometricModels.nowcast_bridgeFunction
nowcast_bridge(Y, nM, nQ; lagM=1, lagQ=1, lagY=1) -> NowcastBridge{T}

Estimate bridge equation combination nowcast.

Each bridge equation uses a pair of monthly indicators (aggregated to quarterly) plus optional lagged quarterly variables and autoregressive terms to predict the target quarterly variable (last column).

Arguments

  • Y::AbstractMatrix — T_obs × N data matrix (NaN for missing)
  • nM::Int — number of monthly variables
  • nQ::Int — number of quarterly variables (last nQ columns)

Keyword Arguments

  • lagM::Int=1 — lags for monthly indicators (after quarterly aggregation)
  • lagQ::Int=1 — lags for quarterly indicators
  • lagY::Int=1 — autoregressive lags for target variable

Returns

NowcastBridge{T} with combined and individual nowcasts.

References

  • Bańbura, M., Belousova, I., Bodnár, K. & Tóth, M. B. (2023). Nowcasting Employment in the Euro Area. ECB Working Paper No 2815.
source

Nowcast and Forecast

MacroEconometricModels.nowcastFunction
nowcast(model::AbstractNowcastModel; target_var=nothing) -> NowcastResult{T}

Generate nowcast result from an estimated nowcasting model.

Returns the current-quarter nowcast and next-quarter forecast for the target variable (default: last quarterly variable).

Arguments

  • model::AbstractNowcastModel — estimated nowcast model

Keyword Arguments

  • target_var::Union{Int,Nothing}=nothing — target variable index (default: last column)

Returns

NowcastResult{T} with nowcast and forecast values.

source
MacroEconometricModels.forecastMethod
forecast(model::NowcastDFM, h; target_var=nothing) -> Vector{T}

Generate h-step ahead monthly forecast from DFM nowcasting model.

Arguments

  • model::NowcastDFM — estimated model
  • h::Int — forecast horizon (months)

Keyword Arguments

  • target_var::Union{Int,Nothing} — variable to forecast (default: all)

Returns

Vector of h forecast values (if target_var specified) or Matrix h × N.

source
MacroEconometricModels.nowcastMethod
nowcast(model::AbstractNowcastModel; target_var=nothing) -> NowcastResult{T}

Generate nowcast result from an estimated nowcasting model.

Returns the current-quarter nowcast and next-quarter forecast for the target variable (default: last quarterly variable).

Arguments

  • model::AbstractNowcastModel — estimated nowcast model

Keyword Arguments

  • target_var::Union{Int,Nothing}=nothing — target variable index (default: last column)

Returns

NowcastResult{T} with nowcast and forecast values.

source

News Decomposition

MacroEconometricModels.nowcast_newsFunction
nowcast_news(X_new, X_old, model::NowcastDFM, target_period;
             target_var=size(X_new,2), groups=nothing) -> NowcastNews{T}

Compute news decomposition between two data vintages.

Identifies new data releases (positions where X_old is NaN but X_new is not), computes their individual impacts on the nowcast via Kalman gain weights, and decomposes the total revision.

Arguments

  • X_new::AbstractMatrix — new data vintage (T_obs × N)
  • X_old::AbstractMatrix — old data vintage (same size, more NaN)
  • model::NowcastDFM — estimated DFM model
  • target_period::Int — time period for which to compute nowcast

Keyword Arguments

  • target_var::Int — target variable index (default: last column)
  • groups::Union{Vector{Int},Nothing} — group assignment per variable (for aggregation)

Returns

NowcastNews{T} with per-release impacts and total decomposition.

References

  • Bańbura, M. & Modugno, M. (2014). Maximum Likelihood Estimation of Factor Models on Datasets with Arbitrary Pattern of Missing Data.
source

Panel Balancing

MacroEconometricModels.balance_panelFunction
balance_panel(pd::PanelData; method=:dfm, r=3, p=2) -> PanelData

Balance a panel dataset by filling missing values (NaN) using DFM-based nowcasting to estimate missing observations.

For each group with missing data, runs nowcast_dfm treating all variables as monthly (nM = n_vars, nQ = 0) to obtain Kalman-smoothed estimates.

Arguments

  • pd::PanelData — input panel data (may be unbalanced or have NaN)

Keyword Arguments

  • method::Symbol=:dfm — fill method (currently only :dfm)
  • r::Int=3 — number of factors for DFM
  • p::Int=2 — VAR lags in DFM factor dynamics

Returns

New PanelData with NaN filled and balanced=true if applicable.

Examples

pd = xtset(df, :id, :t)
pd_bal = balance_panel(pd; r=2, p=1)
isbalanced(pd_bal)
source

Nowcast Display


DSGE Models

Specification

MacroEconometricModels.@dsgeMacro
@dsge begin ... end

Parse a DSGE model specification block into a DSGESpec{Float64}.

Declaration syntax

spec = @dsge begin
    parameters: ρ = 0.9, σ = 0.01
    endogenous: C, K, Y, A
    exogenous: ε_A

    C[t] + K[t] = (1-δ)*K[t-1] + K[t-1]^α
    A[t] = ρ * A[t-1] + σ * ε_A[t]
end

Time references: var[t] (current), var[t-1] (lagged), var[t+1] (lead). Expectations operator: E[t](expr) is stripped under rational expectations.

Returns a DSGESpec{Float64} with callable residual functions f(y_t, y_lag, y_lead, ε, θ) → scalar.

source

Steady State

MacroEconometricModels.compute_steady_stateFunction
compute_steady_state(spec::DSGESpec{T}; initial_guess=nothing, method=:auto,
                      ss_fn=nothing, constraints=DSGEConstraint[],
                      solver=nothing, algorithm=nothing) → DSGESpec{T}

Compute the deterministic steady state: f(yss, yss, y_ss, 0, θ) = 0.

Returns a new DSGESpec with the steady_state field filled.

Keywords

  • initial_guess::Vector{T} — starting point (default: ones)
  • method::Symbol:auto (NonlinearSolve), :analytical
  • ss_fn::Function — for :analytical, a function θ → y_ss::Vector
  • constraints::Vector{<:DSGEConstraint} — variable bounds and nonlinear inequalities
  • solver::Symbol:nonlinearsolve (default), :optim (Fminbox), :nlopt (SLSQP), :ipopt (NLP), or :path (MCP); auto-detected if not specified
  • algorithm — NonlinearSolve.jl algorithm (default: TrustRegion()); passed through to chosen backend
source
MacroEconometricModels.linearizeFunction
linearize(spec::DSGESpec{T}) → LinearDSGE{T}

Linearize a DSGE model around its steady state using numerical Jacobians.

The model f(y_t, y_{t-1}, y_{t+1}, ε, θ) = 0 is expanded to first order. Rearranging into Sims form: Γ₀·y_t = Γ₁·y_{t-1} + C + Ψ·ε_t + Π·η_t.

Requires compute_steady_state to have been called first.

source

Solution Methods

MacroEconometricModels.solveFunction
solve(spec::DSGESpec{T}; method=:gensys, kwargs...) -> DSGESolution or PerfectForesightPath or PerturbationSolution

Solve a DSGE model.

Methods

  • :gensys – Sims (2002) QZ decomposition (default)
  • :blanchard_kahn – Blanchard-Kahn (1980) eigenvalue counting
  • :klein – Klein (2000) generalized Schur decomposition
  • :perturbation – Higher-order perturbation (Schmitt-Grohe & Uribe 2004); pass order=2 for second-order
  • :projection – Chebyshev collocation (Judd 1998); pass degree=5 for polynomial degree
  • :pfi – Policy Function Iteration / Time Iteration (Coleman 1990); pass degree=5, damping=1.0
  • :vfi – Value Function Iteration (Stokey-Lucas-Prescott 1989); pass degree=5, howard_steps=0
  • :perfect_foresight – deterministic Newton solver
source
MacroEconometricModels.gensysFunction
gensys(Gamma0, Gamma1, C, Psi, Pi; div=1.0+1e-8) -> NamedTuple

Solve the linear RE system via QZ decomposition (Sims 2002).

Returns (G1, impact, C_sol, eu, eigenvalues) where:

  • eu = [exist, unique]: 1=yes, 0=no
  • div is the dividing line between stable (|lambda| < div) and unstable eigenvalues.
source
MacroEconometricModels.blanchard_kahnFunction
blanchard_kahn(ld::LinearDSGE{T}, spec::DSGESpec{T}) -> DSGESolution{T}

Solve the linearized DSGE model via the Blanchard-Kahn method.

The BK condition requires that the number of eigenvalues with modulus > 1 equals the number of forward-looking (non-predetermined) variables.

source
MacroEconometricModels.kleinFunction
klein(Gamma0, Gamma1, C, Psi, n_predetermined; div=1.0) → NamedTuple

Solve the linear RE system via the Klein (2000) QZ decomposition method.

The system is in Sims canonical form: Gamma0 * y_t = Gamma1 * y_{t-1} + C + Psi * eps_t + Pi * eta_t

Klein computes the generalized Schur decomposition of the pencil (Gamma0, Gamma1), reorders eigenvalues so stable roots (|λ| < div) come first, and checks the Blanchard-Kahn condition: nstable == npredetermined.

Arguments

  • Gamma0 — n × n coefficient on y_t
  • Gamma1 — n × n coefficient on y_{t-1}
  • C — n × 1 constant vector
  • Psi — n × n_shocks shock loading matrix
  • n_predetermined — number of predetermined (state) variables

Keywords

  • div::Real=1.0 — dividing line for stable vs unstable eigenvalues

Returns

Named tuple (G1, impact, C_sol, eu, eigenvalues) where:

  • G1 — n × n state transition matrix
  • impact — n × n_shocks impact matrix
  • C_sol — n × 1 constants
  • eu[existence, uniqueness]: 1=yes, 0=no
  • eigenvalues — generalized eigenvalues from QZ decomposition
source
MacroEconometricModels.perturbation_solverFunction
perturbation_solver(spec::DSGESpec{T}; order::Int=2, method::Symbol=:gensys) → PerturbationSolution{T}

Compute a perturbation approximation to the policy functions of a DSGE model.

Arguments

  • spec — DSGE model specification (must have computed steady state)

Keywords

  • order::Int=2 — perturbation order (1, 2, or 3)
  • method::Symbol=:gensys — first-order solver (:gensys or :blanchard_kahn)

Returns

A PerturbationSolution{T} containing the policy function coefficients:

  • Order 1: gx (ny x nv), hx (nx x nv) where nv = nx + n_epsilon
  • Order 2: additionally gxx, hxx (nv^2 columns), g_sigma_sigma, h_sigma_sigma
  • Order 3: additionally gxxx, hxxx (nv^3 columns), gσσx, hσσx, gσσσ, hσσσ

Algorithm

  1. Solve the first-order system via gensys/BK to get G1, impact
  2. Partition variables into states (x) and controls (y) via Gamma1
  3. Build the innovations vector v = [x{t-1}; epsilont] and mapping matrices
  4. For order >= 2: compute Hessians, assemble the Kronecker system, solve for f_vv
  5. Solve the sigma^2 correction: fsigmasigma

References

  • Schmitt-Grohe & Uribe (2004), JEDC 28(4), 755-775.
  • Kim, Kim, Schaumburg & Sims (2008), JEDC 32(11), 3397-3414.
source
MacroEconometricModels.collocation_solverFunction
collocation_solver(spec::DSGESpec{T}; kwargs...) -> ProjectionSolution{T}

Solve DSGE model via Chebyshev collocation (projection method).

Keyword Arguments

  • degree::Int=5: Chebyshev polynomial degree
  • grid::Symbol=:auto: :tensor, :smolyak, or :auto
  • smolyak_mu::Int=3: Smolyak exactness level
  • quadrature::Symbol=:auto: :gauss_hermite, :monomial, or :auto
  • n_quad::Int=5: quadrature nodes per shock dimension
  • scale::Real=3.0: state bounds = SS +/- scale * sigma
  • tol::Real=1e-8: Newton convergence tolerance
  • max_iter::Int=100: maximum Newton iterations
  • threaded::Bool=false: enable multi-threaded Jacobian evaluation
  • verbose::Bool=false: print iteration info
  • initial_coeffs::Union{Nothing,AbstractMatrix{<:Real}}=nothing: warm-start coefficients (nvars x nbasis)
source
MacroEconometricModels.pfi_solverFunction
pfi_solver(spec::DSGESpec{T}; kwargs...) -> ProjectionSolution{T}

Solve DSGE model via Policy Function Iteration (Time Iteration).

At each iteration: (1) compute expected next-period values using quadrature, (2) solve Euler equation at each grid point via Newton, (3) refit Chebyshev coefficients via least squares.

Keyword Arguments

  • degree::Int=5: Chebyshev polynomial degree
  • grid::Symbol=:auto: :tensor, :smolyak, or :auto
  • smolyak_mu::Int=3: Smolyak exactness level
  • quadrature::Symbol=:auto: :gauss_hermite, :monomial, or :auto
  • n_quad::Int=5: quadrature nodes per shock dimension
  • scale::Real=3.0: state bounds = SS ± scale × σ
  • tol::Real=1e-8: sup-norm convergence tolerance
  • max_iter::Int=500: maximum PFI iterations
  • damping::Real=1.0: policy mixing factor (1.0 = no damping)
  • anderson_m::Int=0: Anderson acceleration depth (0 = disabled)
  • threaded::Bool=false: enable multi-threaded grid evaluation
  • verbose::Bool=false: print iteration info
source
MacroEconometricModels.perfect_foresightFunction
perfect_foresight(spec::DSGESpec{FT}; T_periods=100, shock_path=nothing,
                   max_iter=100, tol=1e-8, constraints=DSGEConstraint[],
                   solver=nothing, algorithm=nothing) → PerfectForesightPath{FT}

Solve for the deterministic perfect foresight path given a sequence of shocks.

Uses NonlinearSolve.jl as the default Newton solver with block-tridiagonal sparse Jacobian.

Keywords

  • T_periods::Int=100 — number of simulation periods
  • shock_path::Matrix — Tperiods × nexog matrix of shock realizations
  • max_iter::Int=100 — Newton iteration limit
  • tol::Real=1e-8 — convergence tolerance (max abs residual)
  • constraints::Vector{<:DSGEConstraint} — variable bounds and nonlinear inequalities
  • solver::Symbol:nonlinearsolve (default), :nlopt (SLSQP), :ipopt (NLP), or :path (MCP); auto-detected
  • algorithm — NonlinearSolve.jl algorithm (default: NewtonRaphson()); passed through to chosen backend
source
MacroEconometricModels.evaluate_policyFunction
evaluate_policy(sol::ProjectionSolution{T}, x_state::AbstractVector) -> Vector{T}

Evaluate the global policy function at a state vector. x_state should be an nx-vector of state variable levels. Returns n_vars-vector of all endogenous variable levels.

source
evaluate_policy(sol::ProjectionSolution{T}, X_states::AbstractMatrix) -> Matrix{T}

Evaluate at multiple state points. Xstates is npoints x nx. Returns npoints x nvars matrix of levels.

source
MacroEconometricModels.max_euler_errorFunction
max_euler_error(sol::ProjectionSolution{T}; n_test::Int=1000, rng=Random.default_rng()) -> T

Compute maximum Euler equation error on random test points within the state domain.

source

DSGE IRF and FEVD

MacroEconometricModels.fevdMethod
fevd(sol::DSGESolution{T}, horizon::Int) -> FEVD{T}

Compute forecast error variance decomposition from a solved DSGE model.

Uses the analytical IRFs from the solution to compute the proportion of h-step forecast error variance attributable to each structural shock.

Returns a FEVD{T} compatible with plot_result().

source
MacroEconometricModels.irfMethod
irf(sol::DSGESolution{T}, horizon::Int; kwargs...) -> ImpulseResponse{T}

Compute analytical impulse responses from a solved DSGE model.

At horizon h for shock j: Phi_h[:,j] = G1^(h-1) * impact[:,j].

Returns an ImpulseResponse{T} compatible with plot_result().

Arguments

  • sol: solved DSGE model
  • horizon: number of IRF periods

Keyword Arguments

  • ci_type::Symbol=:none: confidence interval type (:none for analytical DSGE)
source
MacroEconometricModels.irfMethod
irf(sol::ProjectionSolution{T}, horizon::Int; kwargs...) -> ImpulseResponse{T}

Monte Carlo IRF: compare paths with/without initial shock.

Arguments

  • sol: projection solution from Chebyshev collocation
  • horizon: number of IRF periods

Keyword Arguments

  • n_sim::Int=500: number of simulation paths for averaging
  • shock_size::Real=1.0: impulse size in standard deviations
  • ci_type::Symbol=:none: confidence interval type
source
MacroEconometricModels.simulateMethod
simulate(sol::DSGESolution{T}, T_periods::Int;
         shock_draws=nothing, rng=Random.default_rng()) -> Matrix{T}

Simulate the solved DSGE model: y_t = G1 * y_{t-1} + impact * e_t + C_sol.

Returns T_periods x n_endog matrix of levels (steady state + deviations).

Arguments

  • sol: solved DSGE model
  • T_periods: number of periods to simulate

Keyword Arguments

  • shock_draws: T_periods x n_shocks matrix of pre-drawn shocks (default: nothing, draws from N(0,1))
  • rng: random number generator (default: Random.default_rng())
source
MacroEconometricModels.simulateMethod
simulate(sol::ProjectionSolution{T}, T_periods::Int; kwargs...) -> Matrix{T}

Simulate using the global policy function from projection solution. Returns T_periods x n_vars matrix of levels.

Arguments

  • sol: projection solution from Chebyshev collocation
  • T_periods: number of periods to simulate

Keyword Arguments

  • shock_draws: T_periods x n_shocks matrix of pre-drawn shocks (default: nothing, draws from N(0,1))
  • rng: random number generator (default: Random.default_rng())
source
MacroEconometricModels._analytical_moments_gmmMethod
_analytical_moments_gmm(sol::PerturbationSolution{T}; lags::Int=1) → Vector{T}

Compute GMM-format moment vector: means + product moments + diagonal autocovariances.

For order >= 2, uses closed-form augmented Lyapunov. For order 1, uses standard Lyapunov (means are zero).

source
MacroEconometricModels._augmented_moments_2ndMethod
_augmented_moments_2nd(sol::PerturbationSolution{T};
                        lags::Vector{Int}=[1]) → Dict{Symbol, Any}

Compute closed-form unconditional moments for a 2nd-order perturbation solution using the augmented-state Lyapunov approach (Andreasen et al. 2018).

The augmented state is z = [xf; xs; vec(xf⊗xf)] of dimension 2nx + nx². The system is z(t+1) = A·z(t) + c + u(t) where u(t) captures stochastic innovations from the pruned dynamics.

Returns moments for ALL n = nx + ny variables, in the original variable ordering (matching sol.state_indices and sol.control_indices).

Returns a Dict with keys:

  • :E_y — n-vector of unconditional means (deviations from SS)
  • :Var_y — n×n unconditional variance-covariance
  • :Cov_y — n×n×max_lag autocovariance tensor
  • :E_z, :Var_z — augmented state moments (for diagnostics)
source
MacroEconometricModels._augmented_moments_3rdMethod
_augmented_moments_3rd(sol::PerturbationSolution{T};
                         lags::Vector{Int}=[1]) → Dict{Symbol, Any}

Compute closed-form unconditional moments for a 3rd-order perturbation solution using the augmented-state Lyapunov approach (Andreasen et al. 2018).

The augmented state is z = [xf; xs; vec(xf⊗xf); xrd; vec(xf⊗xs); vec(xf⊗xf⊗xf)] of dimension 3nx + 2nx² + nx³. The system is z(t+1) = A·z(t) + c + u(t).

Returns a Dict with keys:

  • :E_y — n-vector of unconditional means (deviations from SS)
  • :Var_y — n×n unconditional variance-covariance
  • :Cov_y — n×n×max_lag autocovariance tensor
  • :E_z, :Var_z — augmented state moments (for diagnostics)
source
MacroEconometricModels._dlyap_doublingMethod
_dlyap_doubling(A::AbstractMatrix{T}, B::AbstractMatrix{T};
                tol::Real=1e-12, maxiter::Int=500) -> Matrix{T}

Solve the discrete Lyapunov equation Σ = A·Σ·A' + B via the doubling algorithm.

More numerically stable than Kronecker vectorization for large systems (O(n³) per iteration vs O(n⁶) for the direct solve), and typically converges in O(log(1/ρ(A))) iterations where ρ(A) is the spectral radius.

Algorithm (Smith 1991):

Aₖ = A,  Bₖ = B
repeat:
    Bₖ₊₁ = Aₖ · Bₖ · Aₖ' + Bₖ
    Aₖ₊₁ = Aₖ · Aₖ
until converged
return (Bₖ₊₁ + Bₖ₊₁') / 2

Convergence is declared when maximum(abs.(Bₖ₊₁ - Bₖ)) < tol or norm(Aₖ) < tol.

source
MacroEconometricModels._extract_xx_blockMethod
_extract_xx_block(Mvv::Matrix{T}, nx::Int, nv::Int) → Matrix{T}

Extract the (xf⊗xf) sub-block from a matrix with nv² columns (Kronecker ordering of v = [x; ε]). Returns a matrix with nx² columns corresponding to the state×state indices only.

source
MacroEconometricModels._extract_xxx_blockMethod
_extract_xxx_block(Mvvv::Matrix{T}, nx::Int, nv::Int) → Matrix{T}

Extract the (xf⊗xf⊗xf) sub-block from a matrix with nv³ columns (Kronecker ordering of v = [x; ε]). Returns a matrix with nx³ columns corresponding to the state×state×state indices only.

source
MacroEconometricModels._girfMethod
_girf(sol::PerturbationSolution{T}, horizon::Int;
      n_draws::Int=500, shock_size::T=one(T)) -> ImpulseResponse{T}

Compute Generalized Impulse Response Functions via Monte Carlo simulation.

GIRF = E[y{t+h} | epst = shock] - E[y{t+h} | epst = 0], averaged over n_draws random draws of future shocks.

source
MacroEconometricModels._innovation_variance_2ndMethod
_innovation_variance_2nd(hx_state, eta_x, Var_xf, nx, n_eps;
                          vectorMom3=nothing, vectorMom4=nothing) → Matrix{T}

Compute the innovation covariance matrix for the 2nd-order augmented state z = [xf; xs; vec(xf⊗xf)].

Follows UnconditionalMoments_2nd_Lyap.m from the GMMThirdOrderv2 MATLAB reference code (Andreasen 2015).

Arguments:

  • hx_state: nx × nx state transition
  • eta_x: nx × n_eps shock loading
  • Var_xf: nx × nx unconditional variance of xf (from first-order Lyapunov)
  • vectorMom3: n_eps vector of 3rd moments (default: zeros for symmetric shocks)
  • vectorMom4: n_eps vector of 4th moments (default: 3s for Gaussian shocks)
source
MacroEconometricModels._innovation_variance_3rd_simMethod
_innovation_variance_3rd_sim(A, c, hx_state, hxx_xx, eta_x, hσσ, Var_xf,
                               nx, n_eps, nz, r1, r2, r3, r4, r5, r6;
                               n_sim=500_000) → Matrix{T}

Compute the innovation covariance for the 3rd-order augmented state system via Monte Carlo simulation. This avoids the complex analytical Gaussian moment formulas (which involve up to 6th moments) while providing accurate results.

The innovation u(t) = z(t+1) - A·z(t) - c is computed from simulated paths of the first-order state xf and shocks ε, then Var_inov = E[u·u'].

source
MacroEconometricModels._simulation_momentsMethod
_simulation_moments(sol::PerturbationSolution{T}; lags::Int=1) -> Vector{T}

Compute moments via pruned simulation for higher-order perturbation solutions.

Uses a fixed RNG seed (12345) for reproducibility and T=100,000 simulation periods.

source
MacroEconometricModels.analytical_momentsMethod
analytical_moments(sol::PerturbationSolution{T}; lags::Int=1,
                   format::Symbol=:covariance) -> Vector{T}

Compute analytical moment vector from a perturbation solution.

Keyword Arguments

  • lags::Int=1 — number of autocovariance lags
  • format::Symbol=:covariance — moment format:
    • :covariance (default): upper-triangle of var-cov + diagonal autocov (backward compatible with DSGESolution format)
    • :gmm: means + upper-triangle product moments + diagonal autocov (for GMM estimation with higher-order perturbation)

For order 1 with :covariance format, uses the doubling Lyapunov solver. For order ≥ 2 with :covariance format, uses simulation-based moments. For :gmm format at any order, uses closed-form augmented Lyapunov (order ≥ 2) or standard Lyapunov (order 1).

source
MacroEconometricModels.fevdMethod
fevd(sol::PerturbationSolution{T}, horizon::Int) -> FEVD{T}

Compute forecast error variance decomposition from a perturbation solution.

Uses the analytical first-order IRFs to compute the proportion of h-step forecast error variance attributable to each structural shock. This follows the same IRF-based computation as fevd(::DSGESolution, ...).

source
MacroEconometricModels.irfMethod
irf(sol::PerturbationSolution{T}, horizon::Int;
    irf_type::Symbol=:analytical, n_draws::Int=500,
    shock_size::Real=1.0, ci_type::Symbol=:none) -> ImpulseResponse{T}

Compute impulse responses from a perturbation solution.

For irf_type=:analytical (default), computes the standard first-order analytical IRFs: Phi_h[:,j] = hx_state^(h-1) * eta * e_j (same as DSGESolution).

For irf_type=:girf, computes Generalized IRFs via Monte Carlo simulation, which captures second-order effects.

Keyword Arguments

  • irf_type::Symbol=:analytical: :analytical for first-order, :girf for simulation-based
  • n_draws::Int=500: number of Monte Carlo draws for GIRF
  • shock_size::Real=1.0: size of the impulse (in standard deviations)
  • ci_type::Symbol=:none: confidence interval type
source
MacroEconometricModels.simulateMethod
simulate(sol::PerturbationSolution{T}, T_periods::Int;
         shock_draws=nothing, rng=Random.default_rng(),
         antithetic::Bool=false) -> Matrix{T}

Simulate a higher-order perturbation solution using Kim et al. (2008) pruning.

For order 1, this is the standard linear simulation. For order 2, the pruned simulation tracks first-order and second-order state components separately to prevent the explosive sample paths that arise from naive simulation of second-order decision rules.

Arguments

  • sol: perturbation solution
  • T_periods: number of periods to simulate

Keyword Arguments

  • shock_draws: T_periods x n_shocks matrix of pre-drawn shocks (default: N(0,1))
  • rng: random number generator
  • antithetic::Bool=false: if true, use antithetic variates (negate second half of shocks)

Returns

T_periods x n_vars matrix of levels (steady state + deviations).

source

Simulation and Analysis

MacroEconometricModels.simulateFunction
simulate(sol::DSGESolution{T}, T_periods::Int;
         shock_draws=nothing, rng=Random.default_rng()) -> Matrix{T}

Simulate the solved DSGE model: y_t = G1 * y_{t-1} + impact * e_t + C_sol.

Returns T_periods x n_endog matrix of levels (steady state + deviations).

Arguments

  • sol: solved DSGE model
  • T_periods: number of periods to simulate

Keyword Arguments

  • shock_draws: T_periods x n_shocks matrix of pre-drawn shocks (default: nothing, draws from N(0,1))
  • rng: random number generator (default: Random.default_rng())
source
simulate(sol::ProjectionSolution{T}, T_periods::Int; kwargs...) -> Matrix{T}

Simulate using the global policy function from projection solution. Returns T_periods x n_vars matrix of levels.

Arguments

  • sol: projection solution from Chebyshev collocation
  • T_periods: number of periods to simulate

Keyword Arguments

  • shock_draws: T_periods x n_shocks matrix of pre-drawn shocks (default: nothing, draws from N(0,1))
  • rng: random number generator (default: Random.default_rng())
source
simulate(sol::PerturbationSolution{T}, T_periods::Int;
         shock_draws=nothing, rng=Random.default_rng(),
         antithetic::Bool=false) -> Matrix{T}

Simulate a higher-order perturbation solution using Kim et al. (2008) pruning.

For order 1, this is the standard linear simulation. For order 2, the pruned simulation tracks first-order and second-order state components separately to prevent the explosive sample paths that arise from naive simulation of second-order decision rules.

Arguments

  • sol: perturbation solution
  • T_periods: number of periods to simulate

Keyword Arguments

  • shock_draws: T_periods x n_shocks matrix of pre-drawn shocks (default: N(0,1))
  • rng: random number generator
  • antithetic::Bool=false: if true, use antithetic variates (negate second half of shocks)

Returns

T_periods x n_vars matrix of levels (steady state + deviations).

source
simulate(result::BayesianDSGE{T}, T_periods::Int;
         n_draws::Int=200,
         quantiles::Vector{<:Real}=[0.05, 0.16, 0.84, 0.95],
         solver::Symbol=:gensys,
         solver_kwargs::NamedTuple=NamedTuple(),
         rng::AbstractRNG=Random.default_rng()) → BayesianDSGESimulation{T}

Simulate from the posterior predictive distribution with credible bands.

For each of n_draws randomly selected posterior parameter draws, re-solves the DSGE model and simulates T_periods forward. Reports pointwise posterior median and quantile bands.

Default quantiles give dual 68% (16th–84th) and 90% (5th–95th) credible bands.

source
MacroEconometricModels.solve_lyapunovFunction
solve_lyapunov(G1::AbstractMatrix{T}, impact::AbstractMatrix{T}) -> Matrix{T}

Solve the discrete Lyapunov equation: Sigma = G1 * Sigma * G1' + impact * impact'.

Uses Kronecker vectorization: vec(Sigma) = (I - G1 kron G1)^{-1} * vec(impact * impact').

Returns the unconditional covariance matrix Sigma (n x n, symmetric positive semi-definite).

Throws ArgumentError if G1 is not stable (max |eigenvalue| >= 1).

source
MacroEconometricModels.analytical_momentsFunction
analytical_moments(sol::DSGESolution{T}; lags::Int=1) -> Vector{T}

Compute analytical moment vector from a solved DSGE model.

Uses the discrete Lyapunov equation to compute the unconditional covariance, then extracts the same moment format as autocovariance_moments:

  1. Upper-triangle of variance-covariance matrix: k*(k+1)/2 elements
  2. Diagonal autocovariances at each lag: k elements per lag

Arguments

  • sol – solved DSGE model (must be stable/determined)
  • lags – number of autocovariance lags (default: 1)
source
analytical_moments(sol::PerturbationSolution{T}; lags::Int=1,
                   format::Symbol=:covariance) -> Vector{T}

Compute analytical moment vector from a perturbation solution.

Keyword Arguments

  • lags::Int=1 — number of autocovariance lags
  • format::Symbol=:covariance — moment format:
    • :covariance (default): upper-triangle of var-cov + diagonal autocov (backward compatible with DSGESolution format)
    • :gmm: means + upper-triangle product moments + diagonal autocov (for GMM estimation with higher-order perturbation)

For order 1 with :covariance format, uses the doubling Lyapunov solver. For order ≥ 2 with :covariance format, uses simulation-based moments. For :gmm format at any order, uses closed-form augmented Lyapunov (order ≥ 2) or standard Lyapunov (order 1).

source

Global Solution Methods

MacroEconometricModels.vfi_solverFunction
vfi_solver(spec::DSGESpec{T}; kwargs...) -> ProjectionSolution{T}

Solve DSGE model via Value Function Iteration.

Iterates on the Bellman operator using Euler equation residuals: at each grid point, solve for the policy via Newton on residual_fns, then update the value (Chebyshev coefficients) and check sup-norm convergence on the policy function.

Keyword Arguments

  • degree::Int=5: Chebyshev polynomial degree
  • grid::Symbol=:auto: :tensor, :smolyak, or :auto
  • smolyak_mu::Int=3: Smolyak exactness level
  • quadrature::Symbol=:auto: :gauss_hermite, :monomial, or :auto
  • n_quad::Int=5: quadrature nodes per shock dimension
  • scale::Real=3.0: state bounds = SS ± scale × σ
  • tol::Real=1e-8: sup-norm convergence tolerance on value function
  • max_iter::Int=1000: maximum VFI iterations
  • damping::Real=1.0: coefficient mixing factor (1.0 = no damping)
  • howard_steps::Int=0: Howard improvement steps per iteration (0 = pure VFI)
  • anderson_m::Int=0: Anderson acceleration depth (0 = disabled)
  • threaded::Bool=false: enable multi-threaded grid evaluation
  • verbose::Bool=false: print iteration info
  • initial_coeffs: warm-start coefficients (nvars × nbasis)
source

DSGE GMM Estimation

MacroEconometricModels.estimate_dsgeFunction
estimate_dsge(spec, data, param_names; method=:irf_matching, ...) -> DSGEEstimation

Estimate DSGE deep parameters via GMM.

Arguments

  • spec::DSGESpec{T} – model specification (initial param values as starting point)
  • data::AbstractMatrix – Tobs x nvars data matrix
  • param_names::Vector{Symbol} – which parameters to estimate

Keywords

  • method::Symbol:irf_matching or :euler_gmm
  • target_irfs::ImpulseResponse – pre-computed target IRFs (optional, for IRF matching)
  • var_lags::Int=4 – lag order for VAR when computing target IRFs
  • irf_horizon::Int=20 – horizon for IRF matching
  • weighting::Symbol=:two_step – GMM weighting
  • n_lags_instruments::Int=4 – instrument lags for Euler equation GMM

References

  • Christiano, L., Eichenbaum, M., & Evans, C. (2005). "Nominal Rigidities and the Dynamic Effects of a Shock to Monetary Policy." Journal of Political Economy, 113(1), 1-45.
  • Hansen, L. P. & Singleton, K. J. (1982). "Generalized Instrumental Variables Estimation of Nonlinear Rational Expectations Models." Econometrica, 50(5), 1269-1286.
source

DSGE Bayesian Estimation

MacroEconometricModels.estimate_dsge_bayesFunction
estimate_dsge_bayes(spec, data, θ0; priors, method=:smc, ...) → BayesianDSGE

Bayesian estimation of DSGE model parameters via Sequential Monte Carlo (SMC), SMC², or Random-Walk Metropolis-Hastings (RWMH).

Arguments

  • spec::DSGESpec{T} — model specification from @dsge macro
  • data::AbstractMatrix — observed data (Tobs × nobs or nobs × Tobs, auto-detected)
  • θ0::AbstractVector{<:Real} — initial parameter guess (length must match number of priors)

Keywords

  • priors::Dict{Symbol,<:Distribution} — prior distributions keyed by parameter name
  • method::Symbol=:smc — estimation method: :smc, :smc2, or :mh
  • observables::Vector{Symbol}=Symbol[] — which endogenous variables are observed (default: all spec.endog)
  • n_smc::Int=5000 — number of SMC particles (for :smc and :smc2)
  • n_particles::Int=500 — number of PF particles (for :smc2 only)
  • n_mh_steps::Int=1 — MH mutation steps per SMC stage
  • n_draws::Int=10000 — total draws for :mh (including burnin)
  • burnin::Int=5000 — burnin draws for :mh
  • ess_target::Float64=0.5 — target ESS fraction for adaptive tempering
  • measurement_error::Union{Nothing,Vector{<:Real}}=nothing — measurement error SDs
  • likelihood::Symbol=:auto — likelihood evaluation method (currently auto = Kalman)
  • solver::Symbol=:gensys — DSGE solver method
  • solver_kwargs::NamedTuple=NamedTuple() — additional solver keyword arguments
  • delayed_acceptance::Bool=false — enable two-stage delayed acceptance MH for :smc2 (Christen & Fox 2005). Pre-screens proposals with a cheap bootstrap PF to avoid expensive CSMC evaluations on proposals that would be rejected. Exact posterior.
  • n_screen::Int=200 — particles for screening PF (only used when delayed_acceptance=true)
  • rng::AbstractRNG=Random.default_rng() — random number generator

Returns

BayesianDSGE{T} containing posterior draws, log posterior, marginal likelihood, etc.

References

  • Herbst, E. & Schorfheide, F. (2014). Sequential Monte Carlo Sampling for DSGE Models. Journal of Applied Econometrics, 29(7), 1073-1098.
  • An, S. & Schorfheide, F. (2007). Bayesian Analysis of DSGE Models. Econometric Reviews, 26(2-4), 113-172.
source
MacroEconometricModels.posterior_summaryFunction
posterior_summary(result::BayesianDSGE{T}) → Dict{Symbol, Dict{Symbol, T}}

Compute posterior summary statistics for each estimated parameter.

Returns a dictionary keyed by parameter name, each containing:

  • :mean — posterior mean
  • :median — posterior median (50th percentile)
  • :std — posterior standard deviation
  • :ci_lower — 2.5th percentile (lower bound of 95% credible interval)
  • :ci_upper — 97.5th percentile (upper bound of 95% credible interval)
source
MacroEconometricModels.marginal_likelihoodFunction
marginal_likelihood(result::BayesianDSGE) → T

Return the log marginal likelihood (model evidence) from Bayesian estimation.

For SMC methods, this is the normalizing constant estimate from the adaptive tempering schedule. For RWMH, this is an approximation.

source
MacroEconometricModels.bayes_factorFunction
bayes_factor(r1::BayesianDSGE, r2::BayesianDSGE) → T

Compute the log Bayes factor comparing model 1 to model 2: log BF₁₂ = log p(Y|M₁) - log p(Y|M₂).

A positive value favors model 1; negative favors model 2. Following Kass & Raftery (1995), 2 * log BF > 6 is strong evidence.

References

  • Kass, R. E. & Raftery, A. E. (1995). Bayes Factors. Journal of the American Statistical Association, 90(430), 773-795.
source
MacroEconometricModels.prior_posterior_tableFunction
prior_posterior_table(result::BayesianDSGE{T}) → Vector{NamedTuple}

Generate rows for a prior-posterior comparison table.

Each row contains:

  • param — parameter name
  • prior_dist — prior distribution type
  • prior_mean — prior mean
  • prior_std — prior standard deviation
  • post_mean — posterior mean
  • post_std — posterior standard deviation
  • ci_lower — posterior 2.5th percentile
  • ci_upper — posterior 97.5th percentile
source
MacroEconometricModels.posterior_predictiveFunction
posterior_predictive(result::BayesianDSGE{T}, n_sim::Int;
                      T_periods::Int=100,
                      rng::AbstractRNG=Random.default_rng()) → Array{T,3}

Simulate from the posterior predictive distribution.

For n_sim randomly selected posterior draws, solves the model at those parameter values and simulates forward T_periods periods.

Arguments

  • result — Bayesian estimation result
  • n_sim — number of simulated paths

Keywords

  • T_periods::Int=100 — number of periods per simulation
  • rng::AbstractRNG — random number generator

Returns

n_sim × T_periods × n_vars array of simulated paths.

source

Occasionally Binding Constraints

MacroEconometricModels.parse_constraintFunction
parse_constraint(expr::Expr, spec::DSGESpec{T}) → OccBinConstraint{T}

Parse a constraint expression of the form :(var[t] >= bound) or :(var[t] <= bound).

Arguments

  • expr — constraint expression, e.g. :(i[t] >= 0) or :(y[t] <= 1.0)
  • spec — DSGE model specification (used to validate variable names)

Returns

An OccBinConstraint{T} with extracted variable, bound, and direction.

Throws

  • ArgumentError if the variable is not found in spec.endog
  • ArgumentError if the expression is not a valid constraint format
source
MacroEconometricModels.occbin_solveFunction
occbin_solve(spec::DSGESpec{T}, constraint::OccBinConstraint{T};
             shock_path::Matrix{T}=zeros(T, 40, spec.n_exog),
             nperiods::Int=size(shock_path, 1),
             maxiter::Int=100) → OccBinSolution{T}

Solve a DSGE model with a single occasionally binding constraint using the piecewise-linear algorithm of Guerrieri & Iacoviello (2015).

The algorithm:

  1. Solve the unconstrained (reference) model via gensys → P, Q
  2. Derive the alternative (binding) regime by replacing the constraint equation
  3. Extract linearized coefficient matrices for both regimes
  4. Run the guess-and-verify loop to find the piecewise-linear solution

Arguments

  • spec — DSGE model specification (must have steady state computed)
  • constraint — the occasionally binding constraint

Keyword Arguments

  • shock_path — Tperiods × nexog matrix of shock realizations
  • nperiods — number of periods to simulate (default: rows of shock_path)
  • maxiter — maximum guess-and-verify iterations (default: 100)

Returns

An OccBinSolution{T} with linear and piecewise-linear paths.

source
occbin_solve(spec::DSGESpec{T}, constraint::OccBinConstraint{T},
             alt_spec::DSGESpec{T}; kwargs...) → OccBinSolution{T}

Variant that accepts an explicit alternative regime specification instead of deriving it automatically from the constraint.

source
occbin_solve(spec::DSGESpec{T}, c1::OccBinConstraint{T}, c2::OccBinConstraint{T};
             shock_path, nperiods, maxiter, curb_retrench) → OccBinSolution{T}

Solve a DSGE model with two occasionally binding constraints using the piecewise-linear algorithm of Guerrieri & Iacoviello (2015).

The algorithm generalizes the one-constraint solver to 4 regimes:

  1. Neither constraint binds (reference)
  2. Only constraint 1 binds (alt1)
  3. Only constraint 2 binds (alt2)
  4. Both constraints bind (alt12)

Arguments

  • spec — DSGE model specification (must have steady state computed)
  • c1 — first occasionally binding constraint
  • c2 — second occasionally binding constraint

Keyword Arguments

  • shock_path — Tperiods × nexog matrix of shock realizations
  • nperiods — number of periods to simulate (default: rows of shock_path)
  • maxiter — maximum guess-and-verify iterations (default: 100)
  • curb_retrench — limit constraint relaxation to one period per iteration (default: false)

Returns

An OccBinSolution{T} with linear and piecewise-linear paths and a nperiods × 2 regime history matrix.

source
occbin_solve(spec::DSGESpec{T}, c1::OccBinConstraint{T}, c2::OccBinConstraint{T},
             alt_specs::Dict; kwargs...) → OccBinSolution{T}

Variant that accepts explicit alternative regime specifications as a Dict mapping regime indicators to DSGESpec:

  • (1,0) → alt1_spec (constraint 1 binding only)
  • (0,1) → alt2_spec (constraint 2 binding only)
  • (1,1) → alt12_spec (both constraints binding)
source
MacroEconometricModels.occbin_irfFunction
occbin_irf(spec::DSGESpec{T}, constraint::OccBinConstraint{T},
           shock_idx::Int, horizon::Int;
           magnitude::Real=one(T), maxiter::Int=100) → OccBinIRF{T}

Compute impulse response functions under an occasionally binding constraint.

Compares the unconstrained linear IRF with the piecewise-linear OccBin IRF.

Arguments

  • spec — DSGE model specification
  • constraint — the occasionally binding constraint
  • shock_idx — index of the shock to perturb (1-based)
  • horizon — number of periods for the IRF

Keyword Arguments

  • magnitude — size of the shock (default: 1.0)
  • maxiter — max guess-and-verify iterations (default: 100)
source
occbin_irf(spec::DSGESpec{T}, c1::OccBinConstraint{T}, c2::OccBinConstraint{T},
           shock_idx::Int, horizon::Int;
           magnitude::Real=one(T), maxiter::Int=100,
           curb_retrench::Bool=false) → OccBinIRF{T}

Two-constraint variant of OccBin IRF.

source

Constraint Constructors

MacroEconometricModels.variable_boundFunction
variable_bound(var::Symbol; lower=nothing, upper=nothing) -> VariableBound{Float64}

Create a variable bound constraint.

Examples

variable_bound(:i, lower=0.0)                    # ZLB: i_t >= 0
variable_bound(:c, lower=0.0)                    # positivity
variable_bound(:h, lower=0.0, upper=1.0)         # hours in [0, 1]
source
MacroEconometricModels.nonlinear_constraintFunction
nonlinear_constraint(fn::Function; label="constraint") -> NonlinearConstraint{Float64}

Create a nonlinear inequality constraint fn(y, y_lag, y_lead, e, theta) <= 0.

Examples

# Collateral constraint: debt <= 0.8 * capital
nonlinear_constraint((y, y_lag, y_lead, e, theta) -> y[3] - 0.8 * y[1]; label="collateral")
source

Display and References

MacroEconometricModels._coef_tableMethod
_coef_table(io, title, names, coefs, se; dist=:z, dof_r=0, level=0.95)

Publication-quality 7-column coefficient table (Stata/EViews style).

Columns: Name | Coef. | Std.Err. | z/t | P>|z/t| | [95% CI lower | CI upper] | stars

source
MacroEconometricModels._pretty_tableMethod
_pretty_table(io::IO, data; kwargs...)

Central PrettyTables wrapper that respects the global display backend.

For :text backend, applies _TEXT_TABLE_FORMAT automatically. For :latex and :html backends, omits text-only formatting options.

source
MacroEconometricModels.set_display_backendMethod
set_display_backend(backend::Symbol)

Set the PrettyTables output backend. Options: :text (default), :latex, :html.

Examples

set_display_backend(:latex)   # all show() methods now emit LaTeX
set_display_backend(:html)    # switch to HTML tables
set_display_backend(:text)    # back to terminal-friendly text
source
MacroEconometricModels.refsFunction
refs([io::IO], x; format=get_display_backend())

Print bibliographic references for a model, result, or method.

Supports four output formats via the format keyword:

  • :text — AEA plain text (default, follows get_display_backend())
  • :latex\bibitem{} entries
  • :bibtex — BibTeX @article{}/@book{} entries
  • :html — HTML with clickable DOI links

Dispatch

  • Instance dispatch: refs(model) prints references for the model type
  • Symbol dispatch: refs(:fastica) prints references for a method name

Examples

model = estimate_var(Y, 2)
refs(model)                        # AEA text to stdout
refs(model; format=:bibtex)        # BibTeX entries

refs(:johansen)                    # Johansen (1991)
refs(:fastica; format=:latex)      # Hyvärinen (1999) as \bibitem
source

Output Tables

MacroEconometricModels.tableFunction
table(irf::ImpulseResponse, var, shock; horizons=nothing) -> Matrix

Extract IRF values for a variable-shock pair. Returns matrix with columns: [Horizon, IRF] or [Horizon, IRF, CIlo, CIhi].

source
table(irf::BayesianImpulseResponse, var, shock; horizons=nothing) -> Matrix

Extract Bayesian IRF values. Returns [Horizon, Mean, Q1, Q2, ...].

source
table(f::FEVD, var; horizons=nothing) -> Matrix

Extract FEVD proportions for a variable. Returns [Horizon, Shock1, Shock2, ...].

source
table(f::BayesianFEVD, var; horizons=nothing, stat=:mean) -> Matrix

Extract Bayesian FEVD values. stat can be :mean or quantile index.

source
table(hd::HistoricalDecomposition, var; periods=nothing) -> Matrix

Extract HD contributions for a variable. Returns [Period, Actual, Shock1, ..., ShockN, Initial].

source
table(hd::BayesianHistoricalDecomposition, var; periods=nothing, stat=:mean) -> Matrix

Extract Bayesian HD contributions. stat can be :mean or quantile index.

source
table(fc::VolatilityForecast) -> Matrix

Extract volatility forecast data. Returns matrix with columns: [Horizon, Forecast, CIlo, CIhi, SE].

source
table(fc::ARIMAForecast) -> Matrix

Extract ARIMA forecast data. Returns matrix with columns: [Horizon, Forecast, CIlo, CIhi, SE].

source
table(fc::FactorForecast, var_idx::Int; type=:observable) -> Matrix

Extract factor forecast data for a single variable. type=:observable returns observable forecasts, type=:factor returns factor forecasts. Returns matrix with columns: [Horizon, Forecast, CIlo, CIhi].

source
table(irf::LPImpulseResponse, var_idx::Int) -> Matrix

Extract LP IRF values for a response variable. Returns matrix with columns: [Horizon, IRF, SE, CIlo, CIhi].

source
MacroEconometricModels.print_tableFunction
print_table([io], irf::ImpulseResponse, var, shock; horizons=nothing)

Print formatted IRF table.

source
print_table([io], f::FEVD, var; horizons=nothing)

Print formatted FEVD table.

source
print_table([io], hd::HistoricalDecomposition, var; periods=nothing)

Print formatted HD table.

source
print_table([io], slp::StructuralLP, var, shock; horizons=nothing)

Print formatted IRF table for a specific variable-shock pair from structural LP.

source
print_table([io], fc::LPForecast)

Print formatted LP forecast table.

source
print_table([io], f::LPFEVD, var_idx; horizons=...)

Print formatted LP-FEVD table for variable var_idx.

source
print_table([io], fc::VolatilityForecast)

Print formatted volatility forecast table.

source
print_table([io], fc::ARIMAForecast)

Print formatted ARIMA forecast table.

source
print_table([io], fc::FactorForecast, var_idx; type=:observable)

Print formatted factor forecast table for a single variable.

source
print_table([io], irf::LPImpulseResponse, var_idx)

Print formatted LP IRF table for a response variable.

source

Non-Gaussian Identification

Normality Tests

MacroEconometricModels.jarque_bera_testFunction
jarque_bera_test(model::VARModel; method=:multivariate) -> NormalityTestResult
jarque_bera_test(U::AbstractMatrix; method=:multivariate)  -> NormalityTestResult

Multivariate Jarque-Bera test for normality of VAR residuals.

Methods:

  • :multivariate — joint test based on multivariate skewness and kurtosis (Lütkepohl 2005)
  • :component — component-wise univariate JB tests on standardized residuals

Reference: Jarque & Bera (1980), Lütkepohl (2005, §4.5)

source
MacroEconometricModels.mardia_testFunction
mardia_test(model::VARModel; type=:both) -> NormalityTestResult
mardia_test(U::AbstractMatrix; type=:both) -> NormalityTestResult

Mardia's tests for multivariate normality based on multivariate skewness and kurtosis.

Types:

  • :skewness — tests multivariate skewness b₁,ₖ
  • :kurtosis — tests multivariate kurtosis b₂,ₖ
  • :both — combined test (sum of both statistics)

Under H₀: T·b₁,ₖ/6 ~ χ²(k(k+1)(k+2)/6), (b₂,ₖ - k(k+2)) / √(8k(k+2)/T) ~ N(0,1).

Reference: Mardia (1970)

source
MacroEconometricModels.doornik_hansen_testFunction
doornik_hansen_test(model::VARModel) -> NormalityTestResult
doornik_hansen_test(U::AbstractMatrix)  -> NormalityTestResult

Doornik-Hansen omnibus test for multivariate normality.

Applies the Bowman-Shenton transformation to each component's skewness and kurtosis, then sums z₁² + z₂² across components. Under H₀: DH ~ χ²(2k).

Reference: Doornik & Hansen (2008)

source
MacroEconometricModels.henze_zirkler_testFunction
henze_zirkler_test(model::VARModel) -> NormalityTestResult
henze_zirkler_test(U::AbstractMatrix)  -> NormalityTestResult

Henze-Zirkler test for multivariate normality based on the empirical characteristic function.

The test statistic is:

\[T_{\beta} = \frac{1}{n} \sum_{i,j} e^{-\beta^2 D_{ij}/2} - 2(1+\beta^2)^{-k/2} \sum_i e^{-\beta^2 d_i^2/(2(1+\beta^2))} + n(1+2\beta^2)^{-k/2}\]

where $D_{ij} = (z_i - z_j)'(z_i - z_j)$ and $d_i = z_i' z_i$.

Reference: Henze & Zirkler (1990)

source
MacroEconometricModels.normality_test_suiteFunction
normality_test_suite(model::VARModel) -> NormalityTestSuite
normality_test_suite(U::AbstractMatrix)  -> NormalityTestSuite

Run all available multivariate normality tests and return a NormalityTestSuite.

Tests included:

  1. Multivariate Jarque-Bera
  2. Component-wise Jarque-Bera
  3. Mardia skewness
  4. Mardia kurtosis
  5. Mardia combined
  6. Doornik-Hansen
  7. Henze-Zirkler
source

ICA-based Identification

MacroEconometricModels.identify_fasticaFunction
identify_fastica(model::VARModel; contrast=:logcosh, approach=:deflation,
                 max_iter=200, tol=1e-6) -> ICASVARResult

Identify SVAR via FastICA (Hyvärinen 1999).

Recovers independent non-Gaussian structural shocks by maximizing non-Gaussianity of the recovered sources.

Arguments:

  • contrast — non-Gaussianity measure: :logcosh (default, robust), :exp, :kurtosis
  • approach:deflation (one-by-one) or :symmetric (simultaneous)
  • max_iter — maximum iterations per component
  • tol — convergence tolerance

Reference: Hyvärinen (1999)

source
MacroEconometricModels.identify_jadeFunction
identify_jade(model::VARModel; max_iter=100, tol=1e-6) -> ICASVARResult

Identify SVAR via JADE (Joint Approximate Diagonalization of Eigenmatrices).

Uses fourth-order cumulant matrices and joint diagonalization via Jacobi rotations.

Reference: Cardoso & Souloumiac (1993)

source
MacroEconometricModels.identify_sobiFunction
identify_sobi(model::VARModel; lags=1:12, max_iter=100, tol=1e-6) -> ICASVARResult

Identify SVAR via SOBI (Second-Order Blind Identification).

Uses autocovariance matrices at multiple lags and joint diagonalization. Exploits temporal structure rather than higher-order statistics.

Reference: Belouchrani et al. (1997)

source
MacroEconometricModels.identify_dcovFunction
identify_dcov(model::VARModel; max_iter=200, tol=1e-6) -> ICASVARResult

Identify SVAR by minimizing pairwise distance covariance between recovered shocks.

Distance covariance (Székely et al. 2007) is zero iff the variables are independent, making it a natural criterion for ICA.

Reference: Matteson & Tsay (2017)

source
MacroEconometricModels.identify_hsicFunction
identify_hsic(model::VARModel; kernel=:gaussian, sigma=1.0,
              max_iter=200, tol=1e-6) -> ICASVARResult

Identify SVAR by minimizing pairwise HSIC between recovered shocks.

HSIC with a characteristic kernel (Gaussian) is zero iff variables are independent.

Reference: Gretton et al. (2005)

source

Non-Gaussian ML Identification

MacroEconometricModels.identify_student_tFunction
identify_student_t(model::VARModel; max_iter=500, tol=1e-6) -> NonGaussianMLResult

Identify SVAR assuming Student-t distributed structural shocks.

Each shock εⱼ ~ t(νⱼ) (standardized to unit variance). Identification is achieved when at most one νⱼ = ∞ (Gaussian).

Reference: Lanne, Meitz & Saikkonen (2017)

source
MacroEconometricModels.identify_mixture_normalFunction
identify_mixture_normal(model::VARModel; n_components=2, max_iter=500, tol=1e-6) -> NonGaussianMLResult

Identify SVAR assuming mixture-of-normals distributed structural shocks.

Each shock εⱼ ~ pj N(0,σ₁ⱼ²) + (1-pj) N(0,σ₂ⱼ²) with unit variance constraint.

Reference: Lanne & Lütkepohl (2010)

source
MacroEconometricModels.identify_pmlFunction
identify_pml(model::VARModel; max_iter=500, tol=1e-6) -> NonGaussianMLResult

Identify SVAR via Pseudo Maximum Likelihood using Pearson Type IV distributions.

Allows both skewness and excess kurtosis in the structural shocks.

Reference: Herwartz (2018)

source
MacroEconometricModels.identify_skew_normalFunction
identify_skew_normal(model::VARModel; max_iter=500, tol=1e-6) -> NonGaussianMLResult

Identify SVAR assuming skew-normal distributed structural shocks.

Each shock εⱼ has pdf f(x) = 2 φ(x) Φ(αⱼ x), where αⱼ controls skewness.

Reference: Azzalini (1985)

source
MacroEconometricModels.identify_nongaussian_mlFunction
identify_nongaussian_ml(model::VARModel; distribution=:student_t,
                        max_iter=500, tol=1e-6) -> NonGaussianMLResult

Unified non-Gaussian ML SVAR identification dispatcher.

Supported distributions:

  • :student_t — independent Student-t shocks (Lanne, Meitz & Saikkonen 2017)
  • :mixture_normal — mixture of two normals (Lanne & Lütkepohl 2010)
  • :pml — Pearson Type IV / Pseudo-ML (Herwartz 2018)
  • :skew_normal — skew-normal (Azzalini 1985)
source

Heteroskedasticity Identification

MacroEconometricModels.identify_markov_switchingFunction
identify_markov_switching(model::VARModel; n_regimes=2, max_iter=500, tol=1e-6) -> MarkovSwitchingSVARResult

Identify SVAR via Markov-switching heteroskedasticity (Lanne & Lütkepohl 2008).

Estimates regime-specific covariance matrices Σ₁, Σ₂, ..., Σ_K via EM algorithm, then identifies B₀ from the eigendecomposition of Σ₁⁻¹ Σ₂.

Identification requires that the relative variance ratios (eigenvalues) are distinct.

Reference: Lanne & Lütkepohl (2008), Rigobon (2003)

source
MacroEconometricModels.identify_garchFunction
identify_garch(model::VARModel; max_iter=500, tol=1e-6) -> GARCHSVARResult

Identify SVAR via GARCH-based heteroskedasticity (Normandin & Phaneuf 2004).

Iterative procedure:

  1. Start with Cholesky B₀
  2. Compute structural shocks εt = B₀⁻¹ ut
  3. Fit GARCH(1,1) to each ε_j,t
  4. Use conditional covariances to re-estimate B₀
  5. Repeat until convergence

Reference: Normandin & Phaneuf (2004)

source
MacroEconometricModels.identify_smooth_transitionFunction
identify_smooth_transition(model::VARModel, transition_var::AbstractVector;
                           max_iter=500, tol=1e-6) -> SmoothTransitionSVARResult

Identify SVAR via smooth-transition heteroskedasticity (Lütkepohl & Netšunajev 2017).

The covariance matrix varies smoothly between two regimes:

\[\Sigma_t = B_0 [I + G(s_t)(\Lambda - I)] B_0'\]

where G(st) = 1/(1 + exp(-γ(st - c))) is the logistic transition function.

Arguments:

  • transition_var — the transition variable s_t (e.g., a lagged endogenous variable)

Reference: Lütkepohl & Netšunajev (2017)

source
MacroEconometricModels.identify_external_volatilityFunction
identify_external_volatility(model::VARModel, regime_indicator::AbstractVector{Int};
                             regimes=2) -> ExternalVolatilitySVARResult

Identify SVAR via externally specified volatility regimes (Rigobon 2003).

Uses a known regime indicator (e.g., NBER recessions, financial crises) to split the sample and estimate regime-specific covariance matrices.

Arguments:

  • regime_indicator — integer vector of regime labels (1, 2, ..., K)
  • regimes — number of distinct regimes (default: 2)

Reference: Rigobon (2003)

source

Identifiability Tests

MacroEconometricModels.test_identification_strengthFunction
test_identification_strength(model::VARModel; method=:fastica,
                             n_bootstrap=999) -> IdentifiabilityTestResult

Test the strength of non-Gaussian identification via bootstrap.

Resamples residuals with replacement, re-estimates B₀, and computes the Procrustes distance between bootstrap and original B₀. Small distances indicate strong identification.

Returns: test statistic = median Procrustes distance, p-value from distribution.

source
MacroEconometricModels.test_shock_gaussianityFunction
test_shock_gaussianity(result::ICASVARResult) -> IdentifiabilityTestResult
test_shock_gaussianity(result::NonGaussianMLResult) -> IdentifiabilityTestResult

Test whether recovered structural shocks are non-Gaussian using univariate JB tests.

Non-Gaussian identification requires at most one shock to be Gaussian. This test checks each shock individually and reports the joint result.

At most one Gaussian shock → identification holds.

source
MacroEconometricModels.test_gaussian_vs_nongaussianFunction
test_gaussian_vs_nongaussian(model::VARModel; distribution=:student_t) -> IdentifiabilityTestResult

Likelihood ratio test: H₀ Gaussian vs H₁ non-Gaussian structural shocks.

Under H₀, the LR statistic LR = 2(ℓ₁ - ℓ₀) ~ χ²(nextraparams).

source
MacroEconometricModels.test_shock_independenceFunction
test_shock_independence(result::ICASVARResult; max_lag=10) -> IdentifiabilityTestResult
test_shock_independence(result::NonGaussianMLResult; max_lag=10) -> IdentifiabilityTestResult

Test independence of recovered structural shocks.

Uses both cross-correlation (portmanteau) and distance covariance tests. Independence is a necessary condition for valid identification.

source
MacroEconometricModels.test_overidentificationFunction
test_overidentification(model::VARModel, result::AbstractNonGaussianSVAR;
                        restrictions=nothing, n_bootstrap=499) -> IdentifiabilityTestResult

Test overidentifying restrictions for non-Gaussian SVAR.

When additional restrictions beyond non-Gaussianity are imposed (e.g., zero restrictions on B₀), this test checks whether those restrictions are consistent with the data.

Uses a bootstrap approach: compares the restricted log-likelihood to bootstrap distribution.

source

Covariance Estimators

MacroEconometricModels.newey_westFunction
newey_west(X::AbstractMatrix{T}, residuals::AbstractVector{T};
           bandwidth::Int=0, kernel::Symbol=:bartlett, prewhiten::Bool=false,
           XtX_inv::Union{Nothing,AbstractMatrix{T}}=nothing) -> Matrix{T}

Compute Newey-West HAC covariance matrix.

V_NW = (X'X)^{-1} S (X'X)^{-1} where S = Γ₀ + Σⱼ₌₁ᵐ w(j) (Γⱼ + Γⱼ')

Arguments

  • X: Design matrix (n × k)
  • residuals: Residuals vector (n × 1)
  • bandwidth: Truncation lag (0 = automatic selection)
  • kernel: Kernel function
  • prewhiten: Use AR(1) prewhitening
  • XtX_inv: Pre-computed (X'X)^{-1} for performance (optional)

Returns

Robust covariance matrix (k × k)

Performance

Pass XtX_inv when calling multiple times with the same X to avoid recomputation.

source
newey_west(X::AbstractMatrix{T}, residuals::AbstractMatrix{T}; ...) -> Matrix{T}

Multivariate version for systems of equations.

source
MacroEconometricModels.white_vcovFunction
white_vcov(X::AbstractMatrix{T}, residuals::AbstractVector{T}; variant::Symbol=:hc0,
           XtX_inv::Union{Nothing,AbstractMatrix{T}}=nothing) -> Matrix{T}

White heteroscedasticity-robust covariance estimator.

Variants: :hc0, :hc1, :hc2, :hc3

Arguments

  • X: Design matrix (n × k)
  • residuals: Residuals vector (n × 1)
  • variant: HC variant (:hc0 = standard, :hc1 = small sample, :hc2/:hc3 = leverage-adjusted)
  • XtX_inv: Pre-computed (X'X)^{-1} for performance (optional)

Returns

Robust covariance matrix (k × k)

Performance

Pass XtX_inv when calling multiple times with the same X to avoid recomputation.

source
white_vcov(X::AbstractMatrix{T}, residuals::AbstractMatrix{T}; ...) -> Matrix{T}

Multivariate version.

source
MacroEconometricModels.driscoll_kraayFunction
driscoll_kraay(X::AbstractMatrix{T}, u::AbstractVector{T};
               bandwidth::Int=0, kernel::Symbol=:bartlett,
               XtX_inv::Union{Nothing,AbstractMatrix{T}}=nothing) -> Matrix{T}

Driscoll-Kraay standard errors for time series regression.

In a pure time series context, this is equivalent to Newey-West HAC estimation applied to the moment conditions X'u. For panel data applications, it would average across cross-sectional units first, but here we treat the data as a single time series.

Arguments

  • X: Design matrix (T × k)
  • u: Residuals vector (T × 1)
  • bandwidth: Bandwidth for kernel. If 0, uses optimal bandwidth selection.
  • kernel: Kernel function (:bartlett, :parzen, :quadraticspectral, :tukeyhanning)
  • XtX_inv: Pre-computed (X'X)^{-1} for performance (optional)

Returns

Robust covariance matrix (k × k)

References

  • Driscoll, J. C., & Kraay, A. C. (1998). Consistent covariance matrix estimation with spatially dependent panel data. Review of Economics and Statistics.

Performance

Pass XtX_inv when calling multiple times with the same X to avoid recomputation.

source
driscoll_kraay(X::AbstractMatrix{T}, U::AbstractMatrix{T};
               bandwidth::Int=0, kernel::Symbol=:bartlett) -> Matrix{T}

Driscoll-Kraay standard errors for multi-equation system.

source
MacroEconometricModels.robust_vcovFunction
robust_vcov(X::AbstractMatrix{T}, residuals::AbstractVecOrMat{T},
            estimator::AbstractCovarianceEstimator) -> Matrix{T}

Dispatch to appropriate covariance estimator based on estimator type.

source
MacroEconometricModels.long_run_varianceFunction
long_run_variance(x::AbstractVector{T}; bandwidth::Int=0, kernel::Symbol=:bartlett) -> T

Estimate long-run variance: S = Σⱼ₌₋∞^∞ γⱼ

Used for unit root tests, cointegration tests, and other applications requiring consistent variance estimation under serial correlation.

Arguments

  • x: Time series vector
  • bandwidth: Truncation lag (0 = automatic)
  • kernel: Kernel function

Returns

Long-run variance estimate (scalar)

source
MacroEconometricModels.long_run_covarianceFunction
long_run_covariance(X::AbstractMatrix{T}; bandwidth::Int=0, kernel::Symbol=:bartlett) -> Matrix{T}

Estimate long-run covariance matrix of multivariate time series.

Arguments

  • X: Multivariate time series (T × k)
  • bandwidth: Truncation lag (0 = automatic)
  • kernel: Kernel function

Returns

Long-run covariance matrix (k × k)

Performance

Uses BLAS matrix operations for lag autocovariance computation.

source
MacroEconometricModels.optimal_bandwidth_nwFunction
optimal_bandwidth_nw(residuals::AbstractVector{T}) -> Int

Compute optimal bandwidth using Newey-West (1994) automatic selection.

source
optimal_bandwidth_nw(residuals::AbstractMatrix{T}) -> Int

Multivariate version: average optimal bandwidth across columns.

source
MacroEconometricModels.register_cov_estimator!Function
register_cov_estimator!(name::Symbol, ::Type{T}) where {T<:AbstractCovarianceEstimator}

Register a custom covariance estimator type for use in LP and other estimators.

Example

struct MyCovEstimator <: AbstractCovarianceEstimator end
register_cov_estimator!(:my_cov, MyCovEstimator)
source

Plotting

Core Plot Functions

MacroEconometricModels.save_plotFunction
save_plot(p::PlotOutput, path::String)

Write the HTML visualization to a file.

Example

p = plot_result(irf_result)
save_plot(p, "irf_plot.html")
source

Plot Dispatches

MacroEconometricModels.plot_resultMethod
plot_result(r::BayesianImpulseResponse; var=nothing, shock=nothing, ncols=0, title="", save_path=nothing)

Plot Bayesian IRF with posterior mean and quantile bands.

source
MacroEconometricModels.plot_resultMethod
plot_result(r::ImpulseResponse; var=nothing, shock=nothing, ncols=0, title="", save_path=nothing)

Plot frequentist impulse response functions with confidence bands.

  • var: Select response variable (index or name). nothing = all.
  • shock: Select shock (index or name). nothing = all.
  • ncols: Number of grid columns (0 = auto).
source
MacroEconometricModels.plot_resultMethod
plot_result(f::BayesianFEVD; var=nothing, stat=:mean, ncols=0, title="", save_path=nothing)

Plot Bayesian FEVD (uses posterior mean by default).

f.point_estimate is H × nvars × nshocks.

source
MacroEconometricModels.plot_resultMethod
plot_result(f::FEVD; var=nothing, ncols=0, title="", save_path=nothing)

Plot forecast error variance decomposition as stacked area charts.

f.proportions is nvars × nshocks × H.

source
MacroEconometricModels.plot_resultMethod
plot_result(f::LPFEVD; var=nothing, bias_corrected=true, ncols=0, title="", save_path=nothing)

Plot LP-FEVD (Gorodnichenko & Lee 2019).

f.proportions and f.bias_corrected are nvars × nshocks × H.

source
MacroEconometricModels.plot_resultMethod
plot_result(hd::BayesianHistoricalDecomposition; var=nothing, stat=:mean, ncols=0, title="", save_path=nothing)

Plot Bayesian historical decomposition (uses posterior mean by default).

source
MacroEconometricModels.plot_resultMethod
plot_result(hd::HistoricalDecomposition; var=nothing, ncols=0, title="", save_path=nothing)

Plot historical decomposition: stacked bar of shock contributions + actual line.

  • var: Variable index or name. nothing = all variables.
source
MacroEconometricModels._plot_filter_panelsMethod

Generate 2-panel Figure for a filter result: (1) Original + Trend, (2) Cycle.

  • tr: trend component
  • cyc: cycle component
  • filter_name: display name
  • original: original series (optional, reconstructed from trend+cycle if nil)
  • offset: index offset for shorter filters (Hamilton, BK)
  • T_obs: original series length
source
MacroEconometricModels.plot_resultMethod
plot_result(r::HamiltonFilterResult; original=nothing, title="", save_path=nothing)

Plot Hamilton filter: original+trend and cycle.

Pass the original series via original kwarg since HamiltonFilterResult doesn't store it.

source
MacroEconometricModels.plot_resultMethod
plot_result(fc::ARIMAForecast; history=nothing, n_history=50, title="", save_path=nothing)

Plot ARIMA forecast with CI fan. Pass original series as history to show context.

source
MacroEconometricModels.plot_resultMethod
plot_result(fc::FactorForecast; type=:both, var=nothing, ncols=0, title="",
            n_obs=6, save_path=nothing)

Plot factor model forecast.

  • type=:both: plot factor forecasts and top observable forecasts (default)
  • type=:factor: plot factor forecasts only
  • type=:observable: plot observable forecasts only
  • n_obs: max number of observables to show when type=:both (default 6)
source
MacroEconometricModels.plot_resultMethod
plot_result(result::BayesianDSGE; title="", save_path=nothing, ncols=0)

Plot prior vs posterior density for each estimated parameter. Each panel shows the prior density curve (dashed) and a kernel density estimate of the posterior draws (solid), with a vertical line at the posterior mean.

source
MacroEconometricModels.plot_resultMethod
plot_result(oirf::OccBinIRF; title="", save_path=nothing)

Plot OccBin IRF comparison: linear (dashed) vs piecewise-linear (solid) with shaded binding-period rectangles for each variable.

source
MacroEconometricModels.plot_resultMethod
plot_result(sol::OccBinSolution; title="", save_path=nothing)

Plot OccBin solution comparison: linear (dashed) vs piecewise-linear (solid) with shaded binding-period rectangles for each variable.

source
MacroEconometricModels.plot_resultMethod
plot_result(d::TimeSeriesData; vars=nothing, ncols=0, title="", save_path=nothing)

Plot time series data: one panel per variable (capped at 12).

  • vars: Variable indices or names to plot. nothing = all (up to 12).
source
MacroEconometricModels.plot_resultMethod
plot_result(nr::NowcastResult; ncols=0, title="", save_path=nothing)

Plot nowcast result: smoothed data for target variable with nowcast/forecast values.

source
MacroEconometricModels._render_scatter_jsMethod

Generate D3.js code for a scatter plot with color-coded groups and optional horizontal reference lines.

  • id: SVG container element ID
  • data_json: JSON array of {x, y, group} data points
  • groups_json: JSON array of {name, color} group configs
  • ref_lines_json: JSON array of {value, color, dash, axis} reference lines (axis = "x" or "y", default "y")
  • xlabel, ylabel: axis labels
source
MacroEconometricModels.plot_resultMethod
plot_result(bd::BaconDecomposition; title="", save_path=nothing)

Plot Bacon decomposition as a scatter plot.

X-axis = 2x2 DiD estimate, Y-axis = weight, colored by comparison type. Horizontal dashed line at the overall TWFE estimate.

source
MacroEconometricModels.plot_resultMethod
plot_result(did::DIDResult; title="", save_path=nothing)

Plot DiD event study coefficients with confidence bands.

Displays ATT coefficients by event time with CI bands, a vertical dashed line at treatment time (event time = 0), a horizontal zero reference line, and the reference period marker.

source
MacroEconometricModels.plot_resultMethod
plot_result(eslp::EventStudyLP; title="", save_path=nothing)

Plot LP-based event study dynamic treatment effects with confidence bands.

Same style as DIDResult but uses coefficients from LP regressions. Title includes "(LP-DiD)" if clean_controls is true, else "(Event Study LP)".

source
MacroEconometricModels.plot_resultMethod
plot_result(hd::HonestDiDResult; title="", save_path=nothing)

Plot HonestDiD sensitivity analysis with dual CI bands.

Shows original confidence intervals (narrow) and robust confidence intervals (wide, accounting for parallel trends violations), with breakdown value annotated.

source
MacroEconometricModels._render_coef_plot_jsMethod

Generate D3.js code for a horizontal coefficient plot with CI error bars.

  • id: SVG container element ID
  • data_json: JSON array of {name, effect, cilo, cihi} objects
  • xlabel, ylabel: axis labels
source
MacroEconometricModels.plot_resultMethod
plot_result(m::LogitModel{T}; title="", save_path=nothing)

Plot logit model diagnostics: sorted predicted probabilities by outcome and distribution of predictions by outcome group.

source
MacroEconometricModels.plot_resultMethod
plot_result(m::ProbitModel{T}; title="", save_path=nothing)

Plot probit model diagnostics: sorted predicted probabilities by outcome and distribution of predictions by outcome group.

source
MacroEconometricModels.plot_resultMethod
plot_result(m::RegModel{T}; title="", save_path=nothing)

Plot OLS/WLS/IV regression diagnostics: residuals vs fitted, residual histogram, and Q-Q plot.

source

Utility Functions

MacroEconometricModels.robust_invMethod

Compute inverse with fallback to pseudo-inverse for singular matrices. Pass silent=true to suppress the warning (e.g., in internal loops where singularity is expected).

source

Panel Regression

Panel Linear Models

MacroEconometricModels.estimate_xtregFunction
estimate_xtreg(pd::PanelData{T}, depvar::Symbol, indepvars::Vector{Symbol};
               model=:fe, twoway=false, cov_type=:cluster, bandwidth=nothing) -> PanelRegModel{T}

Estimate a linear panel regression model.

Arguments

  • pd::PanelData{T} — panel data container (created via xtset)
  • depvar::Symbol — dependent variable name
  • indepvars::Vector{Symbol} — independent variable names

Keyword Arguments

  • model::Symbol:fe, :re, :fd, :between, or :cre (default: :fe)
  • twoway::Bool — include time fixed effects (FE only, default: false)
  • cov_type::Symbol — covariance type: :ols, :cluster (default), :twoway, :driscoll_kraay
  • bandwidth::Union{Nothing,Int} — Driscoll-Kraay bandwidth (default: auto)

Returns

PanelRegModel{T} with estimated coefficients, variance components, and R-squared variants.

Examples

using DataFrames
df = DataFrame(id=repeat(1:50, inner=20), t=repeat(1:20, 50),
               x1=randn(1000), x2=randn(1000))
df.y = repeat(randn(50), inner=20) .+ 1.5 .* df.x1 .- 0.8 .* df.x2 .+ 0.5 .* randn(1000)
pd = xtset(df, :id, :t)
m_fe = estimate_xtreg(pd, :y, [:x1, :x2])
m_re = estimate_xtreg(pd, :y, [:x1, :x2]; model=:re)
m_fd = estimate_xtreg(pd, :y, [:x1, :x2]; model=:fd)
m_be = estimate_xtreg(pd, :y, [:x1, :x2]; model=:between)
m_cre = estimate_xtreg(pd, :y, [:x1, :x2]; model=:cre)

References

  • Baltagi, B. H. (2021). Econometric Analysis of Panel Data. 6th ed. Springer.
  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press.
  • Swamy, P. A. V. B. & Arora, S. S. (1972). Econometrica 40(2), 311-323.
  • Mundlak, Y. (1978). Econometrica 46(1), 69-85.
source

Panel Instrumental Variables

MacroEconometricModels.estimate_xtivFunction
estimate_xtiv(pd::PanelData{T}, depvar::Symbol, exog::Vector{Symbol}, endog::Vector{Symbol};
              instruments::Vector{Symbol}, model::Symbol=:fe, cov_type::Symbol=:cluster,
              time_invariant_exog::Vector{Symbol}=Symbol[],
              time_invariant_endog::Vector{Symbol}=Symbol[]) -> PanelIVModel{T}

Estimate a panel instrumental-variables regression model.

Arguments

  • pd::PanelData{T} — panel data container (created via xtset)
  • depvar::Symbol — dependent variable name
  • exog::Vector{Symbol} — exogenous regressors (time-varying for Hausman-Taylor)
  • endog::Vector{Symbol} — endogenous regressors (time-varying for Hausman-Taylor)

Keyword Arguments

  • instruments::Vector{Symbol} — excluded instruments
  • model::Symbol:fe (FE-IV), :re (EC2SLS), :fd (FD-IV), :hausman_taylor
  • cov_type::Symbol:ols, :cluster (default)
  • time_invariant_exog::Vector{Symbol} — time-invariant exogenous (Hausman-Taylor only)
  • time_invariant_endog::Vector{Symbol} — time-invariant endogenous (Hausman-Taylor only)

Returns

PanelIVModel{T} with estimated coefficients, first-stage F, and Sargan test.

Methods

  • FE-IV (model=:fe): Within-transform then 2SLS. No intercept.
  • RE-IV / EC2SLS (model=:re): Quasi-demean then 2SLS with [Z̃, Z̄ᵢ] instruments.
  • FD-IV (model=:fd): First-difference then 2SLS with intercept.
  • Hausman-Taylor (model=:hausman_taylor): GLS-IV using within-deviations of time-varying exogenous as instruments for time-invariant endogenous.

Examples

using DataFrames
df = DataFrame(id=repeat(1:50, inner=20), t=repeat(1:20, 50),
               x=randn(1000), z=randn(1000))
df.x_endog = 0.5 .* df.z .+ randn(1000)
df.y = repeat(randn(50), inner=20) .+ 1.5 .* df.x .+ 2.0 .* df.x_endog .+ randn(1000)
pd = xtset(df, :id, :t)
m = estimate_xtiv(pd, :y, [:x], [:x_endog]; instruments=[:z])

References

  • Baltagi, B. H. (2021). Econometric Analysis of Panel Data. 6th ed. Springer, ch. 7.
  • Hausman, J. A. & Taylor, W. E. (1981). Econometrica 49(6), 1377-1398.
  • Baltagi, B. H. (1981). Econometrica 49(4), 1049-1054. (EC2SLS)
source

Panel Discrete Choice

MacroEconometricModels.estimate_xtlogitFunction
estimate_xtlogit(pd, depvar, indepvars; model=:pooled, cov_type=:cluster,
                 maxiter=200, tol=1e-8, n_quadrature=12) -> PanelLogitModel{T}

Estimate a panel logistic regression model.

Arguments

  • pd::PanelData{T} – panel data container (created via xtset)
  • depvar::Symbol – binary dependent variable (0/1)
  • indepvars::Vector{Symbol} – independent variable names

Keyword Arguments

  • model::Symbol:pooled, :fe, :re, or :cre (default: :pooled)
  • cov_type::Symbol – covariance type: :ols, :cluster (default)
  • maxiter::Int – maximum iterations (default 200)
  • tol – convergence tolerance (default 1e-8)
  • n_quadrature::Int – Gauss-Hermite quadrature points for RE/CRE (default 12)

Returns

PanelLogitModel{T} with estimated coefficients and diagnostics.

Examples

using DataFrames
df = DataFrame(id=repeat(1:50, inner=10), t=repeat(1:10, 50),
               x1=randn(500), x2=randn(500))
df.y = Float64.(rand(500) .< 1 ./ (1 .+ exp.(-1.0 .* df.x1 .+ 0.5 .* df.x2)))
pd = xtset(df, :id, :t)
m = estimate_xtlogit(pd, :y, [:x1, :x2])
m_fe = estimate_xtlogit(pd, :y, [:x1, :x2]; model=:fe)
m_re = estimate_xtlogit(pd, :y, [:x1, :x2]; model=:re)

References

  • Chamberlain, G. (1980). Review of Economic Studies 47(1), 225-238.
  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press.
source
MacroEconometricModels.estimate_xtprobitFunction
estimate_xtprobit(pd, depvar, indepvars; model=:pooled, cov_type=:cluster,
                  maxiter=200, tol=1e-8, n_quadrature=12) -> PanelProbitModel{T}

Estimate a panel probit regression model.

Arguments

  • pd::PanelData{T} – panel data container (created via xtset)
  • depvar::Symbol – binary dependent variable (0/1)
  • indepvars::Vector{Symbol} – independent variable names

Keyword Arguments

  • model::Symbol:pooled, :re, or :cre (default: :pooled). No :fe — the incidental parameters problem has no conditioning trick for probit.
  • cov_type::Symbol – covariance type: :ols, :cluster (default)
  • maxiter::Int – maximum iterations (default 200)
  • tol – convergence tolerance (default 1e-8)
  • n_quadrature::Int – Gauss-Hermite quadrature points for RE/CRE (default 12)

Returns

PanelProbitModel{T} with estimated coefficients and diagnostics.

Examples

using DataFrames, Distributions
df = DataFrame(id=repeat(1:50, inner=10), t=repeat(1:10, 50),
               x1=randn(500), x2=randn(500))
p = cdf.(Normal(), 0.8 .* df.x1 .- 0.5 .* df.x2)
df.y = Float64.(rand(500) .< p)
pd = xtset(df, :id, :t)
m = estimate_xtprobit(pd, :y, [:x1, :x2])
m_re = estimate_xtprobit(pd, :y, [:x1, :x2]; model=:re)

References

  • Wooldridge, J. M. (2010). Econometric Analysis of Cross Section and Panel Data. 2nd ed. MIT Press.
source

Panel Specification Tests

MacroEconometricModels.hausman_testFunction
hausman_test(fe::PanelRegModel, re::PanelRegModel) -> PanelTestResult{T}

Hausman specification test for fixed vs random effects.

H0: Random effects is consistent (both FE and RE consistent under H0). H1: Random effects is inconsistent (only FE consistent).

Computes chi2 = (betaFE - betaRE)' (VFE - VRE)^{-1} (betaFE - betaRE) on the common slope coefficients (intercept excluded from RE).

Arguments

  • fe::PanelRegModel — fixed effects model
  • re::PanelRegModel — random effects model

Returns

PanelTestResult{T} with chi-squared statistic and p-value.

References

  • Hausman, J. A. (1978). Econometrica 46(6), 1251-1271.
source
MacroEconometricModels.breusch_pagan_testFunction
breusch_pagan_test(re::PanelRegModel) -> PanelTestResult{T}

Breusch-Pagan Lagrange multiplier test for random effects.

H0: sigmau^2 = 0 (pooled OLS is adequate). H1: sigmau^2 > 0 (random effects needed).

LM = (nT / (2(T-1))) * [sumi (sumt eit)^2 / (sumi sumt eit^2) - 1]^2

Arguments

  • re::PanelRegModel — random effects model (pooled OLS residuals computed internally)

Returns

PanelTestResult{T} with chi-squared(1) statistic and p-value.

References

  • Breusch, T. S. & Pagan, A. R. (1980). Review of Economic Studies 47(1), 239-253.
source
MacroEconometricModels.pesaran_cd_testFunction
pesaran_cd_test(m::PanelRegModel) -> PanelTestResult{T}

Pesaran CD test for cross-sectional dependence in panel residuals.

H0: No cross-sectional dependence. H1: Cross-sectional dependence present.

CD = sqrt(2 / (N(N-1))) * sum{i<j} sqrt(Tij) * rho_ij

where rho_ij is the pairwise residual correlation for groups i, j over their overlapping time periods.

Arguments

  • m::PanelRegModel — any panel regression model (FE, RE, etc.)

Returns

PanelTestResult{T} with standard normal test statistic and p-value.

References

  • Pesaran, M. H. (2004). Cambridge Working Papers in Economics No. 0435.
  • Pesaran, M. H. (2015). Econometrica 83(4), 1481-1507.
source
MacroEconometricModels.wooldridge_ar_testFunction
wooldridge_ar_test(fe::PanelRegModel) -> PanelTestResult{T}

Wooldridge test for first-order serial correlation in FE panel residuals.

H0: No serial correlation in idiosyncratic errors. H1: AR(1) serial correlation present.

Procedure:

  1. Compute first-differences of FE residuals within each group
  2. Regress Deltaeit on Deltaei,t-1 (pooled OLS)
  3. Test H0: coefficient = -0.5 (under no serial correlation, first-differenced iid errors have autocorrelation -0.5)

Arguments

  • fe::PanelRegModel — fixed effects model

Returns

PanelTestResult{T} with F(1, N-1) statistic and p-value.

References

  • Wooldridge, J. M. (2002). Econometric Analysis of Cross Section and Panel Data. MIT Press. Ch. 10.
  • Drukker, D. M. (2003). Stata Journal 3(2), 168-177.
source
MacroEconometricModels.modified_wald_testFunction
modified_wald_test(fe::PanelRegModel) -> PanelTestResult{T}

Modified Wald test for groupwise heteroskedasticity in FE panel residuals.

H0: sigma_i^2 = sigma^2 for all i (homoskedasticity across groups). H1: At least one group has different error variance.

W = sumi (sigmai^2 - sigma^2)^2 / (2 * sigmai^4 / Ti)

Arguments

  • fe::PanelRegModel — fixed effects model

Returns

PanelTestResult{T} with chi-squared(N) statistic and p-value.

References

  • Greene, W. H. (2018). Econometric Analysis. 8th ed. Pearson. Ch. 9.
  • Baum, C. F. (2001). Stata Journal 1(1), 101-104.
source
MacroEconometricModels.f_test_feFunction
f_test_fe(fe::PanelRegModel) -> PanelTestResult{T}

F-test for joint significance of all entity fixed effects.

H0: all alphai = 0 (pooled OLS is adequate). H1: at least one alphai != 0 (entity effects present).

F = ((SSRpooled - SSRFE) / (N-1)) / (SSR_FE / (NT - N - K))

Arguments

  • fe::PanelRegModel — fixed effects model

Returns

PanelTestResult{T} with F(N-1, NT-N-K) statistic and p-value.

References

  • Baltagi, B. H. (2021). Econometric Analysis of Panel Data. 6th ed. Springer. Ch. 4.
source

Spectral Analysis

Spectral Estimation

MacroEconometricModels.periodogramFunction
periodogram(y::AbstractVector; window::Symbol=:rectangular, conf_level::Real=0.95) -> SpectralDensityResult

Compute the raw periodogram of y.

Arguments

  • y — time series vector
  • window — data window/taper (default: :rectangular; see _spectral_window)
  • conf_level — confidence level for chi-squared CI (default: 0.95)

Returns

SpectralDensityResult with frequency grid, density, and confidence bounds.

source
MacroEconometricModels.spectral_densityFunction
spectral_density(y::AbstractVector; method::Symbol=:welch, kwargs...) -> SpectralDensityResult

Estimate the spectral density of y.

Methods

  • :welch — Welch's averaged modified periodogram (default)
  • :smoothed — kernel-smoothed periodogram (Daniell kernel)
  • :ar — AR parametric spectrum via Burg's method

Common Keyword Arguments

  • window::Symbol=:hann — data window
  • conf_level::Real=0.95 — confidence level

Method-Specific Keywords

:welch

  • segment_length::Int=0 — segment length (default: n ÷ 4, minimum 16)
  • overlap::Real=0.5 — fraction overlap ∈ [0, 1)

:smoothed

  • bandwidth::Int=0 — kernel half-width (default: ⌊√n⌋)

:ar

  • order::Int=0 — AR order (default: AIC-selected)
  • n_freq::Int=256 — number of frequency grid points
source
MacroEconometricModels.cross_spectrumFunction
cross_spectrum(x::AbstractVector, y::AbstractVector;
               window::Symbol=:hann, segment_length::Int=0,
               overlap::Real=0.5) -> CrossSpectrumResult

Estimate the cross-spectral density between x and y using Welch's method.

Arguments

  • x, y — time series vectors (same length)
  • window — data window (default: :hann)
  • segment_length — segment length (default: n ÷ 4)
  • overlap — fraction overlap (default: 0.5)

Returns

CrossSpectrumResult with co-spectrum, quadrature spectrum, coherence, phase, and gain.

source

Autocorrelation Functions

MacroEconometricModels.acfFunction
acf(y::AbstractVector; lags::Int=0, conf_level::Real=0.95) -> ACFResult

Compute the sample autocorrelation function.

Arguments

  • y — time series vector
  • lags — maximum lag (default: min(n-1, 10*log10(n)))
  • conf_level — confidence level for the white-noise band (default: 0.95)

Returns

ACFResult with ACF values, empty PACF, Ljung-Box Q-stats, and p-values.

Example

result = acf(randn(200), lags=20)
result.acf          # autocorrelation at lags 1:20
result.q_pvalues    # Ljung-Box p-values
source
MacroEconometricModels.pacfFunction
pacf(y::AbstractVector; lags::Int=0, method::Symbol=:levinson, conf_level::Real=0.95) -> ACFResult

Compute the sample partial autocorrelation function.

Arguments

  • y — time series vector
  • lags — maximum lag (default: min(n-1, 10*log10(n)))
  • method:levinson (Levinson-Durbin, default) or :ols
  • conf_level — confidence level for the white-noise band (default: 0.95)

Returns

ACFResult with PACF values, empty ACF, and no Q-stats.

source
MacroEconometricModels.ccfFunction
ccf(x::AbstractVector, y::AbstractVector; lags::Int=0, conf_level::Real=0.95) -> ACFResult

Compute the cross-correlation function between x and y.

Returns CCF(k) = Cor(x{t+k}, yt) for k = -lags:lags, stored in the ccf field. Positive lags mean x leads y.

Arguments

  • x, y — time series vectors (same length)
  • lags — maximum lag (default: min(n-1, 10*log10(n)))
  • conf_level — confidence level (default: 0.95)

Returns

ACFResult with ccf field populated. The lags field runs from -lags to +lags.

source
MacroEconometricModels.acf_pacfFunction
acf_pacf(y::AbstractVector; lags::Int=0, method::Symbol=:levinson, conf_level::Real=0.95) -> ACFResult

Compute both ACF and PACF in a single pass.

Arguments

Same as acf() / pacf().

Returns

ACFResult with both acf and pacf fields populated, plus Ljung-Box Q-stats.

source

Spectral Diagnostics

MacroEconometricModels.coherenceFunction
coherence(x::AbstractVector, y::AbstractVector; kwargs...) -> Tuple{Vector, Vector}

Compute squared coherence between x and y. Returns (freq, coherence).

source
MacroEconometricModels.phaseFunction
phase(x::AbstractVector, y::AbstractVector; kwargs...) -> Tuple{Vector, Vector}

Compute phase spectrum between x and y. Returns (freq, phase).

source
MacroEconometricModels.gainFunction
gain(x::AbstractVector, y::AbstractVector; kwargs...) -> Tuple{Vector, Vector}

Compute gain (amplitude ratio) between x and y. Returns (freq, gain).

source
MacroEconometricModels.band_powerFunction
band_power(result::SpectralDensityResult, f_low::Real, f_high::Real) -> Real

Compute the power (integrated spectral density) in frequency band [flow, fhigh].

Frequencies are in radians ∈ [0, π].

Arguments

  • result — a SpectralDensityResult from periodogram or spectral_density
  • f_low — lower frequency bound (radians)
  • f_high — upper frequency bound (radians)

Returns

Integrated spectral density in the specified band.

source
MacroEconometricModels.ideal_bandpassFunction
ideal_bandpass(y::AbstractVector, f_low::Real, f_high::Real) -> Vector

Apply an ideal (brick-wall) bandpass filter in the frequency domain.

Retains frequency components in flow, fhigh and zeroes everything else. Implements via FFT → zero outside band → IFFT.

Arguments

  • y — time series vector
  • f_low — lower cutoff frequency (radians)
  • f_high — upper cutoff frequency (radians)

Returns

Filtered series (real-valued vector of same length as y).

Example

# Extract business-cycle frequencies (6-32 quarters)
y_bc = ideal_bandpass(gdp, 2π/32, 2π/6)
source
MacroEconometricModels.transfer_functionFunction
transfer_function(filter::Symbol; lambda::Real=1600, K::Int=12,
                  h::Int=8, n_freq::Int=256) -> TransferFunctionResult

Compute the frequency response (gain and phase) of a time-series filter.

Arguments

  • filter — filter type: :hp, :bk, or :hamilton
  • lambda — HP filter smoothing parameter (default: 1600 for quarterly)
  • K — Baxter-King half-window length (default: 12)
  • h — Hamilton filter horizon (default: 8)
  • n_freq — number of frequency grid points (default: 256)

Returns

TransferFunctionResult with gain and phase at each frequency.

Example

tf = transfer_function(:hp, lambda=1600)
tf.gain   # HP filter gain at each frequency
source

Portmanteau and Serial Correlation Tests

MacroEconometricModels.ljung_box_testFunction
ljung_box_test(y::AbstractVector; lags::Int=0, fitdf::Int=0) -> LjungBoxResult

Ljung-Box Q test for serial correlation (H₀: no autocorrelation up to lag lags).

Arguments

  • y — time series or residuals
  • lags — number of lags (default: min(n-1, 10*log10(n)))
  • fitdf — number of fitted parameters to subtract from DOF (e.g., p+q for ARMA(p,q))

Returns

LjungBoxResult with Q-statistic and p-value.

source
MacroEconometricModels.box_pierce_testFunction
box_pierce_test(y::AbstractVector; lags::Int=0, fitdf::Int=0) -> BoxPierceResult

Box-Pierce Q₀ test for serial correlation. Simpler (unweighted) version of Ljung-Box.

Arguments

Same as ljung_box_test.

source
MacroEconometricModels.durbin_watson_testFunction
durbin_watson_test(resid::AbstractVector) -> DurbinWatsonResult

Durbin-Watson test for first-order autocorrelation in residuals.

DW ≈ 2(1 - ρ̂₁). Values near 2 indicate no autocorrelation; near 0 indicates positive autocorrelation; near 4 indicates negative.

Arguments

  • resid — regression residuals

Returns

DurbinWatsonResult with DW statistic and approximate p-value.

source
MacroEconometricModels.bartlett_white_noise_testFunction
bartlett_white_noise_test(y::AbstractVector) -> BartlettWhiteNoiseResult

Bartlett's cumulative periodogram test for white noise.

Under H₀ (white noise), the cumulative normalized periodogram should follow a uniform distribution. The KS statistic measures the maximum deviation.

Arguments

  • y — time series vector

Returns

BartlettWhiteNoiseResult with KS statistic and p-value.

source
MacroEconometricModels.fisher_testFunction
fisher_test(y::AbstractVector) -> FisherTestResult

Fisher's exact test for hidden periodicities.

Tests H₀: y is white noise (no dominant frequency) against H₁: there exists a periodic component. The test statistic is g = max(I(ωⱼ)) / Σ I(ωⱼ).

Arguments

  • y — time series vector

Returns

FisherTestResult with test statistic and p-value.

source

Structural Break Tests

MacroEconometricModels.andrews_testFunction
andrews_test(y, X; test=:supwald, trimming=0.15) -> AndrewsResult

Andrews (1993) / Andrews-Ploberger (1994) structural break test for a single unknown break point in a linear regression model y = X*beta + u.

Tests H0: no structural break vs H1: single structural break at unknown date.

Arguments

  • y::AbstractVector: Dependent variable (n x 1)
  • X::AbstractMatrix: Regressor matrix (n x k)
  • test::Symbol: Test variant. One of:
    • :supwald, :suplr, :suplm — supremum (Andrews 1993)
    • :expwald, :explr, :explm — exponential average (Andrews-Ploberger 1994)
    • :meanwald, :meanlr, :meanlm — simple average (Andrews-Ploberger 1994)
  • trimming::Real: Fraction of sample to trim from each end (default: 0.15)

Returns

AndrewsResult{T} with test statistic, p-value, estimated break date, and full sequence of statistics across candidate break dates.

Example

X = hcat(ones(100), randn(100))
y = X * [1.0, 2.0] + randn(100) * 0.5
y[51:end] .+= X[51:end, 2] .* 3.0  # introduce break at t=50
result = andrews_test(y, X; test=:supwald)
result.pvalue < 0.05  # should reject H0

References

  • Andrews, D. W. K. (1993). Tests for parameter instability and structural change with unknown change point. Econometrica, 61(4), 821-856.
  • Andrews, D. W. K., & Ploberger, W. (1994). Optimal tests when a nuisance parameter is present only under the alternative. Econometrica, 62(6), 1383-1414.
  • Hansen, B. E. (1997). Approximate asymptotic p values for structural-change tests. Journal of Business & Economic Statistics, 15(1), 60-67.
source
MacroEconometricModels.bai_perron_testFunction
bai_perron_test(y, X; max_breaks=5, trimming=0.15, criterion=:bic) -> BaiPerronResult

Bai-Perron (1998, 2003) test for multiple structural breaks in a linear regression.

Tests for m unknown structural break points in the linear model y = X β + u, where regression coefficients are allowed to change at each break date. Uses dynamic programming to find globally optimal break dates minimizing total sum of squared residuals. Break number is selected by BIC or LWZ information criteria.

Arguments

  • y::AbstractVector: Dependent variable (length n)
  • X::AbstractMatrix: Regressor matrix (n × k)
  • max_breaks::Int=5: Maximum number of breaks to consider
  • trimming::Real=0.15: Minimum fraction of observations per segment
  • criterion::Symbol=:bic: Information criterion for break selection (:bic or :lwz)

Returns

BaiPerronResult{T} containing estimated break dates, regime coefficients, sup-F and sequential test statistics, BIC/LWZ values, and confidence intervals.

Example

T = 200
X = ones(T, 1)
y = vcat(ones(100) * 2.0, ones(100) * 5.0) + randn(T) * 0.5
result = bai_perron_test(y, X; max_breaks=3)
result.n_breaks   # Should detect 1 break
result.break_dates # Approximately [100]

References

  • Bai, J., & Perron, P. (1998). Estimating and testing linear models with multiple structural changes. Econometrica, 66(1), 47-78.
  • Bai, J., & Perron, P. (2003). Computation and analysis of multiple structural change models. Journal of Applied Econometrics, 18(1), 1-22.
source
MacroEconometricModels.factor_break_testFunction
factor_break_test(X, r; method=:breitung_eickmeier) -> FactorBreakResult
factor_break_test(fm::FactorModel; method=:breitung_eickmeier) -> FactorBreakResult
factor_break_test(X; method=:chen_dolado_gonzalo) -> FactorBreakResult

Test for structural breaks in factor models.

Methods

  • :breitung_eickmeier — Breitung & Eickmeier (2011) loading stability CUSUM test
  • :chen_dolado_gonzalo — Chen, Dolado & Gonzalo (2014) change in number of factors
  • :han_inoue — Han & Inoue (2015) sup-Wald loading instability test

Arguments

  • X: Data matrix (T × N), observations × variables
  • r: Number of factors (required for :breitungeickmeier and :haninoue)
  • fm: Estimated FactorModel (alternative to providing X and r)

Returns

FactorBreakResult{T} with test statistic, p-value, estimated break date, and method.

Examples

X = randn(200, 50)
result = factor_break_test(X, 3; method=:breitung_eickmeier)
result.pvalue < 0.05 && println("Reject loading stability at 5%")

# Using FactorModel dispatch
fm = estimate_factors(X, 3)
result = factor_break_test(fm; method=:han_inoue)

# Chen-Dolado-Gonzalo does not require r
result = factor_break_test(X; method=:chen_dolado_gonzalo)
source

Panel Unit Root Tests

MacroEconometricModels.panic_testFunction
panic_test(X::AbstractMatrix{T}; r=:auto, method=:pooled) -> PANICResult{T}

Bai-Ng (2004, 2010) PANIC panel unit root test.

Decomposes panel data X (T x N) into common factors and idiosyncratic errors via PCA, then tests each component for unit roots.

Arguments

  • X: Panel data matrix (T x N), time in rows, units in columns

Keyword Arguments

  • r::Union{Int,Symbol}=:auto: Number of common factors (:auto uses IC criteria)
  • method::Symbol=:pooled: Pooling method (:pooled or :individual)

Returns

PANICResult{T} with factor ADF statistics, individual unit statistics, and pooled test statistic.

Example

X = randn(100, 20)
result = panic_test(X; r=1)
result.pooled_pvalue  # p-value for pooled idiosyncratic unit root test

References

  • Bai, J., & Ng, S. (2004). Econometrica, 72(4), 1127-1177.
  • Bai, J., & Ng, S. (2010). Econometric Theory, 26(4), 1088-1114.
source
MacroEconometricModels.pesaran_cips_testFunction
pesaran_cips_test(X::AbstractMatrix{T}; lags=:auto, deterministic=:constant) -> PesaranCIPSResult{T}

Pesaran (2007) CIPS panel unit root test.

Augments individual ADF regressions with cross-sectional averages to account for cross-sectional dependence.

Arguments

  • X: Panel data matrix (T x N), time in rows, units in columns

Keyword Arguments

  • lags::Union{Int,Symbol}=:auto: Number of augmenting lags (:auto selects via floor(T^(1/3)))
  • deterministic::Symbol=:constant: Deterministic terms (:none, :constant, :trend)

Returns

PesaranCIPSResult{T} with CIPS statistic, individual CADF statistics, critical values, and p-value.

Example

X = randn(50, 20)
result = pesaran_cips_test(X; lags=1)
result.pvalue  # p-value for panel unit root test

References

  • Pesaran, M. H. (2007). Journal of Applied Econometrics, 22(2), 265-312.
source
MacroEconometricModels.moon_perron_testFunction
moon_perron_test(X::AbstractMatrix{T}; r=:auto) -> MoonPerronResult{T}

Moon-Perron (2004) panel unit root test with factor adjustment.

Projects out common factors from panel data, then constructs modified pooled t-statistics with bias and variance corrections.

Arguments

  • X: Panel data matrix (T x N), time in rows, units in columns

Keyword Arguments

  • r::Union{Int,Symbol}=:auto: Number of common factors (:auto uses IC criteria)

Returns

MoonPerronResult{T} with two modified t-statistics (ta^*, tb^*) and their p-values (standard normal under H0).

Example

X = randn(80, 15)
result = moon_perron_test(X; r=1)
result.pvalue_a  # p-value for t_a^* statistic
result.pvalue_b  # p-value for t_b^* statistic

References

  • Moon, H. R., & Perron, B. (2004). Journal of Econometrics, 122(1), 81-126.
source
MacroEconometricModels.panel_unit_root_summaryFunction
panel_unit_root_summary(X; r=:auto, lags=:auto) -> Nothing

Print a summary of three panel unit root tests: PANIC (Bai-Ng 2004), Pesaran CIPS (2007), and Moon-Perron (2004).

Arguments

  • X::AbstractMatrix: Panel data (T × N)
  • r: Number of factors for PANIC and Moon-Perron (:auto for IC selection)
  • lags: Number of lags for CIPS (:auto for T^{1/3} rule)

Example

X = randn(100, 20)
panel_unit_root_summary(X; r=1)
source

FAVAR

MacroEconometricModels.estimate_favarFunction
estimate_favar(X, Y_key, r, p; method=:two_step, panel_varnames=nothing) -> FAVARModel
estimate_favar(X, key_indices::Vector{Int}, r, p; ...) -> FAVARModel

Estimate a Factor-Augmented VAR (Bernanke, Boivin & Eliasz, 2005).

Two-Step Algorithm (BBE 2005)

  1. Extract r factors from panel X via PCA (estimate_factors)
  2. Remove double-counting: regress each factor on Y_key, use residuals as slow-moving factors F_tilde
  3. Estimate VAR(p) on augmented system [F_tilde, Y_key]

Arguments

  • X: Panel data matrix (T x N) — large cross-section of macroeconomic variables
  • Y_key: Key observed variables (T x n_key) or column indices into X
  • r: Number of latent factors to extract
  • p: VAR lag order

Keyword Arguments

  • method::Symbol=:two_step: Estimation method (currently only :two_step)
  • panel_varnames::Union{Nothing, Vector{String}}=nothing: Names for the N panel variables
  • n_draws::Int=5000: Number of posterior draws (for Bayesian, reserved for future use)
  • burnin::Int=1000: Burn-in draws (for Bayesian, reserved for future use)

Returns

FAVARModel{T} with estimated VAR on [Ftilde, Ykey], factor loadings, and panel variable metadata for panel-wide IRF mapping.

Example

X = randn(200, 50)    # 200 obs, 50 variables
Y_key = X[:, [1, 5]]  # 2 key variables
favar = estimate_favar(X, Y_key, 3, 2)

# Or using column indices:
favar = estimate_favar(X, [1, 5], 3, 2)

# IRFs (via to_var delegation):
irf_result = irf(favar, 20)

# Panel-wide IRFs (all 50 variables):
panel_irfs = favar_panel_irf(favar, irf_result)
source
estimate_favar(X, key_indices::Vector{Int}, r, p; kwargs...) -> FAVARModel or BayesianFAVAR

Estimate FAVAR where key variables are specified as column indices of X.

source
MacroEconometricModels.favar_panel_irfFunction
favar_panel_irf(favar::FAVARModel, irf_result::ImpulseResponse) -> ImpulseResponse

Map factor-space IRFs to all N panel variables using the factor loadings.

For each panel variable i and shock j: panelirf[h, i, j] = sumk Lambda[i, k] * irf_result.values[h, k, j]

where Lambda is the N x r loading matrix from PCA.

Key variables (those in Y_key_indices) use their direct VAR IRF responses instead of the factor mapping, providing exact impulse responses for the variables that enter the FAVAR directly.

Arguments

  • favar: Estimated FAVAR model
  • irf_result: IRF computed on the FAVAR's augmented VAR system

Returns

ImpulseResponse{T} with N panel variables as the response dimension.

Example

favar = estimate_favar(X, [1, 5], 3, 2)
irf_aug = irf(favar, 20)             # IRF in factor space (r + n_key vars)
irf_panel = favar_panel_irf(favar, irf_aug)  # IRF for all N panel vars
source
favar_panel_irf(bfavar::BayesianFAVAR, irf_result::BayesianImpulseResponse) -> BayesianImpulseResponse

Map Bayesian factor-space IRFs to all N panel variables using posterior mean loadings.

For each panel variable i and shock j: panelirf[h, i, j] = sumk Lambdamean[i, k] * irfresult.point_estimate[h, k, j]

Key variables use their direct VAR IRF responses.

Arguments

  • bfavar: Estimated Bayesian FAVAR model
  • irf_result: Bayesian IRF computed on the FAVAR's augmented VAR system

Returns

BayesianImpulseResponse{T} with N panel variables as the response dimension.

source
MacroEconometricModels.favar_panel_forecastFunction
favar_panel_forecast(favar::FAVARModel, fc::VARForecast) -> VARForecast

Map factor-space forecasts to all N panel variables using the factor loadings.

Key variables use their direct VAR forecast; other variables are mapped through Lambda * F_forecast.

Arguments

  • favar: Estimated FAVAR model
  • fc: Forecast from the augmented VAR (via forecast(favar, h))

Returns

VARForecast{T} with N panel variable forecasts.

source

Structural Dynamic Factor Models

MacroEconometricModels.estimate_structural_dfmFunction
estimate_structural_dfm(X, q; identification=:cholesky, p=1, H=40, sign_check=nothing, max_draws=1000) -> StructuralDFM

Estimate a Structural DFM from raw panel data.

This is a one-step convenience wrapper that first estimates a GDFM via estimate_gdfm(X, q), then applies structural identification to the factor dynamics.

Arguments

  • X: Panel data matrix (T x N)
  • q: Number of dynamic factors

Keyword Arguments

  • identification::Symbol=:cholesky: Identification method (:cholesky or :sign)
  • p::Int=1: VAR lag order on factors
  • H::Int=40: IRF horizon
  • sign_check::Union{Nothing,Function}=nothing: Sign restriction check function (required for :sign)
  • max_draws::Int=1000: Maximum draws for sign restriction search
  • standardize::Bool=true: Standardize data for GDFM estimation
  • bandwidth::Int=0: GDFM kernel bandwidth (0 = automatic)
  • kernel::Symbol=:bartlett: GDFM spectral kernel

Returns

StructuralDFM{T} with identified factor IRFs mapped to all N panel variables.

Example

using FFTW
X = randn(200, 50)
sdfm = estimate_structural_dfm(X, 3; identification=:cholesky, p=2, H=20)
irf_result = irf(sdfm, 20)  # panel-wide structural IRFs

References

  • Forni, M., Giannone, D., Lippi, M., & Reichlin, L. (2009). Opening the Black Box: Structural Factor Models with Large Cross-Sections. Econometric Theory, 25(5), 1319-1347.
source
estimate_structural_dfm(gdfm::GeneralizedDynamicFactorModel; identification=:cholesky, p=1, H=40, sign_check=nothing, max_draws=1000) -> StructuralDFM

Estimate a Structural DFM from an existing GDFM estimation.

Arguments

  • gdfm: Pre-estimated GDFM

Keyword Arguments

  • identification::Symbol=:cholesky: Identification method (:cholesky or :sign)
  • p::Int=1: VAR lag order on factors
  • H::Int=40: IRF horizon
  • sign_check::Union{Nothing,Function}=nothing: Sign restriction check function (required for :sign)
  • max_draws::Int=1000: Maximum draws for sign restriction search

Returns

StructuralDFM{T} with identified factor IRFs mapped to all N panel variables.

source
MacroEconometricModels.sdfm_panel_irfFunction
sdfm_panel_irf(sdfm::StructuralDFM, H::Int) -> ImpulseResponse{T}

Compute panel-wide structural IRFs by projecting factor-space IRFs to all N observable variables via the time-domain loading matrix.

Internally computes factor IRFs from the factor VAR using the stored identification matrix Q, then applies Λ * factor_irf at each horizon.

Arguments

  • sdfm: Estimated Structural DFM
  • H: IRF horizon

Returns

ImpulseResponse{T} with dimensions (H, N, q) — N observable responses to q structural shocks.

source
sdfm_panel_irf(sdfm::StructuralDFM, irf_result::ImpulseResponse) -> ImpulseResponse{T}

Project an existing factor-space ImpulseResponse to all N observable panel variables via the time-domain loading matrix.

Analogous to favar_panel_irf: takes factor-space IRFs (from the factor VAR with any identification) and maps them to observable space.

Arguments

  • sdfm: Estimated Structural DFM (provides loadings)
  • irf_result: Factor-space IRF (H x q x q)

Returns

ImpulseResponse{T} with dimensions (H, N, q).

source

Panel Data Utilities

MacroEconometricModels.panel_lagFunction
panel_lag(pd::PanelData{T}, var::Union{String,Symbol}, k::Int=1) -> Vector{T}

Compute within-group lag of variable var by k periods.

Returns a vector of length T_obs with NaN where the lag is unavailable (first k observations per group, or when there is a time gap).

Examples

pd = load_example(:ddcg)
lag1_y = panel_lag(pd, :y, 1)    # L.y
lag4_y = panel_lag(pd, :y, 4)    # L4.y
source
MacroEconometricModels.panel_leadFunction
panel_lead(pd::PanelData{T}, var::Union{String,Symbol}, k::Int=1) -> Vector{T}

Compute within-group lead of variable var by k periods. NaN where the lead is unavailable.

Examples

pd = load_example(:ddcg)
lead1_y = panel_lead(pd, :y, 1)  # F.y
source
MacroEconometricModels.panel_diffFunction
panel_diff(pd::PanelData{T}, var::Union{String,Symbol}) -> Vector{T}

Compute within-group first difference: D.var = var_t - var_{t-1}. NaN at the first observation of each group or when there is a time gap.

Examples

pd = load_example(:ddcg)
d_dem = panel_diff(pd, :dem)  # D.dem (switching indicator)
source