O mercado financeiro brasileiro possui diversas particularidas que complicam a simples tarefa de calcular os preços dos ativos financeiros.
Aqui vamos falar sobre como os desafios de lidar com dias úteis foram vencidos utilizando Python.
Problema: diferentes ativos precisam lidar com a contagem de dias de forma diferente
bizdays
nasceu em R em set/2013NETWORKDAYS
do Excelif
from bizdays import Calendar
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'])
# Dia do Trabalho é dia útil?
cal.isbizday('2015-05-01')
False
# 12/07/2015 (domingo) é dia útil?
cal.isbizday('2015-07-12')
False
# 03/08/2015 (sengunda-feira) é dia útil?
cal.isbizday('2015-08-03')
True
# Quantidade de dias úteis no ano:
cal.bizdays('2015-01-01', '2015-12-31')
249
# Quantidade de dias úteis até hoje:
cal.bizdays('2015-01-01', '2015-07-16')
133
# Todos os dias úteis em um período, pex primeira quinzena de abril
list(cal.seq('2015-04-01', '2015-04-15'))
[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)]
refdate = '2015-03-12'
maturity = '2015-05-01'
cal.bizdays(refdate, maturity)
33
cal.adjust_next(maturity)
datetime.date(2015, 5, 4)
cal.bizdays(refdate, cal.adjust_next(maturity))
34
vec
:/)¶refdate = '2015-03-12'
maturities = ['2015-05-01', '2015-06-01', '2015-08-01']
list(cal.vec.adjust_next(maturities))
[datetime.date(2015, 5, 4), datetime.date(2015, 6, 1), datetime.date(2015, 8, 3)]
list(cal.vec.bizdays(refdate, list(cal.vec.adjust_next(maturities))))
[34, 54, 98]
import pandas as pd
!head -6 ANBIMA.cal
Saturday Sunday 2000-01-01 2000-03-06 2000-03-07 2000-04-21
cal252 = Calendar.load('ANBIMA.cal')
cal360 = Calendar()
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
DC object Taxa_252 object Taxa_360 float64 dtype: object
curva.head()
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 |
Criar 2 curvas uma de taxas em dias corridos e outra em dias úteis.
curva360 = pd.DataFrame({'DC': curva['DC'].apply(int),
'Taxa_360': curva['Taxa_252'].apply(lambda x: float(x)/100)})
curva360.head(3)
DC | Taxa_360 | |
---|---|---|
1 | 1 | 13.64 |
2 | 8 | 13.68 |
3 | 15 | 13.68 |
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(lambda x: float(x)/100)})
curva252.head(3)
DU | Taxa_252 | |
---|---|---|
1 | 1 | 13.64 |
2 | 6 | 13.68 |
3 | 11 | 13.68 |
Vencimento no primeiro dia de cada mês
cal.getdate('first day', 2015, 1)
datetime.date(2015, 1, 1)
cal.getdate('1st day', 2015, 5)
datetime.date(2015, 5, 1)
Vencimento do dia 15 de cada mês
cal.getdate('15th day', 2015, 7)
datetime.date(2015, 7, 15)
Vencimento nos segundos dias úteis
cal.getdate('2nd bizday', 2015, 5)
datetime.date(2015, 5, 5)
Vencimento no último dia útil do mês
cal.getdate('last bizday', 2015, 5)
datetime.date(2015, 5, 29)
Vencimento do sexto dia útil anterior ao último dia do mês
cal.getdate('6th bizday before last day', 2015, 7)
datetime.date(2015, 7, 23)
Vencimento na quarta-feira mais próxima do dia 15 do mês
cal.getdate('first wed after 15th day', 2015, 6)
datetime.date(2015, 6, 17)
cal.getdate('first wed before 15th day', 2015, 6)
datetime.date(2015, 6, 10)