pyield 0.55.0__tar.gz → 0.55.2__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.
Files changed (82) hide show
  1. {pyield-0.55.0 → pyield-0.55.2}/PKG-INFO +12 -128
  2. {pyield-0.55.0 → pyield-0.55.2}/README.md +11 -127
  3. {pyield-0.55.0 → pyield-0.55.2}/pyield/selic/copom.py +5 -5
  4. {pyield-0.55.0 → pyield-0.55.2}/pyield/selic/cpm.py +2 -2
  5. {pyield-0.55.0 → pyield-0.55.2}/pyield/selic/probabilities.py +11 -7
  6. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/_zero_td.py +12 -1
  7. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/lft.py +8 -0
  8. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/ltn.py +12 -3
  9. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/ntnb.py +10 -1
  10. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/ntnbp.py +13 -3
  11. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/ntnf.py +54 -0
  12. pyield-0.55.2/pyield/tpf/vna/__init__.py +5 -0
  13. pyield-0.55.0/pyield/tpf/vna/_utils.py → pyield-0.55.2/pyield/tpf/vna/calculo.py +27 -2
  14. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/vna/ntnb.py +6 -5
  15. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/vna/ntnc.py +6 -5
  16. {pyield-0.55.0 → pyield-0.55.2}/pyproject.toml +1 -1
  17. {pyield-0.55.0 → pyield-0.55.2}/pyproject.toml.orig +1 -1
  18. pyield-0.55.0/pyield/tpf/vna/__init__.py +0 -1
  19. {pyield-0.55.0 → pyield-0.55.2}/LICENSE +0 -0
  20. {pyield-0.55.0 → pyield-0.55.2}/pyield/__init__.py +0 -0
  21. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/__init__.py +0 -0
  22. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/br_numbers.py +0 -0
  23. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/cache.py +0 -0
  24. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/converters.py +0 -0
  25. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/data_cache.py +0 -0
  26. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/excel.py +0 -0
  27. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/numbers.py +0 -0
  28. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/retry.py +0 -0
  29. {pyield-0.55.0 → pyield-0.55.2}/pyield/_internal/types.py +0 -0
  30. {pyield-0.55.0 → pyield-0.55.2}/pyield/anbima/__init__.py +0 -0
  31. {pyield-0.55.0 → pyield-0.55.2}/pyield/anbima/imaq.py +0 -0
  32. {pyield-0.55.0 → pyield-0.55.2}/pyield/anbima/taxas.py +0 -0
  33. {pyield-0.55.0 → pyield-0.55.2}/pyield/b3/__init__.py +0 -0
  34. {pyield-0.55.0 → pyield-0.55.2}/pyield/b3/_contratos.py +0 -0
  35. {pyield-0.55.0 → pyield-0.55.2}/pyield/b3/_validar_pregao.py +0 -0
  36. {pyield-0.55.0 → pyield-0.55.2}/pyield/b3/boletim.py +0 -0
  37. {pyield-0.55.0 → pyield-0.55.2}/pyield/b3/derivativos_intradia.py +0 -0
  38. {pyield-0.55.0 → pyield-0.55.2}/pyield/b3/di_over.py +0 -0
  39. {pyield-0.55.0 → pyield-0.55.2}/pyield/bc/__init__.py +0 -0
  40. {pyield-0.55.0 → pyield-0.55.2}/pyield/bc/_olinda.py +0 -0
  41. {pyield-0.55.0 → pyield-0.55.2}/pyield/bc/leiloes.py +0 -0
  42. {pyield-0.55.0 → pyield-0.55.2}/pyield/bc/lft.py +0 -0
  43. {pyield-0.55.0 → pyield-0.55.2}/pyield/bc/sgs.py +0 -0
  44. {pyield-0.55.0 → pyield-0.55.2}/pyield/du/__init__.py +0 -0
  45. {pyield-0.55.0 → pyield-0.55.2}/pyield/du/core.py +0 -0
  46. {pyield-0.55.0 → pyield-0.55.2}/pyield/du/feriados/__init__.py +0 -0
  47. {pyield-0.55.0 → pyield-0.55.2}/pyield/du/feriados/feriados_antigos_br.txt +0 -0
  48. {pyield-0.55.0 → pyield-0.55.2}/pyield/du/feriados/feriados_br.py +0 -0
  49. {pyield-0.55.0 → pyield-0.55.2}/pyield/du/feriados/feriados_novos_br.txt +0 -0
  50. {pyield-0.55.0 → pyield-0.55.2}/pyield/futuro/__init__.py +0 -0
  51. {pyield-0.55.0 → pyield-0.55.2}/pyield/futuro/contratos.py +0 -0
  52. {pyield-0.55.0 → pyield-0.55.2}/pyield/futuro/di1.py +0 -0
  53. {pyield-0.55.0 → pyield-0.55.2}/pyield/futuro/historico.py +0 -0
  54. {pyield-0.55.0 → pyield-0.55.2}/pyield/futuro/intradia.py +0 -0
  55. {pyield-0.55.0 → pyield-0.55.2}/pyield/fwd.py +0 -0
  56. {pyield-0.55.0 → pyield-0.55.2}/pyield/interpolador.py +0 -0
  57. {pyield-0.55.0 → pyield-0.55.2}/pyield/ipca/__init__.py +0 -0
  58. {pyield-0.55.0 → pyield-0.55.2}/pyield/ipca/historico.py +0 -0
  59. {pyield-0.55.0 → pyield-0.55.2}/pyield/ipca/projetado.py +0 -0
  60. {pyield-0.55.0 → pyield-0.55.2}/pyield/py.typed +0 -0
  61. {pyield-0.55.0 → pyield-0.55.2}/pyield/relogio.py +0 -0
  62. {pyield-0.55.0 → pyield-0.55.2}/pyield/selic/__init__.py +0 -0
  63. {pyield-0.55.0 → pyield-0.55.2}/pyield/selic/compromissada.py +0 -0
  64. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/__init__.py +0 -0
  65. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/_taxas.py +0 -0
  66. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/benchmark.py +0 -0
  67. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/dealers.py +0 -0
  68. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/leiloes.py +0 -0
  69. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/rmd/__init__.py +0 -0
  70. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/rmd/_aba_1_3.py +0 -0
  71. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/rmd/_aba_2_1.py +0 -0
  72. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/rmd/_common.py +0 -0
  73. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/rmd/_download.py +0 -0
  74. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/secundario/__init__.py +0 -0
  75. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/secundario/_intradia.py +0 -0
  76. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/secundario/_mensal.py +0 -0
  77. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/__init__.py +0 -0
  78. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/_utils.py +0 -0
  79. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/ntnb1.py +0 -0
  80. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/ntnc.py +0 -0
  81. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/titulos/pre.py +0 -0
  82. {pyield-0.55.0 → pyield-0.55.2}/pyield/tpf/vna/_download.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyield
3
- Version: 0.55.0
3
+ Version: 0.55.2
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
@@ -306,136 +306,20 @@ yd.ptax("25-12-2025") # -> nan
306
306
 
307
307
  Documentação completa: [crdcj.github.io/PYield](https://crdcj.github.io/PYield/)
308
308
 
309
- ## Quebras de API
310
-
311
- Quebras acumuladas por versão desde a v0.52.0.
312
-
313
- ### v0.55.0
314
-
315
- - `yd.lft.vna(...)`, `yd.lft.cotacao(...)`, `yd.lft.pu(...)`, `yd.ltn.pu(...)`,
316
- `yd.ntnb.vna(...)`, `yd.ntnb.vna_projetado(...)`, `yd.ntnb.cotacao(...)`,
317
- `yd.ntnb.pu(...)`, `yd.ntnbp.cotacao(...)`, `yd.ntnbp.pu(...)`,
318
- `yd.ntnb1.cotacao(...)`, `yd.ntnb1.pu(...)`, `yd.ntnc.vna(...)`,
319
- `yd.ntnc.vna_projetado(...)`, `yd.ntnc.cotacao(...)`, `yd.ntnc.pu(...)` e
320
- `yd.ntnf.pu(...)` retornam `Decimal`, preservando exatamente os valores com
321
- seis casas definidos pela fonte ou pela metodologia. Entradas numéricas
322
- aceitam `float` ou `Decimal`.
323
-
324
- ### v0.54.5
325
-
326
- - `yd.ntnf.fluxos_caixa(...)` não aceita mais `ajustar_datas_pagamento`. Os
327
- cronogramas públicos de NTN-B, NTN-B1, NTN-C e NTN-F usam datas contratuais,
328
- sem ajuste para dias úteis. Para obter datas efetivas de processamento, use
329
- `yd.du.deslocar(..., 0)`.
330
-
331
- ### v0.54.2
332
-
333
- - `yd.tpf.taxas_historicas(...)` foi adicionado para consultas por período ou
334
- de todo o histórico disponível de taxas indicativas.
335
- - `yd.tpf.taxas(..., completo=True)` foi removido. `yd.tpf.taxas(...)` mantém
336
- a visão estável de TPF; para acessar todas as colunas processadas da fonte,
337
- use `pyield.anbima.taxas.buscar(data)` ou `pyield.anbima.taxas.ler(fonte)`.
338
-
339
- ### v0.54.0
340
-
341
- - LFT, NTN-B, NTN-C e NTN-B1 passaram a expor **cotação e valores de fluxo em
342
- base 1** (fator decimal), em vez de base 100 (escala percentual da ANBIMA).
343
- A precisão numérica é preservada: o truncamento de 4 casas na escala ANBIMA
344
- equivale a 6 casas em base 1.
345
-
346
- ```python
347
- # Antes
348
- yd.ntnb.cotacao("31-05-2024", "15-05-2035", 0.061490) # -> 99.3651
349
- yd.lft.pu(15785.324502, 99.9291) # -> 15774.132706
350
-
351
- # Agora
352
- yd.ntnb.cotacao("31-05-2024", "15-05-2035", 0.061490) # -> Decimal('0.993651')
353
- yd.lft.pu(15785.324502, 0.999291) # -> Decimal('15774.132706')
354
- ```
355
-
356
- Também afeta `fluxos_caixa(...)` de NTN-B e NTN-C: o cupom semestral passou
357
- de `2,956301` para `0,02956301` (NTN-C 6% a.a.) e o pagamento final passou
358
- de `102,956301` para `1,02956301`. Chamadas a `pu(vna, cotacao)` que
359
- dividiam por 100 (`cotacao / 100`) devem passar diretamente o fator em
360
- base 1. O PU final permanece na mesma escala financeira.
361
- - `yd.ntnbprinc` (e `yd.tpf.ntnbprinc`) foi renomeado para `yd.ntnbp` (e
362
- `yd.tpf.ntnbp`), alinhando o namespace público aos nomes curtos usados no
363
- restante da biblioteca (`ntnb`, `ntnb1`, `ntnbp`, `ntnc`, `ntnf`).
364
- - `yd.tpf.premio_pre` foi renomeado para `yd.tpf.premios_pre`, coerente com o
365
- retorno tabular (`DataFrame` com múltiplos prêmios).
366
- - Entradas escalares de data inválidas agora **levantam `ValueError`** em
367
- qualquer função pública que aceite `DateLike`. Antes, chamadas como
368
- `yd.du.deslocar("31-02-2024", 1)` retornavam `None` silenciosamente. Em
369
- operações vetorizadas o parse continua tolerante: elementos inválidos viram
370
- `null` para preservar o pipeline Polars. Strings vazias ou só com espaços
371
- continuam sendo tratadas como nulas.
372
-
373
- ### v0.53.0
374
-
375
- - As funções secundárias de TPF migraram do `yd.tpf` para o namespace dedicado
376
- `yd.tpf.secundario`:
377
-
378
- - `yd.tpf.secundario_intradia(...)` → `yd.tpf.secundario.intradia(...)`
379
- - `yd.tpf.secundario_mensal(...)` → `yd.tpf.secundario.mensal(...)`
380
-
381
- ### v0.52.0
382
-
383
- - `Interpolador(...)` e `Interpolador.interpolar(...)` agora aceitam **apenas
384
- inteiro escalar**. Chamadas com lista/`pl.Series` (`interp([30, 60])`),
385
- antes suportadas via sobrecarga vetorial, agora levantam `TypeError`.
386
- Substitua por `Interpolador.interpolar_expr` em pipelines Polars ou pela
387
- função top-level `yd.interpolar(...)` (curva única ou multi-curva).
388
- - `yd.interpolar(...)` passou a usar `extrapolar=False` como padrão, alinhado
389
- com `Interpolador`. Antes era `True`. Chamadas que dependiam da
390
- extrapolação implícita na ponta longa precisam passar `extrapolar=True`
391
- explicitamente.
392
- - As funções `dv01(...)` dos títulos públicos agora recebem `pu` como argumento
393
- explícito. Chamadas antigas que passavam apenas data, vencimento e taxa, ou
394
- que passavam VNA no caso da NTN-B, precisam ser atualizadas.
395
- - `ntnf.taxas_zero(...)` mudou os nomes dos parâmetros de curva para o padrão
396
- `vencimentos_*` / `taxas_*`. Chamadas por posição continuam com a mesma
397
- ordem; chamadas por keyword precisam usar os novos nomes.
398
-
399
- #### `Interpolador(...)` não aceita mais lista/Series
400
-
401
- O ``__call__`` e o método ``interpolar`` da classe agora são estritamente
402
- escalares. O caminho vetorial foi dividido em duas APIs com semântica clara:
309
+ ## Compatibilidade e mudanças da API
403
310
 
404
- ```python
405
- # Antes (v0.51.x)
406
- interp = yd.Interpolador(dus, taxas, metodo="flat_forward")
407
- interp([15, 45, 75]) # pl.Series
408
-
409
- # Agora, dentro de um pipeline Polars
410
- df.with_columns(taxa=interp.interpolar_expr("du"))
411
-
412
- # Agora, ad-hoc (curva única ou multi-curva)
413
- yd.interpolar(
414
- dus_alvo=pl.Series([15, 45, 75]),
415
- dus_curva=pl.Series(dus),
416
- taxas_curva=pl.Series(taxas),
417
- )
418
- ```
419
-
420
- #### `dv01(...)` agora recebe PU
421
-
422
- As funções `dv01(...)` dos títulos públicos recebem o PU usado como base para o
423
- cálculo, não mais o VNA ou apenas a taxa. Se necessário, calcule o PU antes:
424
-
425
- ```python
426
- pu = yd.ntnb.pu(vna, yd.ntnb.cotacao(data, vencimento, taxa))
427
- dv01 = yd.ntnb.dv01(data, vencimento, taxa, pu)
428
- ```
429
-
430
- #### `ntnf.taxas_zero(...)` usa nomes por conceito
311
+ A versão atual é `v0.55.0`. As mudanças abaixo exigem atualização de código:
431
312
 
432
- Os parâmetros de curva da NTN-F foram renomeados para manter o padrão
433
- `vencimentos_*` / `taxas_*`:
313
+ | Versão | Mudança principal |
314
+ |---|---|
315
+ | `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
+ | `v0.54.5` | `fluxos_caixa` não aceita mais `ajustar_datas_pagamento`; os cronogramas usam datas contratuais. |
317
+ | `v0.54.2` | `taxas_historicas` foi adicionada e `tpf.taxas(completo=True)` foi removida. |
318
+ | `v0.54.0` | Cotações e fluxos de LFT, NTN-B, NTN-C e NTN-B1 passaram de base 100 para base 1; `ntnbprinc` virou `ntnbp`; `premio_pre` virou `premios_pre`; datas escalares inválidas passaram a levantar `ValueError`. |
319
+ | `v0.53.0` | O mercado secundário de TPF passou para `yd.tpf.secundario.intradia` e `yd.tpf.secundario.mensal`. |
320
+ | `v0.52.0` | `Interpolador` passou a ser escalar; use `interpolar_expr` ou `yd.interpolar` para vetores. `dv01` passou a exigir `pu` e `ntnf.taxas_zero` adotou nomes `vencimentos_*` / `taxas_*`. |
434
321
 
435
- - `ltn_vencimentos` → `vencimentos_ltn`
436
- - `ltn_taxas` → `taxas_ltn`
437
- - `ntnf_vencimentos` → `vencimentos_ntnf`
438
- - `ntnf_taxas` → `taxas_ntnf`
322
+ O histórico completo está disponível nas [releases do GitHub](https://github.com/crdcj/PYield/releases).
439
323
 
440
324
  ## Testes
441
325
 
@@ -281,136 +281,20 @@ yd.ptax("25-12-2025") # -> nan
281
281
 
282
282
  Documentação completa: [crdcj.github.io/PYield](https://crdcj.github.io/PYield/)
283
283
 
284
- ## Quebras de API
285
-
286
- Quebras acumuladas por versão desde a v0.52.0.
287
-
288
- ### v0.55.0
289
-
290
- - `yd.lft.vna(...)`, `yd.lft.cotacao(...)`, `yd.lft.pu(...)`, `yd.ltn.pu(...)`,
291
- `yd.ntnb.vna(...)`, `yd.ntnb.vna_projetado(...)`, `yd.ntnb.cotacao(...)`,
292
- `yd.ntnb.pu(...)`, `yd.ntnbp.cotacao(...)`, `yd.ntnbp.pu(...)`,
293
- `yd.ntnb1.cotacao(...)`, `yd.ntnb1.pu(...)`, `yd.ntnc.vna(...)`,
294
- `yd.ntnc.vna_projetado(...)`, `yd.ntnc.cotacao(...)`, `yd.ntnc.pu(...)` e
295
- `yd.ntnf.pu(...)` retornam `Decimal`, preservando exatamente os valores com
296
- seis casas definidos pela fonte ou pela metodologia. Entradas numéricas
297
- aceitam `float` ou `Decimal`.
298
-
299
- ### v0.54.5
300
-
301
- - `yd.ntnf.fluxos_caixa(...)` não aceita mais `ajustar_datas_pagamento`. Os
302
- cronogramas públicos de NTN-B, NTN-B1, NTN-C e NTN-F usam datas contratuais,
303
- sem ajuste para dias úteis. Para obter datas efetivas de processamento, use
304
- `yd.du.deslocar(..., 0)`.
305
-
306
- ### v0.54.2
307
-
308
- - `yd.tpf.taxas_historicas(...)` foi adicionado para consultas por período ou
309
- de todo o histórico disponível de taxas indicativas.
310
- - `yd.tpf.taxas(..., completo=True)` foi removido. `yd.tpf.taxas(...)` mantém
311
- a visão estável de TPF; para acessar todas as colunas processadas da fonte,
312
- use `pyield.anbima.taxas.buscar(data)` ou `pyield.anbima.taxas.ler(fonte)`.
313
-
314
- ### v0.54.0
315
-
316
- - LFT, NTN-B, NTN-C e NTN-B1 passaram a expor **cotação e valores de fluxo em
317
- base 1** (fator decimal), em vez de base 100 (escala percentual da ANBIMA).
318
- A precisão numérica é preservada: o truncamento de 4 casas na escala ANBIMA
319
- equivale a 6 casas em base 1.
320
-
321
- ```python
322
- # Antes
323
- yd.ntnb.cotacao("31-05-2024", "15-05-2035", 0.061490) # -> 99.3651
324
- yd.lft.pu(15785.324502, 99.9291) # -> 15774.132706
325
-
326
- # Agora
327
- yd.ntnb.cotacao("31-05-2024", "15-05-2035", 0.061490) # -> Decimal('0.993651')
328
- yd.lft.pu(15785.324502, 0.999291) # -> Decimal('15774.132706')
329
- ```
330
-
331
- Também afeta `fluxos_caixa(...)` de NTN-B e NTN-C: o cupom semestral passou
332
- de `2,956301` para `0,02956301` (NTN-C 6% a.a.) e o pagamento final passou
333
- de `102,956301` para `1,02956301`. Chamadas a `pu(vna, cotacao)` que
334
- dividiam por 100 (`cotacao / 100`) devem passar diretamente o fator em
335
- base 1. O PU final permanece na mesma escala financeira.
336
- - `yd.ntnbprinc` (e `yd.tpf.ntnbprinc`) foi renomeado para `yd.ntnbp` (e
337
- `yd.tpf.ntnbp`), alinhando o namespace público aos nomes curtos usados no
338
- restante da biblioteca (`ntnb`, `ntnb1`, `ntnbp`, `ntnc`, `ntnf`).
339
- - `yd.tpf.premio_pre` foi renomeado para `yd.tpf.premios_pre`, coerente com o
340
- retorno tabular (`DataFrame` com múltiplos prêmios).
341
- - Entradas escalares de data inválidas agora **levantam `ValueError`** em
342
- qualquer função pública que aceite `DateLike`. Antes, chamadas como
343
- `yd.du.deslocar("31-02-2024", 1)` retornavam `None` silenciosamente. Em
344
- operações vetorizadas o parse continua tolerante: elementos inválidos viram
345
- `null` para preservar o pipeline Polars. Strings vazias ou só com espaços
346
- continuam sendo tratadas como nulas.
347
-
348
- ### v0.53.0
349
-
350
- - As funções secundárias de TPF migraram do `yd.tpf` para o namespace dedicado
351
- `yd.tpf.secundario`:
352
-
353
- - `yd.tpf.secundario_intradia(...)` → `yd.tpf.secundario.intradia(...)`
354
- - `yd.tpf.secundario_mensal(...)` → `yd.tpf.secundario.mensal(...)`
355
-
356
- ### v0.52.0
357
-
358
- - `Interpolador(...)` e `Interpolador.interpolar(...)` agora aceitam **apenas
359
- inteiro escalar**. Chamadas com lista/`pl.Series` (`interp([30, 60])`),
360
- antes suportadas via sobrecarga vetorial, agora levantam `TypeError`.
361
- Substitua por `Interpolador.interpolar_expr` em pipelines Polars ou pela
362
- função top-level `yd.interpolar(...)` (curva única ou multi-curva).
363
- - `yd.interpolar(...)` passou a usar `extrapolar=False` como padrão, alinhado
364
- com `Interpolador`. Antes era `True`. Chamadas que dependiam da
365
- extrapolação implícita na ponta longa precisam passar `extrapolar=True`
366
- explicitamente.
367
- - As funções `dv01(...)` dos títulos públicos agora recebem `pu` como argumento
368
- explícito. Chamadas antigas que passavam apenas data, vencimento e taxa, ou
369
- que passavam VNA no caso da NTN-B, precisam ser atualizadas.
370
- - `ntnf.taxas_zero(...)` mudou os nomes dos parâmetros de curva para o padrão
371
- `vencimentos_*` / `taxas_*`. Chamadas por posição continuam com a mesma
372
- ordem; chamadas por keyword precisam usar os novos nomes.
373
-
374
- #### `Interpolador(...)` não aceita mais lista/Series
375
-
376
- O ``__call__`` e o método ``interpolar`` da classe agora são estritamente
377
- escalares. O caminho vetorial foi dividido em duas APIs com semântica clara:
284
+ ## Compatibilidade e mudanças da API
378
285
 
379
- ```python
380
- # Antes (v0.51.x)
381
- interp = yd.Interpolador(dus, taxas, metodo="flat_forward")
382
- interp([15, 45, 75]) # pl.Series
383
-
384
- # Agora, dentro de um pipeline Polars
385
- df.with_columns(taxa=interp.interpolar_expr("du"))
386
-
387
- # Agora, ad-hoc (curva única ou multi-curva)
388
- yd.interpolar(
389
- dus_alvo=pl.Series([15, 45, 75]),
390
- dus_curva=pl.Series(dus),
391
- taxas_curva=pl.Series(taxas),
392
- )
393
- ```
394
-
395
- #### `dv01(...)` agora recebe PU
396
-
397
- As funções `dv01(...)` dos títulos públicos recebem o PU usado como base para o
398
- cálculo, não mais o VNA ou apenas a taxa. Se necessário, calcule o PU antes:
399
-
400
- ```python
401
- pu = yd.ntnb.pu(vna, yd.ntnb.cotacao(data, vencimento, taxa))
402
- dv01 = yd.ntnb.dv01(data, vencimento, taxa, pu)
403
- ```
404
-
405
- #### `ntnf.taxas_zero(...)` usa nomes por conceito
286
+ A versão atual é `v0.55.0`. As mudanças abaixo exigem atualização de código:
406
287
 
407
- Os parâmetros de curva da NTN-F foram renomeados para manter o padrão
408
- `vencimentos_*` / `taxas_*`:
288
+ | Versão | Mudança principal |
289
+ |---|---|
290
+ | `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
+ | `v0.54.5` | `fluxos_caixa` não aceita mais `ajustar_datas_pagamento`; os cronogramas usam datas contratuais. |
292
+ | `v0.54.2` | `taxas_historicas` foi adicionada e `tpf.taxas(completo=True)` foi removida. |
293
+ | `v0.54.0` | Cotações e fluxos de LFT, NTN-B, NTN-C e NTN-B1 passaram de base 100 para base 1; `ntnbprinc` virou `ntnbp`; `premio_pre` virou `premios_pre`; datas escalares inválidas passaram a levantar `ValueError`. |
294
+ | `v0.53.0` | O mercado secundário de TPF passou para `yd.tpf.secundario.intradia` e `yd.tpf.secundario.mensal`. |
295
+ | `v0.52.0` | `Interpolador` passou a ser escalar; use `interpolar_expr` ou `yd.interpolar` para vetores. `dv01` passou a exigir `pu` e `ntnf.taxas_zero` adotou nomes `vencimentos_*` / `taxas_*`. |
409
296
 
410
- - `ltn_vencimentos` → `vencimentos_ltn`
411
- - `ltn_taxas` → `taxas_ltn`
412
- - `ntnf_vencimentos` → `vencimentos_ntnf`
413
- - `ntnf_taxas` → `taxas_ntnf`
297
+ O histórico completo está disponível nas [releases do GitHub](https://github.com/crdcj/PYield/releases).
414
298
 
415
299
  ## Testes
416
300
 
@@ -151,10 +151,10 @@ def calendar(
151
151
 
152
152
  Examples:
153
153
  >>> import pyield as yd
154
- >>> cal = yd.selic.copom.calendar()
155
- >>> "ExpiryDate" in cal.columns
154
+ >>> cal = yd.selic.copom.calendar() # doctest: +SKIP
155
+ >>> "ExpiryDate" in cal.columns # doctest: +SKIP
156
156
  True
157
- >>> cal["EndDate"].is_sorted()
157
+ >>> cal["EndDate"].is_sorted() # doctest: +SKIP
158
158
  True
159
159
  """
160
160
  past = _fetch_past_meetings()
@@ -192,8 +192,8 @@ def next_meeting(reference: DateLike | None = None) -> pl.DataFrame:
192
192
 
193
193
  Examples:
194
194
  >>> import pyield as yd
195
- >>> row = yd.selic.copom.next_meeting()
196
- >>> len(row)
195
+ >>> row = yd.selic.copom.next_meeting() # doctest: +SKIP
196
+ >>> len(row) # doctest: +SKIP
197
197
  1
198
198
  """
199
199
  ref = relogio.hoje() if reference is None else converter_datas(reference)
@@ -254,8 +254,8 @@ def data(date: DateLike) -> pl.DataFrame:
254
254
 
255
255
  Examples:
256
256
  >>> import pyield as yd
257
- >>> df = yd.selic.cpm.data("29-01-2025")
258
- >>> df.is_empty() or set(df.schema.keys()) >= {
257
+ >>> df = yd.selic.cpm.data("29-01-2025") # doctest: +SKIP
258
+ >>> df.is_empty() or set(df.schema.keys()) >= { # doctest: +SKIP
259
259
  ... "data_referencia",
260
260
  ... "codigo_negociacao",
261
261
  ... "data_fim_reuniao",
@@ -253,11 +253,13 @@ def all_meetings(
253
253
  Examples:
254
254
  >>> import pyield as yd
255
255
  >>> import polars as pl
256
- >>> df = yd.selic.probabilities.all_meetings("29-01-2025")
257
- >>> df.is_empty() or df["ranking_reuniao"].min() == 1
256
+ >>> df = yd.selic.probabilities.all_meetings("29-01-2025") # doctest: +SKIP
257
+ >>> df.is_empty() or df["ranking_reuniao"].min() == 1 # doctest: +SKIP
258
258
  True
259
- >>> sums = df.group_by("data_expiracao").agg(pl.col("prob").sum())
260
- >>> df.is_empty() or (sums["prob"] - 1.0).abs().max() < 1e-9
259
+ >>> sums = df.group_by("data_expiracao").agg(
260
+ ... pl.col("prob").sum()
261
+ ... ) # doctest: +SKIP
262
+ >>> df.is_empty() or (sums["prob"] - 1.0).abs().max() < 1e-9 # doctest: +SKIP
261
263
  True
262
264
  """
263
265
  raw = cpm.data(date)
@@ -318,10 +320,12 @@ def meeting(
318
320
 
319
321
  Examples:
320
322
  >>> import pyield as yd
321
- >>> df = yd.selic.probabilities.meeting("29-01-2025")
322
- >>> df.is_empty() or abs(df["prob"].sum() - 1.0) < 1e-9
323
+ >>> df = yd.selic.probabilities.meeting("29-01-2025") # doctest: +SKIP
324
+ >>> df.is_empty() or abs(df["prob"].sum() - 1.0) < 1e-9 # doctest: +SKIP
323
325
  True
324
- >>> df.is_empty() or df["prob_acumulada"].tail(1).item() == 1.0
326
+ >>> df.is_empty() or df["prob_acumulada"].tail(
327
+ ... 1
328
+ ... ).item() == 1.0 # doctest: +SKIP
325
329
  True
326
330
  """
327
331
  df = all_meetings(date, option_type=option_type)
@@ -210,7 +210,8 @@ def taxas_zero(
210
210
  Padrão False, retornando apenas os vencimentos informados.
211
211
 
212
212
  Returns:
213
- pl.DataFrame: Curva zero calibrada pelo método TD.
213
+ pl.DataFrame: Curva zero calibrada pelo método TD. Retorna vazio quando
214
+ não restarem vencimentos posteriores à liquidação.
214
215
 
215
216
  Output Columns:
216
217
  - data_vencimento (Date): Data do vértice da curva.
@@ -228,6 +229,16 @@ def taxas_zero(
228
229
  liquidacao, vencimentos, taxas = _validar_entradas_taxas_zero(
229
230
  data_liquidacao, vencimentos, taxas
230
231
  )
232
+ if vencimentos.is_empty():
233
+ return pl.DataFrame(
234
+ schema={
235
+ "data_vencimento": pl.Date,
236
+ "dias_uteis": pl.Int64,
237
+ "taxa_zero": pl.Float64,
238
+ "taxa_forward": pl.Float64,
239
+ }
240
+ )
241
+
231
242
  titulos = pl.DataFrame({"data_vencimento": vencimentos, "taxa_tir": taxas}).sort(
232
243
  "data_vencimento"
233
244
  )
@@ -122,6 +122,8 @@ def cotacao(
122
122
 
123
123
  Returns:
124
124
  Decimal: Fator de cotação em base 1, truncado em 6 casas decimais.
125
+ Retorna ``Decimal("NaN")`` quando o prazo até o vencimento não é
126
+ positivo.
125
127
 
126
128
  Notes:
127
129
  A STN apresenta a cotação na escala percentual (base 100). Esta
@@ -152,6 +154,8 @@ def cotacao(
152
154
  taxa = utils.normalizar_taxa_precificacao(taxa)
153
155
  # Número de dias úteis entre liquidação (inclusivo) e vencimento (exclusivo)
154
156
  dias_uteis = du.contar(data_liquidacao, data_vencimento)
157
+ if dias_uteis <= 0:
158
+ return Decimal("NaN")
155
159
 
156
160
  # Número de períodos truncado conforme regras da STN
157
161
  anos_truncados = utils.truncar(dias_uteis / 252, 14)
@@ -201,6 +205,10 @@ def taxa(
201
205
  if pu_float <= 0:
202
206
  return float("nan")
203
207
 
208
+ dias_uteis = du.contar(data_liquidacao, data_vencimento)
209
+ if dias_uteis <= 0:
210
+ return float("nan")
211
+
204
212
  def diferenca_preco(taxa: float) -> float:
205
213
  preco = _calcular_pu(vna, cotacao(data_liquidacao, data_vencimento, taxa))
206
214
  return float(preco) - pu_float
@@ -128,7 +128,8 @@ def pu(
128
128
  taxa: Taxa de desconto (YTM) do título em formato decimal.
129
129
 
130
130
  Returns:
131
- Decimal: PU da LTN truncado em seis casas decimais.
131
+ Decimal: PU da LTN truncado em seis casas decimais. Retorna
132
+ ``Decimal("NaN")`` quando o prazo até o vencimento não é positivo.
132
133
 
133
134
  References:
134
135
  - Secretaria do Tesouro Nacional. Metodologia de Cálculo dos Títulos
@@ -148,6 +149,8 @@ def pu(
148
149
  taxa = utils.normalizar_taxa_precificacao(taxa)
149
150
  # Calcula dias úteis entre liquidação e vencimento
150
151
  dias_uteis = du.contar(data_liquidacao, data_vencimento)
152
+ if dias_uteis <= 0:
153
+ return Decimal("NaN")
151
154
 
152
155
  # Calcula anos úteis truncados conforme a STN
153
156
  anos_truncados = utils.truncar(dias_uteis / 252, 14)
@@ -196,6 +199,8 @@ def taxa(
196
199
  return float("nan")
197
200
 
198
201
  dias_uteis = du.contar(data_liquidacao, data_vencimento)
202
+ if dias_uteis <= 0:
203
+ return float("nan")
199
204
  anos_truncados = utils.truncar(dias_uteis / 252, 14)
200
205
  taxa_calculada = (VALOR_FACE / preco_float) ** (1 / anos_truncados) - 1
201
206
  return utils.truncar(taxa_calculada, 8)
@@ -271,7 +276,8 @@ def dv01(
271
276
  pu: PU usado como base para o cálculo.
272
277
 
273
278
  Returns:
274
- float: DV01, variação de preço para 1 bp.
279
+ float: DV01, variação de preço para 1 bp. Retorna ``NaN`` quando o
280
+ prazo até o vencimento não é positivo.
275
281
 
276
282
  Examples:
277
283
  >>> from pyield import ltn
@@ -285,6 +291,8 @@ def dv01(
285
291
  taxa = utils.normalizar_taxa_precificacao(taxa)
286
292
  taxa_mais_1bp = round(taxa + 0.0001, 8)
287
293
  dias_uteis = du.contar(data_liquidacao, data_vencimento)
294
+ if dias_uteis <= 0:
295
+ return float("nan")
288
296
  anos_truncados = utils.truncar(dias_uteis / 252, 14)
289
297
  preco_1 = utils.truncar(VALOR_FACE / (1 + taxa) ** anos_truncados, 6)
290
298
  preco_2 = utils.truncar(
@@ -308,7 +316,8 @@ def duration_expr(
308
316
  Returns:
309
317
  pl.Expr: Expressão sem alias com a duration em anos úteis.
310
318
  """
311
- return du.contar_expr(data_liquidacao, data_vencimento) / 252
319
+ dias_uteis = du.contar_expr(data_liquidacao, data_vencimento)
320
+ return pl.when(dias_uteis > 0).then(dias_uteis / 252).otherwise(float("nan"))
312
321
 
313
322
 
314
323
  def dv01_expr(
@@ -484,7 +484,8 @@ def taxas_zero(
484
484
  Padrão False.
485
485
 
486
486
  Returns:
487
- pl.DataFrame: DataFrame com as taxas zero.
487
+ pl.DataFrame: DataFrame com as taxas zero. Retorna vazio quando não
488
+ restarem vencimentos posteriores à liquidação.
488
489
 
489
490
  Output Columns:
490
491
  - data_vencimento (Date): Data de vencimento.
@@ -561,6 +562,14 @@ def taxas_zero(
561
562
  data_liquidacao, vencimentos, taxas = _validar_entradas_taxas_zero(
562
563
  data_liquidacao, vencimentos, taxas
563
564
  )
565
+ if vencimentos.is_empty():
566
+ return pl.DataFrame(
567
+ schema={
568
+ "data_vencimento": pl.Date,
569
+ "dias_uteis": pl.Int64,
570
+ "taxa_zero": pl.Float64,
571
+ }
572
+ )
564
573
 
565
574
  df = _criar_df_bootstrap(data_liquidacao, taxas, vencimentos)
566
575
 
@@ -27,7 +27,8 @@ def cotacao(
27
27
  taxa_tir: Taxa interna de retorno anualizada do título.
28
28
 
29
29
  Returns:
30
- Decimal: Cotação em base 1, truncada em 6 casas decimais.
30
+ Decimal: Cotação em base 1, truncada em 6 casas decimais. Retorna
31
+ ``Decimal("NaN")`` se a liquidação for igual ou posterior ao vencimento.
31
32
 
32
33
  Examples:
33
34
  >>> from pyield import ntnbp
@@ -38,6 +39,8 @@ def cotacao(
38
39
  return Decimal("NaN")
39
40
 
40
41
  dias_uteis = du.contar(data_liquidacao, data_vencimento)
42
+ if dias_uteis <= 0:
43
+ return Decimal("NaN")
41
44
  anos_uteis = utils.truncar(dias_uteis / 252, 14)
42
45
  fator_desconto = 1 / (1 + float(taxa_tir)) ** anos_uteis
43
46
  return truncar_decimal(fator_desconto, 6)
@@ -108,12 +111,16 @@ def taxa(
108
111
 
109
112
  Returns:
110
113
  float: TIR de mercado anualizada, arredondada em quatro casas decimais.
114
+ Retorna ``NaN`` se a liquidação for igual ou posterior ao vencimento.
111
115
  """
112
116
  if any_is_empty(data_liquidacao, data_vencimento):
113
117
  return float("nan")
114
118
 
115
- curva = _normalizar_curva_zero(curva_zero)
116
119
  dias_uteis = du.contar(data_liquidacao, data_vencimento)
120
+ if dias_uteis <= 0:
121
+ return float("nan")
122
+
123
+ curva = _normalizar_curva_zero(curva_zero)
117
124
  taxa_zero = interpolador.Interpolador(
118
125
  curva["dias_uteis"],
119
126
  curva["taxa_zero"],
@@ -141,7 +148,8 @@ def dv01(
141
148
  pu: PU usado como base para o cálculo.
142
149
 
143
150
  Returns:
144
- float: DV01 (Dollar Value of 01), variação de preço para 1 bp.
151
+ float: DV01 (Dollar Value of 01), variação de preço para 1 bp. Retorna
152
+ ``NaN`` se a liquidação for igual ou posterior ao vencimento.
145
153
 
146
154
  Examples:
147
155
  >>> from pyield import ntnbp as bp
@@ -154,6 +162,8 @@ def dv01(
154
162
  return float("nan")
155
163
 
156
164
  dias_uteis = du.contar(data_liquidacao, data_vencimento)
165
+ if dias_uteis <= 0:
166
+ return float("nan")
157
167
  anos_uteis = utils.truncar(dias_uteis / 252, 14)
158
168
  fator_preco = (1 + taxa_tir) ** anos_uteis
159
169
  fator_preco_1bp = (1 + taxa_tir + 0.0001) ** anos_uteis
@@ -346,6 +346,35 @@ def pu(
346
346
  return truncar_decimal(_calcular_pu(data_liquidacao, data_vencimento, taxa), 6)
347
347
 
348
348
 
349
+ def _filtrar_vertices_futuros(
350
+ liquidacao: dt.date,
351
+ vencimentos: pl.Series,
352
+ taxas: pl.Series,
353
+ nome_curva: str,
354
+ ) -> tuple[pl.Series, pl.Series]:
355
+ """Remove vértices sem prazo preservando o alinhamento com as taxas."""
356
+ if len(vencimentos) != len(taxas):
357
+ raise ValueError(
358
+ f"Vencimentos e taxas de {nome_curva} devem ter o mesmo tamanho."
359
+ )
360
+
361
+ df = pl.DataFrame(
362
+ {"data_vencimento": vencimentos, "taxa": taxas},
363
+ schema={"data_vencimento": pl.Date, "taxa": pl.Float64},
364
+ ).filter(pl.col("data_vencimento") > liquidacao)
365
+
366
+ removidos = len(vencimentos) - df.height
367
+ if removidos > 0:
368
+ logger.warning(
369
+ "Vencimentos de %s menores ou iguais à liquidação foram ignorados: "
370
+ "%s removidos.",
371
+ nome_curva,
372
+ removidos,
373
+ )
374
+
375
+ return df["data_vencimento"], df["taxa"]
376
+
377
+
349
378
  def taxas_zero( # noqa
350
379
  data_liquidacao: DateLike,
351
380
  vencimentos_ltn: DatesLike,
@@ -385,6 +414,10 @@ def taxas_zero( # noqa
385
414
  - dias_uteis (Int64): Dias úteis entre liquidação e vencimento.
386
415
  - taxa_zero (Float64): Taxa zero (zero cupom).
387
416
 
417
+ Notes:
418
+ Vencimentos menores ou iguais à liquidação são ignorados antes da
419
+ construção dos interpoladores.
420
+
388
421
  Examples:
389
422
  >>> from pyield import ntnf, ltn
390
423
  >>> df_ltn = ltn.dados("03-09-2024")
@@ -431,6 +464,27 @@ def taxas_zero( # noqa
431
464
  else:
432
465
  serie_ntnf_taxas = taxas_ntnf
433
466
 
467
+ vencimentos_ltn, serie_ltn_taxas = _filtrar_vertices_futuros(
468
+ liquidacao,
469
+ vencimentos_ltn,
470
+ serie_ltn_taxas,
471
+ "LTN",
472
+ )
473
+ vencimentos_ntnf, serie_ntnf_taxas = _filtrar_vertices_futuros(
474
+ liquidacao,
475
+ vencimentos_ntnf,
476
+ serie_ntnf_taxas,
477
+ "NTN-F",
478
+ )
479
+ if vencimentos_ltn.is_empty() or vencimentos_ntnf.is_empty():
480
+ return pl.DataFrame(
481
+ schema={
482
+ "data_vencimento": pl.Date,
483
+ "dias_uteis": pl.Int64,
484
+ "taxa_zero": pl.Float64,
485
+ }
486
+ )
487
+
434
488
  # 2. Criar interpoladores (aceitam pl.Series diretamente)
435
489
  interpolador_ltn = ip.Interpolador(
436
490
  dias_uteis=du.contar(liquidacao, vencimentos_ltn),
@@ -0,0 +1,5 @@
1
+ """Cálculos de VNA por tipo de título público."""
2
+
3
+ from pyield.tpf.vna.calculo import calcular_vna
4
+
5
+ __all__ = ["calcular_vna"]
@@ -1,4 +1,4 @@
1
- """Operações compartilhadas pelos cálculos de VNA."""
1
+ """Cálculos genéricos de VNA."""
2
2
 
3
3
  import datetime as dt
4
4
 
@@ -20,7 +20,29 @@ def calcular_vna(
20
20
  *,
21
21
  fator_variacao: float | None = None,
22
22
  ) -> float:
23
- """Obtém o VNA publicado ou calcula o pró-rata entre pontos publicados."""
23
+ """Obtém o VNA publicado ou calcula o pró-rata entre pontos publicados.
24
+
25
+ Args:
26
+ df: DataFrame com as colunas ``data`` (Date) e ``vna`` (Float64),
27
+ contendo no máximo um ponto publicado por data.
28
+ data: Data para a qual o VNA será obtido ou interpolado.
29
+ fator_variacao: Fator multiplicativo entre o ponto inicial e o final.
30
+ Se omitido, é calculado pela razão entre os VNAs dos dois pontos.
31
+
32
+ Returns:
33
+ Float: VNA publicado ou calculado por pró-rata exponencial. Retorna
34
+ ``float('nan')`` quando não houver pontos publicados dos dois lados da
35
+ data ou quando ela estiver fora do intervalo disponível.
36
+
37
+ Notes:
38
+ Um ponto publicado exatamente na data tem prioridade e ignora
39
+ ``fator_variacao``. O expoente do pró-rata é truncado em catorze casas
40
+ e o resultado em seis casas.
41
+
42
+ Raises:
43
+ ValueError: Se o VNA-base não for positivo ou a variação for menor ou
44
+ igual a -100%.
45
+ """
24
46
  ponto_exato = df.filter(pl.col("data") == data)
25
47
  if ponto_exato.height == 1:
26
48
  return float(ponto_exato.item(0, "vna"))
@@ -73,3 +95,6 @@ def calcular_vna_projetado(
73
95
  projecao_percentual / 100,
74
96
  expoente,
75
97
  )
98
+
99
+
100
+ __all__ = ["calcular_vna"]
@@ -10,7 +10,8 @@ import pyield._internal.converters as conversores
10
10
  from pyield._internal.numbers import truncar, truncar_decimal
11
11
  from pyield._internal.types import DateLike, any_is_empty
12
12
  from pyield.ipca import historico as _ipca
13
- from pyield.tpf.vna import _download, _utils
13
+ from pyield.tpf.vna import _download
14
+ from pyield.tpf.vna import calculo as _vna
14
15
 
15
16
  _DIA_INICIO_VIGENCIA = 15
16
17
  _QTD_MARCOS_VIGENCIA = 2
@@ -23,7 +24,7 @@ def _processar(df_bruto: pl.DataFrame) -> pl.DataFrame:
23
24
  """Normaliza as duas colunas da planilha de NTN-B."""
24
25
  return (
25
26
  df_bruto.select(
26
- data=_utils.expressao_data(),
27
+ data=_vna.expressao_data(),
27
28
  vna=pl.col("column_2").cast(pl.Float64, strict=False),
28
29
  )
29
30
  .filter(pl.col("data").is_not_null(), pl.col("vna").is_not_null())
@@ -94,7 +95,7 @@ def vna(data: DateLike | None = None) -> Decimal:
94
95
  if math.isnan(fator_ipca):
95
96
  return Decimal("NaN")
96
97
  return truncar_decimal(
97
- _utils.calcular_vna(
98
+ _vna.calcular_vna(
98
99
  df,
99
100
  data_convertida,
100
101
  fator_variacao=fator_ipca,
@@ -174,12 +175,12 @@ def vna_projetado(
174
175
  """
175
176
  if any_is_empty(data, vna_base, inflacao):
176
177
  return Decimal("NaN")
177
- if inflacao <= _utils.LIMITE_INFERIOR_PERCENTUAL:
178
+ if inflacao <= _vna.LIMITE_INFERIOR_PERCENTUAL:
178
179
  raise ValueError("A inflação deve ser maior que -100%.")
179
180
  data_convertida = conversores.converter_datas(data)
180
181
  inicio, fim = _obter_vigencia(data_convertida)
181
182
  expoente = (data_convertida - inicio).days / (fim - inicio).days
182
183
  return truncar_decimal(
183
- _utils.calcular_vna_projetado(float(vna_base), float(inflacao), expoente),
184
+ _vna.calcular_vna_projetado(float(vna_base), float(inflacao), expoente),
184
185
  6,
185
186
  )
@@ -8,7 +8,8 @@ import polars as pl
8
8
  import pyield._internal.converters as conversores
9
9
  from pyield._internal.numbers import truncar_decimal
10
10
  from pyield._internal.types import DateLike, any_is_empty
11
- from pyield.tpf.vna import _download, _utils
11
+ from pyield.tpf.vna import _download
12
+ from pyield.tpf.vna import calculo as _vna
12
13
 
13
14
  _URL_PUBLICACAO = (
14
15
  "https://www.tesourotransparente.gov.br/publicacoes/valor-nominal-de-ntn-c/"
@@ -24,7 +25,7 @@ def _processar(df_bruto: pl.DataFrame) -> pl.DataFrame:
24
25
  series = []
25
26
  for coluna, anos in _ANOS_VENCIMENTO.items():
26
27
  serie = df_bruto.select(
27
- data=_utils.expressao_data(),
28
+ data=_vna.expressao_data(),
28
29
  anos_vencimento=pl.lit(anos, dtype=pl.List(pl.Int64)),
29
30
  vna=pl.col(coluna).cast(pl.Float64, strict=False),
30
31
  ).filter(
@@ -100,7 +101,7 @@ def vna(
100
101
  df = vnas().filter(
101
102
  pl.col("anos_vencimento").list.contains(vencimento_convertido.year)
102
103
  )
103
- return truncar_decimal(_utils.calcular_vna(df, data_convertida), 6)
104
+ return truncar_decimal(_vna.calcular_vna(df, data_convertida), 6)
104
105
 
105
106
 
106
107
  def _obter_vigencia(data: dt.date) -> tuple[dt.date, dt.date]:
@@ -153,12 +154,12 @@ def vna_projetado(
153
154
  """
154
155
  if any_is_empty(data, vna_base, inflacao):
155
156
  return Decimal("NaN")
156
- if inflacao <= _utils.LIMITE_INFERIOR_PERCENTUAL:
157
+ if inflacao <= _vna.LIMITE_INFERIOR_PERCENTUAL:
157
158
  raise ValueError("A inflação deve ser maior que -100%.")
158
159
  data_convertida = conversores.converter_datas(data)
159
160
  inicio, fim = _obter_vigencia(data_convertida)
160
161
  expoente = (data_convertida - inicio).days / (fim - inicio).days
161
162
  return truncar_decimal(
162
- _utils.calcular_vna_projetado(float(vna_base), float(inflacao), expoente),
163
+ _vna.calcular_vna_projetado(float(vna_base), float(inflacao), expoente),
163
164
  6,
164
165
  )
@@ -25,7 +25,7 @@ dependencies = [
25
25
  "fastexcel>=0.19.0",
26
26
  "tzdata>=2024.1; platform_system == 'Windows'",
27
27
  ]
28
- version = "0.55.0"
28
+ version = "0.55.2"
29
29
 
30
30
  [[project.authors]]
31
31
  name = "Carlos Carvalho"
@@ -20,7 +20,7 @@ dependencies = [
20
20
  "fastexcel>=0.19.0",
21
21
  "tzdata>=2024.1; platform_system == 'Windows'",
22
22
  ]
23
- version = "0.55.0"
23
+ version = "0.55.2"
24
24
 
25
25
  [project.urls]
26
26
  Homepage = "https://github.com/crdcj/PYield"
@@ -1 +0,0 @@
1
- """Cálculos de VNA por tipo de título público."""
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