|
|
|
|
|
|
|
|
|
|
|
|
|
|
import streamlit as st |
|
|
import pandas as pd, numpy as np, matplotlib.pyplot as plt |
|
|
from pandas_datareader import data as web |
|
|
from statsmodels.tsa.api import VAR |
|
|
from statsmodels.tsa.vector_ar.vecm import VECM, coint_johansen |
|
|
from statsmodels.tsa.stattools import adfuller |
|
|
|
|
|
|
|
|
st.set_page_config("Choques Macros – VAR/VECM", layout="wide") |
|
|
|
|
|
|
|
|
@st.cache_data(ttl=3600, show_spinner=False) |
|
|
def load_data(start="2000-01-01", end=None): |
|
|
end = end or pd.Timestamp.today().strftime("%Y-%m-%d") |
|
|
fred = web.DataReader(["GDPC1", "PCEPILFE", "DCOILWTICO"], "fred", start, end) |
|
|
|
|
|
df = pd.concat( |
|
|
[ |
|
|
np.log(fred["GDPC1"]).to_period("M").to_timestamp("M"), |
|
|
np.log(fred["PCEPILFE"]).resample("M").last(), |
|
|
np.log(fred["DCOILWTICO"]).resample("M").last(), |
|
|
], |
|
|
axis=1, |
|
|
).dropna() |
|
|
|
|
|
df.columns = ["PIB_log", "CORE_PCE_log", "WTI_log"] |
|
|
return df |
|
|
|
|
|
|
|
|
st.sidebar.title("🎛️ Controles") |
|
|
ini = st.sidebar.date_input("Data inicial", pd.to_datetime("2000-01-01")) |
|
|
lags = st.sidebar.slider("Lags (p)", 1, 12, 6) |
|
|
conf = st.sidebar.slider("Confiança (%)", 80, 99, 95) |
|
|
modelo = st.sidebar.selectbox("Modelo", ["VECM", "VAR"]) |
|
|
show_fevd = st.sidebar.checkbox("FEVD") |
|
|
h_irf = st.sidebar.slider("Horizonte IRF (m)", 1, 36, 12) |
|
|
|
|
|
|
|
|
with st.spinner("🔄 Baixando FRED…"): |
|
|
df = load_data(ini.strftime("%Y-%m-%d")) |
|
|
|
|
|
st.line_chart(df) |
|
|
|
|
|
|
|
|
with st.expander("🧪 Testes"): |
|
|
col1, col2 = st.columns(2) |
|
|
with col1: |
|
|
st.subheader("ADF") |
|
|
for c in df: |
|
|
stat, p, *_ = adfuller(df[c]) |
|
|
st.write(f"{c}: ADF={stat:.2f}, p={p:.4f}") |
|
|
with col2: |
|
|
joh = coint_johansen(df, 0, lags) |
|
|
st.subheader("Johansen") |
|
|
for i, (ts, cv) in enumerate(zip(joh.lr1, joh.cvt[:, 1])): |
|
|
st.write(f"r≤{i}: {ts:.2f} / {cv:.2f}") |
|
|
|
|
|
|
|
|
if modelo == "VAR": |
|
|
res = VAR(df).fit(lags) |
|
|
st.success(f"VAR({lags}) ajustado") |
|
|
else: |
|
|
rank = sum(joh.lr1 > joh.cvt[:, 1]) |
|
|
res = VECM(df, k_ar_diff=lags, coint_rank=rank, deterministic="co").fit() |
|
|
st.success(f"VECM ajustado (rank={rank})") |
|
|
|
|
|
|
|
|
with st.expander("🚀 IRF", expanded=True): |
|
|
imp = st.selectbox("Impulso", df.columns, 2) |
|
|
resp = st.selectbox("Resposta", df.columns, 0) |
|
|
alpha = 1 - conf / 100 |
|
|
fig = res.irf(h_irf).plot(impulse=imp, response=resp, orth=False, signif=alpha) |
|
|
st.pyplot(fig.figure) |
|
|
|
|
|
|
|
|
if show_fevd: |
|
|
st.subheader("📈 FEVD") |
|
|
fevd = res.fevd(h_irf) |
|
|
for h in [1, 6, 12]: |
|
|
if h <= h_irf: |
|
|
st.write(f"**h={h}**") |
|
|
tbl = pd.DataFrame( |
|
|
fevd.decomp[h], |
|
|
columns=[f"Shock_{c}" for c in df.columns], |
|
|
index=df.columns, |
|
|
).round(2) * 100 |
|
|
st.dataframe(tbl) |
|
|
|
|
|
st.caption("Dados: FRED (GDPC1, PCEPILFE, DCOILWTICO) • Demo UnB EPF") |
|
|
|