Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Explorando o Paper: "Do Any Economists Have Superior Forecasting Skills?", Ritong Qu, Allan Timmermann & Yinchu Zhu

0 votos
11 visitas
perguntada Nov 5 em Finanças por Sergio Costa (11 pontos)  
Compartilhe

1 Resposta

0 votos
respondida Nov 5 por Sergio Costa (11 pontos)  
editado Nov 5 por Sergio Costa

Explorando o Paper: "Do Any Economists Have Superior Forecasting Skills?", Ritong Qu, Allan Timmermann & Yinchu Zhu

Introdução (Motivação pela escolha do Paper)

Pela Hipótese do Mercado Eficiente, os preços, e consequentemente os retornos, refletiriam a média do sentimento mercado. Assim, nenhum investidor conseguiria retornos em excesso aos normais.

O artigo em questão procura investigar se algum economista consegue prever indicadores econômicos melhor do que os outros agentes consistentemente - lembrando a Hipótese Forte do Mercado Eficiente, no sentido de que um agente não conseguiria superar retornos de mercado de forma duradoura baseado em informações públicas e privadas.

No fim das contas, talvez o resultado do paper lembre um pouco o wisdom of crowds... dadas as evidências de que em poucos casos especialistas conseguem previsões melhores do que as médias das previsões.

Além da realização de testes Diebold-Mariano para os indicadores isolados, o autor desenvolve um teste Sup, "studentized", que compara erros de previsões de um economista para um grupo de indicadores com os erros de previsões de um dado benchmark. Para esse teste Sup, os autores se baseram nos métodos de bootstrap desenvolvidos por Chernozhukov et al. (2018) para inferência estátisca.

Revisão da Literatura e Testes Artigo

Os testes para comparações de previsões são baseadas em uma função perda, que relaciona o erro quadrático de uma previsão com o erro quadrático de um benchmark. Mais especificamente, a função \(L(y_{i,t+h}, \hat{y}_{i,t+h|t,m})\) é o erro quadrático da previsão de um indicador \(i\), para um tempo \(t+h\) por um previsor \(m\). A diferença entre o previsor \(m\) e o benchmark \(m_{0}\) é o \(\Delta L\).

\[L(y_{i,t+h}, \hat{y}_{i,t+h|t,m})=e_{i,t+h,m}^{2}\]

\[\Delta L_{i,t+h,m}=e_{i,t+h,m_{0}}^{2}-e_{i,t+h,m}^{2}\]

Diebold and Mariano (1995):

Talvez o artigo seminal para esses testes seja o de Diebold and Mariano (1995), verificando se havia diferença entre os erros quadráticos de previsão entre um benchmark e um outro previsor.

\[H_{0}^{DM}:E\left [ \Delta L_{i, t+h,m}\right ] \leqslant 0\]

White (2000), Hansen (2005) e Romano e Wolf (2005):

Em seguida, alguns autores desenvolveram o teste para verificar entre indivíduos se há algum com capacidade preditiva superior ao benchmark para um único indicador.

\[H_{0}^{RC}:\max_{m \in \left \{ 1,...,M \right \} }E\left [ \Delta L_{i, t+h,m} \right ]\leqslant 0\]

Sup Test:

Já o Sup test possibilita detectar se há um indíviduo com capacidade preditiva superior em um grupo de indicadores. Os autores usaram o teste para verificar se havia indivídiuos especialistas em certos tipos de indicadores (e.g. atividade), indivíduos generalistas e melhora das previsões no tempo.

\[H_{0}^{G}:\max_{m \in \left \{ 1,...,M \right \} }E\left [\frac{1}{N}\sum_{i=1}^{N} \Delta L_{i, t+h,m} \right ]\leqslant 0\]

Conclusões Artigo

  • Testes Diebold-Mariano - alguns indivíduos (ainda que poucos) conseguiram resultados melhores do que uma média simples dos especialistas.

  • Testes Sup - levando em consideração testes com múltiplos indicadores, dificilmente um economista é consistentemente superior aos demais. Ainda assim, especialistas têm capacidade de previsão melhores do que algumas técnicas robustas padrão.

  • Melhora das Previsões no Tempo - com base em comparações entre as previsões do outono e da primavera de crescimento do PIB no IMF World Economic Outlook. Previsões mais próximas do final do ano, conforme intuição, tem erros menores.

  • Tomadores de decisão de políticas públicas, levando em conta as fracas evidências de capacidade superior de um especialista ante a média, deveriam focar nas médias das previsões.


Base de Dados do Exercício Empírico

Para o exercício empírico, o indicador ecolhido foi o IPCA, com série mensal (jan/2017 a set/2021), previsões de 96 instituições financeiras, tendo 72 instituições com 5 ou mais estimativas. No total, foram 2.329 estimativas mensais de inflação enviadas à Bloomberg. A primeira figura exibe em linha sólida o IPCA realizado e em bolas vermelhas as previsões das diversas instituições para o IPCA enviadas à Bloomberg aproximadamente 10 dias antes da divulgação do índice.

O foco do exercício empírico foi realizar Testes Diebold-Mariano comparando a qualidade das previsões de uma instituição com um benchmark. Foram realizados 72 testes para cada benchmark escolhido (média das previsões, mediana das previsões, AR(1) e LM).

Para testes comparando instituições com modelos simples AR(1) e LM, houve um período anterior de 24m de treino conforme artigo em tela, atualizando-se os parâmetros e as estimativas a cada período fora do período de treino.

No caso do modelo linear, utilizou-se dados como a inflação implícita, IPCA defasado, IPCA-15, inclinação da curva de juros, índice de difusão do IPCA, cotação do petróleo, taxa Selic, swap de 1 ano, bandeira de energia elétrica etc.

Testou-se também modelos regularizados como Lasso, Ridge e ElasticNet, porém sem resultados melhores. Pelo reduzido período de treino (dificultando mais defasanges e o uso de outras técnicas) além da ausência de dummies para a greve dos caminhoneiros e a pandemia, a capacidade preditiva do modelo foi prejudicada. Provavelmente, o modelo obteria melhores resultados usando dados como as expectativas do Focus ou a mediana das previsões da Bloomberg.

Resultados

Nas figuras abaixo, observa-se uma melhora do fit lançando mão apenas das médias ou das medianas das previsões como estimativa do IPCA.

Os histogramas apresentam a distribuição dos erros quadráticos de estimativas de IPCA baseadas na média das prevsiões, na mediana das previsões e no modelo AR(1) junto aos erros quadráticos das instituições. Os erros nos primeiros dois benchmarks concentraram-se mais à esquerda do que o AR(1) e do que as demais instituições (aparentando superioridade das médias/medianas).

Por fim, segue a tabela com os resultados dos testes Diebold-Mariano para os quatro benchmarks. No caso da mediana, apenas 4 das 72 instituições com mais de 5 previsões conseguiram resultados signicantemente superiores. Resultados similares foram encontrados para a média como o benchmark do teste. Tais resultados corroboram os encontrados no artigo original para indicadores isolados na economia americana.


FIgura IPCA e Estimativas Instituições Financeiras
A imagem será apresentada aqui.
AR(1) IPCA, Estimativas Atualizadas 24m treino
A imagem será apresentada aqui.
LM IPCA, Estimativas Atualizadas 24m treino
A imagem será apresentada aqui.
Média das Estimativas das Instituições
A imagem será apresentada aqui.
Mediana das Estimativas das Instituições
A imagem será apresentada aqui.
Histograma EQM Estimativas vs. Instituições
A imagem será apresentada aqui.

Testes Diebold-Mariano 4 Modelos de Previsão
A imagem será apresentada aqui.


Códigos

Dados

previsoes.py

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import ar1_limpo
import lm_ipca

def estimador_media(dados):
    #estimando médias de previsões por período
    medias = dados[["date", "estimate"]].groupby("date").mean()
    medias = medias.rename(columns= {'estimate': "medias"})
    return medias

def estimador_mediana(dados):
    #estimando medianas de previsões por período
    medianas = dados[["date", "estimate"]].groupby("date").median()
    medianas = medianas.rename(columns= {'estimate': "medianas"})
    return medianas

class dm:
    def __init__(self, dados, estimativa):
        self.dados = dados
        self.estimativa = estimativa
        self.nome = estimativa.columns[0]  

    #testes dm, função perda e comparações
    def funcao_perda(self):
        #função perda
        loss = pd.merge(self.dados, self.estimativa, how="right", on="date")
        loss["erro_estimativa"]= (loss["actual"]-loss[self.nome])**2
        loss["dloss_estimativa"]= loss["erro_estimativa"]-loss["erro"]
        return loss

    def teste_dm(self):   
        #teste Diebold-Mariano
        testes = self.funcao_perda()[self.funcao_perda().nobs>=5]
        testes = testes.groupby('codigo_inst').agg(
             t_dm=("dloss_estimativa", lambda x: sum(x)/(np.std(x)*(len(x)**0.5))))  
        return testes

    def comparacoes(self):
        #comparando com demais previsões
        classificacao = pd.DataFrame(
    {'t_dm < -1.645': self.teste_dm()[self.teste_dm()['t_dm'] < -1.645].count(),
      '-1.645 <= t_dm < 0': self.teste_dm()[(self.teste_dm()['t_dm'] >= -1.645) & (self.teste_dm()['t_dm'] < 0)].count(),
      '0 <= t_dm < 1.645': self.teste_dm()[(self.teste_dm()['t_dm'] >= 0) & (self.teste_dm()['t_dm'] < 1.645)].count(),
      't_dm > 1.645': self.teste_dm()[self.teste_dm()['t_dm'] > +1.645].count()
      })
        return classificacao.transpose()


