pyield 0.48.7__tar.gz → 0.48.9__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 (72) hide show
  1. {pyield-0.48.7 → pyield-0.48.9}/PKG-INFO +1 -1
  2. pyield-0.48.9/pyield/__about__.py +1 -0
  3. pyield-0.48.9/pyield/anbima/__init__.py +9 -0
  4. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/boletim.py +14 -14
  5. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/di1.py +1 -3
  6. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/futuro/__init__.py +4 -4
  7. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/futuro/historico.py +18 -5
  8. pyield-0.48.9/pyield/tn/__init__.py +20 -0
  9. pyield-0.48.7/pyield/__about__.py +0 -1
  10. pyield-0.48.7/pyield/anbima/__init__.py +0 -15
  11. pyield-0.48.7/pyield/anbima/ettj_intradia.py +0 -83
  12. pyield-0.48.7/pyield/anbima/ettj_ultima.py +0 -76
  13. pyield-0.48.7/pyield/anbima/ima_ultimo.py +0 -129
  14. pyield-0.48.7/pyield/tn/__init__.py +0 -7
  15. {pyield-0.48.7 → pyield-0.48.9}/.gitignore +0 -0
  16. {pyield-0.48.7 → pyield-0.48.9}/LICENSE +0 -0
  17. {pyield-0.48.7 → pyield-0.48.9}/README.md +0 -0
  18. {pyield-0.48.7 → pyield-0.48.9}/pyield/__init__.py +1 -1
  19. {pyield-0.48.7 → pyield-0.48.9}/pyield/_internal/__init__.py +0 -0
  20. {pyield-0.48.7 → pyield-0.48.9}/pyield/_internal/br_numbers.py +0 -0
  21. {pyield-0.48.7 → pyield-0.48.9}/pyield/_internal/cache.py +0 -0
  22. {pyield-0.48.7 → pyield-0.48.9}/pyield/_internal/converters.py +0 -0
  23. {pyield-0.48.7 → pyield-0.48.9}/pyield/_internal/data_cache.py +0 -0
  24. {pyield-0.48.7 → pyield-0.48.9}/pyield/_internal/retry.py +0 -0
  25. {pyield-0.48.7 → pyield-0.48.9}/pyield/_internal/types.py +0 -0
  26. {pyield-0.48.7 → pyield-0.48.9}/pyield/anbima/imaq.py +0 -0
  27. {pyield-0.48.7 → pyield-0.48.9}/pyield/anbima/tpf.py +0 -0
  28. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/__init__.py +0 -0
  29. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/_contratos.py +0 -0
  30. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/_validar_pregao.py +0 -0
  31. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/derivativos_intradia.py +0 -0
  32. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/di_over.py +0 -0
  33. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/futuro/contratos.py +0 -0
  34. {pyield-0.48.7 → pyield-0.48.9}/pyield/b3/futuro/intradia.py +0 -0
  35. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/__init__.py +0 -0
  36. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/_olinda.py +0 -0
  37. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/compromissada.py +0 -0
  38. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/copom.py +0 -0
  39. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/leiloes.py +0 -0
  40. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/sgs.py +0 -0
  41. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/tpf_intradia.py +0 -0
  42. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/tpf_mensal.py +0 -0
  43. {pyield-0.48.7 → pyield-0.48.9}/pyield/bc/vna.py +0 -0
  44. {pyield-0.48.7 → pyield-0.48.9}/pyield/du/__init__.py +0 -0
  45. {pyield-0.48.7 → pyield-0.48.9}/pyield/du/core.py +0 -0
  46. {pyield-0.48.7 → pyield-0.48.9}/pyield/du/feriados/__init__.py +0 -0
  47. {pyield-0.48.7 → pyield-0.48.9}/pyield/du/feriados/feriados_antigos_br.txt +0 -0
  48. {pyield-0.48.7 → pyield-0.48.9}/pyield/du/feriados/feriados_br.py +0 -0
  49. {pyield-0.48.7 → pyield-0.48.9}/pyield/du/feriados/feriados_novos_br.txt +0 -0
  50. {pyield-0.48.7 → pyield-0.48.9}/pyield/fwd.py +0 -0
  51. {pyield-0.48.7 → pyield-0.48.9}/pyield/interpolador.py +0 -0
  52. {pyield-0.48.7 → pyield-0.48.9}/pyield/ipca/__init__.py +0 -0
  53. {pyield-0.48.7 → pyield-0.48.9}/pyield/ipca/historico.py +0 -0
  54. {pyield-0.48.7 → pyield-0.48.9}/pyield/ipca/projetado.py +0 -0
  55. {pyield-0.48.7 → pyield-0.48.9}/pyield/py.typed +0 -0
  56. {pyield-0.48.7 → pyield-0.48.9}/pyield/relogio.py +0 -0
  57. {pyield-0.48.7 → pyield-0.48.9}/pyield/selic/__init__.py +0 -0
  58. {pyield-0.48.7 → pyield-0.48.9}/pyield/selic/cpm.py +0 -0
  59. {pyield-0.48.7 → pyield-0.48.9}/pyield/selic/probabilities.py +0 -0
  60. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/benchmark.py +0 -0
  61. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/leiloes.py +0 -0
  62. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/lft.py +0 -0
  63. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/ltn.py +0 -0
  64. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/ntnb.py +0 -0
  65. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/ntnb1.py +0 -0
  66. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/ntnbprinc.py +0 -0
  67. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/ntnc.py +0 -0
  68. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/ntnf.py +0 -0
  69. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/pre.py +0 -0
  70. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/rmd.py +0 -0
  71. {pyield-0.48.7 → pyield-0.48.9}/pyield/tn/utils.py +0 -0
  72. {pyield-0.48.7 → pyield-0.48.9}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyield
