PYield 0.46.7__tar.gz → 0.46.8__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 (69) hide show
  1. {pyield-0.46.7 → pyield-0.46.8}/PKG-INFO +1 -1
  2. pyield-0.46.8/pyield/__about__.py +1 -0
  3. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/futures/__init__.py +29 -35
  4. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/futures/historical.py +7 -11
  5. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/price_report.py +9 -21
  6. pyield-0.46.7/pyield/__about__.py +0 -1
  7. {pyield-0.46.7 → pyield-0.46.8}/.gitignore +0 -0
  8. {pyield-0.46.7 → pyield-0.46.8}/LICENSE +0 -0
  9. {pyield-0.46.7 → pyield-0.46.8}/README.md +0 -0
  10. {pyield-0.46.7 → pyield-0.46.8}/pyield/__init__.py +0 -0
  11. {pyield-0.46.7 → pyield-0.46.8}/pyield/_internal/__init__.py +0 -0
  12. {pyield-0.46.7 → pyield-0.46.8}/pyield/_internal/br_numbers.py +0 -0
  13. {pyield-0.46.7 → pyield-0.46.8}/pyield/_internal/cache.py +0 -0
  14. {pyield-0.46.7 → pyield-0.46.8}/pyield/_internal/converters.py +0 -0
  15. {pyield-0.46.7 → pyield-0.46.8}/pyield/_internal/data_cache.py +0 -0
  16. {pyield-0.46.7 → pyield-0.46.8}/pyield/_internal/retry.py +0 -0
  17. {pyield-0.46.7 → pyield-0.46.8}/pyield/_internal/types.py +0 -0
  18. {pyield-0.46.7 → pyield-0.46.8}/pyield/anbima/__init__.py +0 -0
  19. {pyield-0.46.7 → pyield-0.46.8}/pyield/anbima/ettj_intraday.py +0 -0
  20. {pyield-0.46.7 → pyield-0.46.8}/pyield/anbima/ettj_last.py +0 -0
  21. {pyield-0.46.7 → pyield-0.46.8}/pyield/anbima/ima.py +0 -0
  22. {pyield-0.46.7 → pyield-0.46.8}/pyield/anbima/imaq.py +0 -0
  23. {pyield-0.46.7 → pyield-0.46.8}/pyield/anbima/tpf.py +0 -0
  24. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/__init__.py +0 -0
  25. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/_contracts.py +0 -0
  26. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/_validar_pregao.py +0 -0
  27. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/di1.py +0 -0
  28. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/di_over.py +0 -0
  29. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/futures/common.py +0 -0
  30. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/futures/intraday.py +0 -0
  31. {pyield-0.46.7 → pyield-0.46.8}/pyield/b3/intraday_derivatives.py +0 -0
  32. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/__init__.py +0 -0
  33. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/auction.py +0 -0
  34. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/copom.py +0 -0
  35. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/ptax_api.py +0 -0
  36. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/rates.py +0 -0
  37. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/repo.py +0 -0
  38. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/trades_intraday.py +0 -0
  39. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/trades_monthly.py +0 -0
  40. {pyield-0.46.7 → pyield-0.46.8}/pyield/bc/vna.py +0 -0
  41. {pyield-0.46.7 → pyield-0.46.8}/pyield/bday/__init__.py +0 -0
  42. {pyield-0.46.7 → pyield-0.46.8}/pyield/bday/core.py +0 -0
  43. {pyield-0.46.7 → pyield-0.46.8}/pyield/bday/holidays/br_holidays_new.txt +0 -0
  44. {pyield-0.46.7 → pyield-0.46.8}/pyield/bday/holidays/br_holidays_old.txt +0 -0
  45. {pyield-0.46.7 → pyield-0.46.8}/pyield/bday/holidays/brholidays.py +0 -0
  46. {pyield-0.46.7 → pyield-0.46.8}/pyield/clock.py +0 -0
  47. {pyield-0.46.7 → pyield-0.46.8}/pyield/fwd.py +0 -0
  48. {pyield-0.46.7 → pyield-0.46.8}/pyield/interpolator.py +0 -0
  49. {pyield-0.46.7 → pyield-0.46.8}/pyield/ipca/__init__.py +0 -0
  50. {pyield-0.46.7 → pyield-0.46.8}/pyield/ipca/historical.py +0 -0
  51. {pyield-0.46.7 → pyield-0.46.8}/pyield/ipca/projected.py +0 -0
  52. {pyield-0.46.7 → pyield-0.46.8}/pyield/py.typed +0 -0
  53. {pyield-0.46.7 → pyield-0.46.8}/pyield/rmd.py +0 -0
  54. {pyield-0.46.7 → pyield-0.46.8}/pyield/selic/__init__.py +0 -0
  55. {pyield-0.46.7 → pyield-0.46.8}/pyield/selic/cpm.py +0 -0
  56. {pyield-0.46.7 → pyield-0.46.8}/pyield/selic/probabilities.py +0 -0
  57. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/__init__.py +0 -0
  58. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/auctions.py +0 -0
  59. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/benchmark.py +0 -0
  60. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/lft.py +0 -0
  61. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/ltn.py +0 -0
  62. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/ntnb.py +0 -0
  63. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/ntnb1.py +0 -0
  64. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/ntnbprinc.py +0 -0
  65. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/ntnc.py +0 -0
  66. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/ntnf.py +0 -0
  67. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/pre.py +0 -0
  68. {pyield-0.46.7 → pyield-0.46.8}/pyield/tn/utils.py +0 -0
  69. {pyield-0.46.7 → pyield-0.46.8}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyield
3
- Version: 0.46.7
3
+ Version: 0.46.8
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.46.8"
@@ -19,7 +19,7 @@ logger = logging.getLogger(__name__)
19
19
  def futures(
20
20
  date: DateLike | ArrayLike,
21
21
  contract_code: str | list[str],
22
- full_report: bool | None = None,
22
+ full_report: bool = False,
23
23
  ) -> pl.DataFrame:
24
24
  """Busca dados de um contrato futuro da B3 para a data de referência.
25
25
 
@@ -28,29 +28,25 @@ def futures(
28
28
  Quando uma coleção é fornecida, os dados são buscados para cada
29
29
  data individualmente e concatenados. Datas inválidas (feriados,
30
30
  fins de semana, futuras) são silenciosamente ignoradas.
31
- contract_code: Código do contrato futuro na B3 ou coleção de códigos.
32
- Exemplos de códigos válidos:
33
- - Juros: DI1, DDI, OC1, DAP, IAP
34
- - Moedas: DOL, WDO, EUR, GBR, JAP, CNY
35
- - Índices: IND, WIN, ISP, WSP
36
- - Commodities: BGI, CCM, ICF, CNL, SJC, SOY, ETH, GLD
37
- full_report: Controla a fonte de dados quando o dado não está no cache.
38
- Se None (padrão) e a data é hoje: entre 09:16 e 19:00 prioriza
39
- dados intraday; a partir das 19:00 prioriza os dados consolidados
40
- (SPR → PR) com intraday como fallback.
41
- Se False, usa o simplified price report (SPR, ~2 KB).
42
- Se True, usa apenas o price report completo (PR, ~2 MB) —
31
+ contract_code: Código do contrato futuro na B3 ou coleção de
32
+ códigos. Aceita qualquer código de contrato futuro listado
33
+ na B3. Contratos com histórico pré-cacheado (desde 2018)
34
+ são retornados instantaneamente:
35
+ - Juros: DI1, DDI, FRC, FRO, DAP
36
+ - Moedas: DOL, WDO
37
+ - Índices: IND, WIN
38
+ Para os demais contratos (OC1, IAP, EUR, GBR, JAP, CNY,
39
+ ISP, WSP, BGI, CCM, ICF, SJC, SOY, ETH, GLD, etc.),
40
+ os dados são baixados diretamente da B3 a cada chamada.
41
+ full_report: Controla a fonte de dados quando o dado não está
42
+ no cache. Se False (padrão), tenta o simplified price
43
+ report (SPR, ~2 KB) primeiro e faz fallback para o price
44
+ report completo (PR, ~2 MB). Se True, usa apenas o PR —
43
45
  indicado para processos batch noturnos.
44
46
 
45
47
  Returns:
46
48
  DataFrame Polars com os dados do contrato informado.
47
49
 
48
- Notes:
49
- Os contratos DI1, DDI, FRC, FRO, DAP, DOL, WDO, IND e WIN possuem
50
- histórico pré-cacheado (desde 2018) e são retornados instantaneamente.
51
- Para os demais contratos, os dados são baixados diretamente da B3 a
52
- cada chamada, o que pode ser mais lento.
53
-
54
50
  Examples:
55
51
  >>> df = futures("31-05-2024", "DI1")
56
52
  >>> df = futures("31-05-2024", "DAP")
@@ -101,7 +97,7 @@ def futures(
101
97
  def _buscar_varias_datas(
102
98
  datas: ArrayLike,
103
99
  codigos: list[str],
104
- full_report: bool | None,
100
+ full_report: bool,
105
101
  ) -> pl.DataFrame:
106
102
  """Busca dados para múltiplas datas e concatena os resultados.
