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

Procurando quebras estruturais em séries financeiras

+1 voto
34 visitas
perguntada Dez 8, 2019 em Finanças por Julia Regina Scotti (41 pontos)  

Como encontrar quebras estruturais em séries financeiras, ou seja como identificar bolhas e seus bursts?

Compartilhe

2 Respostas

0 votos
respondida Dez 8, 2019 por Julia Regina Scotti (41 pontos)  
editado Dez 8, 2019 por Julia Regina Scotti

A resposta é baseada no livro Advances in Financial Machine Learning, de Marcos Lopez de Prado, Editora Wiley e usa a biblioteca statsmodels.

No capitulo 17 do livro, chamado "Structural Breaks", ele trata da patentemente interessante questão de encontar uma quebra estrutal, i.e. uma mudança de regime.

Os testes de quebra estrutural podem ser classificados em 2 categorias:

1 testes CUSUM - testes que avaliam quando o erro de previsão acumulado desvia significamente de um erro com média zero
2 testes de explosividade - além do descio de um erro com média zero, esses testes avaliam se o processo exibe crescimento explonencial ou colapso, já que esse comportamente é inconsistente com o passeio aleatório (ou processo estacionário)

  1. testes CUSUM

Um filtro CUSUM ("cumulative sum") é uma maneira de amostrar a série baseado em eventos. No caso, a série é amostrada cada vem que o erro de predição acumulado passa de um ser threshold.

1a) Teste Brown_Durbin-Evans nos resíduos recursivos - O teste consiste em fazer um OLS recursivo em subamostras ([1,k+1], [1,k+2],...[1,T]) resultando em T-k estimações para os parâmetrosd. A partir de então ccomputar o reísdio recursivo. A soma do resíduo recursivo é a estatística CUSUM. A hipótese nula é de que não existe quebra estrutural e assim os parâmetros da regressão recursiva são estáveis a a soma dos resíduos é um white noise.

Mínimos Quadrados Recursivos

Uma das ferramentas que será utilizada para a ivestigação de quebras estruturais é os "Mínimos Quadrados Recursivos", que consistem em uma versão do OLS em que a janela de estimação vai aumentando, assim pode-se analisar a estabilidade dos parâmetros estimados (por exemplo, computando recursivamente os resíduos)

O pacote statsmodels contém a classe RecursiveLS que auxilia no cômputo deste OLS.

Também no statsmodels está implementado o teste de BrownDurbin-Evans com o nome de statsmodels.stats.diagnostic.breakscusumolsresid

Dados

Os dados foram obtidos da Bloomberg, ticker ES1 Index

1. Analisar a série

  %matplotlib inline
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt

e_mini = pd.read_excel("Documents\e-mini.xlsx", sheet_name="dados", index_col=0, parse_dates=True, header=0)

e_mini['price'].plot()
plt.title("Preço do contrato futuro e-mini")
volume_anual = e_mini['volume'].groupby(by=e_mini.index.year).sum()
plt.bar(e_mini.index.year.unique(), volume_anual, align='center', alpha=0.5)
plt.title("Volume transacionado de contrados de futuro e-mini")retorno = e_mini['price'].pct_change()
plt.plot(retorno)

A imagem será apresentada aqui.

A imagem será apresentada aqui.

A imagem será apresentada aqui.

Agora vamos ver qual o resultado de um OLS simples na série (com um autoregressivo)

Y = e_mini['price']
X = pd.concat([ e_mini['price'].shift(1)], axis=1)
X = sm.add_constant(X)

model1=sm.OLS(Y.fillna(0), X.fillna(0))
results = model1.fit()
print(results.summary())

OLS Regression Results                            
==============================================================================
Dep. Variable:                  price   R-squared:                       0.991
Model:                            OLS   Adj. R-squared:                  0.991
Method:                 Least Squares   F-statistic:                 5.514e+05
Date:                Sun, 08 Dec 2019   Prob (F-statistic):               0.00
Time:                        07:26:45   Log-Likelihood:                -27488.
No. Observations:                5062   AIC:                         5.498e+04
Df Residuals:                    5060   BIC:                         5.499e+04
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const          7.7341      2.238      3.456      0.001       3.347      12.121
price          0.9955      0.001    742.589      0.000       0.993       0.998
==============================================================================
Omnibus:                     4801.166   Durbin-Watson:                   2.655
Prob(Omnibus):                  0.000   Jarque-Bera (JB):         77105570.821
Skew:                           2.888   Prob(JB):                         0.00
Kurtosis:                     607.599   Cond. No.                     4.81e+03
==============================================================================
Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 4.81e+03. This might indicate that there are
strong multicollinearity or other numerical problems.

Considerando os retornos, a resposta é:

OLS Regression Results                            
==============================================================================
Dep. Variable:                  price   R-squared:                       0.000
Model:                            OLS   Adj. R-squared:                 -0.000
Method:                 Least Squares   F-statistic:                   0.01677
Date:                Sun, 08 Dec 2019   Prob (F-statistic):              0.897
Time:                        07:25:14   Log-Likelihood:                 15206.
No. Observations:                5062   AIC:                        -3.041e+04
Df Residuals:                    5060   BIC:                        -3.039e+04
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const          0.0003      0.000      0.595      0.552      -0.001       0.001
price      -3.772e-08   2.91e-07     -0.130      0.897   -6.09e-07    5.33e-07
==============================================================================
Omnibus:                      995.170   Durbin-Watson:                   2.121
Prob(Omnibus):                  0.000   Jarque-Bera (JB):            29750.637
Skew:                           0.144   Prob(JB):                         0.00
Kurtosis:                      14.873   Cond. No.                     4.81e+03
==============================================================================
Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 4.81e+03. This might indicate that there are
strong multicollinearity or other numerical problems.

a resposta continua nos cometários

0 votos
respondida Dez 8, 2019 por Julia Regina Scotti (41 pontos)  
editado Dez 8, 2019 por Julia Regina Scotti

Fica patente nos resultados do OLS que a série parece um random walk (coeficiente auto regressivo no nível em 1 e em variação 0)

Computando agora o OLS Recursivo:

#agora o OLS Recursivo
Y = e_mini['price']
X = pd.concat([ e_mini['price'].shift(1)], axis=1)
X = sm.add_constant(X)

mod = sm.RecursiveLS(Y.fillna(0), X.fillna(0))
res = mod.fit()

print(res.summary())

Statespace Model Results                           
==============================================================================
Dep. Variable:                  price   No. Observations:                 5062
Model:                    RecursiveLS   Log Likelihood              -27486.047
Date:                Sat, 07 Dec 2019   AIC                          54976.093
Time:                        18:16:01   BIC                          54989.151
Sample:                             0   HQIC                         54980.667
                               - 5062                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          z      P>|z|      [0.025      0.975]
------------------------------------------------------------------------------
const          7.7341      2.238      3.456      0.001       3.348      12.120
price          0.9955      0.001    742.589      0.000       0.993       0.998
===================================================================================
Ljung-Box (Q):                     5386.89   Jarque-Bera (JB):          42464760.10
Prob(Q):                              0.00   Prob(JB):                         0.00
Heteroskedasticity (H):               0.21   Skew:                            -1.94
Prob(H) (two-sided):                  0.00   Kurtosis:                       451.77
===================================================================================

Warnings:
[1] Parameters and covariance matrix estimates are RLS estimates conditional on the entire sample.

res.plot_recursive_coefficient(range(mod.k_exog), alpha=None, figsize=(10,6));

A imagem será apresentada aqui.

fig = res.plot_cusum();

A imagem será apresentada aqui.

res.plot_cusum_squares();

A imagem será apresentada aqui.

Pelo gráfico dá para notar que em apenas dois periodos a serie era um RW, com dois outros periodos em que estava sofrendo bolhas. No periodo recente, parece que acabou de passar uma bolha (que ainda não voltou) e o mercado está mostrando comportamento compatível com o passeio aleatório

  • para o teste*

Usando

sup_b= sm.stats.diagnostic.breaks_cusumolsresid(res.resid_recursive)

obtemos o p-valor do teste # Probability of observing the data under the null hypothesis of no structural change

no caso, para o dataset inteiro é

1.1937767938435314e-42

ou seja, "existe" quebra estrutural

para fazer o teste em apenas subamostras do dataset:

for u in range(0,int(len(e_mini.index)),60):
    t = 60


    data_inicial = pd.to_datetime(e_mini.index[u])
    data_final = pd.to_datetime(e_mini.index[u+t])

    Y = e_mini['price']
    X = pd.concat([ e_mini['price'].shift(1)], axis=1)
    X = sm.add_constant(X)

    Y = Y[(Y.index>data_inicial) & (Y.index<data_final)]
    X = X[(X.index>data_inicial) & (X.index<data_final)]

    mod = sm.RecursiveLS(Y.fillna(0), X.fillna(0))
    res = mod.fit()
    sup_b= sm.stats.diagnostic.breaks_cusumolsresid(res.resid_recursive)
    print(data_inicial)
    print(sup_b[1]) 
comentou Dez 9, 2019 por Athos Carvalho (11 pontos)  
Obrigado pela resposta, Júlia! Gostaria de acrescentar que, além do teste CUSUM que você utilizou, outros testes com poder de avaliar quebras estruturais são:

1. O teste de Chow, que pode ser utilizado apenas em casos onde há apenas uma quebra estrutural, podendo ela não ter data definida.

2. Os testes sup-Wald, sup-LM (multiplicadores de Lagrange) e sup-LR (razão de verossimilhança). Refiro-me aos três em conjunto pois todos foram formulados em Andrews (1993). Esses testes podem ser utilizados em casos com múltiplas quebras estruturais em datas desconhecidas.

Referências:

Donald W. K. Andrews. "Tests for Parameter Instability and Structural Change With Unknown Change Point." Econometrica 61, no. 4 (1993): 821-56. doi:10.2307/2951764.
...