3
- Version: 0.48.7
3
+ Version: 0.48.9
4
4
  Summary: A Python library for analysis of fixed income instruments in Brazil
5
5
  Project-URL: Homepage, https://github.com/crdcj/PYield
6
6
  Project-URL: Documentation, https://crdcj.github.io/PYield
@@ -0,0 +1 @@
1
+ __version__ = "0.48.9"
@@ -0,0 +1,9 @@
1
+ from pyield.anbima.imaq import imaq
2
+ from pyield.anbima.tpf import tpf, tpf_fonte, tpf_vencimentos
3
+
4
+ __all__ = [
5
+ "imaq",
6
+ "tpf",
7
+ "tpf_vencimentos",
8
+ "tpf_fonte",
9
+ ]
@@ -102,6 +102,13 @@ COLUNAS_PRICE_REPORT: list[tuple[str, str, type[pl.DataType]]] = [
102
102
  SCHEMA_PRICE_REPORT = {nome: tipo for _, nome, tipo in COLUNAS_PRICE_REPORT}
103
103
 
104
104
 
105
+ _SESSAO = requests.Session()
106
+ _SESSAO.headers["User-Agent"] = (
107
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
108
+ " (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"
109
+ )
110
+
111
+
105
112
  @ttl_cache()
106
113
  @retry_padrao
107
114
  def _baixar_zip_url(data: dt.date, boletim_completo: bool) -> bytes:
@@ -113,7 +120,7 @@ def _baixar_zip_url(data: dt.date, boletim_completo: bool) -> bytes:
113
120
  f"https://www.b3.com.br/pesquisapregao/download?filelist=SPRD{data_str}.zip"
114
121
  )
115
122
 
116
- resposta = requests.get(url, timeout=(5, 30))
123
+ resposta = _SESSAO.get(url, timeout=(5, 30))
117
124
  resposta.raise_for_status()
118
125
 
119
126
  if len(resposta.content) < MIN_TAMANHO_ZIP_BYTES:
