In [1]:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
pd.options.display.mpl_style = 'default'
import Quandl
%pylab inline
Populating the interactive namespace from numpy and matplotlib

O objetivo aqui é analisar a variação do IBOVESPA nos períodos dos governos federais desde a estabilização da moeda, o primeiro governo do FHC. Adicionalmente vou considerar a variação do índice deflacionado para entender o impacto da inflação na economia nestes períodos. Já calculei o IBOVESPA deflacionado no post. As contas são simples:

  • calcular os retornos do IBOVESPA mensais nos governos federais
  • calcular estes retornos descontados da inflação (uso o IPCA)
  • agrupar os retornos por períodos (governos federais) e calcular os retornos acumulados
  • calcular os retornos anualizado nos períodos para facilitar a comparação entre governos com períodos diferentes

Vou começar baixando as séries de IPCA e IBOVESPA (mensal) via Quandl (veja como fazer isso no post).

In [2]:
data = Quandl.get(["BCB/433", "BCB/7845"], trim_start="1994-12-01")
data.columns = ["IPCA", "IBOVESPA"]
data.head()
Out[2]:
IPCA IBOVESPA
Date
1994-12-31 1.71 43539
1995-01-31 1.70 38850
1995-02-28 1.02 32708
1995-03-31 1.55 29789
1995-04-30 2.43 38137

O primeiro ponto da série é 1994-12-31, que representa o fim do Governo Itamar Franco, pois dessa forma é possível calcular os retornos desde o primeiro mês do governo FHC.

A seguir os retornos do índice são calculados (IBOVESPA_D) e deflacionados (IBOVESPA_D_DEFL) ( já vimos como calcular os retornos com pandas no post).

In [3]:
data["IBOVESPA_D"] = data["IBOVESPA"].diff()/data["IBOVESPA"].shift(1)
data["IBOVESPA_D_DEFL"] = (1 + data["IBOVESPA_D"])/(1 + data["IPCA"]/100) - 1
data.head()
Out[3]:
IPCA IBOVESPA IBOVESPA_D IBOVESPA_D_DEFL
Date
1994-12-31 1.71 43539 NaN NaN
1995-01-31 1.70 38850 -0.107697 -0.122612
1995-02-28 1.02 32708 -0.158095 -0.166596
1995-03-31 1.55 29789 -0.089244 -0.103145
1995-04-30 2.43 38137 0.280238 0.249866
In [4]:
data.tail()
Out[4]:
IPCA IBOVESPA IBOVESPA_D IBOVESPA_D_DEFL
Date
2016-07-31 0.52 57308 0.112215 0.106462
2016-08-31 0.44 57901 0.010348 0.005922
2016-09-30 0.08 58367 0.008048 0.007242
2016-10-31 0.26 64924 0.112341 0.109456
2016-11-30 0.18 61906 -0.046485 -0.048198

Como o objetivo é agrupar os dados pelos períodos dos governos federais, vou criar uma função governo que recebe uma data e retorna o governo vigente. Em seguida eu aplico essa função ao índice do DataFrame e crio uma coluna chamada GOVERNO.

In [5]:
def governo(data):
    data = data.date()
    if data >= datetime.date(1995, 1, 1) and data <= datetime.date(1998, 12, 31):
        return 'FHC 1'
    elif data >= datetime.date(1999, 1, 1) and data <= datetime.date(2002, 12, 31):
        return 'FHC 2'
    elif data >= datetime.date(2003, 1, 1) and data <= datetime.date(2006, 12, 31):
        return 'LULA 1'
    elif data >= datetime.date(2007, 1, 1) and data <= datetime.date(2010, 12, 31):
        return 'LULA 2'
    elif data >= datetime.date(2011, 1, 1) and data <= datetime.date(2014, 12, 31):
        return 'DILMA 1'
    elif data >= datetime.date(2015, 1, 1) and data < datetime.date(2016, 5, 12):
        return 'DILMA 2'
    elif data >= datetime.date(2016, 5, 12) and data <= datetime.date(2016, 12, 31):
        return 'TEMER'
    else:
        return None

data['GOVERNO'] = data.index.map(governo)

Agora eu agrupo (groupby) pela GOVERNO e sumarizo os dados com a função aggregate calculando o retorno acumulado em cada período de governo federal.

In [21]:
data_gov = data.groupby('GOVERNO')

Vou calcular o retorno acumulado das colunas IBOVESPA_D e IBOVESPA_D_DEFL passando para a função aggregate a função de retorno acumulado abaixo:

$$ 100 \cdot \left( \left[ \prod^{n}_{i=1} \left(1 + x_i \right) \right] - 1 \right) $$

que realiza o produtório do fator de captalização dos retornos e multiplico o resultado por 100 para obter o número em percentual.

In [22]:
data_gov_agg = data_gov[['IBOVESPA_D', 'IBOVESPA_D_DEFL']].aggregate(lambda x: 100*(np.prod(1 + x) - 1))
data_gov_agg
Out[22]:
IBOVESPA_D IBOVESPA_D_DEFL
GOVERNO
DILMA 1 -27.843992 -43.199362
DILMA 2 7.804907 -5.655127
FHC 1 -84.418567 -89.138794
FHC 2 66.096698 18.739626
LULA 1 294.684061 207.855809
LULA 2 55.833877 27.511680
TEMER 14.832128 11.881034

As colunas IBOVESPA_D e IBOVESPA_D_DEFL representam os retornos totais nos períodos dos governos federais. Já é possível notar duas coisas: o primeiro governo do Lula apresenta um retorno muito grande e os governos estão fora de ordem cronológica. Vamos colocar os governos em ordem cronológica para visualizar os dados de forma coerente. Para ordenar os dados por governos de forma cronológica eu vou criar a função sort_by_governo que recebe um DataFrame e o retorna ordenado.

In [23]:
def sort_by_governo(dx):
    governos = ['FHC 1', 'FHC 2', 'LULA 1', 'LULA 2', 'DILMA 1', 'DILMA 2', 'TEMER']
    mapping = {gov: i for i, gov in enumerate(governos)}
    key = dx.index.map(lambda x: mapping[x])
    return dx.iloc[key.argsort()]

data_gov_agg = sort_by_governo(data_gov_agg)
data_gov_agg
Out[23]:
IBOVESPA_D IBOVESPA_D_DEFL
GOVERNO
FHC 1 -84.418567 -89.138794
FHC 2 66.096698 18.739626
LULA 1 294.684061 207.855809
LULA 2 55.833877 27.511680
DILMA 1 -27.843992 -43.199362
DILMA 2 7.804907 -5.655127
TEMER 14.832128 11.881034

Com os dados ordenados vamos visualizá-los em um gráfico de barras.

In [24]:
ax = data_gov_agg[['IBOVESPA_D', 'IBOVESPA_D_DEFL']].plot(kind='bar', figsize=(10,6),
                                                          title="Variação % do IBOVESPA nos Governos Federais")
ax.set_xlabel("Governo")
ax.set_ylabel("Variação (%)");

É possível observar diversas coisas, vou listar os pontos que mais me chamaram a atenção:

  • A inflação no governo DILMA 2 comeu todo o retorno entrege pelo IBOVESPA
  • O pior período para o IBOVESPA foi o primeiro governo do FHC
  • O governo LULA 1 apresentou um retorno espetacular
  • Os governos FHC 2 e LULA 2 apresentam retornos semelhantes, apesar da inflação ser maior em FHC 2 e LULA 2 contempla a crise Sub Prime

No entanto, os governos DILMA 2 e TEMER possuem durações diferentes dos demais, portanto vamos calcular os retornos anualizados para cada governo para facilitar a comparação. Apesar de que governos com maiores durações sofrem mais com a volatilidade do que governos mais curtos, que por outro lado tem menos tempo de recuperação caso recessões ocorram.

Para calcular os retornos anualizados vou fazer uma contagem da quantidade de meses de cada governo. Faço isso contando a quantidade de dados em cada grupo GOVERNO e crio a coluna Meses.

