O documento discute o módulo python-bizdays, que fornece ferramentas para contar dias úteis em Python de forma flexível para lidar com diferentes calendários. O módulo permite calcular dias úteis entre datas, verificar se uma data é útil, ajustar datas de vencimento e manipular curvas de taxas de juros. Ele facilita o cálculo de preços de ativos financeiros que dependem de dias úteis no Brasil.
1. : Dias
Úteis em Qualquer Calendário
Grupy-SP—julho/2015
Wilson Freitas
bizdays
(https://pypi.python.org/pypi/bizdays/v0.2.0)
http://aboutwilson.net (http://aboutwilson.net)
@aboutwilson (http://www.twitter.com/aboutwilson)
3. Motivação
O mercado financeiro brasileiro possui diversas particularidas que complicam a simples tarefa de
calcular os preços dos ativos financeiros.
liquidação de contratos de dólar com a cotação do dia anterior
contratos com vencimento fixo ao contrário do resto do mundo que negocia prazos
fixos
regras absurdas para definição de vencimentos
e ...
vigência do contrato em dias úteis, para diferentes calendários
entre outras
Aqui vamos falar sobre como os desafios de lidar com dias úteis foram vencidos utilizando
Python.
4. Contagem de dias úteis
No Brasil as taxas de juros são calculadas em dias úteis
Herança do período inflacionário
O problema é que com as taxas de juros apuradas em dias úteis força que todos os
demais contratos sigam a mesma convenção:
contratos futuros, títulos públicos, opções
Diferentes mercados diferentes regras:
Mercado de derivativos (antiga BM&F) possui um calendário de feriados
Mercado de ações (antiga Bovespa) possui outro calendário
Contratos de moedas utilizam dias corridos
Problema: diferentes ativos precisam lidar com a contagem de dias de forma diferente
5. Módulo python-bizdays
História
A contagem em dias foi desenvolvida para o módulo
bizdaysnasceu em R em set/2013
Foi portado para Python em seguida
Objetivos
Objetivo 1: realizar operações com dias úteis!
Objetivo 2: fazer uma coisa tão simples de usar quanto a função NETWORKDAYSdo
Excel
Objetivo 3: Poder lidar com mais de 1 calendário sem if
python-fixedincome
(https://github.com/wilsonfreitas/python-fixedincome)
6. bizdays in action
In [1]: frombizdaysimportCalendar
holidays=['2015-01-01','2015-02-16','2015-02-17','2015-04-03','2015-04-21',
'2015-05-01','2015-06-04','2015-09-07','2015-10-12','2015-11-02',
'2015-11-15','2015-12-25','2016-01-01']
cal=Calendar(holidays=holidays,weekdays=['Sunday','Saturday'])
In [2]: # Dia do Trabalho é dia útil?
cal.isbizday('2015-05-01')
Out[2]: False
In [3]: # 12/07/2015 (domingo) é dia útil?
cal.isbizday('2015-07-12')
Out[3]: False
In [4]: # 03/08/2015 (sengunda-feira) é dia útil?
cal.isbizday('2015-08-03')
Out[4]: True
7. In [5]: # Quantidade de dias úteis no ano:
cal.bizdays('2015-01-01','2015-12-31')
Out[5]: 249
In [6]: # Quantidade de dias úteis até hoje:
cal.bizdays('2015-01-01','2015-07-16')
Out[6]: 133
In [7]: # Todos os dias úteis em um período, pex primeira quinzena de abril
list(cal.seq('2015-04-01','2015-04-15'))
Out[7]: [datetime.date(2015, 4, 1),
datetime.date(2015, 4, 2),
datetime.date(2015, 4, 6),
datetime.date(2015, 4, 7),
datetime.date(2015, 4, 8),
datetime.date(2015, 4, 9),
datetime.date(2015, 4, 10),
datetime.date(2015, 4, 13),
datetime.date(2015, 4, 14),
datetime.date(2015, 4, 15)]
8. Cálculo de preços de ativos financeiros
Os ativos financeiros tem data de vencimento fixa
Contratos Futuros de taxas de juros (DI1) expiram no dia 01 do mês de
vencimento
Use adjust_next(ou adjust_previous)
In [8]: refdate='2015-03-12'
maturity='2015-05-01'
In [9]: cal.bizdays(refdate,maturity)
Out[9]: 33
In [10]: cal.adjust_next(maturity)
Out[10]: datetime.date(2015, 5, 4)
In [11]: cal.bizdays(refdate,cal.adjust_next(maturity))
Out[11]: 34
9. Também trabalha com vetores de datas (atributo vec:/)
In [12]: refdate='2015-03-12'
maturities=['2015-05-01','2015-06-01','2015-08-01']
In [13]: list(cal.vec.adjust_next(maturities))
Out[13]: [datetime.date(2015, 5, 4),
datetime.date(2015, 6, 1),
datetime.date(2015, 8, 3)]
In [14]: list(cal.vec.bizdays(refdate,list(cal.vec.adjust_next(maturities))))
Out[14]: [34, 54, 98]
10. Manipulando curvas de taxas de juros
In [15]: importpandasaspd
Carregando um calendário em um arquivo
In [16]: !head -6 ANBIMA.cal
Saturday
Sunday
2000-01-01
2000-03-06
2000-03-07
2000-04-21
In [17]: cal252=Calendar.load('ANBIMA.cal')
cal360=Calendar()
11. Carregando taxas de juros divulgadas pela BM&FBovespa
In [18]: url='http://www2.bmf.com.br/pages/portal/bmfbovespa/boletim1/TxRef1.asp'
dfs=pd.read_html(url)
curva=dfs[2].ix[2:]
curva.columns=['DC','Taxa_252','Taxa_360']
curva.index=range(1,len(curva)+1)
curva.dtypes
Out[18]: DC object
Taxa_252 object
Taxa_360 float64
dtype: object
In [19]: curva.head()
Out[19]: DC Taxa_252 Taxa_360
1 1 1364 1340
2 8 1368 1472
3 15 1368 1438
4 16 1368 1473
5 19 1368 1335
12. Separando as curvas
Criar 2 curvas uma de taxas em dias corridos e outra em dias úteis.
In [20]: curva360=pd.DataFrame({'DC':curva['DC'].apply(int),
'Taxa_360':curva['Taxa_252'].apply(lambdax:float(x)/100)})
curva360.head(3)
Out[20]: DC Taxa_360
1 1 13.64
2 8 13.68
3 15 13.68
In [21]: refdate='2015-07-15'
dates=list(cal360.vec.offset(refdate,curva360['DC']))
curva252=pd.DataFrame({'DU':list(cal252.vec.bizdays(refdate,dates)),
'Taxa_252':curva['Taxa_252'].apply(lambdax:float(x)/100)})
curva252.head(3)
Out[21]: DU Taxa_252
1 1 13.64
2 6 13.68
3 11 13.68
13. Definindo vencimentos dos contratos
Maioria dos contratos futuros
Vencimento no primeiro dia de cada mês
In [22]: cal.getdate('first day',2015,1)
Out[22]: datetime.date(2015, 1, 1)
In [23]: cal.getdate('1st day',2015,5)
Out[23]: datetime.date(2015, 5, 1)
Contratos futuros de inflação
Vencimento do dia 15 de cada mês
In [24]: cal.getdate('15th day',2015,7)
Out[24]: datetime.date(2015, 7, 15)
14. Contratos futuros de soja
Vencimento nos segundos dias úteis
In [25]: cal.getdate('2nd bizday',2015,5)
Out[25]: datetime.date(2015, 5, 5)
Contratos futuros de boi gordo
Vencimento no último dia útil do mês
In [26]: cal.getdate('last bizday',2015,5)
Out[26]: datetime.date(2015, 5, 29)
15. Contratos futuros de café
Vencimento do sexto dia útil anterior ao último dia do mês
In [27]: cal.getdate('6th bizday before last day',2015,7)
Out[27]: datetime.date(2015, 7, 23)
Contratos futuros de índice (IBOVESPA)
Vencimento na quarta-feira mais próxima do dia 15 do mês
In [28]: cal.getdate('first wed after 15th day',2015,6)
Out[28]: datetime.date(2015, 6, 17)
In [29]: cal.getdate('first wed before 15th day',2015,6)
Out[29]: datetime.date(2015, 6, 10)
16. Wilson Freitas — http://blog.aboutwilson.net/ (http://blog.aboutwilson.net/)
github (https://github.com/wilsonfreitas)
@aboutwilson (http://www.twitter.com/aboutwilson)