@@ -215,19 +222,12 @@ def _parsear_xml_registros(xml_bytes: bytes) -> list[dict]:
215
222
 
216
223
 
217
224
  def _converter_para_df(registros: list[dict]) -> pl.DataFrame:
218
- df = pl.DataFrame(registros)
219
- # Casting usa os nomes originais do XML, que são constantes
220
- tipos_coluna = {k: v for k, v in SCHEMA_PRICE_REPORT.items() if k in df.columns}
221
- df = df.cast(tipos_coluna, strict=False) # type: ignore
222
- # Adiciona colunas ausentes com null e garante ordem/schema constante
223
- colunas_faltantes = {
224
- nome: pl.lit(None).cast(tipo)
225
- for nome, tipo in SCHEMA_PRICE_REPORT.items()
226
- if nome not in df.columns
227
- }
228
- if colunas_faltantes:
229
- df = df.with_columns(**colunas_faltantes)
230
- return df.select(SCHEMA_PRICE_REPORT.keys())
225
+ # Schema explícito garante que todas as colunas existam no DataFrame,
226
+ # mesmo que os primeiros registros não tenham todas as chaves.
227
+ # (pl.DataFrame infere colunas de ~50 primeiras linhas por padrão.)
228
+ schema_str = {nome: pl.String for nome in SCHEMA_PRICE_REPORT}
229
+ df = pl.DataFrame(registros, schema=schema_str)
230
+ return df.cast(SCHEMA_PRICE_REPORT, strict=False) # type: ignore
231
231
 
232
232
 
233
233
  def _processar_xml_extraido(xml_bytes: bytes) -> pl.DataFrame:
@@ -236,11 +236,9 @@ def interpolar_taxas(
236
236
  extrapolar=extrapolar,
237
237
  )
238
238
 
239
- # 4. A mágica: map_batches passa a Series inteira para o interpolador
240
- # O interpolador retorna uma Series, que o Polars alinha perfeitamente
241
239
  df_parcial = df_parcial.with_columns(
242
240
  pl.col("dias_uteis")
243
- .map_batches(interpolador_du) # Passa Series -> Recebe Series
241
+ .map_elements(interpolador_du, return_dtype=pl.Float64)
244
242
  .alias("taxa_interpolada")
245
243
  )
246
244
 
@@ -13,12 +13,12 @@ def futuro_enriquecer(
13
13
  """Enriquece DataFrame bruto do Price Report (PR) da B3.
14
14
 
15
15
  Aceita um DataFrame com colunas no schema original da B3
16
- (ex.: ``TradDt``, ``TckrSymb``) ou renomeadas para o padrão
17
- PYield. Adiciona data de vencimento, dias úteis/corridos e
18
- colunas derivadas (dv01, taxa_forward) conforme o contrato.
16
+ (ex.: ``TradDt``, ``TckrSymb``). Filtra pelo contrato informado,
17
+ adiciona data de vencimento, dias úteis/corridos e colunas
18
+ derivadas (dv01, taxa_forward) conforme o contrato.
19
19
 
20
20
  Args:
21
- df: DataFrame com dados do PR da B3.
21
+ df: DataFrame com dados brutos do PR da B3.
22
22
  contrato: Contrato futuro
23
23
  (ex.: "DI1", "DOL").
24
24
 
@@ -76,6 +76,9 @@ _COLUNAS_CONTRATO_TAXA = (
76
76
  "taxa_forward",
77
77
  )
78
78
 
79
+ # Comprimento padrão de ticker de futuro na B3 (prefixo 3 + mês 1 + ano 2).
80
+ _COMPRIMENTO_TICKER = 6
81
+
79
82
  # Normaliza o schema XML bruto da B3 para o padrão de colunas deste módulo.
80
83
  _RENOMEAR_COLUNAS_PR = {
81
84
  "TradDt": "data_referencia",
@@ -125,7 +128,11 @@ def _enriquecer_dados(df: pl.DataFrame, contrato: str) -> pl.DataFrame:
125
128
 
126
129
  if contrato in {"DI1", "DAP"}:
127
130
  df = df.with_columns(
128
- taxa_forward=forwards(dias_uteis=df["dias_uteis"], taxas=df["taxa_ajuste"])
131
+ taxa_forward=forwards(
132
+ dias_uteis=df["dias_uteis"],
133
+ taxas=df["taxa_ajuste"],
134
+ agrupar_por=df["data_referencia"],
135
+ )
129
136
  )
130
137
 
131
138
  return df
@@ -156,12 +163,12 @@ def enriquecer(df: pl.DataFrame, contrato: str) -> pl.DataFrame:
156
163
  """Enriquece DataFrame bruto do Price Report (PR) da B3.
157
164
 
158
165
  Aceita um DataFrame com colunas no schema original da B3 (ex.:
159
- ``TradDt``, ``TckrSymb``) ou renomeadas para o padrão PYield.
160
- Adiciona data de vencimento, dias úteis/corridos e colunas derivadas
161
- (dv01, taxa_forward) conforme o contrato.
166
+ ``TradDt``, ``TckrSymb``). Filtra pelo contrato informado,
167
+ adiciona data de vencimento, dias úteis/corridos e colunas
168
+ derivadas (dv01, taxa_forward) conforme o contrato.
162
169
 
