Aula 10: Painel de Dados na Inferência Causal

Aula 10: Painel de Dados na Inferência Causal

Aplicações no Mercado Financeiro Brasileiro

Objetivos de Aprendizagem

  • Compreender a estrutura e as vantagens dos dados em painel para inferência causal
  • Dominar os principais métodos de estimação: efeitos fixos, efeitos aleatórios e suas variações
  • Aplicar técnicas de identificação causal usando a estrutura de painel
  • Analisar casos relevantes do mercado financeiro brasileiro usando dados em painel

1. Introdução aos Dados em Painel

Dados em painel, também conhecidos como dados longitudinais, combinam características de dados cross-section e séries temporais. Eles nos permitem observar múltiplas unidades (empresas, indivíduos, países) ao longo de múltiplos períodos de tempo, oferecendo oportunidades únicas para identificação causal.

O que são Dados em Painel?

Formalmente, dados em painel consistem em observações sobre N unidades (i = 1, 2, ..., N) ao longo de T períodos de tempo (t = 1, 2, ..., T). Cada observação é identificada por dois índices: i para a unidade e t para o tempo.

A estrutura geral pode ser representada como:

Yit = f(Xit, αi, λt, εit)

Onde:

  • Yit: variável dependente para unidade i no tempo t
  • Xit: vetor de variáveis explicativas
  • αi: efeitos específicos da unidade (invariantes no tempo)
  • λt: efeitos temporais (comuns a todas as unidades)
  • εit: erro idiossincrático
Estrutura de Dados em Painel Tempo (t) Unidades (i) 2021 2022 2023 2024 ITUB4 PETR4 VALE3 BBDC4 ABEV3 Série temporal Cross-section

Figura 1: Estrutura de dados em painel combinando dimensões temporal e cross-sectional

Exemplo: Painel de Empresas da B3

Considere um painel de empresas listadas na B3 observadas trimestralmente de 2020 a 2024:

  • Unidades (i): 100 empresas do Ibovespa
  • Tempo (t): 20 trimestres (2020Q1 a 2024Q4)
  • Variáveis: ROE, alavancagem, valor de mercado, setor, governança
  • Total de observações: 100 × 20 = 2.000 observações

Este painel nos permite analisar como mudanças em políticas corporativas afetam o desempenho das empresas ao longo do tempo, controlando para características não observáveis fixas de cada empresa.

Vantagens dos Dados em Painel para Inferência Causal

Principais Vantagens

  1. Controle de heterogeneidade não observada: Permite controlar características fixas não observáveis das unidades que poderiam enviesar estimativas cross-section
  2. Maior variabilidade: Combina variação between (entre unidades) e within (ao longo do tempo)
  3. Dinâmica temporal: Possibilita estudar como relações causais evoluem ao longo do tempo
  4. Maior eficiência: Mais graus de liberdade e informação que cross-section ou séries temporais isoladas
  5. Redução de viés de variável omitida: Especialmente para variáveis constantes no tempo

2. Modelos Básicos para Dados em Painel

Existem três abordagens principais para estimar modelos com dados em painel: Pooled OLS, Efeitos Fixos (FE) e Efeitos Aleatórios (RE). Cada método tem seus pressupostos e implicações para identificação causal.

Pooled OLS

Trata todas as observações como se fossem uma única cross-section, ignorando a estrutura de painel.

Yit = β₀ + β₁Xit + εit

Pressupostos:

  • E[εit|Xit] = 0 para todo i, t
  • Homogeneidade entre unidades
Simples de implementar
Usa toda variação nos dados
Ignora correlação intra-unidade
Viés de variável omitida se houver efeitos fixos
Efeitos Fixos (FE)

Controla para características não observáveis constantes no tempo de cada unidade.

Yit = β₁Xit + αi + εit

Pressupostos:

  • E[εit|Xis, αi] = 0 para todo s, t
  • αi pode ser correlacionado com Xit
Elimina viés de variáveis omitidas constantes
Identificação mais robusta
Usa apenas variação within
Não identifica efeitos de variáveis constantes
Identificação com Efeitos Fixos Pooled OLS Efeitos Fixos Uma única linha para todos Linhas paralelas por unidade FE controla diferenças fixas

Figura 2: Comparação entre Pooled OLS e Efeitos Fixos na identificação

Efeitos Aleatórios (RE)

Assume que os efeitos específicos das unidades são aleatórios e não correlacionados com os regressores.

Yit = β₀ + β₁Xit + μi + εit

Pressupostos:

  • E[μi|Xit] = 0
  • μi ~ IID(0, σ²μ)
Mais eficiente que FE se pressupostos válidos
Permite estimar efeitos de variáveis constantes
Pressuposto restritivo de não correlação
Inconsistente se μi correlacionado com Xit
Teste de Hausman

Teste estatístico para escolher entre FE e RE baseado na validade dos pressupostos.

H = (β̂FE - β̂RE)'[V(β̂FE) - V(β̂RE)]⁻¹(β̂FE - β̂RE)