In [37]:
data_gov_agg['Meses'] = data_gov['GOVERNO'].count()
data_gov_agg
/Users/wilson/dev/aw/gh-site/lib/python3.4/site-packages/IPython/kernel/__main__.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  if __name__ == '__main__':
Out[37]:
IBOVESPA_D IBOVESPA_D_DEFL Meses
GOVERNO
FHC 1 -84.418567 -89.138794 48
FHC 2 66.096698 18.739626 48
LULA 1 294.684061 207.855809 48
LULA 2 55.833877 27.511680 48
DILMA 1 -27.843992 -43.199362 48
DILMA 2 7.804907 -5.655127 16
TEMER 14.832128 11.881034 7

Os retornos anualizados são calculados a partir dos retornos do período, de acordo com a fórmula:

$$ \left( \left( 1 + r \right)^{12/n} - 1 \right) \cdot 100 $$

onde $r$ são as taxas de retorno e $n$ é a quantidade de meses de cada governo.

In [11]:
data_gov_agg['IBOVESPA_D_anual'] = ((1 + data_gov_agg['IBOVESPA_D']/100)**(12./data_gov_agg['Meses']) - 1)*100
data_gov_agg['IBOVESPA_D_DEFL_anual'] = ((1 + data_gov_agg['IBOVESPA_D_DEFL']/100)**(12./data_gov_agg['Meses']) - 1)*100
data_gov_agg
/Users/wilson/dev/aw/gh-site/lib/python3.4/site-packages/IPython/kernel/__main__.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  if __name__ == '__main__':
/Users/wilson/dev/aw/gh-site/lib/python3.4/site-packages/IPython/kernel/__main__.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  from IPython.kernel.zmq import kernelapp as app
Out[11]:
IBOVESPA_D IBOVESPA_D_DEFL Meses IBOVESPA_D_anual IBOVESPA_D_DEFL_anual
GOVERNO
FHC 1 -84.418567 -89.138794 48 -37.172201 -42.592385
FHC 2 66.096698 18.739626 48 13.524670 4.387602
LULA 1 294.684061 207.855809 48 40.949129 32.460637
LULA 2 55.833877 27.511680 48 11.728886 6.264326
DILMA 1 -27.843992 -43.199362 48 -7.834555 -13.186292
DILMA 2 7.804907 -5.655127 16 5.798351 -4.272056
TEMER 14.832128 11.881034 7 26.755219 21.222301

Agora vamos visualizar os dados.

In [12]:
ax = data_gov_agg[['IBOVESPA_D_anual', 'IBOVESPA_D_DEFL_anual']].plot(kind='bar', figsize=(10,6),
                                                                      title="Variação % do IBOVESPA nos Governos Federais")
ax.set_xlabel("Governo")
ax.set_ylabel("Variação (%)");

Os dados anualizados produzem uma mudança de escala significativa onde o governo LULA 1 ainda apresenta um retorno execepcional, entretanto o governo TEMER aparece em destaque. O governo FHC 1 continua liderando como pior caso e o impacto da inflação no governo DILMA 2 ganha destaque.

Conclusão

A tabela já apresentava os resultados de maneira clara, mas os gráficos são capazes de tornar a compreensão quase que instantânea. A análise deflacionada nos permiter observar que nos períodos de crescimento a figura não é tão boa assim. É importante ficar claro que o IPCA é uma média muito geral, e a inflação medida localmente varia. Estes resultados podem ser bem piores em algumas capitais.

Um gráfico que faltou foi a inflação acumulada em cada período. Vou fazê-la aqui anualizada para facilitar a interpretação.

In [13]:
data_infl = data_gov['IPCA'].aggregate(lambda x: 100*(np.prod(1 + x/100)**(12./len(x)) - 1))
data_infl = sort_by_governo(data_infl)
ax = data_infl.plot(kind='bar', figsize=(10,6),
                    title="IPCA nos Governos Federais")
ax.set_xlabel("Governo")
ax.set_ylabel("IPCA (%)");

Fica aí pra ajudar na interpretação dos demais resultados.

De qualquer formar vimos que é simples fazer uma análise interessante com Python e apresentar os resultados de forma clara e simples. Este é o poder dos dados abertos! O Quandl é muito bom, mas precisamos de mais ferramentas de dados estrutuados com informações do Brasil.