pyield 0.51.2__tar.gz → 0.52.1__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.51.2 → pyield-0.52.1}/PKG-INFO +88 -27
- {pyield-0.51.2 → pyield-0.52.1}/README.md +87 -26
- {pyield-0.51.2 → pyield-0.52.1}/pyield/__init__.py +2 -1
- {pyield-0.51.2 → pyield-0.52.1}/pyield/_internal/converters.py +3 -3
- {pyield-0.51.2 → pyield-0.52.1}/pyield/_internal/types.py +2 -1
- {pyield-0.51.2 → pyield-0.52.1}/pyield/bc/leiloes.py +36 -23
- {pyield-0.51.2 → pyield-0.52.1}/pyield/du/core.py +9 -9
- {pyield-0.51.2 → pyield-0.52.1}/pyield/futuro/di1.py +14 -59
- {pyield-0.51.2 → pyield-0.52.1}/pyield/futuro/historico.py +2 -2
- pyield-0.52.1/pyield/interpolador.py +497 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/lft.py +23 -4
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/ltn.py +85 -63
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/ntnb.py +147 -61
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/ntnb1.py +10 -9
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/ntnbprinc.py +13 -9
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/ntnc.py +89 -14
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/ntnf.py +185 -73
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/leiloes.py +41 -32
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/pre.py +4 -4
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/utils.py +7 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyproject.toml +1 -1
- pyield-0.51.2/pyield/interpolador.py +0 -263
- {pyield-0.51.2 → pyield-0.52.1}/LICENSE +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/_internal/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/_internal/br_numbers.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/_internal/cache.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/_internal/data_cache.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/_internal/retry.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/anbima/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/anbima/imaq.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/anbima/mercado_secundario.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/b3/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/b3/_contratos.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/b3/_validar_pregao.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/b3/boletim.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/b3/derivativos_intradia.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/b3/di_over.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/bc/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/bc/_olinda.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/bc/lft.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/bc/sgs.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/bc/tpf_intradia.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/bc/tpf_mensal.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/du/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/du/feriados/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/du/feriados/feriados_antigos_br.txt +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/du/feriados/feriados_br.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/du/feriados/feriados_novos_br.txt +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/futuro/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/futuro/contratos.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/futuro/intradia.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/fwd.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/ipca/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/ipca/historico.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/ipca/projetado.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/py.typed +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/relogio.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/selic/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/selic/compromissada.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/selic/copom.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/selic/cpm.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/selic/probabilities.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/_titulos/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/benchmark.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/rmd/__init__.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/rmd/_aba_1_3.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/rmd/_aba_2_1.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/rmd/_common.py +0 -0
- {pyield-0.51.2 → pyield-0.52.1}/pyield/tpf/rmd/_download.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pyield
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.52.1
|
|
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
|
|
@@ -86,10 +86,9 @@ df = yd.futuro.historico("31-05-2024", "DI1")
|
|
|
86
86
|
|
|
87
87
|
# Interpolação de taxas (flat forward, convenção 252 dias úteis/ano)
|
|
88
88
|
interp = yd.Interpolador(df["dias_uteis"], df["taxa_ajuste"], metodo="flat_forward")
|
|
89
|
-
interp(45)
|
|
90
|
-
interp([30, 60]) # -> Series do Polars com taxas interpoladas
|
|
89
|
+
interp(45) # -> 0.04833...
|
|
91
90
|
|
|
92
|
-
#
|
|
91
|
+
# Preçificar títulos públicos
|
|
93
92
|
yd.ntnb.cotacao("31-05-2024", "15-05-2035", 0.061490) # -> 99.3651
|
|
94
93
|
|
|
95
94
|
# Indicadores do BCB
|
|
@@ -108,19 +107,20 @@ documentação.
|
|
|
108
107
|
| Componente | Tipo | Finalidade | Funções públicas |
|
|
109
108
|
|---|---|---|---|
|
|
110
109
|
| `yd.du` | módulo | Dias úteis e calendário brasileiro | `contar`, `deslocar`, `eh_dia_util`, `gerar`, `ultimo_dia_util`, `contar_expr`, `deslocar_expr`, `eh_dia_util_expr` |
|
|
111
|
-
| `yd.Interpolador` | classe | Interpolação
|
|
110
|
+
| `yd.Interpolador` | classe | Interpolação escalar e em pipelines Polars | `interpolar`, `interpolar_expr`, `linear`, `flat_forward` |
|
|
111
|
+
| `yd.interpolar(...)` | função | Interpolação vetorizada flat-forward, curva única ou multi-curva | |
|
|
112
112
|
| `yd.forward(...)` | função | Taxa a termo entre dois vértices | |
|
|
113
113
|
| `yd.forwards(...)` | função | Curva de taxas a termo | |
|
|
114
114
|
| `yd.futuro` | módulo | Contratos futuros da B3 | `di1`, `historico`, `intradia`, `datas_disponiveis`, `vencimento`, `enriquecer`, `vencimento_expr` |
|
|
115
115
|
| `yd.di1` | módulo | Curva DI1 e interpolação | `dados`, `interpolar_taxas`, `interpolar_taxa`, `datas_disponiveis` |
|
|
116
116
|
| `yd.tpf` | módulo | Títulos públicos federais | `taxas`, `vencimentos`, `estoque`, `leiloes`, `benchmarks`, `curva_pre`, `premio_pre`, `rmd`, `secundario_mensal`, `secundario_intradia` |
|
|
117
|
-
| `yd.lft` | módulo | LFT | `dados`, `vencimentos`, `cotacao`, `taxa`, `vna` |
|
|
118
|
-
| `yd.ltn` | módulo | LTN | `dados`, `vencimentos`, `pu`, `taxa`, `dv01`, `
|
|
119
|
-
| `yd.ntnb` | módulo | NTN-B | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `taxas_zero`, `duration`, `dv01`, `implicitas`, `curva` |
|
|
117
|
+
| `yd.lft` | módulo | LFT | `dados`, `vencimentos`, `cotacao`, `pu`, `taxa`, `vna`, `rentabilidade`, `rentabilidade_expr` |
|
|
118
|
+
| `yd.ltn` | módulo | LTN | `dados`, `vencimentos`, `pu`, `taxa`, `duration_expr`, `dv01`, `dv01_expr`, `rentabilidade`, `rentabilidade_expr`, `taxas_forward` |
|
|
119
|
+
| `yd.ntnb` | módulo | NTN-B | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `taxas_zero`, `duration`, `duration_expr`, `dv01`, `dv01_expr`, `implicitas`, `curva` |
|
|
120
120
|
| `yd.ntnb1` | módulo | NTN-B1 | `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `duration`, `dv01` |
|
|
121
121
|
| `yd.ntnbprinc` | módulo | NTN-B Principal | `pu`, `dv01` |
|
|
122
|
-
| `yd.ntnc` | módulo | NTN-C | `dados`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `duration`, `dv01` |
|
|
123
|
-
| `yd.ntnf` | módulo | NTN-F | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `pu`, `taxa`, `taxas_zero`, `premio`, `premio_limpo`, `rentabilidade`, `duration`, `dv01` |
|
|
122
|
+
| `yd.ntnc` | módulo | NTN-C | `dados`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
123
|
+
| `yd.ntnf` | módulo | NTN-F | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `pu`, `taxa`, `taxas_zero`, `premio`, `premio_limpo`, `rentabilidade`, `rentabilidade_expr`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
124
124
|
| `yd.selic` | módulo | Selic, COPOM e política monetária | `over`, `over_serie`, `meta`, `meta_serie`, `compromissadas`, `copom`, `cpm`, `probabilities` |
|
|
125
125
|
| `yd.ipca` | módulo | IPCA histórico e projetado | `indice`, `indices`, `indices_ultimos`, `taxa`, `taxas`, `taxas_ultimas`, `taxa_projetada` |
|
|
126
126
|
| `yd.ptax(data)` | função | PTAX para uma data | |
|
|
@@ -178,14 +178,37 @@ interp(45) # -> 0.04833...
|
|
|
178
178
|
linear = Interpolador(dias_uteis, taxas, metodo="linear")
|
|
179
179
|
linear(45) # -> 0.0475
|
|
180
180
|
|
|
181
|
-
#
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
# Extrapolação (desabilitada por padrão, retorna NaN)
|
|
181
|
+
# Extrapolação na ponta longa: desabilitada por padrão (NaN). A ponta
|
|
182
|
+
# curta sempre retorna a primeira taxa conhecida.
|
|
185
183
|
interp(100) # -> nan
|
|
186
184
|
Interpolador(dias_uteis, taxas, metodo="flat_forward", extrapolar=True)(100) # -> 0.055
|
|
187
185
|
```
|
|
188
186
|
|
|
187
|
+
Para interpolar uma coluna inteira dentro de um pipeline Polars, use
|
|
188
|
+
`interpolar_expr`:
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
import polars as pl
|
|
192
|
+
|
|
193
|
+
df = pl.DataFrame({"du": [15, 45, 75]})
|
|
194
|
+
df.with_columns(taxa=interp.interpolar_expr("du"))
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Quando os pontos alvo e a curva vêm de DataFrames diferentes (inclusive com
|
|
198
|
+
múltiplas datas de referência), use a função top-level `yd.interpolar`:
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
import pyield as yd
|
|
202
|
+
|
|
203
|
+
taxas = yd.interpolar(
|
|
204
|
+
dus_alvo=df_alvo["dias_uteis"],
|
|
205
|
+
dus_curva=df_curva["dias_uteis"],
|
|
206
|
+
taxas_curva=df_curva["taxa"],
|
|
207
|
+
datas_alvo=df_alvo["data_referencia"], # opcional (multi-curva)
|
|
208
|
+
datas_curva=df_curva["data_referencia"], # opcional (multi-curva)
|
|
209
|
+
)
|
|
210
|
+
```
|
|
211
|
+
|
|
189
212
|
### Taxas a Termo (`forward`, `forwards`)
|
|
190
213
|
|
|
191
214
|
Calcula taxas a termo a partir de curvas spot:
|
|
@@ -290,28 +313,66 @@ yd.ptax("25-12-2025") # -> nan
|
|
|
290
313
|
|
|
291
314
|
Documentação completa: [crdcj.github.io/PYield](https://crdcj.github.io/PYield/)
|
|
292
315
|
|
|
293
|
-
## Quebra de API (v0.
|
|
316
|
+
## Quebra de API (v0.52.0)
|
|
317
|
+
|
|
318
|
+
Resumo das quebras desta versão:
|
|
319
|
+
|
|
320
|
+
- `Interpolador(...)` e `Interpolador.interpolar(...)` agora aceitam **apenas
|
|
321
|
+
inteiro escalar**. Chamadas com lista/`pl.Series` (`interp([30, 60])`),
|
|
322
|
+
antes suportadas via sobrecarga vetorial, agora levantam `TypeError`.
|
|
323
|
+
Substitua por `Interpolador.interpolar_expr` em pipelines Polars ou pela
|
|
324
|
+
função top-level `yd.interpolar(...)` (curva única ou multi-curva).
|
|
325
|
+
- `yd.interpolar(...)` passou a usar `extrapolar=False` como padrão, alinhado
|
|
326
|
+
com `Interpolador`. Antes era `True`. Chamadas que dependiam da
|
|
327
|
+
extrapolação implícita na ponta longa precisam passar `extrapolar=True`
|
|
328
|
+
explicitamente.
|
|
329
|
+
- As funções `dv01(...)` dos títulos públicos agora recebem `pu` como argumento
|
|
330
|
+
explícito. Chamadas antigas que passavam apenas data, vencimento e taxa, ou
|
|
331
|
+
que passavam VNA no caso da NTN-B, precisam ser atualizadas.
|
|
332
|
+
- `ntnf.taxas_zero(...)` mudou os nomes dos parâmetros de curva para o padrão
|
|
333
|
+
`vencimentos_*` / `taxas_*`. Chamadas por posição continuam com a mesma
|
|
334
|
+
ordem; chamadas por keyword precisam usar os novos nomes.
|
|
294
335
|
|
|
295
|
-
###
|
|
336
|
+
### `Interpolador(...)` não aceita mais lista/Series
|
|
296
337
|
|
|
297
|
-
|
|
298
|
-
|
|
338
|
+
O ``__call__`` e o método ``interpolar`` da classe agora são estritamente
|
|
339
|
+
escalares. O caminho vetorial foi dividido em duas APIs com semântica clara:
|
|
299
340
|
|
|
300
341
|
```python
|
|
301
|
-
|
|
302
|
-
|
|
342
|
+
# Antes (v0.51.x)
|
|
343
|
+
interp = yd.Interpolador(dus, taxas, metodo="flat_forward")
|
|
344
|
+
interp([15, 45, 75]) # pl.Series
|
|
345
|
+
|
|
346
|
+
# Agora, dentro de um pipeline Polars
|
|
347
|
+
df.with_columns(taxa=interp.interpolar_expr("du"))
|
|
348
|
+
|
|
349
|
+
# Agora, ad-hoc (curva única ou multi-curva)
|
|
350
|
+
yd.interpolar(
|
|
351
|
+
dus_alvo=pl.Series([15, 45, 75]),
|
|
352
|
+
dus_curva=pl.Series(dus),
|
|
353
|
+
taxas_curva=pl.Series(taxas),
|
|
354
|
+
)
|
|
303
355
|
```
|
|
304
356
|
|
|
305
|
-
### `
|
|
357
|
+
### `dv01(...)` agora recebe PU
|
|
358
|
+
|
|
359
|
+
As funções `dv01(...)` dos títulos públicos recebem o PU usado como base para o
|
|
360
|
+
cálculo, não mais o VNA ou apenas a taxa. Se necessário, calcule o PU antes:
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
pu = yd.ntnb.pu(vna, yd.ntnb.cotacao(data, vencimento, taxa))
|
|
364
|
+
dv01 = yd.ntnb.dv01(data, vencimento, taxa, pu)
|
|
365
|
+
```
|
|
306
366
|
|
|
307
|
-
|
|
308
|
-
- `taxa_tir` → `taxa_tir_real`
|
|
309
|
-
- `taxa_zero` → `taxa_zero_real`
|
|
367
|
+
### `ntnf.taxas_zero(...)` usa nomes por conceito
|
|
310
368
|
|
|
311
|
-
|
|
369
|
+
Os parâmetros de curva da NTN-F foram renomeados para manter o padrão
|
|
370
|
+
`vencimentos_*` / `taxas_*`:
|
|
312
371
|
|
|
313
|
-
|
|
314
|
-
|
|
372
|
+
- `ltn_vencimentos` → `vencimentos_ltn`
|
|
373
|
+
- `ltn_taxas` → `taxas_ltn`
|
|
374
|
+
- `ntnf_vencimentos` → `vencimentos_ntnf`
|
|
375
|
+
- `ntnf_taxas` → `taxas_ntnf`
|
|
315
376
|
|
|
316
377
|
## Testes
|
|
317
378
|
|
|
@@ -42,10 +42,9 @@ df = yd.futuro.historico("31-05-2024", "DI1")
|
|
|
42
42
|
|
|
43
43
|
# Interpolação de taxas (flat forward, convenção 252 dias úteis/ano)
|
|
44
44
|
interp = yd.Interpolador(df["dias_uteis"], df["taxa_ajuste"], metodo="flat_forward")
|
|
45
|
-
interp(45)
|
|
46
|
-
interp([30, 60]) # -> Series do Polars com taxas interpoladas
|
|
45
|
+
interp(45) # -> 0.04833...
|
|
47
46
|
|
|
48
|
-
#
|
|
47
|
+
# Preçificar títulos públicos
|
|
49
48
|
yd.ntnb.cotacao("31-05-2024", "15-05-2035", 0.061490) # -> 99.3651
|
|
50
49
|
|
|
51
50
|
# Indicadores do BCB
|
|
@@ -64,19 +63,20 @@ documentação.
|
|
|
64
63
|
| Componente | Tipo | Finalidade | Funções públicas |
|
|
65
64
|
|---|---|---|---|
|
|
66
65
|
| `yd.du` | módulo | Dias úteis e calendário brasileiro | `contar`, `deslocar`, `eh_dia_util`, `gerar`, `ultimo_dia_util`, `contar_expr`, `deslocar_expr`, `eh_dia_util_expr` |
|
|
67
|
-
| `yd.Interpolador` | classe | Interpolação
|
|
66
|
+
| `yd.Interpolador` | classe | Interpolação escalar e em pipelines Polars | `interpolar`, `interpolar_expr`, `linear`, `flat_forward` |
|
|
67
|
+
| `yd.interpolar(...)` | função | Interpolação vetorizada flat-forward, curva única ou multi-curva | |
|
|
68
68
|
| `yd.forward(...)` | função | Taxa a termo entre dois vértices | |
|
|
69
69
|
| `yd.forwards(...)` | função | Curva de taxas a termo | |
|
|
70
70
|
| `yd.futuro` | módulo | Contratos futuros da B3 | `di1`, `historico`, `intradia`, `datas_disponiveis`, `vencimento`, `enriquecer`, `vencimento_expr` |
|
|
71
71
|
| `yd.di1` | módulo | Curva DI1 e interpolação | `dados`, `interpolar_taxas`, `interpolar_taxa`, `datas_disponiveis` |
|
|
72
72
|
| `yd.tpf` | módulo | Títulos públicos federais | `taxas`, `vencimentos`, `estoque`, `leiloes`, `benchmarks`, `curva_pre`, `premio_pre`, `rmd`, `secundario_mensal`, `secundario_intradia` |
|
|
73
|
-
| `yd.lft` | módulo | LFT | `dados`, `vencimentos`, `cotacao`, `taxa`, `vna` |
|
|
74
|
-
| `yd.ltn` | módulo | LTN | `dados`, `vencimentos`, `pu`, `taxa`, `dv01`, `
|
|
75
|
-
| `yd.ntnb` | módulo | NTN-B | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `taxas_zero`, `duration`, `dv01`, `implicitas`, `curva` |
|
|
73
|
+
| `yd.lft` | módulo | LFT | `dados`, `vencimentos`, `cotacao`, `pu`, `taxa`, `vna`, `rentabilidade`, `rentabilidade_expr` |
|
|
74
|
+
| `yd.ltn` | módulo | LTN | `dados`, `vencimentos`, `pu`, `taxa`, `duration_expr`, `dv01`, `dv01_expr`, `rentabilidade`, `rentabilidade_expr`, `taxas_forward` |
|
|
75
|
+
| `yd.ntnb` | módulo | NTN-B | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `taxas_zero`, `duration`, `duration_expr`, `dv01`, `dv01_expr`, `implicitas`, `curva` |
|
|
76
76
|
| `yd.ntnb1` | módulo | NTN-B1 | `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `duration`, `dv01` |
|
|
77
77
|
| `yd.ntnbprinc` | módulo | NTN-B Principal | `pu`, `dv01` |
|
|
78
|
-
| `yd.ntnc` | módulo | NTN-C | `dados`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `duration`, `dv01` |
|
|
79
|
-
| `yd.ntnf` | módulo | NTN-F | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `pu`, `taxa`, `taxas_zero`, `premio`, `premio_limpo`, `rentabilidade`, `duration`, `dv01` |
|
|
78
|
+
| `yd.ntnc` | módulo | NTN-C | `dados`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
79
|
+
| `yd.ntnf` | módulo | NTN-F | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `pu`, `taxa`, `taxas_zero`, `premio`, `premio_limpo`, `rentabilidade`, `rentabilidade_expr`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
80
80
|
| `yd.selic` | módulo | Selic, COPOM e política monetária | `over`, `over_serie`, `meta`, `meta_serie`, `compromissadas`, `copom`, `cpm`, `probabilities` |
|
|
81
81
|
| `yd.ipca` | módulo | IPCA histórico e projetado | `indice`, `indices`, `indices_ultimos`, `taxa`, `taxas`, `taxas_ultimas`, `taxa_projetada` |
|
|
82
82
|
| `yd.ptax(data)` | função | PTAX para uma data | |
|
|
@@ -134,14 +134,37 @@ interp(45) # -> 0.04833...
|
|
|
134
134
|
linear = Interpolador(dias_uteis, taxas, metodo="linear")
|
|
135
135
|
linear(45) # -> 0.0475
|
|
136
136
|
|
|
137
|
-
#
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
# Extrapolação (desabilitada por padrão, retorna NaN)
|
|
137
|
+
# Extrapolação na ponta longa: desabilitada por padrão (NaN). A ponta
|
|
138
|
+
# curta sempre retorna a primeira taxa conhecida.
|
|
141
139
|
interp(100) # -> nan
|
|
142
140
|
Interpolador(dias_uteis, taxas, metodo="flat_forward", extrapolar=True)(100) # -> 0.055
|
|
143
141
|
```
|
|
144
142
|
|
|
143
|
+
Para interpolar uma coluna inteira dentro de um pipeline Polars, use
|
|
144
|
+
`interpolar_expr`:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
import polars as pl
|
|
148
|
+
|
|
149
|
+
df = pl.DataFrame({"du": [15, 45, 75]})
|
|
150
|
+
df.with_columns(taxa=interp.interpolar_expr("du"))
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Quando os pontos alvo e a curva vêm de DataFrames diferentes (inclusive com
|
|
154
|
+
múltiplas datas de referência), use a função top-level `yd.interpolar`:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
import pyield as yd
|
|
158
|
+
|
|
159
|
+
taxas = yd.interpolar(
|
|
160
|
+
dus_alvo=df_alvo["dias_uteis"],
|
|
161
|
+
dus_curva=df_curva["dias_uteis"],
|
|
162
|
+
taxas_curva=df_curva["taxa"],
|
|
163
|
+
datas_alvo=df_alvo["data_referencia"], # opcional (multi-curva)
|
|
164
|
+
datas_curva=df_curva["data_referencia"], # opcional (multi-curva)
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
145
168
|
### Taxas a Termo (`forward`, `forwards`)
|
|
146
169
|
|
|
147
170
|
Calcula taxas a termo a partir de curvas spot:
|
|
@@ -246,28 +269,66 @@ yd.ptax("25-12-2025") # -> nan
|
|
|
246
269
|
|
|
247
270
|
Documentação completa: [crdcj.github.io/PYield](https://crdcj.github.io/PYield/)
|
|
248
271
|
|
|
249
|
-
## Quebra de API (v0.
|
|
272
|
+
## Quebra de API (v0.52.0)
|
|
273
|
+
|
|
274
|
+
Resumo das quebras desta versão:
|
|
275
|
+
|
|
276
|
+
- `Interpolador(...)` e `Interpolador.interpolar(...)` agora aceitam **apenas
|
|
277
|
+
inteiro escalar**. Chamadas com lista/`pl.Series` (`interp([30, 60])`),
|
|
278
|
+
antes suportadas via sobrecarga vetorial, agora levantam `TypeError`.
|
|
279
|
+
Substitua por `Interpolador.interpolar_expr` em pipelines Polars ou pela
|
|
280
|
+
função top-level `yd.interpolar(...)` (curva única ou multi-curva).
|
|
281
|
+
- `yd.interpolar(...)` passou a usar `extrapolar=False` como padrão, alinhado
|
|
282
|
+
com `Interpolador`. Antes era `True`. Chamadas que dependiam da
|
|
283
|
+
extrapolação implícita na ponta longa precisam passar `extrapolar=True`
|
|
284
|
+
explicitamente.
|
|
285
|
+
- As funções `dv01(...)` dos títulos públicos agora recebem `pu` como argumento
|
|
286
|
+
explícito. Chamadas antigas que passavam apenas data, vencimento e taxa, ou
|
|
287
|
+
que passavam VNA no caso da NTN-B, precisam ser atualizadas.
|
|
288
|
+
- `ntnf.taxas_zero(...)` mudou os nomes dos parâmetros de curva para o padrão
|
|
289
|
+
`vencimentos_*` / `taxas_*`. Chamadas por posição continuam com a mesma
|
|
290
|
+
ordem; chamadas por keyword precisam usar os novos nomes.
|
|
250
291
|
|
|
251
|
-
###
|
|
292
|
+
### `Interpolador(...)` não aceita mais lista/Series
|
|
252
293
|
|
|
253
|
-
|
|
254
|
-
|
|
294
|
+
O ``__call__`` e o método ``interpolar`` da classe agora são estritamente
|
|
295
|
+
escalares. O caminho vetorial foi dividido em duas APIs com semântica clara:
|
|
255
296
|
|
|
256
297
|
```python
|
|
257
|
-
|
|
258
|
-
|
|
298
|
+
# Antes (v0.51.x)
|
|
299
|
+
interp = yd.Interpolador(dus, taxas, metodo="flat_forward")
|
|
300
|
+
interp([15, 45, 75]) # pl.Series
|
|
301
|
+
|
|
302
|
+
# Agora, dentro de um pipeline Polars
|
|
303
|
+
df.with_columns(taxa=interp.interpolar_expr("du"))
|
|
304
|
+
|
|
305
|
+
# Agora, ad-hoc (curva única ou multi-curva)
|
|
306
|
+
yd.interpolar(
|
|
307
|
+
dus_alvo=pl.Series([15, 45, 75]),
|
|
308
|
+
dus_curva=pl.Series(dus),
|
|
309
|
+
taxas_curva=pl.Series(taxas),
|
|
310
|
+
)
|
|
259
311
|
```
|
|
260
312
|
|
|
261
|
-
### `
|
|
313
|
+
### `dv01(...)` agora recebe PU
|
|
314
|
+
|
|
315
|
+
As funções `dv01(...)` dos títulos públicos recebem o PU usado como base para o
|
|
316
|
+
cálculo, não mais o VNA ou apenas a taxa. Se necessário, calcule o PU antes:
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
pu = yd.ntnb.pu(vna, yd.ntnb.cotacao(data, vencimento, taxa))
|
|
320
|
+
dv01 = yd.ntnb.dv01(data, vencimento, taxa, pu)
|
|
321
|
+
```
|
|
262
322
|
|
|
263
|
-
|
|
264
|
-
- `taxa_tir` → `taxa_tir_real`
|
|
265
|
-
- `taxa_zero` → `taxa_zero_real`
|
|
323
|
+
### `ntnf.taxas_zero(...)` usa nomes por conceito
|
|
266
324
|
|
|
267
|
-
|
|
325
|
+
Os parâmetros de curva da NTN-F foram renomeados para manter o padrão
|
|
326
|
+
`vencimentos_*` / `taxas_*`:
|
|
268
327
|
|
|
269
|
-
|
|
270
|
-
|
|
328
|
+
- `ltn_vencimentos` → `vencimentos_ltn`
|
|
329
|
+
- `ltn_taxas` → `taxas_ltn`
|
|
330
|
+
- `ntnf_vencimentos` → `vencimentos_ntnf`
|
|
331
|
+
- `ntnf_taxas` → `taxas_ntnf`
|
|
271
332
|
|
|
272
333
|
## Testes
|
|
273
334
|
|
|
@@ -13,7 +13,7 @@ from pyield.futuro import di1
|
|
|
13
13
|
from pyield import selic, tpf
|
|
14
14
|
from pyield.bc.sgs import ptax, ptax_serie
|
|
15
15
|
from pyield.fwd import forward, forwards, forwards_expr
|
|
16
|
-
from pyield.interpolador import Interpolador
|
|
16
|
+
from pyield.interpolador import Interpolador, interpolar
|
|
17
17
|
from pyield.relogio import agora, hoje
|
|
18
18
|
from pyield.tpf import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf
|
|
19
19
|
|
|
@@ -35,6 +35,7 @@ __all__ = [
|
|
|
35
35
|
"futuro",
|
|
36
36
|
"hoje",
|
|
37
37
|
"Interpolador",
|
|
38
|
+
"interpolar",
|
|
38
39
|
"ipca",
|
|
39
40
|
"lft",
|
|
40
41
|
"ltn",
|
|
@@ -4,7 +4,7 @@ from typing import overload
|
|
|
4
4
|
import polars as pl
|
|
5
5
|
|
|
6
6
|
from pyield._internal import types
|
|
7
|
-
from pyield._internal.types import
|
|
7
|
+
from pyield._internal.types import DateLike, DatesLike
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def data_referencia_valida(date: dt.date | None) -> bool:
|
|
@@ -68,11 +68,11 @@ def converter_datas(dates: None) -> None: ...
|
|
|
68
68
|
@overload
|
|
69
69
|
def converter_datas(dates: DateLike) -> dt.date: ...
|
|
70
70
|
@overload
|
|
71
|
-
def converter_datas(dates:
|
|
71
|
+
def converter_datas(dates: DatesLike) -> pl.Series: ...
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def converter_datas(
|
|
75
|
-
dates: DateLike |
|
|
75
|
+
dates: DateLike | DatesLike | None,
|
|
76
76
|
) -> dt.date | pl.Series | None:
|
|
77
77
|
"""Converte diferentes tipos de entrada para ``datetime.date`` ou ``pl.Series``.
|
|
78
78
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import datetime as dt
|
|
2
2
|
import math
|
|
3
|
-
from collections.abc import Sized
|
|
3
|
+
from collections.abc import Sequence, Sized
|
|
4
4
|
from typing import Any, TypeAlias, TypeGuard
|
|
5
5
|
|
|
6
6
|
import polars as pl
|
|
7
7
|
|
|
8
8
|
DateLike: TypeAlias = str | dt.datetime | dt.date
|
|
9
9
|
ArrayLike: TypeAlias = list[Any] | tuple[Any, ...] | pl.Series
|
|
10
|
+
DatesLike: TypeAlias = Sequence[DateLike] | pl.Series
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def _is_empty(arg: Any) -> bool:
|
|
@@ -19,8 +19,7 @@ from pyield._internal.br_numbers import float_br, taxa_br
|
|
|
19
19
|
from pyield._internal.types import DateLike
|
|
20
20
|
from pyield.bc._olinda import buscar_csv, montar_url, parsear_csv
|
|
21
21
|
from pyield.bc.sgs import ptax_serie
|
|
22
|
-
from pyield.tpf._titulos
|
|
23
|
-
from pyield.tpf._titulos.ntnf import duration as duration_f
|
|
22
|
+
from pyield.tpf._titulos import ltn, ntnb, ntnf
|
|
24
23
|
|
|
25
24
|
registro = logging.getLogger(__name__)
|
|
26
25
|
|
|
@@ -90,22 +89,26 @@ def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
|
90
89
|
"""Filtra, converte tipos e calcula colunas derivadas."""
|
|
91
90
|
data_mudanca = dt.date(2024, 6, 11)
|
|
92
91
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return duration_f(
|
|
99
|
-
linha["data_liquidacao"], linha["data_vencimento"], linha["taxa_media"]
|
|
92
|
+
expr_dv01_unitario = (
|
|
93
|
+
pl.when(pl.col("titulo") == "LTN")
|
|
94
|
+
.then(
|
|
95
|
+
ltn.dv01_expr(
|
|
96
|
+
"data_liquidacao", "data_vencimento", "taxa_media", "pu_medio"
|
|
100
97
|
)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
)
|
|
99
|
+
.when(pl.col("titulo") == "NTN-F")
|
|
100
|
+
.then(
|
|
101
|
+
ntnf.dv01_expr(
|
|
102
|
+
"data_liquidacao", "data_vencimento", "taxa_media", "pu_medio"
|
|
104
103
|
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
)
|
|
105
|
+
.when(pl.col("titulo") == "NTN-B")
|
|
106
|
+
.then(
|
|
107
|
+
ntnb.dv01_expr(
|
|
108
|
+
"data_liquidacao", "data_vencimento", "taxa_media", "pu_medio"
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
.otherwise(0.0)
|
|
109
112
|
)
|
|
110
113
|
|
|
111
114
|
colunas_preco_taxa = ["taxa_media", "taxa_corte", "pu_medio", "pu_corte"]
|
|
@@ -177,13 +180,23 @@ def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
|
177
180
|
.name.keep()
|
|
178
181
|
)
|
|
179
182
|
.with_columns(
|
|
180
|
-
duration=
|
|
181
|
-
"titulo"
|
|
182
|
-
"data_liquidacao",
|
|
183
|
-
"
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
duration=(
|
|
184
|
+
pl.when(pl.col("titulo") == "LTN")
|
|
185
|
+
.then(ltn.duration_expr("data_liquidacao", "data_vencimento"))
|
|
186
|
+
.when(pl.col("titulo") == "NTN-F")
|
|
187
|
+
.then(
|
|
188
|
+
ntnf.duration_expr(
|
|
189
|
+
"data_liquidacao", "data_vencimento", "taxa_media"
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
.when(pl.col("titulo") == "NTN-B")
|
|
193
|
+
.then(
|
|
194
|
+
ntnb.duration_expr(
|
|
195
|
+
"data_liquidacao", "data_vencimento", "taxa_media"
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
.otherwise(0.0)
|
|
199
|
+
)
|
|
187
200
|
)
|
|
188
201
|
.with_columns(
|
|
189
202
|
dv01_total=expr_dv01_unitario * pl.col("quantidade_aceita_total"),
|
|
@@ -6,7 +6,7 @@ import polars as pl
|
|
|
6
6
|
import pyield._internal.converters as cv
|
|
7
7
|
import pyield._internal.types as tp
|
|
8
8
|
from pyield import relogio
|
|
9
|
-
from pyield._internal.types import ArrayLike, DateLike
|
|
9
|
+
from pyield._internal.types import ArrayLike, DateLike, DatesLike
|
|
10
10
|
from pyield.du.feriados.feriados_br import FeriadosBrasil
|
|
11
11
|
|
|
12
12
|
LIMITE_DIA_UTIL = 6
|
|
@@ -87,9 +87,9 @@ def contar_expr(
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
@overload
|
|
90
|
-
def contar(inicio:
|
|
90
|
+
def contar(inicio: DatesLike, fim: DatesLike | DateLike | None) -> pl.Series: ...
|
|
91
91
|
@overload
|
|
92
|
-
def contar(inicio: DateLike | None, fim:
|
|
92
|
+
def contar(inicio: DateLike | None, fim: DatesLike) -> pl.Series: ...
|
|
93
93
|
@overload
|
|
94
94
|
def contar(inicio: DateLike, fim: DateLike) -> int: ...
|
|
95
95
|
@overload
|
|
@@ -99,8 +99,8 @@ def contar(inicio: None, fim: DateLike | None) -> None: ...
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
def contar(
|
|
102
|
-
inicio: None | DateLike |
|
|
103
|
-
fim: None | DateLike |
|
|
102
|
+
inicio: None | DateLike | DatesLike,
|
|
103
|
+
fim: None | DateLike | DatesLike,
|
|
104
104
|
) -> None | int | pl.Series:
|
|
105
105
|
"""Conta dias úteis entre ``inicio`` (inclusivo) e ``fim`` (exclusivo).
|
|
106
106
|
|
|
@@ -286,7 +286,7 @@ def deslocar_expr(
|
|
|
286
286
|
|
|
287
287
|
@overload
|
|
288
288
|
def deslocar(
|
|
289
|
-
datas:
|
|
289
|
+
datas: DatesLike,
|
|
290
290
|
deslocamento: ArrayLike | int | None,
|
|
291
291
|
rolagem: Literal["forward", "backward"] = ...,
|
|
292
292
|
) -> pl.Series: ...
|
|
@@ -317,7 +317,7 @@ def deslocar(
|
|
|
317
317
|
|
|
318
318
|
|
|
319
319
|
def deslocar(
|
|
320
|
-
datas: DateLike |
|
|
320
|
+
datas: DateLike | DatesLike | None,
|
|
321
321
|
deslocamento: int | ArrayLike | None,
|
|
322
322
|
rolagem: Literal["forward", "backward"] = "forward",
|
|
323
323
|
) -> dt.date | pl.Series | None:
|
|
@@ -604,10 +604,10 @@ def eh_dia_util(datas: None) -> None: ...
|
|
|
604
604
|
@overload
|
|
605
605
|
def eh_dia_util(datas: DateLike) -> bool: ...
|
|
606
606
|
@overload
|
|
607
|
-
def eh_dia_util(datas:
|
|
607
|
+
def eh_dia_util(datas: DatesLike) -> pl.Series: ...
|
|
608
608
|
|
|
609
609
|
|
|
610
|
-
def eh_dia_util(datas: None | DateLike |
|
|
610
|
+
def eh_dia_util(datas: None | DateLike | DatesLike) -> None | bool | pl.Series:
|
|
611
611
|
"""Determina se data(s) são dias úteis brasileiros.
|
|
612
612
|
|
|
613
613
|
REGIME DE FERIADOS POR LINHA: Para CADA data de entrada, a lista de feriados
|
|
@@ -12,10 +12,10 @@ import polars as pl
|
|
|
12
12
|
import pyield._internal.converters as cv
|
|
13
13
|
from pyield import du
|
|
14
14
|
from pyield._internal.data_cache import obter_dataset_cacheado
|
|
15
|
-
from pyield._internal.types import
|
|
15
|
+
from pyield._internal.types import DateLike, DatesLike, any_is_array_like, any_is_empty
|
|
16
16
|
from pyield.futuro.historico import buscar_historico_cacheado
|
|
17
17
|
from pyield.futuro.historico import datas_disponiveis as _datas_futuro
|
|
18
|
-
from pyield.interpolador import
|
|
18
|
+
from pyield.interpolador import interpolar
|
|
19
19
|
|
|
20
20
|
TipoTaxaDI1 = Literal["ajuste", "fechamento"]
|
|
21
21
|
|
|
@@ -26,7 +26,7 @@ _COLUNAS_TIPO_TAXA: dict[TipoTaxaDI1, str] = {
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def dados(
|
|
29
|
-
datas: DateLike |
|
|
29
|
+
datas: DateLike | DatesLike,
|
|
30
30
|
inicio_mes: bool = False,
|
|
31
31
|
filtrar_pre: bool = False,
|
|
32
32
|
) -> pl.DataFrame:
|
|
@@ -117,8 +117,8 @@ def dados(
|
|
|
117
117
|
|
|
118
118
|
|
|
119
119
|
def interpolar_taxas(
|
|
120
|
-
datas_referencia: DateLike |
|
|
121
|
-
datas_vencimento: DateLike |
|
|
120
|
+
datas_referencia: DateLike | DatesLike,
|
|
121
|
+
datas_vencimento: DateLike | DatesLike,
|
|
122
122
|
extrapolar: bool = True,
|
|
123
123
|
tipo_taxa: TipoTaxaDI1 = "ajuste",
|
|
124
124
|
) -> pl.Series:
|
|
@@ -223,69 +223,24 @@ def interpolar_taxas(
|
|
|
223
223
|
if df_entrada.is_empty():
|
|
224
224
|
return pl.Series(dtype=pl.Float64)
|
|
225
225
|
|
|
226
|
-
# Carrega
|
|
226
|
+
# Carrega curva de DI para todas as datas únicas do alvo.
|
|
227
227
|
datas_unicas = df_entrada["data_referencia"].drop_nulls().unique().sort().to_list()
|
|
228
228
|
df_ref = buscar_historico_cacheado(datas_unicas, "DI1")
|
|
229
|
-
# Retorna Series vazia se nenhuma taxa for encontrada
|
|
230
229
|
if df_ref.is_empty():
|
|
231
230
|
return pl.Series(dtype=pl.Float64)
|
|
232
231
|
|
|
233
|
-
# 1. CRIA O ÍNDICE ORIGINAL AQUI
|
|
234
|
-
# Isso garante que saberemos a ordem exata depois
|
|
235
|
-
df_entrada = df_entrada.with_row_index("_temp_idx")
|
|
236
|
-
|
|
237
|
-
# Inicializa taxa_interpolada como None
|
|
238
232
|
df_entrada = df_entrada.with_columns(
|
|
239
233
|
dias_uteis=du.contar_expr("data_referencia", "data_vencimento"),
|
|
240
|
-
taxa_interpolada=pl.lit(None, dtype=pl.Float64),
|
|
241
234
|
)
|
|
242
235
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
# 2. Busca as taxas de referência para esta data
|
|
252
|
-
df_referencia = df_ref.filter(pl.col("data_referencia") == data_ref)
|
|
253
|
-
|
|
254
|
-
# Se não houver dados de curva, adicionamos o bloco como está (com nulos)
|
|
255
|
-
# e continuamos.
|
|
256
|
-
if df_referencia.is_empty():
|
|
257
|
-
blocos_processados.append(df_parcial)
|
|
258
|
-
continue
|
|
259
|
-
|
|
260
|
-
df_curva = df_referencia.select("dias_uteis", coluna_taxa).drop_nulls()
|
|
261
|
-
if df_curva.is_empty():
|
|
262
|
-
blocos_processados.append(df_parcial)
|
|
263
|
-
continue
|
|
264
|
-
|
|
265
|
-
# Inicializa o interpolador com taxas e dias úteis conhecidos
|
|
266
|
-
interpolador_du = Interpolador(
|
|
267
|
-
dias_uteis=df_curva["dias_uteis"],
|
|
268
|
-
taxas=df_curva[coluna_taxa],
|
|
269
|
-
metodo="flat_forward",
|
|
270
|
-
extrapolar=extrapolar,
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
df_parcial = df_parcial.with_columns(
|
|
274
|
-
pl.col("dias_uteis")
|
|
275
|
-
.map_elements(interpolador_du, return_dtype=pl.Float64)
|
|
276
|
-
.alias("taxa_interpolada")
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
blocos_processados.append(df_parcial)
|
|
280
|
-
|
|
281
|
-
if not blocos_processados:
|
|
282
|
-
return pl.Series(dtype=pl.Float64)
|
|
283
|
-
|
|
284
|
-
# 2. CONCATENA E ORDENA DE VOLTA
|
|
285
|
-
# O sort("_temp_idx") restaura a ordem original dos inputs
|
|
286
|
-
df_saida = pl.concat(blocos_processados).sort("_temp_idx")
|
|
287
|
-
|
|
288
|
-
return df_saida["taxa_interpolada"].fill_nan(None)
|
|
236
|
+
return interpolar(
|
|
237
|
+
dus_alvo=df_entrada["dias_uteis"],
|
|
238
|
+
dus_curva=df_ref["dias_uteis"],
|
|
239
|
+
taxas_curva=df_ref[coluna_taxa],
|
|
240
|
+
datas_alvo=df_entrada["data_referencia"],
|
|
241
|
+
datas_curva=df_ref["data_referencia"],
|
|
242
|
+
extrapolar=extrapolar,
|
|
243
|
+
)
|
|
289
244
|
|
|
290
245
|
|
|
291
246
|
def interpolar_taxa(
|