163
170
  Args:
164
- df: DataFrame com dados do PR da B3.
171
+ df: DataFrame com dados brutos do PR da B3.
165
172
  contrato: Contrato futuro (ex.: "DI1", "DOL").
166
173
 
167
174
  Returns:
@@ -171,6 +178,12 @@ def enriquecer(df: pl.DataFrame, contrato: str) -> pl.DataFrame:
171
178
  return pl.DataFrame()
172
179
 
173
180
  df = df.rename(_RENOMEAR_COLUNAS_PR)
181
+ df = df.filter(
182
+ pl.col("codigo_negociacao").str.starts_with(contrato),
183
+ pl.col("codigo_negociacao").str.len_chars() == _COMPRIMENTO_TICKER,
184
+ )
185
+ if df.is_empty():
186
+ return pl.DataFrame()
174
187
  df = adicionar_vencimento(df, contrato, coluna_ticker="codigo_negociacao")
175
188
  df = _enriquecer_dados(df, contrato)
176
189
  df = _selecionar_colunas_saida(df, contrato)
@@ -0,0 +1,20 @@
1
+ from pyield.tn import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf, pre
2
+ from pyield.tn.benchmark import benchmarks
3
+ from pyield.tn.leiloes import leilao
4
+ from pyield.tn.rmd import rmd
5
+ from pyield.tn.utils import premio_pre
6
+
7
+ __all__ = [
8
+ "benchmarks",
9
+ "leilao",
10
+ "lft",
11
+ "ltn",
12
+ "ntnb",
13
+ "ntnb1",
14
+ "ntnbprinc",
15
+ "ntnc",
16
+ "ntnf",
17
+ "pre",
18
+ "premio_pre",
19
+ "rmd",
20
+ ]
@@ -1 +0,0 @@
1
- __version__ = "0.48.7"
@@ -1,15 +0,0 @@
1
- from pyield.anbima.ettj_intradia import ettj_intradia
2
- from pyield.anbima.ettj_ultima import ettj_ultima
3
- from pyield.anbima.ima_ultimo import ima_ultimo
4
- from pyield.anbima.imaq import imaq
5
- from pyield.anbima.tpf import tpf, tpf_fonte, tpf_vencimentos
6
-
7
- __all__ = [
8
- "ima_ultimo",
9
- "imaq",
10
- "tpf",
11
- "tpf_vencimentos",
12
- "tpf_fonte",
13
- "ettj_ultima",
14
- "ettj_intradia",
15
- ]
@@ -1,83 +0,0 @@
1
- import datetime as dt
2
-
3
- import polars as pl
4
- import requests
5
-
6
- from pyield._internal.br_numbers import float_br, taxa_br
7
- from pyield._internal.cache import ttl_cache
8
- from pyield._internal.retry import retry_padrao
9
-
10
- URL_ETTJ_INTRADIA = (
11
- "https://www.anbima.com.br/informacoes/curvas-intradiarias/cIntra-down.asp"
12
- )
13
-
14
- # Dados ETTJ: taxas com 4 casas decimais em percentual (ex.: 14,2644%).
15
-
16
-
17
- @ttl_cache()
18
- @retry_padrao
19
- def _buscar_texto_intradia() -> str:
20
- carga_requisicao = {"Dt_Ref": "", "saida": "csv"}
21
- resposta = requests.post(URL_ETTJ_INTRADIA, data=carga_requisicao, timeout=10)
22
- resposta.raise_for_status()
23
- resposta.encoding = "latin1"
24
- return resposta.text
25
-
26
-
27
- def _extrair_data_e_tabelas(texto: str) -> tuple[dt.date, str, str]:
28
- """Separa o texto bruto em data de referência e as duas tabelas CSV."""
29
- # Cada seção (PREFIXADOS e IPCA) é separada por linha em branco
30
- secao_pre, secao_ipca = texto.strip().replace("\r\n", "\n").split("\n\n")
31
-
32
- # Estrutura de cada seção: título, data, header+dados
33
- linhas_pre = secao_pre.splitlines()
34
- data_ref = dt.datetime.strptime(linhas_pre[1], "%d/%m/%Y").date()
35
- tabela_pre = "\n".join(linhas_pre[2:])
36
-
37
- linhas_ipca = secao_ipca.splitlines()
38
- tabela_ipca = "\n".join(linhas_ipca[2:])
39
-
40
- return data_ref, tabela_pre, tabela_ipca
41
-
42
-
43
- def _parsear_tabela_intradia(texto: str, nome_taxa: str) -> pl.DataFrame:
44
- return pl.read_csv(texto.encode(), separator=";", infer_schema=False).select(
45
- vertice=float_br("Vertices").cast(pl.Int64),
46
- **{nome_taxa: taxa_br("D0")},
47
- )
48
-
49
-
50
- def ettj_intradia() -> pl.DataFrame:
51
- """Obtém e processa a curva de juros intradiária da ANBIMA.
52
-
53
- Busca os dados mais recentes da curva de juros intradiária publicada pela
54
- ANBIMA, contendo taxas reais (indexadas ao IPCA), taxas nominais e inflação
55
- implícita em diversos vértices. A curva é publicada por volta das 12h30 BRT.
56
-
57
- Returns:
58
- pl.DataFrame: DataFrame com os dados intradiários da ETTJ.
59
-
60
- Output Columns:
61
- - data_referencia (Date): data de referência da curva de juros.
62
- - vertice (Int64): vértice em dias úteis.
63
- - taxa_nominal (Float64): taxa de juros nominal zero-cupom.
64
- - taxa_real (Float64): taxa de juros real zero-cupom (indexada ao IPCA).
65
- - inflacao_implicita (Float64): taxa de inflação implícita (breakeven).
66
-
67
- Notes:
68
- Todas as taxas são expressas em formato decimal (ex: 0.12 para 12%).
69
- """
70
- texto_api = _buscar_texto_intradia()
71
-
72
- data_ref, tabela_pre, tabela_ipca = _extrair_data_e_tabelas(texto_api)
73
-
74
- df_pre = _parsear_tabela_intradia(tabela_pre, "taxa_nominal")
75
- df_ipca = _parsear_tabela_intradia(tabela_ipca, "taxa_real")
76
- expr_inflacao_impl = (pl.col("taxa_nominal") + 1) / (pl.col("taxa_real") + 1) - 1
77
- df = df_pre.join(df_ipca, on="vertice", how="right").with_columns(
78
- data_referencia=data_ref,
79
- inflacao_implicita=expr_inflacao_impl.round(6),
80
- )
81
- return df.select(
82
- "data_referencia", "vertice", "taxa_nominal", "taxa_real", "inflacao_implicita"
83
- )
@@ -1,76 +0,0 @@
1
- import datetime as dt
2
-
3
- import polars as pl
4
- import requests
5
-
6
- from pyield._internal.br_numbers import float_br, taxa_br
7
- from pyield._internal.cache import ttl_cache
8
- from pyield._internal.retry import retry_padrao
9
-
10
- URL_ETTJ_ULTIMA = "https://www.anbima.com.br/informacoes/est-termo/CZ-down.asp"
11
-
12
- # Dados ETTJ: taxas com 4 casas decimais em percentual (ex.: 14,2644%).
13
-
14
-
15
- @ttl_cache()
16
- @retry_padrao
17
- def _buscar_texto_ettj_ultima() -> str:
18
- """Busca o texto bruto da curva de juros na ANBIMA."""
19
- carga_requisicao = {
20
- "Idioma": "PT",
21
- "Dt_Ref": "",
22
- "saida": "csv",
23
- }
24
- resposta = requests.post(URL_ETTJ_ULTIMA, data=carga_requisicao, timeout=10)
25
- resposta.raise_for_status()
26
- resposta.encoding = "latin1"
27
- return resposta.text
28
-
29
-
30
- def _extrair_data_e_tabela(texto: str) -> tuple[dt.date, str]:
31
- """Separa o texto bruto em data de referência e a tabela CSV principal."""
32
- # Seções separadas por linha em branco: betas, ETTJ, circular, erros
33
- secoes = texto.strip().replace("\r\n", "\n").split("\n\n")
34
- # A data está na primeira linha da primeira seção (ex.: "20/03/2026;Beta 1;...")
35
- data_str = secoes[0].splitlines()[0][:10]
36
- data_ref = dt.datetime.strptime(data_str, "%d/%m/%Y").date()
37
- # A tabela ETTJ é a segunda seção; pular o título (primeira linha)
38
- linhas_ettj = secoes[1].splitlines()
39
- tabela = "\n".join(linhas_ettj[1:])
40
- return data_ref, tabela
41
-
42
-
43
- def _processar_tabela(texto: str, data_referencia: dt.date) -> pl.DataFrame:
44
- """Lê o CSV e converte para DataFrame com taxas decimais."""
45
- return pl.read_csv(texto.encode(), separator=";", infer_schema=False).select(
46
- data_referencia=data_referencia,
47
- vertice=float_br("Vertices").cast(pl.Int64),
48
- taxa_nominal=taxa_br("ETTJ PREF"),
49
- taxa_real=taxa_br("ETTJ IPCA"),
50
- inflacao_implicita=taxa_br("Inflação Implícita"),
51
- )
52
-
53
-
54
- def ettj_ultima() -> pl.DataFrame:
55
- """Obtém e processa a última curva de juros (ETTJ) publicada pela ANBIMA.
56
-
57
- Busca os dados mais recentes da curva de juros de fechamento publicada pela
58
- ANBIMA, contendo taxas reais (indexadas ao IPCA), taxas nominais e inflação
59
- implícita em diversos vértices.
60
-
61
- Returns:
62
- pl.DataFrame: DataFrame com os dados da ETTJ de fechamento.
63
-
64
- Output Columns:
65
- - data_referencia (Date): data de referência da curva de juros.
66
- - vertice (Int64): vértice em dias úteis.
67
- - taxa_nominal (Float64): taxa de juros nominal zero-cupom.
68
- - taxa_real (Float64): taxa de juros real zero-cupom (indexada ao IPCA).
69
- - inflacao_implicita (Float64): taxa de inflação implícita (breakeven).
70
-
71
- Notes:
72
- Todas as taxas são expressas em formato decimal (ex: 0.12 para 12%).
73
- """
74
- texto = _buscar_texto_ettj_ultima()
75
- data_ref, tabela = _extrair_data_e_tabela(texto)
76
- return _processar_tabela(tabela, data_ref)
@@ -1,129 +0,0 @@
1
- from typing import Literal
2
-
3
- import polars as pl
4
- import requests
5
-
6
- from pyield._internal.br_numbers import float_br, inteiro_m, taxa_br
7
- from pyield._internal.cache import ttl_cache
8
- from pyield._internal.retry import retry_padrao
9
-
10
- TiposIMA = Literal[
11
- "IRF-M 1",
12
- "IRF-M 1+",
13
- "IRF-M",
14
- "IMA-B 5",
15
- "IMA-B 5+",
16
- "IMA-B",
17
- "IMA-S",
18
- "IMA-GERAL-EX-C",
19
- "IMA-GERAL",
20
- ]
21
-
22
-
23
- URL_IMA_ULTIMO = "https://www.anbima.com.br/informacoes/ima/arqs/ima_completo.txt"
24
-
25
-
26
- @ttl_cache()
27
- @retry_padrao
28
- def _buscar_texto_ima_ultimo() -> str:
29
- resposta = requests.get(URL_IMA_ULTIMO, timeout=3)
30
- resposta.raise_for_status()
31
- resposta.encoding = "latin1"
32
- return resposta.text
33
-
34
-
35
- def _parsear_df(texto: str) -> pl.DataFrame:
36
- texto_csv = texto.split("2@COMPOSIÇÃO DE CARTEIRA")[1].strip()
37
- return pl.read_csv(
38
- texto_csv.encode(),
39
- separator="@",
40
- infer_schema=False,
41
- null_values="--",
42
- )
43
-
44
-
45
- def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
46
- mduration_expr = pl.col("duration") / (1 + pl.col("taxa_indicativa"))
47
- dv01_mercado_expr = pl.col("dv01") * pl.col("quantidade_mercado")
48
- df = (
49
- df.with_columns(
50
- pu=float_br("PU (R$)"),
51
- duration=pl.col("Duration (d.u.)").cast(pl.Int64).truediv(252),
52
- taxa_indicativa=taxa_br("Taxa Indicativa (% a.a.)", 4),
53
- quantidade_mercado=inteiro_m("Quantidade (1.000 títulos)"),
54
- )
55
- .with_columns(dv01=0.0001 * pl.col("pu") * mduration_expr)
56
- .select(
57
- data_referencia=pl.col("Data de Referência").str.to_date("%d/%m/%Y"),
58
- indice=pl.col("INDICE"),
59
- titulo=pl.col("Títulos"),
60
- data_vencimento=pl.col("Data de Vencimento").str.to_date("%d/%m/%Y"),
61
- codigo_selic=pl.col("Código SELIC").cast(pl.Int64),
62
- isin=pl.col("Código ISIN"),
63
- dias_uteis=pl.col("Prazo (d.u.)").cast(pl.Int64),
64
- duration=pl.col("duration"),
65
- taxa_indicativa=pl.col("taxa_indicativa"),
66
- pu=pl.col("pu"),
67
- pu_juros=float_br("PU de Juros (R$)"),
68
- dv01=pl.col("dv01"),
69
- pmr=float_br("PMR"),
70
- peso=float_br("Peso (%)"),
71
- convexidade=float_br("Convexidade"),
72
- quantidade_teorica=float_br("Quantidade Teórica (1.000 títulos)"),
73
- operacoes=pl.col("Número de Operações *").cast(pl.Int64),
74
- quantidade_negociada=inteiro_m("Quant. Negociada (1.000 títulos) *"),
75
- valor_negociado=inteiro_m("Valor Negociado (R$ mil) *"),
76
- dv01_mercado=dv01_mercado_expr.round(0).cast(pl.Int64),
77
- quantidade_mercado=pl.col("quantidade_mercado"),
78
- valor_mercado=inteiro_m("Carteira a Mercado (R$ mil)"),
79
- )
80
- )
81
- return df
82
-
83
-
84
- def ima_ultimo(indice: TiposIMA | None = None) -> pl.DataFrame:
85
- """Obtém os últimos dados de composição de carteira IMA disponíveis na ANBIMA.
86
-
87
- Busca e processa os dados do arquivo IMA completo publicado pela ANBIMA,
88
- retornando um DataFrame estruturado.
89
-
90
- Args:
91
- indice (str, optional): Tipo de índice IMA para filtrar os dados.
92
- Se None, retorna todos os índices. Padrão é None.
93
-
94
- Returns:
95
- pl.DataFrame: DataFrame com os dados do IMA.
96
-
97
- Output Columns:
98
- - data_referencia (Date): data de referência.
99
- - indice (String): índice IMA (ex: 'IMA-B', 'IRF-M').
100
- - titulo (String): título (ex: 'LTN', 'NTN-B').
101
- - data_vencimento (Date): data de vencimento do título.
102
- - codigo_selic (Int64): código do título no sistema SELIC.
103
- - isin (String): código ISIN.
104
- - dias_uteis (Int64): dias úteis até o vencimento.
105
- - duration (Float64): duration do título em anos úteis (252 d.u./ano).
106
- - taxa_indicativa (Float64): taxa indicativa em decimal (ex: 0.10 para 10%).
107
- - pu (Float64): preço unitário (PU) em R$.
108
- - pu_juros (Float64): PU de juros em R$.
109
- - dv01 (Float64): DV01 em R$.
110
- - pmr (Float64): prazo médio de repactuação.
111
- - peso (Float64): peso do título no índice (%).
112
- - convexidade (Float64): convexidade do título.
113
- - quantidade_teorica (Float64): quantidade teórica (em 1.000 títulos).
114
- - operacoes (Int64): número de operações.
115
- - quantidade_negociada (Int64): quantidade negociada (unidades).
116
- - valor_negociado (Int64): valor negociado em R$.
117
- - dv01_mercado (Int64): DV01 de mercado em R$.
118
- - quantidade_mercado (Int64): quantidade em carteira (unidades).
119
- - valor_mercado (Int64): valor de mercado em R$.
120
-
121
- Examples:
122
- >>> yd.anbima.ima_ultimo("IMA-B") # doctest: +SKIP
123
- """
124
- texto_ima = _buscar_texto_ima_ultimo()
125
- df = _parsear_df(texto_ima)
126
- df = _processar_df(df)
127
- if indice:
128
- df = df.filter(pl.col("indice") == indice)
129
- return df.sort("indice", "titulo", "data_vencimento")
@@ -1,7 +0,0 @@
1
- from pyield.tn import pre
2
- from pyield.tn.benchmark import benchmarks
3
- from pyield.tn.leiloes import leilao
4
- from pyield.tn.rmd import rmd
5
- from pyield.tn.utils import premio_pre
6
-
7
- __all__ = ["benchmarks", "leilao", "pre", "premio_pre", "rmd"]
File without changes
File without changes
File without changes
@@ -10,7 +10,6 @@ from pyield.selic.cpm import data as copom_options
10
10
  from pyield.tn import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf
11
11
 
12
12
  __all__ = [
13
- "Interpolador",
14
13
  "__version__",
15
14
  "agora",
16
15
  "anbima",
@@ -22,6 +21,7 @@ __all__ = [
22
21
  "forward",
23
22
  "forwards",
24
23
  "hoje",
24
+ "Interpolador",
25
25
  "ipca",
26
26
  "lft",
27
27
  "ltn",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes