pyield 0.55.2__tar.gz → 0.56.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyield-0.55.2 → pyield-0.56.0}/PKG-INFO +12 -2
- {pyield-0.55.2 → pyield-0.56.0}/README.md +11 -1
- pyield-0.56.0/pyield/.DS_Store +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/du/core.py +148 -51
- {pyield-0.55.2 → pyield-0.56.0}/pyield/du/feriados/feriados_br.py +22 -21
- {pyield-0.55.2 → pyield-0.56.0}/pyield/interpolador.py +5 -0
- pyield-0.55.2/pyield/tpf/titulos/_zero_td.py → pyield-0.56.0/pyield/tpf/titulos/_bootstrap_forwards.py +19 -5
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/ntnb.py +10 -7
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/ntnbp.py +2 -2
- {pyield-0.55.2 → pyield-0.56.0}/pyproject.toml +1 -1
- {pyield-0.55.2 → pyield-0.56.0}/pyproject.toml.orig +1 -1
- {pyield-0.55.2 → pyield-0.56.0}/LICENSE +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/br_numbers.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/cache.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/converters.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/data_cache.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/excel.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/numbers.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/retry.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/_internal/types.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/anbima/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/anbima/imaq.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/anbima/taxas.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/b3/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/b3/_contratos.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/b3/_validar_pregao.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/b3/boletim.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/b3/derivativos_intradia.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/b3/di_over.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/bc/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/bc/_olinda.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/bc/leiloes.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/bc/lft.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/bc/sgs.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/du/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/du/feriados/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/du/feriados/feriados_antigos_br.txt +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/du/feriados/feriados_novos_br.txt +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/futuro/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/futuro/contratos.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/futuro/di1.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/futuro/historico.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/futuro/intradia.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/fwd.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/ipca/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/ipca/historico.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/ipca/projetado.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/py.typed +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/relogio.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/selic/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/selic/compromissada.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/selic/copom.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/selic/cpm.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/selic/probabilities.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/_taxas.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/benchmark.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/dealers.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/leiloes.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/rmd/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/rmd/_aba_1_3.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/rmd/_aba_2_1.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/rmd/_common.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/rmd/_download.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/secundario/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/secundario/_intradia.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/secundario/_mensal.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/_utils.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/lft.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/ltn.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/ntnb1.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/ntnc.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/ntnf.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/titulos/pre.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/vna/__init__.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/vna/_download.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/vna/calculo.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/vna/ntnb.py +0 -0
- {pyield-0.55.2 → pyield-0.56.0}/pyield/tpf/vna/ntnc.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyield
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.56.0
|
|
4
4
|
Summary: Polars-powered toolkit for Brazilian fixed income analysis
|
|
5
5
|
Keywords: fixed-income,brazil,finance,analysis,bonds
|
|
6
6
|
Author: Carlos Carvalho
|
|
@@ -142,6 +142,15 @@ du.gerar("22-12-2023", "02-01-2024")
|
|
|
142
142
|
du.eh_dia_util("25-12-2023") # -> False (Natal)
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
Por padrão, `calendario="auto"` seleciona a lista de feriados conforme a data.
|
|
146
|
+
Use `calendario="anterior"` para forçar o regime anterior a 26/12/2023 ou
|
|
147
|
+
`calendario="atual"` para forçar a lista vigente na versão instalada:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
du.contar("20-11-2024", "21-11-2024", calendario="anterior") # -> 1
|
|
151
|
+
du.contar("20-11-2024", "21-11-2024", calendario="atual") # -> 0
|
|
152
|
+
```
|
|
153
|
+
|
|
145
154
|
As principais funções de cálculo (`contar`, `deslocar` e `eh_dia_util`)
|
|
146
155
|
suportam operações vetorizadas com listas, Series ou arrays.
|
|
147
156
|
|
|
@@ -308,10 +317,11 @@ Documentação completa: [crdcj.github.io/PYield](https://crdcj.github.io/PYield
|
|
|
308
317
|
|
|
309
318
|
## Compatibilidade e mudanças da API
|
|
310
319
|
|
|
311
|
-
A versão atual é `v0.
|
|
320
|
+
A versão atual é `v0.56.0`. As mudanças abaixo podem exigir atualização de código:
|
|
312
321
|
|
|
313
322
|
| Versão | Mudança principal |
|
|
314
323
|
|---|---|
|
|
324
|
+
| `v0.56.0` | As funções de dias úteis adotaram `calendario="auto" \| "anterior" \| "atual"`. Em `du.gerar`, substitua `opcao_feriado` por `calendario`; os valores `"inferir"`, `"antigo"` e `"novo"` correspondem agora a `"auto"`, `"anterior"` e `"atual"`. O padrão passou a ser `"auto"`. `Interpolador` agora levanta `ValueError` quando a curva não contém vértices válidos. |
|
|
315
325
|
| `v0.55.0` | Funções de PU, cotação e VNA dos títulos passaram a retornar `Decimal` com seis casas. Entradas numéricas aceitam `float` ou `Decimal`. |
|
|
316
326
|
| `v0.54.5` | `fluxos_caixa` não aceita mais `ajustar_datas_pagamento`; os cronogramas usam datas contratuais. |
|
|
317
327
|
| `v0.54.2` | `taxas_historicas` foi adicionada e `tpf.taxas(completo=True)` foi removida. |
|
|
@@ -117,6 +117,15 @@ du.gerar("22-12-2023", "02-01-2024")
|
|
|
117
117
|
du.eh_dia_util("25-12-2023") # -> False (Natal)
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
+
Por padrão, `calendario="auto"` seleciona a lista de feriados conforme a data.
|
|
121
|
+
Use `calendario="anterior"` para forçar o regime anterior a 26/12/2023 ou
|
|
122
|
+
`calendario="atual"` para forçar a lista vigente na versão instalada:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
du.contar("20-11-2024", "21-11-2024", calendario="anterior") # -> 1
|
|
126
|
+
du.contar("20-11-2024", "21-11-2024", calendario="atual") # -> 0
|
|
127
|
+
```
|
|
128
|
+
|
|
120
129
|
As principais funções de cálculo (`contar`, `deslocar` e `eh_dia_util`)
|
|
121
130
|
suportam operações vetorizadas com listas, Series ou arrays.
|
|
122
131
|
|
|
@@ -283,10 +292,11 @@ Documentação completa: [crdcj.github.io/PYield](https://crdcj.github.io/PYield
|
|
|
283
292
|
|
|
284
293
|
## Compatibilidade e mudanças da API
|
|
285
294
|
|
|
286
|
-
A versão atual é `v0.
|
|
295
|
+
A versão atual é `v0.56.0`. As mudanças abaixo podem exigir atualização de código:
|
|
287
296
|
|
|
288
297
|
| Versão | Mudança principal |
|
|
289
298
|
|---|---|
|
|
299
|
+
| `v0.56.0` | As funções de dias úteis adotaram `calendario="auto" \| "anterior" \| "atual"`. Em `du.gerar`, substitua `opcao_feriado` por `calendario`; os valores `"inferir"`, `"antigo"` e `"novo"` correspondem agora a `"auto"`, `"anterior"` e `"atual"`. O padrão passou a ser `"auto"`. `Interpolador` agora levanta `ValueError` quando a curva não contém vértices válidos. |
|
|
290
300
|
| `v0.55.0` | Funções de PU, cotação e VNA dos títulos passaram a retornar `Decimal` com seis casas. Entradas numéricas aceitam `float` ou `Decimal`. |
|
|
291
301
|
| `v0.54.5` | `fluxos_caixa` não aceita mais `ajustar_datas_pagamento`; os cronogramas usam datas contratuais. |
|
|
292
302
|
| `v0.54.2` | `taxas_historicas` foi adicionada e `tpf.taxas(completo=True)` foi removida. |
|
|
Binary file
|
|
@@ -12,21 +12,35 @@ from pyield.du.feriados.feriados_br import FeriadosBrasil
|
|
|
12
12
|
LIMITE_DIA_UTIL = 6
|
|
13
13
|
|
|
14
14
|
feriados_br = FeriadosBrasil()
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
FERIADOS_ANTERIORES = feriados_br.obter_feriados(calendario="anterior")
|
|
16
|
+
FERIADOS_ATUAIS = feriados_br.obter_feriados(calendario="atual")
|
|
17
17
|
DATA_TRANSICAO = FeriadosBrasil.DATA_TRANSICAO
|
|
18
|
+
Calendario = Literal["auto", "anterior", "atual"]
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
def _expressao_feriados(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
def _expressao_feriados(
|
|
22
|
+
expr_data: pl.Expr,
|
|
23
|
+
calendario: Calendario = "auto",
|
|
24
|
+
) -> pl.Expr:
|
|
25
|
+
match calendario:
|
|
26
|
+
case "anterior":
|
|
27
|
+
return pl.lit(FERIADOS_ANTERIORES)
|
|
28
|
+
case "atual":
|
|
29
|
+
return pl.lit(FERIADOS_ATUAIS)
|
|
30
|
+
case "auto":
|
|
31
|
+
return (
|
|
32
|
+
pl.when(expr_data < DATA_TRANSICAO)
|
|
33
|
+
.then(pl.lit(FERIADOS_ANTERIORES))
|
|
34
|
+
.otherwise(pl.lit(FERIADOS_ATUAIS))
|
|
35
|
+
)
|
|
36
|
+
case _:
|
|
37
|
+
raise ValueError("Opção inválida para calendario.")
|
|
26
38
|
|
|
27
39
|
|
|
28
40
|
def contar_expr(
|
|
29
|
-
inicio: pl.Expr | str | dt.date,
|
|
41
|
+
inicio: pl.Expr | str | dt.date,
|
|
42
|
+
fim: pl.Expr | str | dt.date,
|
|
43
|
+
calendario: Calendario = "auto",
|
|
30
44
|
) -> pl.Expr:
|
|
31
45
|
"""Cria uma expressão Polars para contar dias úteis (com suporte a LazyFrame).
|
|
32
46
|
|
|
@@ -36,6 +50,10 @@ def contar_expr(
|
|
|
36
50
|
Args:
|
|
37
51
|
inicio: Nome da coluna, expressão Polars ou data literal.
|
|
38
52
|
fim: Nome da coluna, expressão Polars ou data literal.
|
|
53
|
+
calendario: Lista de feriados a considerar. ``"anterior"`` usa a lista
|
|
54
|
+
vigente antes de 26-12-2023, ``"atual"`` usa a lista vigente a partir
|
|
55
|
+
dessa data e ``"auto"`` seleciona a lista por linha com base em
|
|
56
|
+
``inicio``. Padrão: ``"auto"``.
|
|
39
57
|
|
|
40
58
|
Returns:
|
|
41
59
|
Uma ``pl.Expr`` que resulta em Int64.
|
|
@@ -82,25 +100,46 @@ def contar_expr(
|
|
|
82
100
|
return pl.business_day_count(
|
|
83
101
|
start=data_inicio,
|
|
84
102
|
end=data_fim,
|
|
85
|
-
holidays=_expressao_feriados(data_inicio),
|
|
103
|
+
holidays=_expressao_feriados(data_inicio, calendario),
|
|
86
104
|
).cast(pl.Int64)
|
|
87
105
|
|
|
88
106
|
|
|
89
107
|
@overload
|
|
90
|
-
def contar(
|
|
108
|
+
def contar(
|
|
109
|
+
inicio: DatesLike,
|
|
110
|
+
fim: DatesLike | DateLike | None,
|
|
111
|
+
calendario: Calendario = ...,
|
|
112
|
+
) -> pl.Series: ...
|
|
91
113
|
@overload
|
|
92
|
-
def contar(
|
|
114
|
+
def contar(
|
|
115
|
+
inicio: DateLike | None,
|
|
116
|
+
fim: DatesLike,
|
|
117
|
+
calendario: Calendario = ...,
|
|
118
|
+
) -> pl.Series: ...
|
|
93
119
|
@overload
|
|
94
|
-
def contar(
|
|
120
|
+
def contar(
|
|
121
|
+
inicio: DateLike,
|
|
122
|
+
fim: DateLike,
|
|
123
|
+
calendario: Calendario = ...,
|
|
124
|
+
) -> int: ...
|
|
95
125
|
@overload
|
|
96
|
-
def contar(
|
|
126
|
+
def contar(
|
|
127
|
+
inicio: DateLike,
|
|
128
|
+
fim: None,
|
|
129
|
+
calendario: Calendario = ...,
|
|
130
|
+
) -> None: ...
|
|
97
131
|
@overload
|
|
98
|
-
def contar(
|
|
132
|
+
def contar(
|
|
133
|
+
inicio: None,
|
|
134
|
+
fim: DateLike | None,
|
|
135
|
+
calendario: Calendario = ...,
|
|
136
|
+
) -> None: ...
|
|
99
137
|
|
|
100
138
|
|
|
101
139
|
def contar(
|
|
102
140
|
inicio: None | DateLike | DatesLike,
|
|
103
141
|
fim: None | DateLike | DatesLike,
|
|
142
|
+
calendario: Calendario = "auto",
|
|
104
143
|
) -> None | int | pl.Series:
|
|
105
144
|
"""Conta dias úteis entre ``inicio`` (inclusivo) e ``fim`` (exclusivo).
|
|
106
145
|
|
|
@@ -112,10 +151,10 @@ def contar(
|
|
|
112
151
|
resultado corresponde ao i-ésimo par de (``inicio``, ``fim``) após expansão.
|
|
113
152
|
Isso garante atribuição segura de volta ao DataFrame de origem.
|
|
114
153
|
|
|
115
|
-
Regime de feriados:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
154
|
+
Regime de feriados: Por padrão, para cada valor de ``inicio``, a lista de
|
|
155
|
+
feriados (anterior vs. atual) é escolhida com base na data de transição 2023-12-26
|
|
156
|
+
(``DATA_TRANSICAO``). Também é possível selecionar explicitamente uma das listas
|
|
157
|
+
para toda a contagem.
|
|
119
158
|
|
|
120
159
|
Propagação de nulos: Se qualquer argumento escalar for nulo, retorna ``None``.
|
|
121
160
|
Nulos dentro de arrays de entrada produzem nulos nas posições correspondentes
|
|
@@ -129,6 +168,10 @@ def contar(
|
|
|
129
168
|
Args:
|
|
130
169
|
inicio: Data única ou coleção (limite inclusivo).
|
|
131
170
|
fim: Data única ou coleção (limite exclusivo).
|
|
171
|
+
calendario: Lista de feriados a considerar. ``"anterior"`` usa a lista
|
|
172
|
+
vigente antes de 26-12-2023, ``"atual"`` usa a lista vigente a partir
|
|
173
|
+
dessa data e ``"auto"`` seleciona a lista por elemento com base em
|
|
174
|
+
``inicio``. Padrão: ``"auto"``.
|
|
132
175
|
|
|
133
176
|
Returns:
|
|
134
177
|
Inteiro ou ``None`` se ``inicio`` e ``fim`` forem datas únicas, ou Series
|
|
@@ -136,7 +179,8 @@ def contar(
|
|
|
136
179
|
|
|
137
180
|
Notes:
|
|
138
181
|
- Esta função é um encapsulamento de ``polars.business_day_count``.
|
|
139
|
-
-
|
|
182
|
+
- Com ``calendario="auto"``, a lista é determinada por linha com base na
|
|
183
|
+
data ``inicio``.
|
|
140
184
|
- Strings de data aceitas: ``DD-MM-YYYY``, ``DD/MM/YYYY`` e ``YYYY-MM-DD``.
|
|
141
185
|
- Strings inválidas são tratadas como ``null`` e propagadas ao resultado.
|
|
142
186
|
|
|
@@ -151,6 +195,10 @@ def contar(
|
|
|
151
195
|
>>> du.contar("20-11-2024", "21-11-2024")
|
|
152
196
|
0
|
|
153
197
|
|
|
198
|
+
Seleção explícita da lista anterior, que não inclui 20 de novembro:
|
|
199
|
+
>>> du.contar("20-11-2024", "21-11-2024", calendario="anterior")
|
|
200
|
+
1
|
|
201
|
+
|
|
154
202
|
Contagem negativa quando ``inicio`` é posterior a ``fim``:
|
|
155
203
|
>>> du.contar("08-01-2023", "01-01-2023")
|
|
156
204
|
-5
|
|
@@ -210,7 +258,7 @@ def contar(
|
|
|
210
258
|
data={"inicio": inicio, "fim": fim},
|
|
211
259
|
nan_to_null=True,
|
|
212
260
|
)
|
|
213
|
-
.select(dias_uteis=contar_expr("inicio", "fim"))
|
|
261
|
+
.select(dias_uteis=contar_expr("inicio", "fim", calendario))
|
|
214
262
|
.get_column("dias_uteis")
|
|
215
263
|
)
|
|
216
264
|
|
|
@@ -224,6 +272,7 @@ def deslocar_expr(
|
|
|
224
272
|
data: pl.Expr | str,
|
|
225
273
|
deslocamento: int | pl.Expr | str,
|
|
226
274
|
rolagem: Literal["forward", "backward"] = "forward",
|
|
275
|
+
calendario: Calendario = "auto",
|
|
227
276
|
) -> pl.Expr:
|
|
228
277
|
"""Cria uma expressão Polars para somar dias úteis.
|
|
229
278
|
|
|
@@ -234,6 +283,10 @@ def deslocar_expr(
|
|
|
234
283
|
deslocamento: Número de dias úteis a somar. Pode ser um inteiro fixo ou
|
|
235
284
|
outra coluna.
|
|
236
285
|
rolagem: Como tratar a data inicial se ela cair em fim de semana/feriado.
|
|
286
|
+
calendario: Lista de feriados a considerar. ``"anterior"`` usa a lista
|
|
287
|
+
vigente antes de 26-12-2023, ``"atual"`` usa a lista vigente a partir
|
|
288
|
+
dessa data e ``"auto"`` seleciona a lista por linha com base em
|
|
289
|
+
``data``. Padrão: ``"auto"``.
|
|
237
290
|
|
|
238
291
|
Returns:
|
|
239
292
|
Uma ``pl.Expr`` que resulta em Date.
|
|
@@ -280,7 +333,7 @@ def deslocar_expr(
|
|
|
280
333
|
return data_expr.dt.add_business_days(
|
|
281
334
|
n=deslocamento,
|
|
282
335
|
roll=rolagem,
|
|
283
|
-
holidays=_expressao_feriados(data_expr),
|
|
336
|
+
holidays=_expressao_feriados(data_expr, calendario),
|
|
284
337
|
)
|
|
285
338
|
|
|
286
339
|
|
|
@@ -289,30 +342,35 @@ def deslocar(
|
|
|
289
342
|
datas: DatesLike,
|
|
290
343
|
deslocamento: ArrayLike | int | None,
|
|
291
344
|
rolagem: Literal["forward", "backward"] = ...,
|
|
345
|
+
calendario: Calendario = ...,
|
|
292
346
|
) -> pl.Series: ...
|
|
293
347
|
@overload
|
|
294
348
|
def deslocar(
|
|
295
349
|
datas: DateLike | None,
|
|
296
350
|
deslocamento: ArrayLike,
|
|
297
351
|
rolagem: Literal["forward", "backward"] = ...,
|
|
352
|
+
calendario: Calendario = ...,
|
|
298
353
|
) -> pl.Series: ...
|
|
299
354
|
@overload
|
|
300
355
|
def deslocar(
|
|
301
356
|
datas: DateLike,
|
|
302
357
|
deslocamento: int,
|
|
303
358
|
rolagem: Literal["forward", "backward"] = ...,
|
|
359
|
+
calendario: Calendario = ...,
|
|
304
360
|
) -> dt.date: ...
|
|
305
361
|
@overload
|
|
306
362
|
def deslocar(
|
|
307
363
|
datas: None,
|
|
308
364
|
deslocamento: int,
|
|
309
365
|
rolagem: Literal["forward", "backward"] = ...,
|
|
366
|
+
calendario: Calendario = ...,
|
|
310
367
|
) -> None: ...
|
|
311
368
|
@overload
|
|
312
369
|
def deslocar(
|
|
313
370
|
datas: DateLike,
|
|
314
371
|
deslocamento: None,
|
|
315
372
|
rolagem: Literal["forward", "backward"] = ...,
|
|
373
|
+
calendario: Calendario = ...,
|
|
316
374
|
) -> None: ...
|
|
317
375
|
|
|
318
376
|
|
|
@@ -320,6 +378,7 @@ def deslocar(
|
|
|
320
378
|
datas: DateLike | DatesLike | None,
|
|
321
379
|
deslocamento: int | ArrayLike | None,
|
|
322
380
|
rolagem: Literal["forward", "backward"] = "forward",
|
|
381
|
+
calendario: Calendario = "auto",
|
|
323
382
|
) -> dt.date | pl.Series | None:
|
|
324
383
|
"""Desloca data(s) por um número de dias úteis com regime de feriados brasileiro.
|
|
325
384
|
|
|
@@ -335,10 +394,10 @@ def deslocar(
|
|
|
335
394
|
corresponde ao i-ésimo par (data, deslocamento), permitindo atribuição segura
|
|
336
395
|
de volta ao DataFrame de origem.
|
|
337
396
|
|
|
338
|
-
Regime de feriados:
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
397
|
+
Regime de feriados: Por padrão, para cada data, a lista de feriados apropriada
|
|
398
|
+
(anterior vs. atual) é escolhida com base na data de transição 2023-12-26
|
|
399
|
+
(``DATA_TRANSICAO``). Também é possível selecionar explicitamente uma das listas
|
|
400
|
+
para todo o deslocamento.
|
|
342
401
|
|
|
343
402
|
Semântica da rolagem: ``rolagem`` só atua quando a data original não é um dia útil
|
|
344
403
|
sob seu regime. Após o roll, a adição de dias úteis subsequente é aplicada a
|
|
@@ -365,6 +424,10 @@ def deslocar(
|
|
|
365
424
|
move para frente, negativo para trás, zero mantém a âncora após roll.
|
|
366
425
|
rolagem: Direção para ajustar uma data inicial não-útil ("forward" ou
|
|
367
426
|
"backward"). Padrão é "forward".
|
|
427
|
+
calendario: Lista de feriados a considerar. ``"anterior"`` usa a lista
|
|
428
|
+
vigente antes de 26-12-2023, ``"atual"`` usa a lista vigente a partir
|
|
429
|
+
dessa data e ``"auto"`` seleciona a lista por elemento com base em
|
|
430
|
+
``datas``. Padrão: ``"auto"``.
|
|
368
431
|
|
|
369
432
|
Returns:
|
|
370
433
|
Um ``date`` Python para entradas escalares, uma Series Polars de datas para
|
|
@@ -374,8 +437,8 @@ def deslocar(
|
|
|
374
437
|
Notes:
|
|
375
438
|
- Encapsulamento de ``polars.Expr.dt.add_business_days`` aplicado
|
|
376
439
|
condicionalmente.
|
|
377
|
-
-
|
|
378
|
-
``DATA_TRANSICAO``.
|
|
440
|
+
- Com ``calendario="auto"``, o regime é decidido por elemento comparando
|
|
441
|
+
com ``DATA_TRANSICAO``.
|
|
379
442
|
- Fins de semana são sempre tratados como não-úteis.
|
|
380
443
|
- Strings de data aceitas: ``DD-MM-YYYY``, ``DD/MM/YYYY`` e ``YYYY-MM-DD``.
|
|
381
444
|
- Strings inválidas são tratadas como ``null`` e propagadas ao resultado.
|
|
@@ -389,6 +452,10 @@ def deslocar(
|
|
|
389
452
|
>>> du.deslocar("20-11-2024", 0)
|
|
390
453
|
datetime.date(2024, 11, 21)
|
|
391
454
|
|
|
455
|
+
Seleção explícita da lista anterior, que não inclui 20 de novembro:
|
|
456
|
+
>>> du.deslocar("20-11-2024", 0, calendario="anterior")
|
|
457
|
+
datetime.date(2024, 11, 20)
|
|
458
|
+
|
|
392
459
|
Desloca sábado antes do Natal para o próximo dia útil (terça após Natal):
|
|
393
460
|
>>> du.deslocar("23-12-2023", 0)
|
|
394
461
|
datetime.date(2023, 12, 26)
|
|
@@ -484,7 +551,10 @@ def deslocar(
|
|
|
484
551
|
)
|
|
485
552
|
.select(
|
|
486
553
|
data_ajustada=deslocar_expr(
|
|
487
|
-
"datas",
|
|
554
|
+
"datas",
|
|
555
|
+
deslocamento="deslocamento",
|
|
556
|
+
rolagem=rolagem,
|
|
557
|
+
calendario=calendario,
|
|
488
558
|
)
|
|
489
559
|
)
|
|
490
560
|
.get_column("data_ajustada")
|
|
@@ -500,7 +570,7 @@ def gerar(
|
|
|
500
570
|
inicio: DateLike | None = None,
|
|
501
571
|
fim: DateLike | None = None,
|
|
502
572
|
fechamento: Literal["both", "left", "right", "none"] = "both",
|
|
503
|
-
|
|
573
|
+
calendario: Calendario = "auto",
|
|
504
574
|
) -> pl.Series:
|
|
505
575
|
"""Gera uma Series de dias úteis entre ``inicio`` e ``fim``.
|
|
506
576
|
|
|
@@ -511,10 +581,10 @@ def gerar(
|
|
|
511
581
|
fim: Data final. Se None, usa a data atual.
|
|
512
582
|
fechamento: Define quais lados do intervalo são fechados (inclusivos).
|
|
513
583
|
Opções válidas: 'both', 'left', 'right', 'none'. Padrão: 'both'.
|
|
514
|
-
|
|
515
|
-
- '
|
|
516
|
-
- '
|
|
517
|
-
- '
|
|
584
|
+
calendario: Especifica a lista de feriados a considerar. Padrão: "auto".
|
|
585
|
+
- 'anterior': Usa a lista de feriados vigente antes de 2023-12-26.
|
|
586
|
+
- 'atual': Usa a lista de feriados vigente a partir de 2023-12-26.
|
|
587
|
+
- 'auto': Seleciona com base na data ``inicio`` relativa à transição.
|
|
518
588
|
|
|
519
589
|
Returns:
|
|
520
590
|
Series de dias úteis (nome: 'data').
|
|
@@ -537,6 +607,10 @@ def gerar(
|
|
|
537
607
|
2023-12-29
|
|
538
608
|
2024-01-02
|
|
539
609
|
]
|
|
610
|
+
|
|
611
|
+
Seleção automática do calendário conforme a data inicial:
|
|
612
|
+
>>> len(du.gerar("20-11-2020", "20-11-2020", calendario="auto"))
|
|
613
|
+
1
|
|
540
614
|
"""
|
|
541
615
|
hoje = relogio.hoje()
|
|
542
616
|
data_inicio = cv.converter_datas(inicio) or hoje
|
|
@@ -549,18 +623,25 @@ def gerar(
|
|
|
549
623
|
|
|
550
624
|
# Pega feriados aplicáveis
|
|
551
625
|
feriados = feriados_br.obter_feriados(
|
|
552
|
-
datas=data_inicio,
|
|
626
|
+
datas=data_inicio, calendario=calendario
|
|
553
627
|
)
|
|
554
628
|
|
|
555
629
|
# Filtra: só dias úteis (seg-sex e não feriado)
|
|
556
630
|
return s.filter((s.dt.weekday() < LIMITE_DIA_UTIL) & (~s.is_in(feriados)))
|
|
557
631
|
|
|
558
632
|
|
|
559
|
-
def eh_dia_util_expr(
|
|
633
|
+
def eh_dia_util_expr(
|
|
634
|
+
data: pl.Expr | str,
|
|
635
|
+
calendario: Calendario = "auto",
|
|
636
|
+
) -> pl.Expr:
|
|
560
637
|
"""Cria expressão Polars para verificar se é dia útil (True/False).
|
|
561
638
|
|
|
562
639
|
Args:
|
|
563
640
|
data: Coluna de datas ou expressão Polars.
|
|
641
|
+
calendario: Lista de feriados a considerar. ``"anterior"`` usa a lista
|
|
642
|
+
vigente antes de 26-12-2023, ``"atual"`` usa a lista vigente a partir
|
|
643
|
+
dessa data e ``"auto"`` seleciona a lista por linha com base em
|
|
644
|
+
``data``. Padrão: ``"auto"``.
|
|
564
645
|
|
|
565
646
|
Returns:
|
|
566
647
|
Uma ``pl.Expr`` booleana.
|
|
@@ -597,26 +678,31 @@ def eh_dia_util_expr(data: pl.Expr | str) -> pl.Expr:
|
|
|
597
678
|
"""
|
|
598
679
|
data_expr = cv.converter_datas_expr(data)
|
|
599
680
|
|
|
600
|
-
return data_expr.dt.is_business_day(
|
|
681
|
+
return data_expr.dt.is_business_day(
|
|
682
|
+
holidays=_expressao_feriados(data_expr, calendario)
|
|
683
|
+
)
|
|
601
684
|
|
|
602
685
|
|
|
603
686
|
@overload
|
|
604
|
-
def eh_dia_util(datas: None) -> None: ...
|
|
687
|
+
def eh_dia_util(datas: None, calendario: Calendario = ...) -> None: ...
|
|
605
688
|
@overload
|
|
606
|
-
def eh_dia_util(datas: DateLike) -> bool: ...
|
|
689
|
+
def eh_dia_util(datas: DateLike, calendario: Calendario = ...) -> bool: ...
|
|
607
690
|
@overload
|
|
608
|
-
def eh_dia_util(
|
|
691
|
+
def eh_dia_util(
|
|
692
|
+
datas: DatesLike, calendario: Calendario = ...
|
|
693
|
+
) -> pl.Series: ...
|
|
609
694
|
|
|
610
695
|
|
|
611
|
-
def eh_dia_util(
|
|
696
|
+
def eh_dia_util(
|
|
697
|
+
datas: None | DateLike | DatesLike,
|
|
698
|
+
calendario: Calendario = "auto",
|
|
699
|
+
) -> None | bool | pl.Series:
|
|
612
700
|
"""Determina se data(s) são dias úteis brasileiros.
|
|
613
701
|
|
|
614
|
-
REGIME DE FERIADOS
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
Isso espelha o comportamento de ``contar`` e ``deslocar`` que aplicam a lógica
|
|
619
|
-
de regime elemento a elemento.
|
|
702
|
+
REGIME DE FERIADOS: Por padrão, para cada data, a lista de feriados apropriada
|
|
703
|
+
(anterior vs. atual) é escolhida com base na data de transição 2023-12-26
|
|
704
|
+
(``DATA_TRANSICAO``). Também é possível selecionar explicitamente uma das listas
|
|
705
|
+
para toda a avaliação.
|
|
620
706
|
|
|
621
707
|
PRESERVAÇÃO DE ORDEM E FORMA: A saída preserva a ordem original dos elementos.
|
|
622
708
|
Nenhuma ordenação, deduplicação, remodelação ou alinhamento é realizado; o
|
|
@@ -639,6 +725,10 @@ def eh_dia_util(datas: None | DateLike | DatesLike) -> None | bool | pl.Series:
|
|
|
639
725
|
Args:
|
|
640
726
|
datas: Data única ou coleção (list/tuple/Polars Series).
|
|
641
727
|
Pode incluir nulos que propagam. Entrada escalar nula retorna ``None``.
|
|
728
|
+
calendario: Lista de feriados a considerar. ``"anterior"`` usa a lista
|
|
729
|
+
vigente antes de 26-12-2023, ``"atual"`` usa a lista vigente a partir
|
|
730
|
+
dessa data e ``"auto"`` seleciona a lista por elemento com base em
|
|
731
|
+
``datas``. Padrão: ``"auto"``.
|
|
642
732
|
|
|
643
733
|
Returns:
|
|
644
734
|
``True`` se for dia útil, ``False`` caso contrário para entrada escalar;
|
|
@@ -647,10 +737,12 @@ def eh_dia_util(datas: None | DateLike | DatesLike) -> None | bool | pl.Series:
|
|
|
647
737
|
|
|
648
738
|
Examples:
|
|
649
739
|
>>> from pyield import du
|
|
650
|
-
>>> du.eh_dia_util("25-12-2023") # Natal (calendário
|
|
740
|
+
>>> du.eh_dia_util("25-12-2023") # Natal (calendário anterior)
|
|
651
741
|
False
|
|
652
|
-
>>> du.eh_dia_util("20-11-2024") # Dia Nacional de Zumbi
|
|
742
|
+
>>> du.eh_dia_util("20-11-2024") # Dia Nacional de Zumbi
|
|
653
743
|
False
|
|
744
|
+
>>> du.eh_dia_util("20-11-2024", calendario="anterior")
|
|
745
|
+
True
|
|
654
746
|
>>> du.eh_dia_util(["22-12-2023", "26-12-2023"]) # Períodos mistos
|
|
655
747
|
shape: (2,)
|
|
656
748
|
Series: 'eh_dia_util' [bool]
|
|
@@ -661,7 +753,8 @@ def eh_dia_util(datas: None | DateLike | DatesLike) -> None | bool | pl.Series:
|
|
|
661
753
|
|
|
662
754
|
Notes:
|
|
663
755
|
- Data de transição definida em ``DATA_TRANSICAO``.
|
|
664
|
-
-
|
|
756
|
+
- Com ``calendario="auto"``, espelha a lógica por linha usada em
|
|
757
|
+
``contar`` e ``deslocar``.
|
|
665
758
|
- Fins de semana sempre avaliam como ``False``.
|
|
666
759
|
- Elementos nulos propagam.
|
|
667
760
|
- Strings de data aceitas: ``DD-MM-YYYY``, ``DD/MM/YYYY`` e ``YYYY-MM-DD``.
|
|
@@ -669,7 +762,11 @@ def eh_dia_util(datas: None | DateLike | DatesLike) -> None | bool | pl.Series:
|
|
|
669
762
|
"""
|
|
670
763
|
s = (
|
|
671
764
|
pl.DataFrame({"datas": datas}, nan_to_null=True)
|
|
672
|
-
.select(
|
|
765
|
+
.select(
|
|
766
|
+
eh_dia_util=eh_dia_util_expr(
|
|
767
|
+
"datas", calendario=calendario
|
|
768
|
+
)
|
|
769
|
+
)
|
|
673
770
|
.get_column("eh_dia_util")
|
|
674
771
|
)
|
|
675
772
|
|
|
@@ -8,19 +8,21 @@ import polars as pl
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class FeriadosBrasil:
|
|
11
|
-
"""Calendário de feriados nacionais (lista
|
|
11
|
+
"""Calendário de feriados nacionais (lista anterior e atual).
|
|
12
12
|
|
|
13
13
|
Uso interno do módulo `dus`.
|
|
14
|
-
DATA_TRANSICAO (inclusive): 2023-12-26. Antes desta data usa lista
|
|
15
|
-
A partir desta data usa lista
|
|
14
|
+
DATA_TRANSICAO (inclusive): 2023-12-26. Antes desta data usa lista anterior.
|
|
15
|
+
A partir desta data usa a lista atual.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
DATA_TRANSICAO = dt.date(2023, 12, 26)
|
|
19
19
|
|
|
20
20
|
def __init__(self) -> None:
|
|
21
21
|
base = Path(__file__).parent
|
|
22
|
-
self.
|
|
23
|
-
|
|
22
|
+
self.feriados_atuais = self._carregar_feriados(
|
|
23
|
+
base / "feriados_novos_br.txt"
|
|
24
|
+
)
|
|
25
|
+
self.feriados_anteriores = self._carregar_feriados(
|
|
24
26
|
base / "feriados_antigos_br.txt"
|
|
25
27
|
)
|
|
26
28
|
|
|
@@ -37,23 +39,22 @@ class FeriadosBrasil:
|
|
|
37
39
|
def obter_feriados(
|
|
38
40
|
self,
|
|
39
41
|
datas: dt.date | pl.Series | None = None,
|
|
40
|
-
|
|
42
|
+
calendario: Literal["auto", "anterior", "atual"] = "auto",
|
|
41
43
|
) -> list[dt.date]:
|
|
42
|
-
"""Retorna a lista de feriados conforme opção
|
|
44
|
+
"""Retorna a lista de feriados conforme a opção selecionada.
|
|
43
45
|
|
|
44
|
-
datas:
|
|
45
|
-
|
|
46
|
-
opcao_feriado: 'antigo', 'novo' ou 'inferir'.
|
|
46
|
+
datas: Data única ou série de datas para seleção automática.
|
|
47
|
+
calendario: ``"auto"``, ``"anterior"`` ou ``"atual"``.
|
|
47
48
|
"""
|
|
48
|
-
match
|
|
49
|
-
case "
|
|
50
|
-
return self.
|
|
51
|
-
case "
|
|
52
|
-
return self.
|
|
53
|
-
case "
|
|
49
|
+
match calendario:
|
|
50
|
+
case "anterior":
|
|
51
|
+
return self.feriados_anteriores
|
|
52
|
+
case "atual":
|
|
53
|
+
return self.feriados_atuais
|
|
54
|
+
case "auto":
|
|
54
55
|
if datas is None:
|
|
55
56
|
raise ValueError(
|
|
56
|
-
"'datas' é obrigatório quando
|
|
57
|
+
"'datas' é obrigatório quando calendario='auto'."
|
|
57
58
|
)
|
|
58
59
|
if isinstance(datas, dt.date):
|
|
59
60
|
data_minima = datas
|
|
@@ -61,12 +62,12 @@ class FeriadosBrasil:
|
|
|
61
62
|
data_minima = datas.drop_nulls().min()
|
|
62
63
|
|
|
63
64
|
if not isinstance(data_minima, dt.date):
|
|
64
|
-
raise ValueError("Não foi possível
|
|
65
|
+
raise ValueError("Não foi possível selecionar o calendário.")
|
|
65
66
|
|
|
66
67
|
if data_minima < self.DATA_TRANSICAO:
|
|
67
|
-
return self.
|
|
68
|
+
return self.feriados_anteriores
|
|
68
69
|
else:
|
|
69
|
-
return self.
|
|
70
|
+
return self.feriados_atuais
|
|
70
71
|
|
|
71
72
|
case _:
|
|
72
|
-
raise ValueError("Opção inválida para
|
|
73
|
+
raise ValueError("Opção inválida para calendario.")
|
|
@@ -20,6 +20,9 @@ class Interpolador:
|
|
|
20
20
|
abaixo do menor vértice) sempre retorna a primeira taxa conhecida,
|
|
21
21
|
independentemente desta flag.
|
|
22
22
|
|
|
23
|
+
Raises:
|
|
24
|
+
ValueError: Se não houver ao menos um vértice válido na curva.
|
|
25
|
+
|
|
23
26
|
Notes:
|
|
24
27
|
- Esta classe usa convenção de 252 dias úteis por ano.
|
|
25
28
|
- Instâncias desta classe são **imutáveis**. Para modificar as
|
|
@@ -68,6 +71,8 @@ class Interpolador:
|
|
|
68
71
|
.unique(subset="dus", keep="last")
|
|
69
72
|
.sort("dus")
|
|
70
73
|
)
|
|
74
|
+
if df.is_empty():
|
|
75
|
+
raise ValueError("A curva deve conter ao menos um vértice válido.")
|
|
71
76
|
self._df = df
|
|
72
77
|
self._method = str(metodo)
|
|
73
78
|
self._dus = tuple(df.get_column("dus"))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Bootstrap
|
|
1
|
+
"""Bootstrap de forwards para a curva zero de NTN-B."""
|
|
2
2
|
|
|
3
3
|
import datetime as dt
|
|
4
4
|
from collections.abc import Callable
|
|
@@ -145,12 +145,13 @@ def taxas_zero(
|
|
|
145
145
|
incluir_vertices: bool = False,
|
|
146
146
|
) -> pl.DataFrame:
|
|
147
147
|
r"""
|
|
148
|
-
Calcula a curva zero de NTN-B pelo bootstrap de forwards
|
|
148
|
+
Calcula a curva zero de NTN-B pelo bootstrap de forwards.
|
|
149
149
|
|
|
150
150
|
O método parte das TIRs observadas das NTN-B, mas não as trata como taxas
|
|
151
151
|
zero. Ele encontra uma taxa forward para cada vencimento de título para que
|
|
152
152
|
os fluxos descontados pela curva zero reproduzam exatamente a cotação que a
|
|
153
|
-
TIR daquele título produz.
|
|
153
|
+
TIR daquele título produz. A calibração é iterativa e tem convergência
|
|
154
|
+
condicional: depende da existência de um intervalo válido para cada raiz.
|
|
154
155
|
|
|
155
156
|
Notes:
|
|
156
157
|
**Racional**
|
|
@@ -193,7 +194,16 @@ def taxas_zero(
|
|
|
193
194
|
|
|
194
195
|
Os forwards e taxas zero já calibrados nos títulos curtos permanecem
|
|
195
196
|
fixos durante a calibração dos títulos longos. Por isso, cada etapa tem
|
|
196
|
-
apenas uma incógnita e
|
|
197
|
+
apenas uma incógnita e é resolvida por bisseção quando há mudança de
|
|
198
|
+
sinal no intervalo pesquisado.
|
|
199
|
+
|
|
200
|
+
**Convergência condicional**
|
|
201
|
+
|
|
202
|
+
A bisseção é determinística quando encontra um intervalo que contém uma
|
|
203
|
+
raiz. A função tenta expandir o limite superior para encontrar esse
|
|
204
|
+
intervalo, mas pode não encontrá-lo para entradas incompatíveis ou
|
|
205
|
+
extremos. Nesse caso, a calibração não produz uma curva e lança
|
|
206
|
+
``RuntimeError``.
|
|
197
207
|
|
|
198
208
|
**Precisão do método**
|
|
199
209
|
|
|
@@ -210,9 +220,13 @@ def taxas_zero(
|
|
|
210
220
|
Padrão False, retornando apenas os vencimentos informados.
|
|
211
221
|
|
|
212
222
|
Returns:
|
|
213
|
-
pl.DataFrame: Curva zero calibrada pelo
|
|
223
|
+
pl.DataFrame: Curva zero calibrada pelo bootstrap de forwards. Retorna vazio quando
|
|
214
224
|
não restarem vencimentos posteriores à liquidação.
|
|
215
225
|
|
|
226
|
+
Raises:
|
|
227
|
+
RuntimeError: Se não for possível encontrar um intervalo válido para
|
|
228
|
+
alguma taxa forward.
|
|
229
|
+
|
|
216
230
|
Output Columns:
|
|
217
231
|
- data_vencimento (Date): Data do vértice da curva.
|
|
218
232
|
- dias_uteis (Int64): Dias úteis entre liquidação e vértice.
|
|
@@ -470,10 +470,12 @@ def taxas_zero(
|
|
|
470
470
|
incluir_cupons: bool = False,
|
|
471
471
|
) -> pl.DataFrame:
|
|
472
472
|
"""
|
|
473
|
-
Calcula as taxas zero da NTN-B
|
|
473
|
+
Calcula as taxas zero da NTN-B pelo bootstrap de cupons.
|
|
474
474
|
|
|
475
|
-
O
|
|
476
|
-
|
|
475
|
+
O método monta uma grade trimestral de datas de pagamento, interpola as TIRs
|
|
476
|
+
dos títulos nos vértices intermediários e resolve sequencialmente as taxas
|
|
477
|
+
zero. Para cada vértice, a taxa é obtida diretamente do preço-alvo e do
|
|
478
|
+
valor presente dos cupons anteriores; não há busca iterativa de raiz.
|
|
477
479
|
|
|
478
480
|
Args:
|
|
479
481
|
data_liquidacao (DateLike): Data de liquidação.
|
|
@@ -551,10 +553,13 @@ def taxas_zero(
|
|
|
551
553
|
|
|
552
554
|
Notes:
|
|
553
555
|
O cálculo considera:
|
|
554
|
-
- Mapear todas as datas de pagamento até o último vencimento.
|
|
556
|
+
- Mapear todas as datas trimestrais de pagamento até o último vencimento.
|
|
555
557
|
- Interpolar as TIRs nas datas intermediárias.
|
|
556
558
|
- Calcular a cotação da NTN-B para cada vencimento.
|
|
557
559
|
- Calcular as taxas zero reais.
|
|
560
|
+
|
|
561
|
+
Este bootstrap usa a cotação normativa da NTN-B, que arredonda o valor
|
|
562
|
+
presente de cada fluxo e trunca a cotação final em seis casas.
|
|
558
563
|
"""
|
|
559
564
|
if any_is_empty(data_liquidacao, vencimentos, taxas):
|
|
560
565
|
return pl.DataFrame()
|
|
@@ -589,9 +594,7 @@ def taxas_zero(
|
|
|
589
594
|
valor_presente_cupons = _calcular_valor_presente_cupons(
|
|
590
595
|
df, data_liquidacao, vencimento
|
|
591
596
|
)
|
|
592
|
-
preco_titulo = float(
|
|
593
|
-
cotacao(data_liquidacao, vencimento, linha["taxa_tir"])
|
|
594
|
-
)
|
|
597
|
+
preco_titulo = float(cotacao(data_liquidacao, vencimento, linha["taxa_tir"]))
|
|
595
598
|
fator_preco = VALOR_FINAL / (preco_titulo - valor_presente_cupons)
|
|
596
599
|
taxa_zero = fator_preco ** (1 / linha["anos_uteis"]) - 1
|
|
597
600
|
|
|
@@ -7,10 +7,10 @@ import polars as pl
|
|
|
7
7
|
from pyield import du, interpolador
|
|
8
8
|
from pyield._internal.numbers import truncar_decimal
|
|
9
9
|
from pyield._internal.types import DateLike, any_is_empty
|
|
10
|
+
from pyield.tpf.titulos import _bootstrap_forwards
|
|
10
11
|
from pyield.tpf.titulos import _utils as utils
|
|
11
|
-
from pyield.tpf.titulos import _zero_td
|
|
12
12
|
|
|
13
|
-
taxas_zero =
|
|
13
|
+
taxas_zero = _bootstrap_forwards.taxas_zero
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def cotacao(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|