pyield 0.59.0__tar.gz → 0.60.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.60.0/PKG-INFO +221 -0
- pyield-0.60.0/README.md +196 -0
- pyield-0.60.0/pyield/_internal/calendario_igpm.py +115 -0
- pyield-0.60.0/pyield/_internal/igpm.py +138 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/numbers.py +6 -1
- {pyield-0.59.0 → pyield-0.60.0}/pyield/bc/sgs.py +38 -10
- pyield-0.60.0/pyield/igpm.py +8 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/ipca/__init__.py +2 -0
- pyield-0.60.0/pyield/ipca/_calendario.py +105 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/ipca/historico.py +55 -36
- {pyield-0.59.0 → pyield-0.60.0}/pyield/ipca/projetado.py +9 -3
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/_ntnb_bootstrap.py +48 -21
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/lft.py +106 -15
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/ltn.py +161 -24
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/ntnb.py +164 -27
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/ntnc.py +189 -20
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/ntnf.py +281 -38
- {pyield-0.59.0 → pyield-0.60.0}/pyield/vna/__init__.py +4 -0
- pyield-0.60.0/pyield/vna/_calculo.py +176 -0
- pyield-0.60.0/pyield/vna/_consulta.py +461 -0
- pyield-0.60.0/pyield/vna/_contexto.py +157 -0
- pyield-0.60.0/pyield/vna/_download.py +29 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/vna/_lft.py +5 -6
- {pyield-0.59.0 → pyield-0.60.0}/pyield/vna/_ntnb.py +42 -43
- {pyield-0.59.0 → pyield-0.60.0}/pyield/vna/_ntnc.py +35 -32
- {pyield-0.59.0 → pyield-0.60.0}/pyproject.toml +2 -2
- {pyield-0.59.0 → pyield-0.60.0}/pyproject.toml.orig +2 -2
- pyield-0.59.0/PKG-INFO +0 -190
- pyield-0.59.0/README.md +0 -165
- pyield-0.59.0/pyield/.DS_Store +0 -0
- pyield-0.59.0/pyield/igpm.py +0 -6
- pyield-0.59.0/pyield/vna/_calculo.py +0 -100
- pyield-0.59.0/pyield/vna/_consulta.py +0 -244
- pyield-0.59.0/pyield/vna/_download.py +0 -53
- {pyield-0.59.0 → pyield-0.60.0}/LICENSE +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/br_numbers.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/cache.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/converters.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/data_cache.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/excel.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/retry.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/_internal/types.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/anbima/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/anbima/imaq.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/anbima/taxas.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/b3/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/b3/_contratos.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/b3/_validar_pregao.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/b3/boletim.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/b3/derivativos_intradia.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/b3/di_over.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/bc/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/bc/_olinda.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/compromissada.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/copom/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/copom/_calendario.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/cpm/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/cpm/_contratos.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/cpm/_probabilidades.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/du/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/du/core.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/du/feriados_br/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/du/feriados_br/anteriores.txt +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/du/feriados_br/atuais.txt +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/futuro/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/futuro/contratos.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/futuro/di1.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/futuro/historico.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/futuro/intradia.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/fwd.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/interpolador.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/py.typed +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/relogio.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/rmd/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/rmd/_aba_1_3.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/rmd/_aba_2_1.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/rmd/_common.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/rmd/_download.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/selic/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/_leiloes_bcb.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/_taxas.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/benchmark.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/dealers.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/leiloes.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/secundario/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/secundario/_intradia.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/secundario/_mensal.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/__init__.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/_ntnf_bootstrap.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/_utils.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/ntnb1.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/ntnbp.py +0 -0
- {pyield-0.59.0 → pyield-0.60.0}/pyield/tpf/titulos/pre.py +0 -0
pyield-0.60.0/PKG-INFO
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyield
|
|
3
|
+
Version: 0.60.0
|
|
4
|
+
Summary: Polars-powered toolkit for Brazilian fixed income analysis
|
|
5
|
+
Keywords: fixed-income,brazil,finance,analysis,bonds
|
|
6
|
+
Author: Carlos Carvalho
|
|
7
|
+
Author-email: Carlos Carvalho <carlos.carvalho.jr@gmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
14
|
+
Requires-Dist: polars>=1.39.0
|
|
15
|
+
Requires-Dist: lxml>=6.0.0
|
|
16
|
+
Requires-Dist: requests>=2.31.0
|
|
17
|
+
Requires-Dist: fastexcel>=0.19.0
|
|
18
|
+
Requires-Dist: tzdata>=2024.1 ; sys_platform == 'win32'
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Project-URL: Homepage, https://github.com/crdcj/PYield
|
|
21
|
+
Project-URL: Documentation, https://crdcj.github.io/PYield
|
|
22
|
+
Project-URL: Source, https://github.com/crdcj/PYield
|
|
23
|
+
Project-URL: Bug Tracker, https://github.com/crdcj/PYield/issues
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
[](https://pypi.python.org/pypi/pyield)
|
|
27
|
+
[](https://python.org "Go to Python homepage")
|
|
28
|
+
[](https://pola.rs/)
|
|
29
|
+
[](https://github.com/crdcj/PYield/blob/main/LICENSE)
|
|
30
|
+
[](https://crdcj.github.io/PYield/)
|
|
31
|
+
|
|
32
|
+
# PYield: Toolkit de Renda Fixa Brasileira
|
|
33
|
+
|
|
34
|
+
Português | [English](https://github.com/crdcj/PYield/blob/main/README.en.md)
|
|
35
|
+
|
|
36
|
+
PYield é uma biblioteca Python voltada para análise de títulos públicos
|
|
37
|
+
brasileiros. Ela busca e processa dados da ANBIMA, BCB, IBGE, B3 e Tesouro
|
|
38
|
+
Nacional, retornando tipos nativos do Python, `polars.Series` ou
|
|
39
|
+
`polars.DataFrame`, conforme a operação.
|
|
40
|
+
|
|
41
|
+
Embora inclua dados e ferramentas de outros mercados, como DI1, DAP e PTAX,
|
|
42
|
+
esses recursos apoiam o objetivo central da biblioteca: análise, precificação e
|
|
43
|
+
acompanhamento de títulos públicos brasileiros.
|
|
44
|
+
|
|
45
|
+
## Instalação
|
|
46
|
+
|
|
47
|
+
Com `pip`:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pip install pyield
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Em um projeto gerenciado pelo `uv`:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
uv add pyield
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Próximos passos
|
|
60
|
+
|
|
61
|
+
- [Quickstart](https://crdcj.github.io/PYield/quickstart/): primeiros usos da biblioteca.
|
|
62
|
+
- [Documentação completa](https://crdcj.github.io/PYield/): conceitos e referência por módulo.
|
|
63
|
+
- [Mapa da API](https://crdcj.github.io/PYield/api-map/): namespaces e funções públicas.
|
|
64
|
+
- [Desenvolvimento e publicação](https://crdcj.github.io/PYield/desenvolvimento/): ambiente, verificações, build e PyPI.
|
|
65
|
+
- [Gerar e publicar a documentação](docs/desenvolvimento.md#documentação): geração, visualização local e GitHub Pages.
|
|
66
|
+
- [Notebook no Colab](https://colab.research.google.com/github/crdcj/PYield/blob/main/examples/pyield_quickstart.ipynb): exploração interativa.
|
|
67
|
+
- [Pacote no PyPI](https://pypi.org/project/pyield/).
|
|
68
|
+
|
|
69
|
+
## Mapa da API
|
|
70
|
+
|
|
71
|
+
| Componente | Tipo | Finalidade | Funções públicas |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `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` |
|
|
74
|
+
| `yd.Interpolador` | classe | Interpolação escalar e em pipelines Polars, com métodos `linear` e `flat_forward` | `interpolar`, `interpolar_expr` |
|
|
75
|
+
| `yd.interpolar(...)` | função | Interpolação vetorizada flat-forward, curva única ou multi-curva | |
|
|
76
|
+
| `yd.forward(...)` | função | Taxa a termo entre dois vértices | |
|
|
77
|
+
| `yd.forwards(...)` | função | Curva de taxas a termo | |
|
|
78
|
+
| `yd.futuro` | módulo | Contratos futuros da B3 | `di1`, `historico`, `intradia`, `datas_disponiveis`, `vencimento`, `enriquecer`, `vencimento_expr` |
|
|
79
|
+
| `yd.di1` | módulo | Curva DI1 e interpolação | `dados`, `interpolar_taxas`, `interpolar_taxa`, `datas_disponiveis` |
|
|
80
|
+
| `yd.tpf` | módulo | Títulos públicos federais | `taxas`, `taxas_historicas`, `vencimentos`, `estoque`, `leiloes`, `leiloes_bcb`, `benchmarks`, `dealers`, `curva_pre`, `premios_pre`, `secundario` |
|
|
81
|
+
| `yd.rmd(aba)` | função | Relatório Mensal da Dívida do Tesouro Nacional | |
|
|
82
|
+
| `yd.lft` | módulo | LFT | `dados`, `vencimentos`, `cotacao`, `pu`, `taxa`, `rentabilidade`, `rentabilidade_expr` |
|
|
83
|
+
| `yd.ltn` | módulo | LTN | `dados`, `vencimentos`, `pu`, `taxa`, `duration_expr`, `dv01`, `dv01_expr`, `rentabilidade`, `rentabilidade_expr`, `taxas_forward` |
|
|
84
|
+
| `yd.ntnb` | módulo | NTN-B | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `taxas_zero`, `duration`, `duration_expr`, `dv01`, `dv01_expr`, `implicitas` |
|
|
85
|
+
| `yd.ntnb1` | módulo | NTN-B1 (Educa+ e Renda+) | `NomeComercial`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `cotacao_curva_zero`, `taxa_curva_zero`, `pu`, `duration`, `dv01` |
|
|
86
|
+
| `yd.ntnbp` | módulo | NTN-B Principal | `cotacao`, `taxa`, `pu`, `dv01` |
|
|
87
|
+
| `yd.ntnc` | módulo | NTN-C | `dados`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `cotacao_curva_zero`, `taxa_curva_zero`, `pu`, `taxa`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
88
|
+
| `yd.ntnf` | módulo | NTN-F | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `pu`, `taxa`, `taxas_zero`, `taxas_zero_forwards`, `premio_limpo`, `premio_limpo_expr`, `rentabilidade`, `rentabilidade_expr`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
89
|
+
| `yd.vna` | módulo | Valores nominais atualizados dos títulos públicos | `valor`, `historico`, `ultimo`, `projetado`, `vigencia`, `contexto`, `calcular_vna`, `calcular_base` |
|
|
90
|
+
| `yd.copom` | módulo | Calendário automático do Copom | `calendario`, `proxima_reuniao` |
|
|
91
|
+
| `yd.compromissadas(inicio, fim)` | função | Leilões de operações compromissadas do BCB | |
|
|
92
|
+
| `yd.selic` | módulo | Selic e política monetária | `over`, `over_serie`, `meta`, `meta_serie` |
|
|
93
|
+
| `yd.cpm` | módulo | Opções digitais do COPOM e análises derivadas | `contratos`, `probabilidades` |
|
|
94
|
+
| `yd.ipca` | módulo | IPCA histórico e projetado | `indice`, `indice_serie`, `taxa`, `taxa_serie`, `taxa_projetada`, `calendario` |
|
|
95
|
+
| `yd.igpm` | módulo | Taxas e números-índice do IGP-M | `taxa`, `taxa_serie`, `indice`, `indice_serie`, `calendario` |
|
|
96
|
+
| `yd.ptax(data)` | função | PTAX para uma data | |
|
|
97
|
+
| `yd.ptax_serie(inicio, fim)` | função | Série histórica da PTAX | |
|
|
98
|
+
| `yd.di_over(data)` | função | Taxa DI Over | |
|
|
99
|
+
| `yd.hoje()` | função | Data atual no Brasil | |
|
|
100
|
+
| `yd.agora()` | função | Data e hora atual no Brasil | |
|
|
101
|
+
|
|
102
|
+
O [mapa completo da API](https://crdcj.github.io/PYield/api-map/) inclui a
|
|
103
|
+
documentação detalhada e as assinaturas públicas.
|
|
104
|
+
|
|
105
|
+
## Novidades na versão 0.60.0
|
|
106
|
+
|
|
107
|
+
Esta seção cobre apenas as mudanças da `0.59.0` para a `0.60.0`. Consulte também as
|
|
108
|
+
[notas de migração](https://crdcj.github.io/PYield/release-0.60.0/).
|
|
109
|
+
|
|
110
|
+
### Contratos com Decimal
|
|
111
|
+
|
|
112
|
+
Os históricos e cálculos de VNA e os indicadores de inflação passam a preservar
|
|
113
|
+
precisão decimal. Revise operações que misturam esses retornos com `float`:
|
|
114
|
+
use `Decimal("0.0045")` para constantes exatas e `.is_nan()` para verificar
|
|
115
|
+
um retorno escalar `Decimal("NaN")`. Converta para `float` explicitamente
|
|
116
|
+
apenas quando a aplicação aceitar perder essa precisão.
|
|
117
|
+
|
|
118
|
+
| Operação | Retorno na 0.60.0 |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `vna.valor`, `vna.projetado`, `vna.calcular_vna`, `vna.calcular_base` | `Decimal` |
|
|
121
|
+
| Coluna `vna` de `vna.historico` e `vna.ultimo` | `Decimal(18, 6)` |
|
|
122
|
+
| `ipca.indice` / coluna `indice` de `ipca.indice_serie` | `Decimal` / `Decimal(18, 2)` |
|
|
123
|
+
| `ipca.taxa` / coluna `taxa` de `ipca.taxa_serie` | `Decimal` / `Decimal(18, 4)` |
|
|
124
|
+
| `ipca.taxa_projetada().valor_projetado` | `Decimal` com quatro casas |
|
|
125
|
+
| `igpm.taxa` / coluna `taxa` de `igpm.taxa_serie` | `Decimal` / `Decimal(18, 4)` |
|
|
126
|
+
| `igpm.indice` / coluna `indice` de `igpm.indice_serie` | `Decimal` / `Decimal(18, 10)` |
|
|
127
|
+
|
|
128
|
+
`vna.calcular_vna` também passa de `float("nan")` para `Decimal("NaN")`
|
|
129
|
+
na ausência de dados. Os cálculos de VNA usam 28 dígitos de precisão e aplicam
|
|
130
|
+
os truncamentos e arredondamentos da metodologia; resultados intermediários
|
|
131
|
+
podem diferir dos obtidos anteriormente com `float`.
|
|
132
|
+
|
|
133
|
+
### Séries do IPCA
|
|
134
|
+
|
|
135
|
+
As consultas históricas do IPCA seguem o padrão das séries de Selic e PTAX:
|
|
136
|
+
`taxa(data)` e `indice(data)` retornam um valor; `taxa_serie` e `indice_serie`
|
|
137
|
+
retornam séries por intervalo ou pelos últimos meses.
|
|
138
|
+
|
|
139
|
+
Para migrar, substitua `ipca.taxas(inicio, fim)` por
|
|
140
|
+
`ipca.taxa_serie(inicio, fim)` e `ipca.indices(inicio, fim)` por
|
|
141
|
+
`ipca.indice_serie(inicio, fim)`. Substitua `ipca.taxas_ultimas(n)` por
|
|
142
|
+
`ipca.taxa_serie(ultimos=n)` e `ipca.indices_ultimos(n)` por
|
|
143
|
+
`ipca.indice_serie(ultimos=n)`. Os nomes antigos foram removidos. As colunas e unidades são preservadas;
|
|
144
|
+
os tipos numéricos mudam conforme descrito acima.
|
|
145
|
+
|
|
146
|
+
O número-índice agora usa `Decimal`: `ipca.indice(data)` retorna `Decimal`
|
|
147
|
+
(ou `Decimal("NaN")` quando indisponível), e a coluna `indice` de
|
|
148
|
+
`ipca.indice_serie(...)` usa `Decimal(18, 2)`. A conversão parte do texto do
|
|
149
|
+
IBGE, sem passar por `float`.
|
|
150
|
+
|
|
151
|
+
As taxas também usam `Decimal`: `ipca.taxa(data)` retorna `Decimal` (ou
|
|
152
|
+
`Decimal("NaN")`), e a coluna `taxa` de `ipca.taxa_serie(...)` usa
|
|
153
|
+
`Decimal(18, 4)`. O campo `valor_projetado` de `ipca.taxa_projetada()` passa a
|
|
154
|
+
ser `Decimal` com quatro casas. A unidade permanece decimal: 0,45% corresponde
|
|
155
|
+
a `Decimal("0.0045")`.
|
|
156
|
+
|
|
157
|
+
Nas séries, `fim=None` usa a data atual no Brasil. Informe `inicio` ou
|
|
158
|
+
`ultimos`; quando informado, `ultimos` tem prioridade sobre as datas.
|
|
159
|
+
|
|
160
|
+
### Contexto de VNA e calendários de inflação
|
|
161
|
+
|
|
162
|
+
- `yd.vna.contexto(...)` reúne os parâmetros da vigência de NTN-B ou NTN-C:
|
|
163
|
+
VNAs publicados, competência, inflação e pendências. Exige `vencimento` para
|
|
164
|
+
NTN-C e aceita uma projeção explícita quando a inflação realizada não existe.
|
|
165
|
+
As entradas de inflação em `contexto` e `projetado` aceitam números decimais
|
|
166
|
+
(`0.0045`) ou percentuais explícitos (`"0.45%"` ou `"0,45%"`). A coluna
|
|
167
|
+
`inflacao` de `contexto` usa Decimal e pode ser passada diretamente a
|
|
168
|
+
`projetado`.
|
|
169
|
+
Migração: substitua o antigo `inflacao=0.45` por `inflacao="0.45%"` ou
|
|
170
|
+
`inflacao=0.0045`; números puros agora representam taxas decimais.
|
|
171
|
+
- `yd.ipca.calendario(ano, atualizar=False)` consulta as datas previstas de
|
|
172
|
+
divulgação no IBGE pelo ano da competência, incluindo dezembro divulgado no
|
|
173
|
+
ano seguinte.
|
|
174
|
+
- `yd.igpm.calendario(ano, atualizar=False)` consulta as divulgações mensais
|
|
175
|
+
na FGV IBRE, excluindo prévias decendiais. Os calendários não comprovam
|
|
176
|
+
que os índices já foram publicados.
|
|
177
|
+
|
|
178
|
+
### Outras mudanças
|
|
179
|
+
|
|
180
|
+
- `yd.vna.calcular_base(titulo, indice_atual, vencimento=None)` calcula a base
|
|
181
|
+
mensal da NTN-B ou NTN-C com o número-índice realizado do IPCA ou IGP-M,
|
|
182
|
+
ou o VNA da LFT com o fator Selic acumulado desde 01/07/2000, sem acesso
|
|
183
|
+
à rede. As origens e os índices iniciais são constantes internas;
|
|
184
|
+
NTN-C exige vencimento para selecionar a série e seu ajuste de emissão.
|
|
185
|
+
Para LFT, arredonda o fator em dezesseis casas; para NTN-B e NTN-C, trunca
|
|
186
|
+
o fator nessa precisão. Trunca o VNA em seis casas, preservando a
|
|
187
|
+
precisão da origem e evitando encadear VNAs mensais já truncados.
|
|
188
|
+
- Novo módulo `yd.igpm`, com `taxa` e `taxa_serie` para consultar taxas mensais
|
|
189
|
+
do IGP-M via SGS/BCB. `taxa` retorna `Decimal` (ou `Decimal("NaN")` quando
|
|
190
|
+
indisponível), e a coluna `taxa` de `taxa_serie` usa `Decimal(18, 4)`.
|
|
191
|
+
A unidade é decimal: 0,27% corresponde a `Decimal("0.0027")`.
|
|
192
|
+
`indice` e `indice_serie` fornecem os números-índice da FGV via Ipeadata
|
|
193
|
+
(série `IGP12_IGPM12`), como `Decimal` e coluna `Decimal(18, 10)`.
|
|
194
|
+
As dez casas preservam o histórico anterior a 1994. As séries aceitam
|
|
195
|
+
intervalo ou `ultimos`, com competência `periodo` no formato `YYYYMM`.
|
|
196
|
+
- No CPM, substitua `yd.cpm.data(data)` por `yd.cpm.contratos(data)` e use
|
|
197
|
+
`yd.cpm.probabilidades(data, tipo_opcao="call")` para as probabilidades.
|
|
198
|
+
Esta última retorna todas as reuniões disponíveis; filtre o DataFrame para
|
|
199
|
+
selecionar uma reunião.
|
|
200
|
+
- Leilões do BCB passam de `yd.bc.leiloes` para `yd.tpf.leiloes_bcb`, com nomes
|
|
201
|
+
de colunas alinhados aos de `yd.tpf.leiloes`.
|
|
202
|
+
- No mercado secundário, `yd.tpf.secundario.ler(fonte)` substitui `ler_zip` e
|
|
203
|
+
`zip_para_silver`: aceita caminho ou bytes de ZIP e inclui `financeiro` na
|
|
204
|
+
saída. `nome_arquivo_mensal` deixa de ser público.
|
|
205
|
+
- `yd.ntnf.premio` foi removida. Use `yd.tpf.premios_pre(data)` e filtre
|
|
206
|
+
`titulo == "NTN-F"` para obter o prêmio bruto.
|
|
207
|
+
- `yd.tpf.taxas` e as consultas `dados` de LFT, LTN, NTN-B, NTN-C e NTN-F
|
|
208
|
+
preservam colunas e tipos quando não há dados. Nos leilões do Tesouro, PU
|
|
209
|
+
mínimo informado como zero passa a ser nulo, e o financeiro ofertado usa o
|
|
210
|
+
PU médio calculado quando necessário.
|
|
211
|
+
- `yd.rmd` passa a propagar erros de download e processamento, em vez de
|
|
212
|
+
retornar um DataFrame vazio nessas situações.
|
|
213
|
+
|
|
214
|
+
Consulte as [releases do GitHub](https://github.com/crdcj/PYield/releases)
|
|
215
|
+
para o histórico completo e as notas de migração de versões anteriores.
|
|
216
|
+
|
|
217
|
+
## Projeto
|
|
218
|
+
|
|
219
|
+
- [Código-fonte](https://github.com/crdcj/PYield)
|
|
220
|
+
- [Issues](https://github.com/crdcj/PYield/issues)
|
|
221
|
+
- [Licença MIT](LICENSE)
|
pyield-0.60.0/README.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
[](https://pypi.python.org/pypi/pyield)
|
|
2
|
+
[](https://python.org "Go to Python homepage")
|
|
3
|
+
[](https://pola.rs/)
|
|
4
|
+
[](https://github.com/crdcj/PYield/blob/main/LICENSE)
|
|
5
|
+
[](https://crdcj.github.io/PYield/)
|
|
6
|
+
|
|
7
|
+
# PYield: Toolkit de Renda Fixa Brasileira
|
|
8
|
+
|
|
9
|
+
Português | [English](https://github.com/crdcj/PYield/blob/main/README.en.md)
|
|
10
|
+
|
|
11
|
+
PYield é uma biblioteca Python voltada para análise de títulos públicos
|
|
12
|
+
brasileiros. Ela busca e processa dados da ANBIMA, BCB, IBGE, B3 e Tesouro
|
|
13
|
+
Nacional, retornando tipos nativos do Python, `polars.Series` ou
|
|
14
|
+
`polars.DataFrame`, conforme a operação.
|
|
15
|
+
|
|
16
|
+
Embora inclua dados e ferramentas de outros mercados, como DI1, DAP e PTAX,
|
|
17
|
+
esses recursos apoiam o objetivo central da biblioteca: análise, precificação e
|
|
18
|
+
acompanhamento de títulos públicos brasileiros.
|
|
19
|
+
|
|
20
|
+
## Instalação
|
|
21
|
+
|
|
22
|
+
Com `pip`:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
pip install pyield
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Em um projeto gerenciado pelo `uv`:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
uv add pyield
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Próximos passos
|
|
35
|
+
|
|
36
|
+
- [Quickstart](https://crdcj.github.io/PYield/quickstart/): primeiros usos da biblioteca.
|
|
37
|
+
- [Documentação completa](https://crdcj.github.io/PYield/): conceitos e referência por módulo.
|
|
38
|
+
- [Mapa da API](https://crdcj.github.io/PYield/api-map/): namespaces e funções públicas.
|
|
39
|
+
- [Desenvolvimento e publicação](https://crdcj.github.io/PYield/desenvolvimento/): ambiente, verificações, build e PyPI.
|
|
40
|
+
- [Gerar e publicar a documentação](docs/desenvolvimento.md#documentação): geração, visualização local e GitHub Pages.
|
|
41
|
+
- [Notebook no Colab](https://colab.research.google.com/github/crdcj/PYield/blob/main/examples/pyield_quickstart.ipynb): exploração interativa.
|
|
42
|
+
- [Pacote no PyPI](https://pypi.org/project/pyield/).
|
|
43
|
+
|
|
44
|
+
## Mapa da API
|
|
45
|
+
|
|
46
|
+
| Componente | Tipo | Finalidade | Funções públicas |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| `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` |
|
|
49
|
+
| `yd.Interpolador` | classe | Interpolação escalar e em pipelines Polars, com métodos `linear` e `flat_forward` | `interpolar`, `interpolar_expr` |
|
|
50
|
+
| `yd.interpolar(...)` | função | Interpolação vetorizada flat-forward, curva única ou multi-curva | |
|
|
51
|
+
| `yd.forward(...)` | função | Taxa a termo entre dois vértices | |
|
|
52
|
+
| `yd.forwards(...)` | função | Curva de taxas a termo | |
|
|
53
|
+
| `yd.futuro` | módulo | Contratos futuros da B3 | `di1`, `historico`, `intradia`, `datas_disponiveis`, `vencimento`, `enriquecer`, `vencimento_expr` |
|
|
54
|
+
| `yd.di1` | módulo | Curva DI1 e interpolação | `dados`, `interpolar_taxas`, `interpolar_taxa`, `datas_disponiveis` |
|
|
55
|
+
| `yd.tpf` | módulo | Títulos públicos federais | `taxas`, `taxas_historicas`, `vencimentos`, `estoque`, `leiloes`, `leiloes_bcb`, `benchmarks`, `dealers`, `curva_pre`, `premios_pre`, `secundario` |
|
|
56
|
+
| `yd.rmd(aba)` | função | Relatório Mensal da Dívida do Tesouro Nacional | |
|
|
57
|
+
| `yd.lft` | módulo | LFT | `dados`, `vencimentos`, `cotacao`, `pu`, `taxa`, `rentabilidade`, `rentabilidade_expr` |
|
|
58
|
+
| `yd.ltn` | módulo | LTN | `dados`, `vencimentos`, `pu`, `taxa`, `duration_expr`, `dv01`, `dv01_expr`, `rentabilidade`, `rentabilidade_expr`, `taxas_forward` |
|
|
59
|
+
| `yd.ntnb` | módulo | NTN-B | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `pu`, `taxa`, `taxas_zero`, `duration`, `duration_expr`, `dv01`, `dv01_expr`, `implicitas` |
|
|
60
|
+
| `yd.ntnb1` | módulo | NTN-B1 (Educa+ e Renda+) | `NomeComercial`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `cotacao_curva_zero`, `taxa_curva_zero`, `pu`, `duration`, `dv01` |
|
|
61
|
+
| `yd.ntnbp` | módulo | NTN-B Principal | `cotacao`, `taxa`, `pu`, `dv01` |
|
|
62
|
+
| `yd.ntnc` | módulo | NTN-C | `dados`, `datas_pagamento`, `fluxos_caixa`, `cotacao`, `cotacao_curva_zero`, `taxa_curva_zero`, `pu`, `taxa`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
63
|
+
| `yd.ntnf` | módulo | NTN-F | `dados`, `vencimentos`, `datas_pagamento`, `fluxos_caixa`, `pu`, `taxa`, `taxas_zero`, `taxas_zero_forwards`, `premio_limpo`, `premio_limpo_expr`, `rentabilidade`, `rentabilidade_expr`, `duration`, `duration_expr`, `dv01`, `dv01_expr` |
|
|
64
|
+
| `yd.vna` | módulo | Valores nominais atualizados dos títulos públicos | `valor`, `historico`, `ultimo`, `projetado`, `vigencia`, `contexto`, `calcular_vna`, `calcular_base` |
|
|
65
|
+
| `yd.copom` | módulo | Calendário automático do Copom | `calendario`, `proxima_reuniao` |
|
|
66
|
+
| `yd.compromissadas(inicio, fim)` | função | Leilões de operações compromissadas do BCB | |
|
|
67
|
+
| `yd.selic` | módulo | Selic e política monetária | `over`, `over_serie`, `meta`, `meta_serie` |
|
|
68
|
+
| `yd.cpm` | módulo | Opções digitais do COPOM e análises derivadas | `contratos`, `probabilidades` |
|
|
69
|
+
| `yd.ipca` | módulo | IPCA histórico e projetado | `indice`, `indice_serie`, `taxa`, `taxa_serie`, `taxa_projetada`, `calendario` |
|
|
70
|
+
| `yd.igpm` | módulo | Taxas e números-índice do IGP-M | `taxa`, `taxa_serie`, `indice`, `indice_serie`, `calendario` |
|
|
71
|
+
| `yd.ptax(data)` | função | PTAX para uma data | |
|
|
72
|
+
| `yd.ptax_serie(inicio, fim)` | função | Série histórica da PTAX | |
|
|
73
|
+
| `yd.di_over(data)` | função | Taxa DI Over | |
|
|
74
|
+
| `yd.hoje()` | função | Data atual no Brasil | |
|
|
75
|
+
| `yd.agora()` | função | Data e hora atual no Brasil | |
|
|
76
|
+
|
|
77
|
+
O [mapa completo da API](https://crdcj.github.io/PYield/api-map/) inclui a
|
|
78
|
+
documentação detalhada e as assinaturas públicas.
|
|
79
|
+
|
|
80
|
+
## Novidades na versão 0.60.0
|
|
81
|
+
|
|
82
|
+
Esta seção cobre apenas as mudanças da `0.59.0` para a `0.60.0`. Consulte também as
|
|
83
|
+
[notas de migração](https://crdcj.github.io/PYield/release-0.60.0/).
|
|
84
|
+
|
|
85
|
+
### Contratos com Decimal
|
|
86
|
+
|
|
87
|
+
Os históricos e cálculos de VNA e os indicadores de inflação passam a preservar
|
|
88
|
+
precisão decimal. Revise operações que misturam esses retornos com `float`:
|
|
89
|
+
use `Decimal("0.0045")` para constantes exatas e `.is_nan()` para verificar
|
|
90
|
+
um retorno escalar `Decimal("NaN")`. Converta para `float` explicitamente
|
|
91
|
+
apenas quando a aplicação aceitar perder essa precisão.
|
|
92
|
+
|
|
93
|
+
| Operação | Retorno na 0.60.0 |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `vna.valor`, `vna.projetado`, `vna.calcular_vna`, `vna.calcular_base` | `Decimal` |
|
|
96
|
+
| Coluna `vna` de `vna.historico` e `vna.ultimo` | `Decimal(18, 6)` |
|
|
97
|
+
| `ipca.indice` / coluna `indice` de `ipca.indice_serie` | `Decimal` / `Decimal(18, 2)` |
|
|
98
|
+
| `ipca.taxa` / coluna `taxa` de `ipca.taxa_serie` | `Decimal` / `Decimal(18, 4)` |
|
|
99
|
+
| `ipca.taxa_projetada().valor_projetado` | `Decimal` com quatro casas |
|
|
100
|
+
| `igpm.taxa` / coluna `taxa` de `igpm.taxa_serie` | `Decimal` / `Decimal(18, 4)` |
|
|
101
|
+
| `igpm.indice` / coluna `indice` de `igpm.indice_serie` | `Decimal` / `Decimal(18, 10)` |
|
|
102
|
+
|
|
103
|
+
`vna.calcular_vna` também passa de `float("nan")` para `Decimal("NaN")`
|
|
104
|
+
na ausência de dados. Os cálculos de VNA usam 28 dígitos de precisão e aplicam
|
|
105
|
+
os truncamentos e arredondamentos da metodologia; resultados intermediários
|
|
106
|
+
podem diferir dos obtidos anteriormente com `float`.
|
|
107
|
+
|
|
108
|
+
### Séries do IPCA
|
|
109
|
+
|
|
110
|
+
As consultas históricas do IPCA seguem o padrão das séries de Selic e PTAX:
|
|
111
|
+
`taxa(data)` e `indice(data)` retornam um valor; `taxa_serie` e `indice_serie`
|
|
112
|
+
retornam séries por intervalo ou pelos últimos meses.
|
|
113
|
+
|
|
114
|
+
Para migrar, substitua `ipca.taxas(inicio, fim)` por
|
|
115
|
+
`ipca.taxa_serie(inicio, fim)` e `ipca.indices(inicio, fim)` por
|
|
116
|
+
`ipca.indice_serie(inicio, fim)`. Substitua `ipca.taxas_ultimas(n)` por
|
|
117
|
+
`ipca.taxa_serie(ultimos=n)` e `ipca.indices_ultimos(n)` por
|
|
118
|
+
`ipca.indice_serie(ultimos=n)`. Os nomes antigos foram removidos. As colunas e unidades são preservadas;
|
|
119
|
+
os tipos numéricos mudam conforme descrito acima.
|
|
120
|
+
|
|
121
|
+
O número-índice agora usa `Decimal`: `ipca.indice(data)` retorna `Decimal`
|
|
122
|
+
(ou `Decimal("NaN")` quando indisponível), e a coluna `indice` de
|
|
123
|
+
`ipca.indice_serie(...)` usa `Decimal(18, 2)`. A conversão parte do texto do
|
|
124
|
+
IBGE, sem passar por `float`.
|
|
125
|
+
|
|
126
|
+
As taxas também usam `Decimal`: `ipca.taxa(data)` retorna `Decimal` (ou
|
|
127
|
+
`Decimal("NaN")`), e a coluna `taxa` de `ipca.taxa_serie(...)` usa
|
|
128
|
+
`Decimal(18, 4)`. O campo `valor_projetado` de `ipca.taxa_projetada()` passa a
|
|
129
|
+
ser `Decimal` com quatro casas. A unidade permanece decimal: 0,45% corresponde
|
|
130
|
+
a `Decimal("0.0045")`.
|
|
131
|
+
|
|
132
|
+
Nas séries, `fim=None` usa a data atual no Brasil. Informe `inicio` ou
|
|
133
|
+
`ultimos`; quando informado, `ultimos` tem prioridade sobre as datas.
|
|
134
|
+
|
|
135
|
+
### Contexto de VNA e calendários de inflação
|
|
136
|
+
|
|
137
|
+
- `yd.vna.contexto(...)` reúne os parâmetros da vigência de NTN-B ou NTN-C:
|
|
138
|
+
VNAs publicados, competência, inflação e pendências. Exige `vencimento` para
|
|
139
|
+
NTN-C e aceita uma projeção explícita quando a inflação realizada não existe.
|
|
140
|
+
As entradas de inflação em `contexto` e `projetado` aceitam números decimais
|
|
141
|
+
(`0.0045`) ou percentuais explícitos (`"0.45%"` ou `"0,45%"`). A coluna
|
|
142
|
+
`inflacao` de `contexto` usa Decimal e pode ser passada diretamente a
|
|
143
|
+
`projetado`.
|
|
144
|
+
Migração: substitua o antigo `inflacao=0.45` por `inflacao="0.45%"` ou
|
|
145
|
+
`inflacao=0.0045`; números puros agora representam taxas decimais.
|
|
146
|
+
- `yd.ipca.calendario(ano, atualizar=False)` consulta as datas previstas de
|
|
147
|
+
divulgação no IBGE pelo ano da competência, incluindo dezembro divulgado no
|
|
148
|
+
ano seguinte.
|
|
149
|
+
- `yd.igpm.calendario(ano, atualizar=False)` consulta as divulgações mensais
|
|
150
|
+
na FGV IBRE, excluindo prévias decendiais. Os calendários não comprovam
|
|
151
|
+
que os índices já foram publicados.
|
|
152
|
+
|
|
153
|
+
### Outras mudanças
|
|
154
|
+
|
|
155
|
+
- `yd.vna.calcular_base(titulo, indice_atual, vencimento=None)` calcula a base
|
|
156
|
+
mensal da NTN-B ou NTN-C com o número-índice realizado do IPCA ou IGP-M,
|
|
157
|
+
ou o VNA da LFT com o fator Selic acumulado desde 01/07/2000, sem acesso
|
|
158
|
+
à rede. As origens e os índices iniciais são constantes internas;
|
|
159
|
+
NTN-C exige vencimento para selecionar a série e seu ajuste de emissão.
|
|
160
|
+
Para LFT, arredonda o fator em dezesseis casas; para NTN-B e NTN-C, trunca
|
|
161
|
+
o fator nessa precisão. Trunca o VNA em seis casas, preservando a
|
|
162
|
+
precisão da origem e evitando encadear VNAs mensais já truncados.
|
|
163
|
+
- Novo módulo `yd.igpm`, com `taxa` e `taxa_serie` para consultar taxas mensais
|
|
164
|
+
do IGP-M via SGS/BCB. `taxa` retorna `Decimal` (ou `Decimal("NaN")` quando
|
|
165
|
+
indisponível), e a coluna `taxa` de `taxa_serie` usa `Decimal(18, 4)`.
|
|
166
|
+
A unidade é decimal: 0,27% corresponde a `Decimal("0.0027")`.
|
|
167
|
+
`indice` e `indice_serie` fornecem os números-índice da FGV via Ipeadata
|
|
168
|
+
(série `IGP12_IGPM12`), como `Decimal` e coluna `Decimal(18, 10)`.
|
|
169
|
+
As dez casas preservam o histórico anterior a 1994. As séries aceitam
|
|
170
|
+
intervalo ou `ultimos`, com competência `periodo` no formato `YYYYMM`.
|
|
171
|
+
- No CPM, substitua `yd.cpm.data(data)` por `yd.cpm.contratos(data)` e use
|
|
172
|
+
`yd.cpm.probabilidades(data, tipo_opcao="call")` para as probabilidades.
|
|
173
|
+
Esta última retorna todas as reuniões disponíveis; filtre o DataFrame para
|
|
174
|
+
selecionar uma reunião.
|
|
175
|
+
- Leilões do BCB passam de `yd.bc.leiloes` para `yd.tpf.leiloes_bcb`, com nomes
|
|
176
|
+
de colunas alinhados aos de `yd.tpf.leiloes`.
|
|
177
|
+
- No mercado secundário, `yd.tpf.secundario.ler(fonte)` substitui `ler_zip` e
|
|
178
|
+
`zip_para_silver`: aceita caminho ou bytes de ZIP e inclui `financeiro` na
|
|
179
|
+
saída. `nome_arquivo_mensal` deixa de ser público.
|
|
180
|
+
- `yd.ntnf.premio` foi removida. Use `yd.tpf.premios_pre(data)` e filtre
|
|
181
|
+
`titulo == "NTN-F"` para obter o prêmio bruto.
|
|
182
|
+
- `yd.tpf.taxas` e as consultas `dados` de LFT, LTN, NTN-B, NTN-C e NTN-F
|
|
183
|
+
preservam colunas e tipos quando não há dados. Nos leilões do Tesouro, PU
|
|
184
|
+
mínimo informado como zero passa a ser nulo, e o financeiro ofertado usa o
|
|
185
|
+
PU médio calculado quando necessário.
|
|
186
|
+
- `yd.rmd` passa a propagar erros de download e processamento, em vez de
|
|
187
|
+
retornar um DataFrame vazio nessas situações.
|
|
188
|
+
|
|
189
|
+
Consulte as [releases do GitHub](https://github.com/crdcj/PYield/releases)
|
|
190
|
+
para o histórico completo e as notas de migração de versões anteriores.
|
|
191
|
+
|
|
192
|
+
## Projeto
|
|
193
|
+
|
|
194
|
+
- [Código-fonte](https://github.com/crdcj/PYield)
|
|
195
|
+
- [Issues](https://github.com/crdcj/PYield/issues)
|
|
196
|
+
- [Licença MIT](LICENSE)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Calendário de divulgação do IGP-M publicado pela FGV IBRE."""
|
|
2
|
+
|
|
3
|
+
import datetime as dt
|
|
4
|
+
import re
|
|
5
|
+
import ssl
|
|
6
|
+
|
|
7
|
+
import polars as pl
|
|
8
|
+
import requests
|
|
9
|
+
from lxml import html
|
|
10
|
+
from requests.adapters import HTTPAdapter
|
|
11
|
+
|
|
12
|
+
from pyield._internal.cache import ttl_cache
|
|
13
|
+
from pyield._internal.retry import retry_padrao
|
|
14
|
+
|
|
15
|
+
_URL = "https://portalibre.fgv.br/calendario-de-divulgacao"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class _AdaptadorFGV(HTTPAdapter):
|
|
19
|
+
def init_poolmanager(self, *args, **kwargs):
|
|
20
|
+
contexto = ssl.create_default_context()
|
|
21
|
+
# O servidor da FGV negocia TLS 1.2 com RSA e AES-GCM, sem ECDHE.
|
|
22
|
+
cifras = ":".join(cifra["name"] for cifra in contexto.get_ciphers())
|
|
23
|
+
contexto.set_ciphers(f"{cifras}:AES128-GCM-SHA256")
|
|
24
|
+
kwargs["ssl_context"] = contexto
|
|
25
|
+
return super().init_poolmanager(*args, **kwargs)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@ttl_cache()
|
|
29
|
+
@retry_padrao
|
|
30
|
+
def _buscar_calendario(ano: int) -> bytes:
|
|
31
|
+
with requests.Session() as sessao:
|
|
32
|
+
sessao.mount(_URL, _AdaptadorFGV())
|
|
33
|
+
resposta = sessao.get(
|
|
34
|
+
_URL,
|
|
35
|
+
params={
|
|
36
|
+
"field_indice_target_id": "128",
|
|
37
|
+
"field_divulgacao_data_value": f"{ano}-01-01",
|
|
38
|
+
"field_divulgacao_data_value_1": f"{ano}-12-31",
|
|
39
|
+
},
|
|
40
|
+
timeout=30,
|
|
41
|
+
)
|
|
42
|
+
resposta.raise_for_status()
|
|
43
|
+
return resposta.content
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _parsear_calendario(conteudo: bytes) -> pl.DataFrame:
|
|
47
|
+
linhas = []
|
|
48
|
+
for item in html.fromstring(conteudo).iter("li"):
|
|
49
|
+
texto = " ".join(" ".join(str(trecho) for trecho in item.itertext()).split())
|
|
50
|
+
if not re.search(r"\bIGP-M e os componentes:", texto):
|
|
51
|
+
continue
|
|
52
|
+
data = re.search(r"\b\d{2}/\d{2}/\d{4}\b", texto)
|
|
53
|
+
if data is None:
|
|
54
|
+
raise ValueError("Divulgação do IGP-M sem data válida.")
|
|
55
|
+
linhas.append(data[0])
|
|
56
|
+
return pl.DataFrame(
|
|
57
|
+
{"data_divulgacao": linhas}, schema={"data_divulgacao": pl.String}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _processar_calendario(dados: pl.DataFrame) -> pl.DataFrame:
|
|
62
|
+
calendario = (
|
|
63
|
+
dados.with_columns(
|
|
64
|
+
data_divulgacao=pl.col("data_divulgacao").str.to_date("%d/%m/%Y")
|
|
65
|
+
)
|
|
66
|
+
.select(
|
|
67
|
+
competencia=pl.col("data_divulgacao").dt.month_start(),
|
|
68
|
+
data_divulgacao=pl.col("data_divulgacao"),
|
|
69
|
+
)
|
|
70
|
+
.unique()
|
|
71
|
+
)
|
|
72
|
+
if calendario["competencia"].is_duplicated().any():
|
|
73
|
+
raise ValueError("Datas conflitantes no calendário do IGP-M.")
|
|
74
|
+
return calendario.sort("competencia")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def calendario(ano: int, *, atualizar: bool = False) -> pl.DataFrame:
|
|
78
|
+
"""Consulta o calendário de divulgação mensal do IGP-M na FGV IBRE.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
ano: Ano das divulgações e competências.
|
|
82
|
+
atualizar: Ignora e renova o cache de 60 segundos desse ano.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
DataFrame ordenado por competência. Sem registros, retorna vazio com
|
|
86
|
+
o mesmo esquema.
|
|
87
|
+
|
|
88
|
+
Output Columns:
|
|
89
|
+
competencia (Date): Primeiro dia do mês da divulgação mensal do IGP-M.
|
|
90
|
+
data_divulgacao (Date): Data prevista pela FGV IBRE.
|
|
91
|
+
|
|
92
|
+
Notes:
|
|
93
|
+
Fonte: calendário de divulgação da FGV IBRE. Seleciona o IGP-M mensal
|
|
94
|
+
com seus componentes, excluindo prévias decendiais e outros índices.
|
|
95
|
+
A competência corresponde ao mês da divulgação mensal. A data prevista
|
|
96
|
+
não comprova publicação. Não cria janelas estimadas quando faltam dados.
|
|
97
|
+
Erros de rede e payload inválido são propagados.
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
ValueError: Ano inválido, data inválida ou datas conflitantes.
|
|
101
|
+
|
|
102
|
+
Examples:
|
|
103
|
+
Seleciona as divulgações previstas a partir de hoje, sem incluir
|
|
104
|
+
prévias decendiais. O resultado depende do calendário da FGV IBRE
|
|
105
|
+
e não comprova que os índices já tenham sido publicados:
|
|
106
|
+
|
|
107
|
+
>>> hoje = yd.hoje()
|
|
108
|
+
>>> agenda = yd.igpm.calendario(hoje.year)
|
|
109
|
+
>>> proximas = agenda.filter(pl.col("data_divulgacao") >= hoje)
|
|
110
|
+
"""
|
|
111
|
+
if type(ano) is not int or not dt.MINYEAR <= ano <= dt.MAXYEAR:
|
|
112
|
+
raise ValueError("ano deve ser um inteiro entre 1 e 9999.")
|
|
113
|
+
return _processar_calendario(
|
|
114
|
+
_parsear_calendario(_buscar_calendario(ano, _atualizar=atualizar))
|
|
115
|
+
).filter(pl.col("competencia").dt.year() == ano)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Números-índice do IGP-M da FGV disponibilizados pelo Ipeadata."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from decimal import Decimal
|
|
5
|
+
|
|
6
|
+
import polars as pl
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from pyield import relogio
|
|
10
|
+
from pyield._internal.cache import ttl_cache
|
|
11
|
+
from pyield._internal.converters import converter_datas
|
|
12
|
+
from pyield._internal.retry import retry_padrao
|
|
13
|
+
from pyield._internal.types import DateLike, any_is_empty
|
|
14
|
+
|
|
15
|
+
_URL_INDICES = (
|
|
16
|
+
"https://www.ipeadata.gov.br/api/odata4/ValoresSerie(SERCODIGO='IGP12_IGPM12')"
|
|
17
|
+
)
|
|
18
|
+
_TIPO_INDICE = pl.Decimal(precision=18, scale=10)
|
|
19
|
+
_ESQUEMA = {"periodo": pl.Int64, "indice": _TIPO_INDICE}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@ttl_cache()
|
|
23
|
+
@retry_padrao
|
|
24
|
+
def _buscar_historico() -> bytes:
|
|
25
|
+
"""Busca o JSON bruto da série de números-índice do IGP-M."""
|
|
26
|
+
resposta = requests.get(_URL_INDICES, timeout=30)
|
|
27
|
+
resposta.raise_for_status()
|
|
28
|
+
return resposta.content
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _parsear_historico(conteudo: bytes) -> list[dict[str, str | Decimal | None]]:
|
|
32
|
+
"""Decodifica os números do JSON diretamente como Decimal."""
|
|
33
|
+
return json.loads(conteudo, parse_float=Decimal)["value"]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _processar_historico(dados: list[dict[str, str | Decimal | None]]) -> pl.DataFrame:
|
|
37
|
+
"""Normaliza as competências mensais e preserva a precisão dos índices."""
|
|
38
|
+
return (
|
|
39
|
+
pl.from_dicts(dados, schema={"VALDATA": pl.String, "VALVALOR": _TIPO_INDICE})
|
|
40
|
+
.select(
|
|
41
|
+
periodo=pl.col("VALDATA")
|
|
42
|
+
.str.slice(0, 10)
|
|
43
|
+
.str.to_date("%Y-%m-%d")
|
|
44
|
+
.dt.strftime("%Y%m")
|
|
45
|
+
.cast(pl.Int64),
|
|
46
|
+
indice=pl.col("VALVALOR"),
|
|
47
|
+
)
|
|
48
|
+
.drop_nulls("indice")
|
|
49
|
+
.sort("periodo")
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def indice_serie(
|
|
54
|
+
inicio: DateLike | None = None,
|
|
55
|
+
fim: DateLike | None = None,
|
|
56
|
+
*,
|
|
57
|
+
ultimos: int | None = None,
|
|
58
|
+
) -> pl.DataFrame:
|
|
59
|
+
"""Obtém os números-índice mensais do IGP-M por intervalo ou últimos meses.
|
|
60
|
+
|
|
61
|
+
Fonte: FGV/Conjuntura Econômica, disponibilizada pelo Ipeadata na série
|
|
62
|
+
``IGP12_IGPM12``, com base agosto de 1994 = 100.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
inicio: Qualquer data no primeiro mês do intervalo.
|
|
66
|
+
fim: Qualquer data no último mês do intervalo. Se ``None``, usa a
|
|
67
|
+
data atual no Brasil.
|
|
68
|
+
ultimos: Número de meses mais recentes a recuperar. Se informado,
|
|
69
|
+
tem prioridade sobre ``inicio`` e ``fim``.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
DataFrame com os números-índice em ordem crescente de competência.
|
|
73
|
+
Retorna vazio, preservando o esquema, se não houver dados no intervalo.
|
|
74
|
+
|
|
75
|
+
Output Columns:
|
|
76
|
+
* periodo (Int64): competência mensal no formato YYYYMM.
|
|
77
|
+
* indice (Decimal(18, 10)): número-índice do IGP-M.
|
|
78
|
+
|
|
79
|
+
Notes:
|
|
80
|
+
Os números do JSON são lidos diretamente como Decimal, sem passagem
|
|
81
|
+
por float. As dez casas preservam também os valores anteriores a 1994,
|
|
82
|
+
que podem ser menores que 0.001. Valores ausentes são omitidos.
|
|
83
|
+
|
|
84
|
+
Raises:
|
|
85
|
+
ValueError: Se não informar ``inicio`` nem ``ultimos``, se ``ultimos``
|
|
86
|
+
for menor ou igual a zero ou se alguma data for inválida.
|
|
87
|
+
|
|
88
|
+
Examples:
|
|
89
|
+
>>> yd.igpm.indice_serie("01-06-2000", "31-07-2000").to_dicts()
|
|
90
|
+
[{'periodo': 200006, 'indice': Decimal('183.7450000000')},
|
|
91
|
+
{'periodo': 200007, 'indice': Decimal('186.6340000000')}]
|
|
92
|
+
"""
|
|
93
|
+
if ultimos is not None:
|
|
94
|
+
if ultimos <= 0:
|
|
95
|
+
raise ValueError("O número de meses deve ser maior que 0.")
|
|
96
|
+
return _processar_historico(_parsear_historico(_buscar_historico())).tail(
|
|
97
|
+
ultimos
|
|
98
|
+
)
|
|
99
|
+
if inicio is None:
|
|
100
|
+
raise ValueError("Informe 'inicio' ou 'ultimos'.")
|
|
101
|
+
data_inicio = converter_datas(inicio)
|
|
102
|
+
data_fim = converter_datas(fim) if fim is not None else relogio.hoje()
|
|
103
|
+
if data_inicio is None or data_fim is None:
|
|
104
|
+
raise ValueError("As datas do intervalo devem ser informadas.")
|
|
105
|
+
periodo_inicio = data_inicio.year * 100 + data_inicio.month
|
|
106
|
+
periodo_fim = data_fim.year * 100 + data_fim.month
|
|
107
|
+
if periodo_inicio > periodo_fim:
|
|
108
|
+
return pl.DataFrame(schema=_ESQUEMA)
|
|
109
|
+
return _processar_historico(_parsear_historico(_buscar_historico())).filter(
|
|
110
|
+
pl.col("periodo").is_between(periodo_inicio, periodo_fim)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def indice(data: DateLike | None) -> Decimal:
|
|
115
|
+
"""Obtém o número-índice do IGP-M para um mês específico.
|
|
116
|
+
|
|
117
|
+
Fonte: FGV/Conjuntura Econômica, disponibilizada pelo Ipeadata na série
|
|
118
|
+
``IGP12_IGPM12``, com base agosto de 1994 = 100.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
data: Qualquer data dentro do mês desejado, nos formatos da biblioteca.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
Decimal: Número-índice com dez casas decimais ou ``Decimal('NaN')``
|
|
125
|
+
se a data for nula, vazia ou o índice não estiver disponível.
|
|
126
|
+
|
|
127
|
+
Examples:
|
|
128
|
+
>>> yd.igpm.indice("01-06-2000")
|
|
129
|
+
Decimal('183.7450000000')
|
|
130
|
+
>>> yd.igpm.indice("01-06-1989")
|
|
131
|
+
Decimal('0.0000308619')
|
|
132
|
+
"""
|
|
133
|
+
if data is None or any_is_empty(data):
|
|
134
|
+
return Decimal("NaN")
|
|
135
|
+
df = indice_serie(data, data)
|
|
136
|
+
if df.is_empty():
|
|
137
|
+
return Decimal("NaN")
|
|
138
|
+
return df.item(0, "indice")
|