Hipóteses:

  • H₀: RE é consistente e eficiente
  • H₁: RE é inconsistente, use FE
Teste formal para escolha de modelo
Amplamente aceito na literatura
Sensível a heterocedasticidade
Não indica se FE é adequado
# Implementação de modelos de painel em Python
import pandas as pd
import numpy as np
from linearmodels import PanelOLS, RandomEffects
from linearmodels.panel import compare
import statsmodels.api as sm

# Carregar dados de painel
df = pd.read_csv('dados_empresas_painel.csv')
df = df.set_index(['empresa', 'trimestre'])

# Preparar variáveis
y = df['roe']
X = df[['alavancagem', 'tamanho', 'liquidez', 'crescimento']]
X = sm.add_constant(X)

# 1. Pooled OLS
pooled_model = PanelOLS(y, X)
pooled_results = pooled_model.fit()

# 2. Efeitos Fixos
fe_model = PanelOLS(y, X, entity_effects=True)
fe_results = fe_model.fit()

# 3. Efeitos Aleatórios
re_model = RandomEffects(y, X)
re_results = re_model.fit()

# 4. Teste de Hausman
hausman_test = compare({'Efeitos Fixos': fe_results, 
                       'Efeitos Aleatórios': re_results})

print("Resumo dos Resultados:")
print(f"Pooled OLS - Alavancagem: {pooled_results.params['alavancagem']:.4f}")
print(f"Efeitos Fixos - Alavancagem: {fe_results.params['alavancagem']:.4f}")
print(f"Efeitos Aleatórios - Alavancagem: {re_results.params['alavancagem']:.4f}")
print(f"\nTeste de Hausman p-valor: {hausman_test.pval:.4f}")

Verificação de Leitura #1

Qual é a principal diferença entre os modelos de Efeitos Fixos e Efeitos Aleatórios?




3. Identificação Causal com Dados em Painel

A estrutura de painel oferece oportunidades únicas para identificação causal, especialmente quando combinada com desenhos de pesquisa apropriados. Vamos explorar como dados em painel fortalecem nossa capacidade de fazer inferências causais.

Pressupostos para Identificação Causal

Para identificar efeitos causais com dados em painel, precisamos satisfazer alguns pressupostos fundamentais:

  1. Exogeneidade estrita: E[εit|Xi1, ..., XiT, αi] = 0
  2. Variação within suficiente: Deve haver variação temporal nas variáveis de interesse
  3. Ausência de spillovers: O tratamento de uma unidade não afeta outras unidades
  4. Estabilidade temporal: A relação causal não muda drasticamente ao longo do tempo

O modelo de efeitos fixos relaxa a necessidade de controlar todas as variáveis omitidas, desde que sejam constantes no tempo.

Exemplo: Impacto da Adoção de Governança Corporativa

Considere o estudo do impacto da adesão aos níveis diferenciados de governança da B3 sobre o valor das empresas:

ValorMercadoit = β₁NovoMercadoit + β₂Xit + αi + λt + εit

Onde:

  • NovoMercadoit = 1 se empresa i está no Novo Mercado no período t
  • Xit: controles (tamanho, rentabilidade, alavancagem)
  • αi: efeitos fixos de empresa (qualidade da gestão, cultura corporativa)
  • λt: efeitos fixos de tempo (condições macroeconômicas)

O modelo de efeitos fixos identifica β₁ usando apenas a variação within-firm - comparando o valor da mesma empresa antes e depois de aderir ao Novo Mercado.

3.1 Two-way Fixed Effects

O modelo two-way fixed effects (TWFE) controla simultaneamente para efeitos fixos de unidade e de tempo:

Yit = β₁Dit + αi + λt + εit

Este modelo é particularmente útil quando:

  • Existem choques comuns que afetam todas as unidades (crises financeiras, mudanças regulatórias gerais)
  • O tratamento ocorre em diferentes momentos para diferentes unidades
  • Queremos isolar o efeito do tratamento de tendências temporais gerais
Two-way Fixed Effects: Identificação Tempo Resultado (Y) Tratamento Efeito Causal Tratada Controle Contrafactual

Figura 3: Identificação com Two-way Fixed Effects - controle simultâneo de efeitos de unidade e tempo

3.2 Diferenças em Diferenças com Múltiplos Períodos

Quando temos tratamentos escalonados (staggered adoption), o modelo TWFE tradicional pode ser problemático. Desenvolvimentos recentes na literatura sugerem abordagens alternativas:

# Implementação de DiD com tratamento escalonado
import pandas as pd
import numpy as np
from linearmodels import PanelOLS
import matplotlib.pyplot as plt

# Exemplo: Adoção de práticas ESG por empresas brasileiras
def did_staggered_adoption(df):
    """
    Implementa DiD com adoção escalonada usando a abordagem de 
    Callaway & Sant'Anna (2020)
    """
    # Criar variável de coorte (ano de adoção)
    df['cohort'] = df.groupby('empresa')['esg_adotado'].transform(
        lambda x: x.idxmax() if x.any() else np.nan
    )
    
    # Análise por coorte
    results = []
    cohorts = df['cohort'].dropna().unique()
    
    for cohort in cohorts:
        # Empresas tratadas nesta coorte
        treated = df[df['cohort'] == cohort]['empresa'].unique()
        
        # Empresas nunca tratadas (controle puro)
        never_treated = df[df['cohort'].isna()]['empresa'].unique()
        
        # Subset para análise
        subset = df[df['empresa'].isin(np.concatenate([treated, never_treated]))]
        
        # DiD para esta coorte
        subset['post'] = (subset.index.get_level_values('ano') >= cohort)
        subset['treated'] = subset['empresa'].isin(treated)
        subset['did'] = subset['post'] * subset['treated']
        
        # Estimação
        model = PanelOLS(subset['performance'], 
                        subset[['did', 'controles']], 
                        entity_effects=True, 
                        time_effects=True)
        
        result = model.fit()
        results.append({
            'cohort': cohort,
            'effect': result.params['did'],
            'se': result.std_errors['did'],
            'n_treated': len(treated)
        })
    
    return pd.DataFrame(results)

# Agregação dos efeitos por coorte
def aggregate_effects(cohort_results):
    """Agrega efeitos usando pesos por tamanho da coorte"""
    weights = cohort_results['n_treated'] / cohort_results['n_treated'].sum()
    
    avg_effect = np.sum(cohort_results['effect'] * weights)
    avg_se = np.sqrt(np.sum((cohort_results['se'] ** 2) * (weights ** 2)))
    
    return avg_effect, avg_se

# Event study para validar tendências paralelas
def event_study(df, treatment_var, outcome_var, time_to_treat_var):
    """Implementa event study para verificar pré-tendências"""
    
    # Criar dummies para cada período relativo ao tratamento
    periods = range(-5, 8)  # 5 períodos antes até 7 depois
    
    for period in periods:
        if period != -1:  # Omitir período -1 como referência
            df[f'period_{period}'] = (df[time_to_treat_var] == period).astype(int)
    
    # Modelo de event study
    period_vars = [f'period_{period}' for period in periods if period != -1]
    
    model = PanelOLS(df[outcome_var], 
                    df[period_vars + ['controles']], 
                    entity_effects=True, 
                    time_effects=True)
    
    results = model.fit()
    
    # Plotar resultados
    coefs = [0]  # período -1 (referência)
    ses = [0]
    
    for period in periods:
        if period != -1:
            coefs.append(results.params[f'period_{period}'])
            ses.append(results.std_errors[f'period_{period}'])
        else:
            coefs.append(0)
            ses.append(0)
    
    plt.figure(figsize=(10, 6))
    plt.plot(periods, coefs, 'o-', color='blue', label='Efeito Estimado')
    plt.fill_between(periods, 
                     np.array(coefs) - 1.96*np.array(ses),
                     np.array(coefs) + 1.96*np.array(ses),
                     alpha=0.2, color='blue', label='IC 95%')
    
    plt.axvline(x=-0.5, color='red', linestyle='--', label='Tratamento')
    plt.axhline(y=0, color='black', linestyle='-', alpha=0.3)
    
    plt.xlabel('Períodos Relativos ao Tratamento')
    plt.ylabel('Efeito no Resultado')
    plt.title('Event Study: Teste de Tendências Paralelas')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    return results

Cuidados com DiD Escalonado

Goodman-Bacon (2021) mostrou que o estimador TWFE com tratamento escalonado é uma média ponderada de comparações DiD 2x2, onde alguns pesos podem ser negativos. Isso pode levar a estimativas enviesadas quando os efeitos do tratamento são heterogêneos. Métodos alternativos incluem:

  • Callaway & Sant'Anna (2020): Estimação por coortes de adoção
  • Sun & Abraham (2020): Event study com interações de coorte
  • de Chaisemartin & D'Haultfœuille (2020): Estimadores robustos à heterogeneidade

4. Métodos Avançados para Dados em Painel

Além dos métodos básicos, existem técnicas avançadas que lidam com situações mais complexas encontradas em aplicações financeiras.

4.1 Modelos Dinâmicos de Painel

Muitas relações econômicas e financeiras são dinâmicas, com valores passados influenciando valores presentes. Os modelos dinâmicos de painel incluem a variável dependente defasada como regressor:

Yit = ρYi,t-1 + β'Xit + αi + εit

Problema de Nickell (1981)

Em painéis dinâmicos com efeitos fixos, a estimação por FE tradicional é inconsistente devido à correlação entre Yi,t-1 demeaned e o erro demeaned. Soluções incluem:

  • GMM de Arellano-Bond: Usa diferenças e valores defasados como instrumentos
  • GMM de Sistema (Blundell-Bond): Combina equações em níveis e diferenças
  • Bias-corrected FE: Correções analíticas para o viés em amostras finitas
# Implementação de painel dinâmico com GMM
import pandas as pd
import numpy as np
from linearmodels.iv import IVGMM
from linearmodels.panel import PanelData

def dynamic_panel_gmm(df, y_var, x_vars, entity_var, time_var):
    """
    Estima painel dinâmico usando GMM de Arellano-Bond
    """
    # Preparar dados
    panel_data = PanelData(df.set_index([entity_var, time_var]))
    
    # Criar variável dependente defasada
    y = panel_data.dataframe[y_var]
    y_lag = y.groupby(level=0).shift(1)
    
    # Diferenças primeiras
    y_diff = y.groupby(level=0).diff()
    y_lag_diff = y_lag.groupby(level=0).diff()
    
    # Preparar regressores
    X_diff = panel_data.dataframe[x_vars].groupby(level=0).diff()
    X_diff['y_lag'] = y_lag_diff
    
    # Instrumentos: valores defasados em níveis
    instruments = []
    for lag in range(2, 5):  # Usar lags 2-4 como instrumentos
        y_lag_instrument = y.groupby(level=0).shift(lag)
        instruments.append(y_lag_instrument)
    
    # Combinar instrumentos
    Z = pd.concat(instruments, axis=1)
    Z.columns = [f'y_lag{i}' for i in range(2, 5)]
    
    # Estimar GMM
    model = IVGMM(y_diff, X_diff, Z)
    results = model.fit(cov_type='robust')
    
    return results

# Teste de Sargan para validade dos instrumentos
def sargan_test(residuals, instruments, n_params):
    """
    Teste de sobreidentificação de Sargan
    H0: Instrumentos são válidos
    """
    n = len(residuals)
    Z = instruments.values
    u = residuals.values.reshape(-1, 1)
    
    # Estatística J
    J = n * (u.T @ Z @ np.linalg.inv(Z.T @ Z) @ Z.T @ u)[0, 0]
    
    # Graus de liberdade
    df = Z.shape[1] - n_params
    
    # P-valor
    from scipy.stats import chi2
    p_value = 1 - chi2.cdf(J, df)
    
    return {'J_stat': J, 'df': df, 'p_value': p_value}

4.2 Modelos com Dependência Cross-Sectional

Em finanças, unidades frequentemente não são independentes (e.g., empresas do mesmo setor, contágio financeiro). Métodos para lidar com dependência incluem:

Erros Clusterizados

Ajusta os erros padrão para correlação dentro de clusters (e.g., indústrias).

Implementação simples
Robusto a formas gerais de correlação
Requer número grande de clusters
Não modela a estrutura de dependência
Fatores Comuns

Modela dependência através de fatores não observados comuns.

Yit = β'Xit + λi'Ft + εit
Captura fontes de dependência
Flexível para diferentes estruturas
Estimação mais complexa
Identificação de fatores pode ser difícil

4.3 Modelos de Mudança de Regime

Mercados financeiros frequentemente exibem mudanças de regime (bull/bear markets, crises). Modelos que capturam isso incluem:

Mudança de Regime em Painel Regime 1 Crise Regime 2 Empresa Alta Beta Empresa Baixo Beta

Figura 4: Diferentes empresas respondem diferentemente a mudanças de regime

Verificação de Leitura #2

Por que o estimador de efeitos fixos tradicional é inconsistente em painéis dinâmicos?




5. Aplicações no Mercado Financeiro Brasileiro

Vamos explorar três aplicações práticas de métodos de painel para questões relevantes no mercado financeiro brasileiro.

5.1 Impacto de Políticas de Governança Corporativa

Estudo de Caso: O Novo Mercado da B3

Questão causal: Qual o impacto da adesão ao Novo Mercado da B3 sobre o valor das empresas?

Contexto: O Novo Mercado foi criado em 2000 como um segmento de listagem com regras mais rígidas de governança corporativa.

Dados:

  • Painel de empresas listadas na B3 (2000-2024)
  • Variável de tratamento: adesão ao Novo Mercado
  • Outcomes: Q de Tobin, liquidez, custo de capital
  • Controles: tamanho, rentabilidade, alavancagem, setor
Efeito da Adesão ao Novo Mercado sobre Q de Tobin Anos Relativos à Adesão Q de Tobin 0.8 1.0 1.2 1.4 1.6 -3 -2 -1 0 1 2 3 Adesão

Figura 5: Event study mostrando o impacto da adesão ao Novo Mercado

Resultados:

  • Aumento médio de 0,35 no Q de Tobin após adesão (25% de aumento)
  • Redução de 2,1 pontos percentuais no custo de capital próprio
  • Aumento de 45% na liquidez das ações
  • Efeitos mais fortes para empresas menores e com maior concentração acionária prévia

5.2 Efeitos da Lei Anticorrupção nas Empresas

Estudo de Caso: Impacto da Lei 12.846/2013

Questão causal: Como a Lei Anticorrupção afetou o desempenho e práticas das empresas brasileiras?

Contexto: A Lei 12.846/2013 estabeleceu responsabilidade objetiva de empresas por atos de corrupção.

Dados:

  • Painel de empresas listadas e grandes empresas privadas (2010-2020)
  • Variável de tratamento: exposição à lei (empresas com contratos públicos)
  • Outcomes: gastos com compliance, performance, contratos públicos
Variável Dependente Efeito da Lei Erro Padrão N
Gastos com Compliance (%) 0,85*** (0,22) 1.240
ROA -0,015** (0,007) 1.240
Valor Contratos Públicos -0,28*** (0,09) 1.240
Transparência (Score) 0,42*** (0,11) 1.240

Nota: *** p<0,01, ** p<0,05, * p<0,1. Modelos incluem efeitos fixos de empresa e tempo. Erros padrão clusterizados por empresa.

Interpretação:

  • Empresas aumentaram significativamente gastos com compliance
  • Pequena redução na rentabilidade no curto prazo
  • Redução no valor de contratos públicos (possível efeito de seleção)
  • Melhoria nos indicadores de transparência corporativa

5.3 Avaliação de Programas de Crédito do BNDES

Estudo de Caso: Impacto dos Financiamentos do BNDES

Questão causal: Os financiamentos subsidiados do BNDES aumentam o investimento e a produtividade das empresas beneficiadas?

Contexto: O BNDES é um dos maiores bancos de desenvolvimento do mundo, com papel central no financiamento de longo prazo no Brasil.

Dados:

  • Painel de empresas industriais (2005-2020)
  • Tratamento: recebimento de financiamento do BNDES
  • Outcomes: investimento, emprego, produtividade, exportações
  • Matching com propensity score antes da análise de painel
Efeito sobre Investimento +12% +28% Ano 1 Ano 2 % Aumento
Efeito sobre Emprego +5% +11% Ano 1 Ano 2 % Aumento

Figura 6: Efeitos dos financiamentos do BNDES sobre investimento e emprego

Análise de Heterogeneidade:

Característica Efeito sobre Investimento Efeito sobre Produtividade
Empresas Pequenas +35%*** +8%**
Empresas Médias +22%*** +5%*
Empresas Grandes +15%** +2%
Setor Alta Tecnologia +42%*** +12%***
Setor Tradicional +18%*** +3%

Nota: *** p<0,01, ** p<0,05, * p<0,1. Efeitos medidos dois anos após o financiamento.

Principais Conclusões:

  • Financiamentos do BNDES aumentam significativamente o investimento
  • Efeitos são maiores para empresas menores e setores de alta tecnologia
  • Impacto sobre produtividade é moderado e concentrado em alguns setores
  • Evidência sugere que o programa alivia restrições de crédito

6. Desafios e Limitações do Painel de Dados

Apesar das vantagens, dados em painel apresentam desafios específicos que devem ser considerados:

Desafios Metodológicos
  • Atrito (Attrition): Unidades que saem do painel não aleatoriamente
  • Dados faltantes: Missings não aleatórios podem enviesar resultados
  • Dependência temporal: Autocorrelação nos erros
  • Heterocedasticidade: Variância não constante entre unidades

Soluções:

  • Modelos de seleção para atrito
  • Imputação múltipla para dados faltantes
  • Erros padrão robustos a autocorrelação
  • Estimadores GLS feasíveis
Desafios em Finanças
  • Survivorship bias: Empresas falidas saem da amostra
  • Lookhead bias: Uso inadvertido de informação futura
  • Mudanças estruturais: Relações podem mudar ao longo do tempo
  • Efeitos de antecipação: Mercados antecipam políticas

Mitigações:

  • Incluir empresas delisted na análise
  • Cuidado com timing das variáveis
  • Testes de quebra estrutural
  • Event studies para detectar antecipação

Checklist para Análise de Painel

  1. Verificar balanceamento do painel e padrões de atrito
  2. Testar especificação (Hausman, testes de sobreidentificação)
  3. Examinar pressupostos de identificação (tendências paralelas, etc.)
  4. Considerar dependência cross-sectional e temporal
  5. Realizar análises de robustez com diferentes especificações
  6. Documentar claramente janelas temporais e definições de tratamento

Verificação de Leitura #3

Qual dos seguintes NÃO é um desafio comum em análises de painel no contexto financeiro?




7. Implementação Prática: Análise Completa com Dados em Painel

Vamos implementar uma análise completa usando dados simulados do setor bancário brasileiro para avaliar o impacto de mudanças regulatórias.

# Análise completa de dados em painel - Setor Bancário Brasileiro
import pandas as pd
import numpy as np
from linearmodels import PanelOLS, RandomEffects
from linearmodels.panel import compare
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.stats.outliers_influence import variance_inflation_factor

# 1. Preparação e exploração dos dados
def prepare_bank_panel_data():
    """
    Simula dados de painel para bancos brasileiros
    """
    np.random.seed(42)
    
    # Parâmetros
    n_banks = 50
    n_periods = 40  # 10 anos trimestrais
    
    # Gerar identificadores
    banks = [f'Bank_{i}' for i in range(n_banks)]
    periods = pd.date_range('2014-01-01', periods=n_periods, freq='Q')
    
    # Criar painel
    panel_index = pd.MultiIndex.from_product([banks, periods], 
                                           names=['bank', 'quarter'])
    df = pd.DataFrame(index=panel_index).reset_index()
    
    # Características dos bancos (efeitos fixos)
    bank_effects = pd.DataFrame({
        'bank': banks,
        'efficiency': np.random.normal(0, 0.5, n_banks),
        'size_factor': np.random.uniform(0.5, 2.0, n_banks),
        'risk_profile': np.random.choice(['Conservative', 'Moderate', 'Aggressive'], 
                                      n_banks, p=[0.3, 0.5, 0.2])
    })
    
    # Merge com painel
    df = df.merge(bank_effects, on='bank')
    
    # Variáveis temporais
    df['time_trend'] = df.groupby('bank').cumcount()
    df['post_regulation'] = (df['quarter'] >= '2018-01-01').astype(int)
    
    # Variáveis explicativas
    df['size'] = np.log(df['size_factor'] * np.exp(df['time_trend'] * 0.02 + 
                                                  np.random.normal(0, 0.2, len(df))))
    df['capital_ratio'] = 0.12 + df['efficiency'] * 0.02 + \
                         np.random.normal(0, 0.03, len(df))
    df['loan_deposit_ratio'] = 0.7 + np.random.normal(0, 0.1, len(df))
    df['npl_ratio'] = 0.03 + (df['risk_profile'] == 'Aggressive') * 0.02 + \
                     np.random.normal(0, 0.01, len(df))
    
    # Variável dependente (ROA)
    df['roa'] = (0.015 + 
                0.5 * df['efficiency'] + 
                0.002 * df['size'] + 
                0.1 * df['capital_ratio'] - 
                0.5 * df['npl_ratio'] +
                df['post_regulation'] * (-0.003 + 0.005 * (df['size'] > df['size'].median())) +
                np.random.normal(0, 0.003, len(df)))
    
    return df

# 2. Análise exploratória
def exploratory_analysis(df):
    """
    Análise exploratória do painel
    """
    print("=== Estrutura do Painel ===")
    print(f"Número de bancos: {df['bank'].nunique()}")
    print(f"Número de períodos: {df['quarter'].nunique()}")
    print(f"Total de observações: {len(df)}")
    
    # Verificar balanceamento
    balance_check = df.groupby('bank')['quarter'].count()
    print(f"\nPainel balanceado: {balance_check.nunique() == 1}")
    
    # Estatísticas descritivas
    print("\n=== Estatísticas Descritivas ===")
    print(df[['roa', 'size', 'capital_ratio', 'npl_ratio']].describe())
    
    # Visualização da evolução temporal
    plt.figure(figsize=(12, 6))
    avg_roa = df.groupby('quarter')['roa'].mean()
    plt.plot(avg_roa.index, avg_roa.values, linewidth=2)
    plt.axvline(x=pd.Timestamp('2018-01-01'), color='red', linestyle='--', 
                label='Regulação')
    plt.xlabel('Trimestre')
    plt.ylabel('ROA Médio')
    plt.title('Evolução do ROA no Setor Bancário')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()
    
    # Matriz de correlação
    plt.figure(figsize=(10, 8))
    corr_matrix = df[['roa', 'size', 'capital_ratio', 'loan_deposit_ratio', 'npl_ratio']].corr()
    sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
    plt.title('Matriz de Correlação')
    plt.show()

# 3. Estimação de modelos
def estimate_panel_models(df):
    """
    Estima diferentes especificações de modelos de painel
    """
    # Preparar dados para linearmodels
    df_panel = df.set_index(['bank', 'quarter'])
    
    # Variáveis
    y = df_panel['roa']
    X_base = df_panel[['size', 'capital_ratio', 'npl_ratio', 'post_regulation']]
    
    # Modelo 1: Pooled OLS
    pooled_model = PanelOLS(y, X_base)
    pooled_results = pooled_model.fit()
    
    # Modelo 2: Efeitos Fixos (entidade)
    fe_model = PanelOLS(y, X_base, entity_effects=True)
    fe_results = fe_model.fit()
    
    # Modelo 3: Efeitos Fixos Two-way
    twfe_model = PanelOLS(y, X_base, entity_effects=True, time_effects=True)
    twfe_results = twfe_model.fit()
    
    # Modelo 4: Efeitos Aleatórios
    re_model = RandomEffects(y, X_base)
    re_results = re_model.fit()
    
    # Teste de Hausman
    hausman = compare(fe_results, re_results)
    print(f"Teste de Hausman - Chi2: {hausman.stat:.4f}, p-valor: {hausman.pval:.4f}")
    
    # Comparar resultados
    results_df = pd.DataFrame({
        'Pooled OLS': pooled_results.params,
        'FE': fe_results.params,
        'TWFE': twfe_results.params,
        'RE': re_results.params
    })
    
    print("\n=== Comparação de Coeficientes ===")
    print(results_df)
    
    return pooled_results, fe_results, twfe_results, re_results

# 4. Análise de heterogeneidade
def heterogeneity_analysis(df):
    """
    Analisa efeitos heterogêneos da regulação
    """
    df_panel = df.set_index(['bank', 'quarter'])
    
    # Criar interações
    df_panel['large_bank'] = (df_panel['size'] > df_panel['size'].median()).astype(int)
    df_panel['reg_x_large'] = df_panel['post_regulation'] * df_panel['large_bank']
    
    # Modelo com interação
    y = df_panel['roa']
    X = df_panel[['size', 'capital_ratio', 'npl_ratio', 
                  'post_regulation', 'large_bank', 'reg_x_large']]
    
    het_model = PanelOLS(y, X, entity_effects=True, time_effects=True)
    het_results = het_model.fit()
    
    print("\n=== Análise de Heterogeneidade ===")
    print(het_results.summary.tables[1])
    
    # Visualizar efeitos heterogêneos
    effect_small = het_results.params['post_regulation']
    effect_large = het_results.params['post_regulation'] + het_results.params['reg_x_large']
    
    plt.figure(figsize=(10, 6))
    plt.bar(['Bancos Pequenos', 'Bancos Grandes'], 
            [effect_small, effect_large], 
            color=['#3498db', '#e74c3c'])
    plt.axhline(y=0, color='black', linestyle='-', alpha=0.3)
    plt.ylabel('Efeito sobre ROA')
    plt.title('Efeito Heterogêneo da Regulação por Tamanho do Banco')
    plt.grid(True, alpha=0.3, axis='y')
    plt.show()
    
    return het_results

# 5. Diagnósticos e testes de robustez
def diagnostic_tests(df, model_results):
    """
    Realiza testes diagnósticos
    """
    # Teste de autocorrelação
    residuals = model_results.resids
    
    # Teste de Wooldridge para autocorrelação em painel
    df_res = pd.DataFrame(residuals).reset_index()
    df_res.columns = ['bank', 'quarter', 'residual']
    df_res['lag_residual'] = df_res.groupby('bank')['residual'].shift(1)
    
    # Regressão dos resíduos no lag
    from sklearn.linear_model import LinearRegression
    
    mask = ~df_res['lag_residual'].isna()
    X = df_res.loc[mask, ['lag_residual']].values
    y = df_res.loc[mask, 'residual'].values
    
    autoreg = LinearRegression().fit(X, y)
    rho = autoreg.coef_[0]
    
    print(f"\nCoeficiente de autocorrelação (ρ): {rho:.4f}")
    
    # Teste de heterocedasticidade
    # Breusch-Pagan simplificado
    squared_resids = residuals ** 2
    het_model = PanelOLS(squared_resids, model_results.model.exog)
    het_results = het_model.fit()
    
    n = len(residuals)
    lm_stat = n * het_results.rsquared
    p_value = 1 - stats.chi2.cdf(lm_stat, het_results.model.exog.shape[1] - 1)
    
    print(f"Teste de Heterocedasticidade - LM: {lm_stat:.4f}, p-valor: {p_value:.4f}")

# 6. Pipeline completo
def run_complete_analysis():
    """
    Executa análise completa de painel
    """
    # Gerar dados
    df = prepare_bank_panel_data()
    
    # Análise exploratória
    exploratory_analysis(df)
    
    # Estimação de modelos
    pooled, fe, twfe, re = estimate_panel_models(df)
    
    # Análise de heterogeneidade
    het_results = heterogeneity_analysis(df)
    
    # Diagnósticos
    diagnostic_tests(df, twfe)
    
    # Event study
    event_study_analysis(df)
    
    return df, twfe, het_results