if __name__=="__main__":
    #1. baixando e organizando os dados
    #1.1 baixando os dados
    previsoes = pd.read_excel("C:/Users/Sergio G Costa/Desktop/UnB/MNMCE/Trabalho Final/dados1.xlsx", sheet_name="base")

    #1.2 número de observações por instituição
    contagem = previsoes.groupby("codigo_inst")['codigo_inst'].count()
    contagem = contagem.to_frame()
    contagem = contagem.rename(columns={"codigo_inst":'nobs'})
    previsoes = pd.merge(previsoes, contagem, how="left", on="codigo_inst")

    #1.3 erro quadrado das previsões
    previsoes["erro"] = (previsoes["actual"]-previsoes["estimate"])**2

    #1.4 importando arquivo inflação e colocando datas como índice para AR1
    inflacao = pd.read_excel("C:/Users/Sergio G Costa/Desktop/UnB/MNMCE/Trabalho Final/ar.xlsx", sheet_name="ar")
    inflacao = inflacao.set_index('date')
    inflacao = inflacao.asfreq(freq='MS')

    #2. testes Diebold-Mariano Mediana
    dm_mediana = dm(previsoes, estimador_mediana(previsoes))
    resultado_mediana = dm_mediana.teste_dm()
    perda = dm_mediana.funcao_perda()
    classificacao_mediana = dm_mediana.comparacoes()

    #3. testes Diebold-Mariano Média
    dm_media = dm(previsoes, estimador_media(previsoes))
    resultado_media = dm_media.teste_dm()
    perda_media = dm_media.funcao_perda()
    classificacao_media = dm_media.comparacoes()

    #4. testes Diebold-Mariano AR(1)
    ar1 = ar1_limpo.estimador_ar1(inflacao, "ipca", 23, 58).to_frame()
    dm_ar = dm(previsoes, ar1)
    resultado_ar = dm_ar.teste_dm()
    perda_ar = dm_ar.funcao_perda()
    classificacao_ar = dm_ar.comparacoes()

    #5. testes Diebold-Mariano LM
    lm = lm_ipca.get_data().to_frame()
    dm_lm = dm(previsoes, lm)
    resultado_lm = dm_lm.teste_dm()
    perda_lm = dm_lm.funcao_perda()
    classificacao_lm = dm_lm.comparacoes()

    #6. gráficos
    perda = perda.rename(columns={"erro_estimativa":"erro_mediana"})  
    perda_media = perda_media.rename(columns={"erro_estimativa":"erro_media"})
    perda_ar = perda_ar.rename(columns={"erro_estimativa":"erro_ar"}) 
    perda = pd.merge(perda,perda_media[['date','erro_media']], on='date', how='left')
    perda = pd.merge(perda,perda_ar[['date','erro_ar']], on='date', how='left')
    #agrupando comparativos das funções de perda por instituição'
    perda = perda[["codigo_inst","erro_media","erro_mediana", "erro_ar", "erro"]].groupby("codigo_inst").mean()

    #6.1. histogramas
    bins = np.linspace(0, 0.2)

    plt.subplot(311)
    plt.title("Histograma Funções de Perda")
    plt.hist(perda["erro"], bins, alpha=0.4, label='EQM Estimativas', edgecolor='black')
    plt.hist(perda["erro_media"], bins, alpha=0.4, facecolor='g', label='EQM Média das Estimativas', edgecolor='black')
    plt.legend(loc='upper right')

    plt.subplot(312)
    plt.hist(perda["erro"], bins, alpha=0.4, label='EQM Estimativas', edgecolor='black')
    plt.hist(perda["erro_mediana"], bins, alpha=0.4, facecolor='r', label='EQM Mediana das Estimativas', edgecolor='black')
    plt.legend(loc='upper right')

    plt.subplot(313)
    plt.hist(perda["erro"], bins, alpha=0.4, label='EQM Estimativas', edgecolor='black')
    plt.hist(perda["erro_ar"], bins, alpha=0.4, facecolor='k', label='EQM AR1', edgecolor='black')
    plt.legend(loc='upper right')
    plt.show()

    #6.2. ipca e previsões
    # plt.title("IPCA e Estimativas")
    # plt.plot(perda_media["date"], perda_media["actual"], marker='+', label='IPCA', alpha=0.9)
    # plt.scatter(perda_media["date"], perda_media["estimate"], color='r', alpha=0.1, label='Estimativas')
    # plt.legend(loc='lower left')

    #6.3. ipca e previsões
    plt.title("IPCA e Média Estimativas")
    plt.plot(perda_media["date"], perda_media["actual"], marker='+', label='IPCA', alpha=0.9)
    plt.plot(perda_media["date"], perda_media["medias"], color='black', linestyle= '--', alpha=0.7, label='Média Est.')
    plt.legend(loc='lower left')

    #7. tabela para latex
    classificacao_ar = classificacao_ar.rename(columns={"t_dm":"AR_t_dm"})
    classificacao_lm = classificacao_lm.rename(columns={"t_dm":"LM_t_dm"})
    classificacao_media = classificacao_media.rename(columns={"t_dm":"Média_t_dm"})
    classificacao_mediana = classificacao_mediana.rename(columns={"t_dm":"Mediana_t_dm"})
    classificacao = pd.concat([classificacao_ar, classificacao_lm, classificacao_media, classificacao_mediana], axis=1)

    with open('mytable.tex','w') as tf:
        tf.write(classificacao.to_latex())

ar1_limpo.py

###  AR(1)
import pandas as pd
import numpy as np
from statsmodels.tsa.ar_model import AutoReg
import matplotlib.pyplot as plt


#previsões ar1 da série a partir de certo ponto
def estimador_ar1(dados, serie, inicio, final):
    dados["fcast"] = np.nan
    for i in range(1, final):
        sel = AutoReg(dados[serie][1:inicio+i], 1, old_names=False)
        fcast = sel.fit().forecast()
        dados["fcast"][inicio+i] = fcast
    return dados["fcast"]

if __name__=="__main__":
    #importando arquivo e colocando datas como índice
    inflacao = pd.read_excel("C:/Users/Sergio G Costa/Desktop/UnB/MNMCE/Trabalho Final/ar.xlsx", sheet_name="ar")
    inflacao = inflacao.set_index('date')
    inflacao = inflacao.asfreq(freq='MS')

    #previsões
    estimador_ar1(inflacao, "ipca", 23, 58)

    #plotando séries
    plt.title("AR(1) - IPCA")
    plt.plot(inflacao["ipca"], label='IPCA', alpha=0.9)
    plt.plot(inflacao["fcast"], label='ar1', color='black', linestyle= '--', alpha=0.9)
    plt.style.use('seaborn')
    plt.legend(loc='lower left')

lm_ipca.py

###  Modelo Linear
import pandas as pd
import numpy as np
from sklearn import linear_model
import matplotlib.pyplot as plt


class MySklearningModel:
    def __init__(self,model, df1, df2,independent_variable_list,dependent_variable):
        self.model=model
        self.independent_variable_list=independent_variable_list
        self.dependent_variable=dependent_variable
        self.Xtrain=df1[self.independent_variable_list].values
        self.Xfcast=df2[self.independent_variable_list].values
        self.ytrain=np.squeeze(df1[[self.dependent_variable]].values)
        self.yfcast=np.squeeze(df2[[self.dependent_variable]].values)
    def run_sklearn_regression(self):
        self.model.fit(self.Xtrain, self.ytrain)
    def get_parameters(self):
        return self.model.coef_

def get_data():
    return lm

#importando dados
inflacao = pd.read_excel("C:/Users/Sergio G Costa/Desktop/UnB/MNMCE/Trabalho Final/inflacao.xlsx", sheet_name="inflacao")
inflacao = inflacao.set_index('date')
inflacao = inflacao.asfreq(freq='MS')
df=inflacao
independent_variable_list= ['ipca(-1)','ipca_15','delta_ipca','difusao', 'bandeira', 'oil', 'cambio','inclinacao', 'ex_ante','selic', 'swap_1', 'breakeven_1']
dependent_variable='ipca'

df["lm"] = np.nan

#Rodando Modelo
for i in range(1,58):
    df1 = df.iloc[:23+i, :]
    df2 = df.iloc[23+i:24+i, :]
    model = linear_model.LinearRegression()
    my_model=MySklearningModel(model,df1, df2,independent_variable_list, dependent_variable)
    my_model.run_sklearn_regression()
    forecast = my_model.model.predict(my_model.Xfcast)
    df["lm"][23+i] = forecast[len(forecast)-1]

lm = df['lm']
#Plot
plt.title("LM - IPCA")
plt.plot(df['ipca'], label='IPCA', alpha=0.9)
plt.plot(df['lm'], label='LM', color='black', linestyle= '--', alpha=0.9)
plt.legend(loc='lower left')
...