pyield 0.49.0__tar.gz → 0.49.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 (67) hide show
  1. {pyield-0.49.0 → pyield-0.49.2}/PKG-INFO +1 -1
  2. {pyield-0.49.0 → pyield-0.49.2}/pyield/__init__.py +4 -4
  3. pyield-0.49.2/pyield/b3/__init__.py +7 -0
  4. {pyield-0.49.0 → pyield-0.49.2}/pyield/b3/boletim.py +115 -57
  5. {pyield-0.49.0 → pyield-0.49.2}/pyield/bc/leiloes.py +2 -2
  6. {pyield-0.49.0/pyield/b3 → pyield-0.49.2/pyield}/di1.py +2 -2
  7. pyield-0.49.2/pyield/futuro/__init__.py +14 -0
  8. {pyield-0.49.0/pyield/b3 → pyield-0.49.2/pyield}/futuro/historico.py +1 -1
  9. {pyield-0.49.0/pyield/b3 → pyield-0.49.2/pyield}/futuro/intradia.py +1 -1
  10. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield}/lft.py +1 -1
  11. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield}/ltn.py +1 -1
  12. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield}/ntnb.py +1 -1
  13. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield}/ntnb1.py +1 -1
  14. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield}/ntnbprinc.py +1 -1
  15. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield}/ntnc.py +1 -1
  16. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield}/ntnf.py +1 -1
  17. {pyield-0.49.0 → pyield-0.49.2}/pyield/selic/cpm.py +2 -2
  18. pyield-0.49.0/pyield/tpf.py → pyield-0.49.2/pyield/tpf/__init__.py +5 -5
  19. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield/tpf}/leiloes.py +2 -2
  20. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield/tpf}/pre.py +2 -2
  21. {pyield-0.49.0 → pyield-0.49.2}/pyproject.toml +1 -1
  22. pyield-0.49.0/pyield/b3/__init__.py +0 -1
  23. pyield-0.49.0/pyield/b3/futuro/__init__.py +0 -14
  24. pyield-0.49.0/pyield/tn/__init__.py +0 -1
  25. {pyield-0.49.0 → pyield-0.49.2}/LICENSE +0 -0
  26. {pyield-0.49.0 → pyield-0.49.2}/README.md +0 -0
  27. {pyield-0.49.0 → pyield-0.49.2}/pyield/_internal/__init__.py +0 -0
  28. {pyield-0.49.0 → pyield-0.49.2}/pyield/_internal/br_numbers.py +0 -0
  29. {pyield-0.49.0 → pyield-0.49.2}/pyield/_internal/cache.py +0 -0
  30. {pyield-0.49.0 → pyield-0.49.2}/pyield/_internal/converters.py +0 -0
  31. {pyield-0.49.0 → pyield-0.49.2}/pyield/_internal/data_cache.py +0 -0
  32. {pyield-0.49.0 → pyield-0.49.2}/pyield/_internal/retry.py +0 -0
  33. {pyield-0.49.0 → pyield-0.49.2}/pyield/_internal/types.py +0 -0
  34. {pyield-0.49.0 → pyield-0.49.2}/pyield/anbima/__init__.py +0 -0
  35. {pyield-0.49.0 → pyield-0.49.2}/pyield/anbima/imaq.py +0 -0
  36. {pyield-0.49.0 → pyield-0.49.2}/pyield/anbima/mercado_secundario.py +0 -0
  37. {pyield-0.49.0 → pyield-0.49.2}/pyield/b3/_contratos.py +0 -0
  38. {pyield-0.49.0 → pyield-0.49.2}/pyield/b3/_validar_pregao.py +0 -0
  39. {pyield-0.49.0 → pyield-0.49.2}/pyield/b3/derivativos_intradia.py +0 -0
  40. {pyield-0.49.0 → pyield-0.49.2}/pyield/b3/di_over.py +0 -0
  41. {pyield-0.49.0 → pyield-0.49.2}/pyield/bc/__init__.py +0 -0
  42. {pyield-0.49.0 → pyield-0.49.2}/pyield/bc/_olinda.py +0 -0
  43. {pyield-0.49.0 → pyield-0.49.2}/pyield/bc/sgs.py +0 -0
  44. {pyield-0.49.0 → pyield-0.49.2}/pyield/bc/tpf_intradia.py +0 -0
  45. {pyield-0.49.0 → pyield-0.49.2}/pyield/bc/tpf_mensal.py +0 -0
  46. {pyield-0.49.0 → pyield-0.49.2}/pyield/bc/vna.py +0 -0
  47. {pyield-0.49.0 → pyield-0.49.2}/pyield/du/__init__.py +0 -0
  48. {pyield-0.49.0 → pyield-0.49.2}/pyield/du/core.py +0 -0
  49. {pyield-0.49.0 → pyield-0.49.2}/pyield/du/feriados/__init__.py +0 -0
  50. {pyield-0.49.0 → pyield-0.49.2}/pyield/du/feriados/feriados_antigos_br.txt +0 -0
  51. {pyield-0.49.0 → pyield-0.49.2}/pyield/du/feriados/feriados_br.py +0 -0
  52. {pyield-0.49.0 → pyield-0.49.2}/pyield/du/feriados/feriados_novos_br.txt +0 -0
  53. {pyield-0.49.0/pyield/b3 → pyield-0.49.2/pyield}/futuro/contratos.py +0 -0
  54. {pyield-0.49.0 → pyield-0.49.2}/pyield/fwd.py +0 -0
  55. {pyield-0.49.0 → pyield-0.49.2}/pyield/interpolador.py +0 -0
  56. {pyield-0.49.0 → pyield-0.49.2}/pyield/ipca/__init__.py +0 -0
  57. {pyield-0.49.0 → pyield-0.49.2}/pyield/ipca/historico.py +0 -0
  58. {pyield-0.49.0 → pyield-0.49.2}/pyield/ipca/projetado.py +0 -0
  59. {pyield-0.49.0 → pyield-0.49.2}/pyield/py.typed +0 -0
  60. {pyield-0.49.0 → pyield-0.49.2}/pyield/relogio.py +0 -0
  61. {pyield-0.49.0 → pyield-0.49.2}/pyield/selic/__init__.py +0 -0
  62. {pyield-0.49.0 → pyield-0.49.2}/pyield/selic/compromissada.py +0 -0
  63. {pyield-0.49.0 → pyield-0.49.2}/pyield/selic/copom.py +0 -0
  64. {pyield-0.49.0 → pyield-0.49.2}/pyield/selic/probabilities.py +0 -0
  65. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield/tpf}/benchmark.py +0 -0
  66. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield/tpf}/rmd.py +0 -0
  67. {pyield-0.49.0/pyield/tn → pyield-0.49.2/pyield/tpf}/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyield
3
- Version: 0.49.0
3
+ Version: 0.49.2
4
4
  Summary: A Python library for analysis of fixed income instruments in Brazil
5
5
  Keywords: fixed-income,brazil,finance,analysis,bonds
6
6
  Author: Carlos Carvalho
@@ -3,10 +3,9 @@
3
3
  import logging
4
4
  from importlib.metadata import PackageNotFoundError, version
5
5
 
6
- from pyield import du, ipca
7
- from pyield.b3 import futuro
8
- from pyield.b3 import di1
6
+ from pyield import b3, du, ipca
9
7
  from pyield.b3.di_over import di_over
8
+ from pyield import futuro, di1
10
9
 
11
10
  # Ordem intencional: alguns módulos importam `di1` a partir de `pyield`
12
11
  # durante a inicialização do pacote.
@@ -15,7 +14,7 @@ from pyield.bc.sgs import ptax, ptax_serie
15
14
  from pyield.fwd import forward, forwards
16
15
  from pyield.interpolador import Interpolador
17
16
  from pyield.relogio import agora, hoje
18
- from pyield.tn import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf
17
+ from pyield import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf
19
18
 
20
19
  try:
21
20
  __version__ = version("pyield")
@@ -25,6 +24,7 @@ except PackageNotFoundError:
25
24
  __all__ = [
26
25
  "__version__",
27
26
  "agora",
27
+ "b3",
28
28
  "di1",
29
29
  "di_over",
30
30
  "du",
@@ -0,0 +1,7 @@
1
+ """APIs técnicas da B3."""
2
+
3
+ from pyield.b3 import boletim as boletim
4
+
5
+ __all__ = [
6
+ "boletim",
7
+ ]
@@ -1,38 +1,38 @@
1
- """
2
- Exemplo de trecho do XML bruto da B3:
1
+ """Boletim de Negociação da B3.
2
+
3
+ Este módulo expõe helpers técnicos para buscar e ler o Price Report da B3.
4
+ As funções preservam o schema bruto da fonte e servem como base para
5
+ camadas públicas enriquecidas, como ``futuro`` e ``selic.cpm``.
6
+
7
+ Estrutura resumida de um registro do XML bruto da B3::
8
+
3
9
  <PricRpt>
4
- <TradDt>
5
- <Dt>2026-04-01</Dt>
6
- </TradDt>
7
- <SctyId>
8
- <TckrSymb>DI1F31</TckrSymb>
9
- </SctyId>
10
+ <TradDt><Dt>2026-04-01</Dt></TradDt>
11
+ <SctyId><TckrSymb>DI1F31</TckrSymb></SctyId>
10
12
  <FinInstrmId>
11
13
  <OthrId>
12
14
  <Id>200000235664</Id>
13
- <Tp>
14
- <Prtry>8</Prtry>
15
- </Tp>
15
+ <Tp><Prtry>8</Prtry></Tp>
16
16
  </OthrId>
17
- <PlcOfListg>
18
- <MktIdrCd>BVMF</MktIdrCd>
19
- </PlcOfListg>
17
+ <PlcOfListg><MktIdrCd>BVMF</MktIdrCd></PlcOfListg>
20
18
  </FinInstrmId>
21
- <TradDtls>
22
- <TradQty>29880</TradQty>
23
- </TradDtls>
19
+ <TradDtls><TradQty>29880</TradQty></TradDtls>
24
20
  <FinInstrmAttrbts>
25
21
  <MktDataStrmId>E</MktDataStrmId>
26
22
  ...
27
23
  <MinTradLmt Ccy="BRL">12.87</MinTradLmt>
28
24
  </FinInstrmAttrbts>
29
25
  </PricRpt>
26
+
27
+ Ref: https://www.b3.com.br/data/files/16/70/29/9C/6219D710C8F297D7AC094EA8/Catalogo_precos_v1.3.pdf
30
28
  """
31
29
 
32
30
  import datetime as dt
33
31
  import io
32
+ import logging
34
33
  import re
35
34
  import zipfile
35
+ from pathlib import Path
36
36
 
37
37
  import polars as pl
38
38
  import requests
@@ -45,17 +45,15 @@ from pyield._internal.types import DateLike, any_is_empty
45
45
  from pyield.b3._contratos import normalizar_contratos
46
46
  from pyield.b3._validar_pregao import data_negociacao_valida
47
47
 
48
- # --- Constantes de Processamento XML ---
49
- NAMESPACE_B3 = "urn:bvmf.217.01.xsd"
50
- NAMESPACES = {"ns": NAMESPACE_B3}
51
- # ZIP válido do price report ~2KB; 1KB detecta arquivos "sem dados"
52
- MIN_TAMANHO_ZIP_BYTES = 1024
53
- XPATH_PRICE_REPORT = "//ns:PricRpt"
48
+ __all__ = [
49
+ "baixar_zip",
50
+ "buscar",
51
+ "ler",
52
+ ]
54
53
 
55
54
  # --- Mapeamento de Colunas ---
56
55
  # Estrutura: (id_pdf, nome_xml, tipo_polars)
57
56
  # Esta camada base preserva os nomes originais do XML da B3.
58
- # https://www.b3.com.br/data/files/16/70/29/9C/6219D710C8F297D7AC094EA8/Catalogo_precos_v1.3.pdf
59
57
  COLUNAS_PRICE_REPORT: list[tuple[str, str, type[pl.DataType]]] = [
60
58
  ("1.00", "TradDt", pl.Date),
61
59
  ("2.01", "TckrSymb", pl.String),
@@ -101,7 +99,7 @@ COLUNAS_PRICE_REPORT: list[tuple[str, str, type[pl.DataType]]] = [
101
99
  # Schema completo: nome_xml → tipo_polars. Garante ordem e tipagem constante.
102
100
  SCHEMA_PRICE_REPORT = {nome: tipo for _, nome, tipo in COLUNAS_PRICE_REPORT}
103
101
 
104
-
102
+ logger = logging.getLogger(__name__)
105
103
  _SESSAO = requests.Session()
106
104
  _SESSAO.headers["User-Agent"] = (
107
105
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
@@ -111,24 +109,76 @@ _SESSAO.headers["User-Agent"] = (
111
109
 
112
110
  @ttl_cache()
113
111
  @retry_padrao
114
- def _baixar_zip_url(data: dt.date, boletim_completo: bool) -> bytes:
112
+ def baixar_zip(data: DateLike, boletim_completo: bool = False) -> bytes:
113
+ """Baixa o ZIP bruto do Boletim de Negociação da B3.
114
+
115
+ Faz o download do Price Report da B3, no formato completo (PR) ou no
116
+ simplified price report (SPR), e retorna apenas ZIPs estruturalmente
117
+ válidos para persistência como dado bruto.
118
+
119
+ Args:
120
+ data: Data de negociação no formato 'DD-MM-YYYY', 'DD/MM/YYYY',
121
+ 'YYYY-MM-DD' ou objeto datetime.date.
122
+ boletim_completo: Se False (padrão), usa o simplified price report
123
+ (SPR). Se True, usa o price report completo (PR).
124
+
125
+ Returns:
126
+ Conteúdo do ZIP externo em bytes quando o ZIP contém um XML legível.
127
+ Retorna ``b""`` quando a resposta não contém um ZIP válido.
128
+ """
129
+ if any_is_empty(data):
130
+ return bytes()
131
+
132
+ data = cv.converter_datas(data)
115
133
  data_str = data.strftime("%y%m%d")
116
- if boletim_completo:
117
- url = f"https://www.b3.com.br/pesquisapregao/download?filelist=PR{data_str}.zip"
118
- else:
119
- url = (
120
- f"https://www.b3.com.br/pesquisapregao/download?filelist=SPRD{data_str}.zip"
121
- )
134
+ prefixo = "PR" if boletim_completo else "SPRD"
135
+ url = f"https://www.b3.com.br/pesquisapregao/download?filelist={prefixo}{data_str}.zip"
122
136
 
123
137
  resposta = _SESSAO.get(url, timeout=(5, 10))
124
138
  resposta.raise_for_status()
125
139
 
126
- if len(resposta.content) < MIN_TAMANHO_ZIP_BYTES:
140
+ if not _zip_valido(resposta.content):
127
141
  return bytes()
128
142
  return resposta.content
129
143
 
130
144
 
131
- def boletim_negociacao_extrair(conteudo_zip: bytes) -> bytes:
145
+ def _zip_valido(conteudo_zip: bytes) -> bool: # noqa: PLR0911
146
+ """Verifica se o ZIP bruto do boletim contém um XML legível."""
147
+ tamanho_minimo = 1024 # ZIP válido ~2KB; 1KB detecta arquivos "sem dados"
148
+ if len(conteudo_zip) < tamanho_minimo:
149
+ logger.debug("ZIP do boletim ignorado: tamanho menor que o mínimo.")
150
+ return False
151
+
152
+ try:
153
+ with zipfile.ZipFile(io.BytesIO(conteudo_zip), "r") as zip_externo:
154
+ nomes = zip_externo.namelist()
155
+ if not nomes:
156
+ logger.debug("ZIP externo do boletim está vazio.")
157
+ return False
158
+ if zip_externo.testzip() is not None:
159
+ logger.debug("ZIP externo do boletim contém arquivo corrompido.")
160
+ return False
161
+
162
+ conteudo_interno = zip_externo.read(nomes[0])
163
+ with zipfile.ZipFile(io.BytesIO(conteudo_interno), "r") as zip_interno:
164
+ nomes_xml = [
165
+ nome for nome in zip_interno.namelist() if nome.endswith(".xml")
166
+ ]
167
+ if not nomes_xml:
168
+ logger.debug("ZIP interno do boletim não contém XML.")
169
+ return False
170
+ if zip_interno.testzip() is not None:
171
+ logger.debug("ZIP interno do boletim contém arquivo corrompido.")
172
+ return False
173
+
174
+ except (zipfile.BadZipFile, KeyError, OSError, RuntimeError):
175
+ logger.debug("ZIP do boletim inválido ou ilegível.")
176
+ return False
177
+
178
+ return True
179
+
180
+
181
+ def _extrair(conteudo_zip: bytes) -> bytes:
132
182
  """Extrai o XML válido do ZIP aninhado do Price Report da B3.
133
183
 
134
184
  O ZIP da B3 contém um ZIP interno, que por sua vez contém um ou
@@ -201,6 +251,7 @@ def _extrair_dados_contrato(pric_rpt: etree._Element) -> dict | None:
201
251
 
202
252
 
203
253
  def _parsear_xml_registros(xml_bytes: bytes) -> list[dict]:
254
+ namespaces = {"ns": "urn:bvmf.217.01.xsd"}
204
255
  analisador = etree.XMLParser(
205
256
  ns_clean=True,
206
257
  remove_blank_text=True,
@@ -211,7 +262,7 @@ def _parsear_xml_registros(xml_bytes: bytes) -> list[dict]:
211
262
  load_dtd=False,
212
263
  )
213
264
  arvore = etree.parse(io.BytesIO(xml_bytes), parser=analisador)
214
- resultado = arvore.xpath(XPATH_PRICE_REPORT, namespaces=NAMESPACES)
265
+ resultado = arvore.xpath("//ns:PricRpt", namespaces=namespaces)
215
266
  elementos: list[etree._Element] = resultado # type: ignore[assignment]
216
267
  registros = [
217
268
  dados
@@ -251,25 +302,26 @@ def _filtrar_df(
251
302
  return df.sort("TckrSymb")
252
303
 
253
304
 
254
- def _obter_df_boletim_negociacao(data: dt.date, boletim_completo: bool) -> pl.DataFrame:
255
- dados_zip = _baixar_zip_url(data, boletim_completo)
305
+ def _obter_df_boletim(data: dt.date, boletim_completo: bool) -> pl.DataFrame:
306
+ dados_zip = baixar_zip(data, boletim_completo)
256
307
  if not dados_zip:
257
308
  return pl.DataFrame()
258
- xml_bytes = boletim_negociacao_extrair(dados_zip)
309
+ xml_bytes = _extrair(dados_zip)
259
310
  return _processar_xml_extraido(xml_bytes)
260
311
 
261
312
 
262
- def boletim_negociacao(
313
+ def buscar(
263
314
  data: DateLike,
264
315
  prefixo_ticker: str | list[str] | None = None,
265
316
  comprimento_ticker: int | None = None,
266
317
  boletim_completo: bool = False,
267
318
  ) -> pl.DataFrame:
268
- """Busca e processa o Boletim de Negociacao da B3 no site oficial.
319
+ """Busca e processa o Boletim de Negociação da B3 no site oficial.
269
320
 
270
- Faz o download do ZIP com XML, extrai os dados do contrato e devolve um
271
- DataFrame Polars com os dados brutos do XML e colunas no padrão
272
- original da B3 (nomes em inglês das tags XML).
321
+ Faz o download do Price Report da B3, no formato completo (PR) ou no
322
+ simplified price report (SPR), extrai o XML do ZIP publicado em
323
+ ``pesquisapregao`` e devolve um DataFrame Polars com dados brutos e
324
+ colunas no padrão original da B3 (nomes em inglês das tags XML).
273
325
 
274
326
  O DataFrame retornado **não** contém colunas calculadas
275
327
  (dias_uteis, dias_corridos, dv01, taxa_forward)
@@ -353,14 +405,14 @@ def boletim_negociacao(
353
405
  etree.XMLSyntaxError: Se o XML recebido estiver malformado.
354
406
 
355
407
  Examples:
356
- >>> from pyield.b3.boletim import boletim_negociacao
357
- >>> df = boletim_negociacao("26-04-2024", "DI1")
408
+ >>> import pyield as yd
409
+ >>> df = yd.b3.boletim.buscar("26-04-2024", "DI1")
358
410
 
359
411
  >>> # Múltiplos contratos de uma vez
360
- >>> df = boletim_negociacao("26-04-2024", ["DI1", "DAP"])
412
+ >>> df = yd.b3.boletim.buscar("26-04-2024", ["DI1", "DAP"])
361
413
 
362
414
  >>> # Feriado ou fim de semana (retorna DataFrame vazio)
363
- >>> df = boletim_negociacao("25-12-2023", "DI1") # Véspera de Natal
415
+ >>> df = yd.b3.boletim.buscar("25-12-2023", "DI1")
364
416
  >>> df.is_empty()
365
417
  True
366
418
  """
@@ -372,7 +424,7 @@ def boletim_negociacao(
372
424
  if not data_negociacao_valida(data):
373
425
  return pl.DataFrame()
374
426
 
375
- df = _obter_df_boletim_negociacao(data, boletim_completo)
427
+ df = _obter_df_boletim(data, boletim_completo)
376
428
  if df.is_empty() or prefixo_ticker is None:
377
429
  return df
378
430
 
@@ -382,21 +434,23 @@ def boletim_negociacao(
382
434
  return _filtrar_df(df, prefixos, comprimento_ticker)
383
435
 
384
436
 
385
- def boletim_negociacao_ler(
386
- xml_bytes: bytes,
437
+ def ler(
438
+ fonte: bytes | Path,
387
439
  prefixo_ticker: str | list[str] | None = None,
388
440
  comprimento_ticker: int | None = None,
389
441
  ) -> pl.DataFrame:
390
- """Lê e processa o price report da B3 a partir do conteúdo XML bruto.
442
+ """Lê e processa o price report da B3 a partir do dado bruto.
391
443
 
392
- Mesma saída de :func:`boletim_negociacao`, mas recebe o XML
393
- descomprimido em vez de baixar da rede.
444
+ Mesma saída de :func:`buscar`, mas recebe o dado bruto em vez de
445
+ baixar da rede. Aceita o ZIP externo como ``bytes`` ou ``Path``
446
+ (caminho para o arquivo ZIP), e também XML descomprimido como ``bytes``.
394
447
 
395
- Por operar diretamente sobre o XML bruto, esta função preserva a
448
+ Por operar diretamente sobre o dado bruto, esta função preserva a
396
449
  terminologia da fonte para filtros de `TckrSymb`.
397
450
 
398
451
  Args:
399
- xml_bytes: Conteúdo do XML em bytes ( descomprimido).
452
+ fonte: ZIP externo em bytes, caminho (``Path``) para um arquivo ZIP
453
+ no disco, ou XML já descomprimido em bytes.
400
454
  prefixo_ticker: Prefixo do ticker B3 (ex.: 'DI1', 'DOL',
401
455
  'CPM') ou lista de prefixos (ex.: ['DI1', 'DAP']).
402
456
  Se None (padrão), retorna todos os ativos sem filtro.
@@ -406,11 +460,15 @@ def boletim_negociacao_ler(
406
460
 
407
461
  Returns:
408
462
  pl.DataFrame: DataFrame com as mesmas colunas documentadas em
409
- :func:`boletim_negociacao`.
463
+ :func:`buscar`.
410
464
  """
411
- if any_is_empty(xml_bytes):
465
+ conteudo = fonte.read_bytes() if isinstance(fonte, Path) else fonte
466
+
467
+ if any_is_empty(conteudo):
412
468
  return pl.DataFrame()
413
469
 
470
+ xml_bytes = _extrair(conteudo) if conteudo[:4] == b"PK\x03\x04" else conteudo
471
+
414
472
  df = _processar_xml_extraido(xml_bytes)
415
473
  if df.is_empty() or prefixo_ticker is None:
416
474
  return df
@@ -19,8 +19,8 @@ from pyield._internal.br_numbers import float_br, taxa_br
19
19
  from pyield._internal.types import DateLike
20
20
  from pyield.bc._olinda import buscar_csv, montar_url, parsear_csv
21
21
  from pyield.bc.sgs import ptax_serie
22
- from pyield.tn.ntnb import duration as duration_b
23
- from pyield.tn.ntnf import duration as duration_f
22
+ from pyield.ntnb import duration as duration_b
23
+ from pyield.ntnf import duration as duration_f
24
24
 
25
25
  registro = logging.getLogger(__name__)
26
26
 
@@ -11,8 +11,8 @@ import pyield._internal.converters as cv
11
11
  from pyield import du
12
12
  from pyield._internal.data_cache import obter_dataset_cacheado
13
13
  from pyield._internal.types import ArrayLike, DateLike, any_is_collection, any_is_empty
14
- from pyield.b3.futuro.historico import buscar_historico_cacheado
15
- from pyield.b3.futuro.historico import datas_disponiveis as _datas_futuro
14
+ from pyield.futuro.historico import buscar_historico_cacheado
15
+ from pyield.futuro.historico import datas_disponiveis as _datas_futuro
16
16
  from pyield.interpolador import Interpolador
17
17
 
18
18
 
@@ -0,0 +1,14 @@
1
+ """Contratos futuros negociados na B3."""
2
+
3
+ from pyield.futuro.contratos import vencimento, vencimento_expr
4
+ from pyield.futuro.historico import datas_disponiveis, enriquecer, historico
5
+ from pyield.futuro.intradia import intradia
6
+
7
+ __all__ = [
8
+ "datas_disponiveis",
9
+ "enriquecer",
10
+ "historico",
11
+ "intradia",
12
+ "vencimento",
13
+ "vencimento_expr",
14
+ ]
@@ -9,7 +9,7 @@ from pyield._internal.br_numbers import pct_para_decimal
9
9
  from pyield._internal.data_cache import obter_dataset_cacheado
10
10
  from pyield._internal.types import ArrayLike, DateLike, any_is_empty
11
11
  from pyield.b3._validar_pregao import data_negociacao_valida
12
- from pyield.b3.futuro import contratos as ct
12
+ from pyield.futuro import contratos as ct
13
13
  from pyield.fwd import forwards
14
14
 
15
15
  # Renomeação preco_* → taxa_* para contratos cotados por taxa.
@@ -5,7 +5,7 @@ from pyield import du
5
5
  from pyield._internal.br_numbers import pct_para_decimal
6
6
  from pyield.b3._validar_pregao import intradia_disponivel
7
7
  from pyield.b3.derivativos_intradia import derivativo_intradia
8
- from pyield.b3.futuro.contratos import CONTRATOS_TAXA, dv01_expr
8
+ from pyield.futuro.contratos import CONTRATOS_TAXA, dv01_expr
9
9
  from pyield.fwd import forwards
10
10
 
11
11
  # Renomeação preco_* → taxa_* para contratos cotados por taxa.
@@ -4,7 +4,7 @@ import pyield._internal.converters as cv
4
4
  from pyield import du
5
5
  from pyield._internal.types import DateLike, any_is_empty
6
6
  from pyield.bc.vna import vna
7
- from pyield.tn import utils
7
+ from pyield.tpf import utils
8
8
 
9
9
  __all__ = ["cotacao", "dados", "inflacao_implicita", "taxa", "vencimentos", "vna"]
10
10
 
@@ -3,7 +3,7 @@ import polars as pl
3
3
  import pyield._internal.converters as cv
4
4
  from pyield import du, fwd
5
5
  from pyield._internal.types import DateLike, any_is_empty
6
- from pyield.tn import utils
6
+ from pyield.tpf import utils
7
7
 
8
8
  VALOR_FACE = 1000
9
9
 
@@ -6,7 +6,7 @@ import polars as pl
6
6
  import pyield._internal.converters as conversores
7
7
  from pyield import du, fwd, interpolador
8
8
  from pyield._internal.types import ArrayLike, DateLike, any_is_empty
9
- from pyield.tn import utils
9
+ from pyield.tpf import utils
10
10
 
11
11
  """
12
12
  Constantes calculadas conforme regras da ANBIMA e em base 100.
@@ -5,7 +5,7 @@ import polars as pl
5
5
  import pyield._internal.converters as conversores
6
6
  from pyield import du
7
7
  from pyield._internal.types import DateLike, any_is_empty
8
- from pyield.tn import utils
8
+ from pyield.tpf import utils
9
9
 
10
10
  """
11
11
  Parâmetros globais para cálculos de NTN-B1.
@@ -1,6 +1,6 @@
1
1
  from pyield import du
2
2
  from pyield._internal.types import DateLike, any_is_empty
3
- from pyield.tn import utils
3
+ from pyield.tpf import utils
4
4
 
5
5
 
6
6
  def pu(
@@ -5,7 +5,7 @@ import polars as pl
5
5
  import pyield._internal.converters as conversores
6
6
  from pyield import du
7
7
  from pyield._internal.types import DateLike, any_is_empty
8
- from pyield.tn import utils
8
+ from pyield.tpf import utils
9
9
 
10
10
  """
11
11
  Constantes calculadas conforme regras da ANBIMA e em base 100.
@@ -8,7 +8,7 @@ import pyield._internal.converters as cv
8
8
  import pyield.interpolador as ip
9
9
  from pyield import di1, du
10
10
  from pyield._internal.types import ArrayLike, DateLike, any_is_empty
11
- from pyield.tn import utils
11
+ from pyield.tpf import utils
12
12
 
13
13
  """
14
14
  Constantes calculadas conforme regras da ANBIMA
@@ -41,7 +41,7 @@ import pyield._internal.converters as cv
41
41
  from pyield import du
42
42
  from pyield._internal.retry import retry_padrao
43
43
  from pyield._internal.types import DateLike
44
- from pyield.b3.boletim import boletim_negociacao
44
+ from pyield.b3 import boletim
45
45
 
46
46
  logger = logging.getLogger(__name__)
47
47
 
@@ -271,7 +271,7 @@ def data(date: DateLike) -> pl.DataFrame:
271
271
  return _empty_schema()
272
272
 
273
273
  try:
274
- df = boletim_negociacao(trade_date, prefixo_ticker="CPM")
274
+ df = boletim.buscar(trade_date, prefixo_ticker="CPM")
275
275
  except Exception:
276
276
  logger.exception("CPM: falha ao baixar SPR para %s.", trade_date)
277
277
  return _empty_schema()
@@ -4,11 +4,11 @@ from pyield.anbima.imaq import estoque
4
4
  from pyield.anbima.mercado_secundario import TipoTPF, taxas, vencimentos
5
5
  from pyield.bc.tpf_intradia import secundario_intradia
6
6
  from pyield.bc.tpf_mensal import secundario_mensal
7
- from pyield.tn.benchmark import benchmarks
8
- from pyield.tn.leiloes import leilao
9
- from pyield.tn.pre import curva_pre
10
- from pyield.tn.rmd import rmd
11
- from pyield.tn.utils import premio_pre
7
+ from pyield.tpf.benchmark import benchmarks
8
+ from pyield.tpf.leiloes import leilao
9
+ from pyield.tpf.pre import curva_pre
10
+ from pyield.tpf.rmd import rmd
11
+ from pyield.tpf.utils import premio_pre
12
12
 
13
13
  __all__ = [
14
14
  "TipoTPF",
@@ -13,8 +13,8 @@ from pyield._internal.cache import ttl_cache
13
13
  from pyield._internal.retry import retry_padrao
14
14
  from pyield._internal.types import DateLike, any_is_empty, is_collection
15
15
  from pyield.bc.sgs import ptax_serie
16
- from pyield.tn.ntnb import duration as duration_b
17
- from pyield.tn.ntnf import duration as duration_f
16
+ from pyield.ntnb import duration as duration_b
17
+ from pyield.ntnf import duration as duration_f
18
18
 
19
19
  logger = logging.getLogger(__name__)
20
20
 
@@ -1,8 +1,8 @@
1
1
  import polars as pl
2
2
 
3
- from pyield import du
3
+ from pyield import du, ntnf
4
4
  from pyield._internal.types import DateLike
5
- from pyield.tn import ntnf, utils
5
+ from pyield.tpf import utils
6
6
 
7
7
 
8
8
  def curva_pre(data: DateLike) -> pl.DataFrame:
@@ -18,7 +18,7 @@ dependencies = [
18
18
  "requests>=2.31.0",
19
19
  "fastexcel>=0.19.0",
20
20
  ]
21
- version = "0.49.0"
21
+ version = "0.49.2"
22
22
 
23
23
  [project.urls]
24
24
  Homepage = "https://github.com/crdcj/PYield"
@@ -1 +0,0 @@
1
-
@@ -1,14 +0,0 @@
1
- """Contratos futuros negociados na B3."""
2
-
3
- from pyield.b3.futuro.contratos import vencimento, vencimento_expr
4
- from pyield.b3.futuro.historico import datas_disponiveis, enriquecer, historico
5
- from pyield.b3.futuro.intradia import intradia
6
-
7
- __all__ = [
8
- "datas_disponiveis",
9
- "enriquecer",
10
- "historico",
11
- "intradia",
12
- "vencimento",
13
- "vencimento_expr",
14
- ]
@@ -1 +0,0 @@
1
-
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