107
103
 
@@ -142,27 +138,25 @@ def _buscar_varias_datas(
142
138
  def _buscar_por_fonte(
143
139
  data: dt.date,
144
140
  codigos: list[str],
145
- full_report: bool | None,
141
+ full_report: bool,
146
142
  ) -> pl.DataFrame:
147
- """Seleciona a fonte de dados com base no horário e parâmetros."""
148
- if full_report is not None or data != clock.today():
143
+ """Seleciona a fonte de dados com base na data e horário.
144
+
145
+ Para datas passadas, usa dados consolidados (historical).
146
+ Para a data de hoje, depende do horário:
147
+ - Antes das 09:16: sem dados disponíveis (DataFrame vazio).
148
+ - Entre 09:16 e 19:00: dados intraday.
149
+ - A partir das 19:00: dados consolidados (historical).
150
+ """
151
+ if data != clock.today():
149
152
  return historical.historical(data, codigos, full_report)
150
153
 
151
154
  horario = clock.now().time()
152
155
  if horario >= HORA_INICIO_CONSOLIDADO:
153
- # Consolidado (SPR → PR) primeiro; intraday como fallback
154
- df = historical.historical(data, codigos, full_report)
155
- if not df.is_empty():
156
- return df
157
- return intraday.intraday(codigos)
158
-
156
+ return historical.historical(data, codigos, full_report)
159
157
  if horario >= HORA_INICIO_INTRADAY:
160
- # Intraday primeiro; historical como fallback
161
- df = intraday.intraday(codigos)
162
- if not df.is_empty():
163
- return df
164
-
165
- return historical.historical(data, codigos, full_report)
158
+ return intraday.intraday(codigos)
159
+ return pl.DataFrame()
166
160
 
167
161
 
168
162
  def available_dates(contract_code: str) -> pl.Series:
@@ -63,16 +63,15 @@ def _obter_pr_normalizado() -> pl.DataFrame:
63
63
  def historical(
64
64
  data: dt.date,
65
65
  codigo_contrato: str | list[str],
66
- full_report: bool | None = None,
66
+ full_report: bool = False,
67
67
  ) -> pl.DataFrame:
68
68
  """Busca histórico de futuros priorizando o dataset PR cacheado.
69
69
 
70
70
  Args:
71
71
  data: Data de negociação.
72
72
  codigo_contrato: Código(s) do contrato futuro na B3.
73
- full_report: Se None (padrão), tenta SPR primeiro e PR como fallback.
74
- Se False, usa o simplified price report (SPR, ~2 KB).
75
- Se True, usa o price report completo (PR, ~2 MB).
73
+ full_report: Se False (padrão), tenta SPR primeiro e PR como
74
+ fallback. Se True, usa apenas o PR completo (~2 MB).
76
75
 
77
76
  Returns:
78
77
  DataFrame Polars com dados históricos de futuros.
@@ -202,16 +201,13 @@ def listar_datas_disponiveis(codigo_contrato: str) -> pl.Series:
202
201
  )
203
202
 
204
203
 
205
- def _buscar_price_report(
206
- data: dt.date, codigo: str, full_report: bool | None
207
- ) -> pl.DataFrame:
204
+ def _buscar_price_report(data: dt.date, codigo: str, full_report: bool) -> pl.DataFrame:
208
205
  """Busca o price report da B3, com fallback SPR→PR.
209
206
 
210
- Quando full_report é True, usa apenas o PR (completo).
211
- Nos demais casos (None ou False), tenta o SPR (leve) primeiro
212
- e faz fallback para o PR se o SPR estiver vazio.
207
+ Se full_report é True, usa apenas o PR (completo).
208
+ Se False, tenta o SPR (leve) primeiro e faz fallback para o PR.
213
209
  """
214
- if full_report is True:
210
+ if full_report:
215
211
  return _normalizar_colunas_pr(
216
212
  fetch_price_report(date=data, contract_code=codigo, full_report=True)
217
213
  )
@@ -102,30 +102,18 @@ def _baixar_zip_url(data: dt.date, relatorio_completo: bool) -> bytes:
102
102
 
103
103
 
104
104
  def _extrair_xml_de_zip(conteudo_zip: bytes) -> bytes:
105
- """Extrai o XML de um ZIP, suportando ZIP aninhado (ZIP→ZIP→XML) ou simples (ZIP→XML)."""
105
+ """Extrai o XML do ZIP aninhado da B3 (ZIP externo → ZIP interno → XML)."""
106
106
  with zipfile.ZipFile(io.BytesIO(conteudo_zip), "r") as zip_externo:
107
- nomes_externos = zip_externo.namelist()
108
- if not nomes_externos:
107
+ nomes = zip_externo.namelist()
108
+ if not nomes:
109
109
  raise ValueError("ZIP externo está vazio")
110
110
 
111
- # Caso 1: ZIP contém XML diretamente
112
- nomes_xml = sorted(n for n in nomes_externos if n.endswith(".xml"))
113
- if nomes_xml:
114
- return zip_externo.read(nomes_xml[-1])
115
-
116
- # Caso 2: ZIP aninhado — busca o primeiro ZIP interno válido
117
- for nome in nomes_externos:
118
- conteudo_interno = zip_externo.read(nome)
119
- if conteudo_interno[:4] != b"PK\x03\x04":
120
- continue
121
- with zipfile.ZipFile(io.BytesIO(conteudo_interno), "r") as zip_interno:
122
- nomes_xml = sorted(
123
- n for n in zip_interno.namelist() if n.endswith(".xml")
124
- )
125
- if nomes_xml:
126
- return zip_interno.read(nomes_xml[-1])
127
-
128
- raise ValueError("Nenhum XML encontrado no ZIP")
111
+ conteudo_interno = zip_externo.read(nomes[0])
112
+ with zipfile.ZipFile(io.BytesIO(conteudo_interno), "r") as zip_interno:
113
+ nomes_xml = sorted(n for n in zip_interno.namelist() if n.endswith(".xml"))
114
+ if not nomes_xml:
115
+ raise ValueError("Nenhum XML encontrado no ZIP interno")
116
+ return zip_interno.read(nomes_xml[-1])
129
117
 
130
118
 
131
119
  def _ticker_valido_para_contrato(ticker: str, codigo_contrato: str) -> bool:
@@ -1 +0,0 @@
1
- __version__ = "0.46.7"
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes