Tarefa3 / app.py
matheusbm's picture
Update app.py
f6da36a verified
# ======================================================
# 📉 Choques Macros • VAR · VECM · IRF · FEVD (FRED-only)
# ======================================================
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
# ---------- Página ----------
st.set_page_config("Choques Macros – VAR/VECM", layout="wide")
# ---------- Função de dados ----------
@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
# ---------- Sidebar ----------
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)
# ---------- Dados ----------
with st.spinner("🔄 Baixando FRED…"):
df = load_data(ini.strftime("%Y-%m-%d"))
st.line_chart(df)
# ---------- Testes ----------
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}")
# ---------- Ajuste ----------
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})")
# ---------- IRF ----------
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)
# ---------- FEVD ----------
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")