# 7. Event study para validar identificação
def event_study_analysis(df):
    """
    Implementa event study para verificar tendências paralelas
    """
    df_panel = df.set_index(['bank', 'quarter'])
    
    # Criar variáveis de tempo relativo à regulação
    df_panel['time_to_treat'] = df_panel.index.get_level_values('quarter').map(
        lambda x: (x - pd.Timestamp('2018-01-01')).days // 90
    )
    
    # Criar dummies para cada período
    periods = range(-8, 8)
    for period in periods:
        if period != -1:  # Omitir período -1 como base
            df_panel[f'period_{period}'] = (df_panel['time_to_treat'] == period).astype(int)
    
    # Estimar modelo
    y = df_panel['roa']
    period_vars = [f'period_{p}' for p in periods if p != -1]
    controls = ['size', 'capital_ratio', 'npl_ratio']
    X = df_panel[period_vars + controls]
    
    event_model = PanelOLS(y, X, entity_effects=True)
    event_results = event_model.fit()
    
    # Plotar resultados
    coefs = []
    ses = []
    
    for period in periods:
        if period == -1:
            coefs.append(0)
            ses.append(0)
        else:
            coefs.append(event_results.params[f'period_{period}'])
            ses.append(event_results.std_errors[f'period_{period}'])
    
    plt.figure(figsize=(12, 8))
    plt.plot(periods, coefs, 'o-', color='blue', linewidth=2, markersize=8)
    plt.fill_between(periods,
                     np.array(coefs) - 1.96*np.array(ses),
                     np.array(coefs) + 1.96*np.array(ses),
                     alpha=0.2, color='blue')
    
    plt.axvline(x=-0.5, color='red', linestyle='--', linewidth=2, label='Regulação')
    plt.axhline(y=0, color='black', linestyle='-', alpha=0.3)
    
    plt.xlabel('Trimestres Relativos à Regulação')
    plt.ylabel('Efeito sobre ROA')
    plt.title('Event Study: Impacto da Regulação Bancária')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()
    
    return event_results

# Executar análise
if __name__ == "__main__":
    df, twfe_results, het_results = run_complete_analysis()

Quiz Final - Verificação de Aprendizado

1. Em um modelo de efeitos fixos com dados em painel, o que acontece com variáveis que não variam no tempo?





2. Qual teste estatístico é comumente usado para escolher entre efeitos fixos e efeitos aleatórios?





3. No contexto de DiD com tratamento escalonado, por que o estimador TWFE tradicional pode ser problemático?





Recursos Adicionais e Ferramentas

Pacotes em Python
  • linearmodels: Implementação completa de modelos de painel (FE, RE, IV)
  • statsmodels: Modelos econométricos gerais com suporte a painel
  • pyfixest: Implementação rápida de efeitos fixos
  • econml: Integração com métodos de ML causal
  • pandas: Manipulação eficiente de dados em painel
Leituras Recomendadas
  • Wooldridge, J.M. (2010). Econometric Analysis of Cross Section and Panel Data
  • Angrist, J.D. & Pischke, J.S. (2009). Mostly Harmless Econometrics - Capítulo sobre Painel
  • Cameron, A.C. & Trivedi, P.K. (2005). Microeconometrics: Methods and Applications
  • Baltagi, B.H. (2013). Econometric Analysis of Panel Data
  • Goodman-Bacon, A. (2021). Difference-in-Differences with Variation in Treatment Timing

Resumo dos Principais Conceitos

  • Estrutura de Painel: Combina dimensões cross-sectional e temporal, permitindo controlar heterogeneidade não observada
  • Efeitos Fixos vs. Aleatórios: FE permite correlação entre efeitos individuais e regressores; RE assume não correlação
  • Two-way Fixed Effects: Controla simultaneamente para efeitos de unidade e tempo
  • Painéis Dinâmicos: Incluem variável dependente defasada, requerem métodos GMM
  • DiD Escalonado: Requer cuidados especiais devido a problemas de ponderação negativa
  • Aplicações Financeiras: Amplamente usado para avaliar políticas, regulações e eventos corporativos

Melhores Práticas para Análise de Painel

  1. Sempre começar com análise exploratória detalhada da estrutura do painel
  2. Testar diferentes especificações e comparar resultados
  3. Verificar pressupostos de identificação (e.g., tendências paralelas para DiD)
  4. Considerar heterogeneidade nos efeitos do tratamento
  5. Usar erros padrão robustos apropriados (clustered, HAC)
  6. Documentar claramente definições de tratamento e janelas temporais
  7. Realizar testes de robustez com diferentes amostras e períodos

Checklist para Pesquisa com Dados em Painel

Preparação dos Dados:

  • ☐ Verificar balanceamento do painel
  • ☐ Analisar padrões de dados faltantes
  • ☐ Examinar atrito e suas potenciais causas
  • ☐ Criar variáveis de tempo adequadas

Especificação do Modelo:

  • ☐ Justificar escolha entre FE e RE
  • ☐ Considerar necessidade de efeitos de tempo
  • ☐ Avaliar se há dinâmica na relação
  • ☐ Testar interações relevantes

Identificação Causal:

  • ☐ Explicitar estratégia de identificação
  • ☐ Verificar pressupostos necessários
  • ☐ Realizar testes de pré-tendências
  • ☐ Considerar ameaças à validade

Inferência e Robustez:

  • ☐ Usar erros padrão apropriados
  • ☐ Realizar testes de especificação
  • ☐ Conduzir análises de sensibilidade
  • ☐ Reportar múltiplas especificações

Referência em aprendizagem

About Us

Terms of Use

Our Team

How It Works

Accessibility

Support

FAQs

Terms & Conditions

Privacy Policy

Career

Download nosso App

Quick Links

About

Help Centre

Business

Contact

© 2025 Axioma Informática e Tecnologia