PYield 0.46.8__tar.gz → 0.47.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.
Files changed (69) hide show
  1. {pyield-0.46.8 → pyield-0.47.0}/PKG-INFO +1 -1
  2. pyield-0.47.0/pyield/__about__.py +1 -0
  3. {pyield-0.46.8 → pyield-0.47.0}/pyield/__init__.py +2 -1
  4. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/__init__.py +2 -1
  5. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/di1.py +2 -2
  6. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/futures/__init__.py +58 -65
  7. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/futures/historical.py +9 -49
  8. pyield-0.46.8/pyield/__about__.py +0 -1
  9. {pyield-0.46.8 → pyield-0.47.0}/.gitignore +0 -0
  10. {pyield-0.46.8 → pyield-0.47.0}/LICENSE +0 -0
  11. {pyield-0.46.8 → pyield-0.47.0}/README.md +0 -0
  12. {pyield-0.46.8 → pyield-0.47.0}/pyield/_internal/__init__.py +0 -0
  13. {pyield-0.46.8 → pyield-0.47.0}/pyield/_internal/br_numbers.py +0 -0
  14. {pyield-0.46.8 → pyield-0.47.0}/pyield/_internal/cache.py +0 -0
  15. {pyield-0.46.8 → pyield-0.47.0}/pyield/_internal/converters.py +0 -0
  16. {pyield-0.46.8 → pyield-0.47.0}/pyield/_internal/data_cache.py +0 -0
  17. {pyield-0.46.8 → pyield-0.47.0}/pyield/_internal/retry.py +0 -0
  18. {pyield-0.46.8 → pyield-0.47.0}/pyield/_internal/types.py +0 -0
  19. {pyield-0.46.8 → pyield-0.47.0}/pyield/anbima/__init__.py +0 -0
  20. {pyield-0.46.8 → pyield-0.47.0}/pyield/anbima/ettj_intraday.py +0 -0
  21. {pyield-0.46.8 → pyield-0.47.0}/pyield/anbima/ettj_last.py +0 -0
  22. {pyield-0.46.8 → pyield-0.47.0}/pyield/anbima/ima.py +0 -0
  23. {pyield-0.46.8 → pyield-0.47.0}/pyield/anbima/imaq.py +0 -0
  24. {pyield-0.46.8 → pyield-0.47.0}/pyield/anbima/tpf.py +0 -0
  25. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/_contracts.py +0 -0
  26. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/_validar_pregao.py +0 -0
  27. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/di_over.py +0 -0
  28. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/futures/common.py +0 -0
  29. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/futures/intraday.py +0 -0
  30. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/intraday_derivatives.py +0 -0
  31. {pyield-0.46.8 → pyield-0.47.0}/pyield/b3/price_report.py +0 -0
  32. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/__init__.py +0 -0
  33. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/auction.py +0 -0
  34. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/copom.py +0 -0
  35. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/ptax_api.py +0 -0
  36. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/rates.py +0 -0
  37. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/repo.py +0 -0
  38. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/trades_intraday.py +0 -0
  39. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/trades_monthly.py +0 -0
  40. {pyield-0.46.8 → pyield-0.47.0}/pyield/bc/vna.py +0 -0
  41. {pyield-0.46.8 → pyield-0.47.0}/pyield/bday/__init__.py +0 -0
  42. {pyield-0.46.8 → pyield-0.47.0}/pyield/bday/core.py +0 -0
  43. {pyield-0.46.8 → pyield-0.47.0}/pyield/bday/holidays/br_holidays_new.txt +0 -0
  44. {pyield-0.46.8 → pyield-0.47.0}/pyield/bday/holidays/br_holidays_old.txt +0 -0
  45. {pyield-0.46.8 → pyield-0.47.0}/pyield/bday/holidays/brholidays.py +0 -0
  46. {pyield-0.46.8 → pyield-0.47.0}/pyield/clock.py +0 -0
  47. {pyield-0.46.8 → pyield-0.47.0}/pyield/fwd.py +0 -0
  48. {pyield-0.46.8 → pyield-0.47.0}/pyield/interpolator.py +0 -0
  49. {pyield-0.46.8 → pyield-0.47.0}/pyield/ipca/__init__.py +0 -0
  50. {pyield-0.46.8 → pyield-0.47.0}/pyield/ipca/historical.py +0 -0
  51. {pyield-0.46.8 → pyield-0.47.0}/pyield/ipca/projected.py +0 -0
  52. {pyield-0.46.8 → pyield-0.47.0}/pyield/py.typed +0 -0
  53. {pyield-0.46.8 → pyield-0.47.0}/pyield/rmd.py +0 -0
  54. {pyield-0.46.8 → pyield-0.47.0}/pyield/selic/__init__.py +0 -0
  55. {pyield-0.46.8 → pyield-0.47.0}/pyield/selic/cpm.py +0 -0
  56. {pyield-0.46.8 → pyield-0.47.0}/pyield/selic/probabilities.py +0 -0
  57. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/__init__.py +0 -0
  58. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/auctions.py +0 -0
  59. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/benchmark.py +0 -0
  60. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/lft.py +0 -0
  61. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/ltn.py +0 -0
  62. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/ntnb.py +0 -0
  63. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/ntnb1.py +0 -0
  64. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/ntnbprinc.py +0 -0
  65. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/ntnc.py +0 -0
  66. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/ntnf.py +0 -0
  67. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/pre.py +0 -0
  68. {pyield-0.46.8 → pyield-0.47.0}/pyield/tn/utils.py +0 -0
  69. {pyield-0.46.8 → pyield-0.47.0}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyield
3
- Version: 0.46.8
3
+ Version: 0.47.0
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.47.0"
@@ -2,7 +2,7 @@ import logging
2
2
 
3
3
  from pyield import anbima, b3, bc, bday, ipca, selic, tn
4
4
  from pyield.__about__ import __version__
5
- from pyield.b3 import di1, futures
5
+ from pyield.b3 import di1, futures, futures_intraday
6
6
  from pyield.clock import now, today
7
7
  from pyield.fwd import forward, forwards
8
8
  from pyield.interpolator import Interpolator
@@ -37,6 +37,7 @@ __all__ = [
37
37
  "rmd",
38
38
  "bday",
39
39
  "selic",
40
+ "futures_intraday",
40
41
  ]
41
42
 
42
43
  # Configura o logger do pacote principal com um NullHandler
@@ -1,6 +1,6 @@
1
1
  from pyield.b3 import di1
2
2
  from pyield.b3.di_over import di_over
3
- from pyield.b3.futures import futures
3
+ from pyield.b3.futures import futures, futures_intraday
4
4
  from pyield.b3.intraday_derivatives import fetch_intraday_derivatives
5
5
  from pyield.b3.price_report import fetch_price_report, read_price_report
6
6
 
@@ -8,6 +8,7 @@ __all__ = [
8
8
  "fetch_intraday_derivatives",
9
9
  "di_over",
10
10
  "futures",
11
+ "futures_intraday",
11
12
  "fetch_price_report",
12
13
  "read_price_report",
13
14
  "di1",
@@ -62,7 +62,7 @@ def data(
62
62
  else:
63
63
  datas_lista = [datas_convertidas]
64
64
 
65
- df = b3.futures(date=datas_lista, contract_code="DI1", full_report=False)
65
+ df = b3.futures(date=datas_lista, contract_code="DI1")
66
66
  if df.is_empty():
67
67
  return df
68
68
 
@@ -195,7 +195,7 @@ def interpolate_rates(
195
195
 
196
196
  # Carrega dataset de taxas DI usando datas já convertidas do df_entrada
197
197
  datas_unicas = df_entrada["data_referencia"].drop_nulls().unique().sort().to_list()
198
- df_ref = b3.futures(date=datas_unicas, contract_code="DI1", full_report=False)
198
+ df_ref = b3.futures(date=datas_unicas, contract_code="DI1")
199
199
  # Retorna Series vazia se nenhuma taxa for encontrada
200
200
  if df_ref.is_empty():
201
201
  return pl.Series(dtype=pl.Float64)
@@ -1,48 +1,33 @@
1
1
  import datetime as dt
2
- import logging
3
2
 
4
3
  import polars as pl
5
4
 
6
5
  import pyield._internal.converters as cv
7
- from pyield import clock
8
6
  from pyield._internal.types import ArrayLike, DateLike, any_is_empty, is_collection
9
7
  from pyield.b3._contracts import normalizar_codigos_contrato
10
- from pyield.b3._validar_pregao import HORA_INICIO_INTRADAY, data_negociacao_valida
8
+ from pyield.b3._validar_pregao import data_negociacao_valida
11
9
  from pyield.b3.futures import historical, intraday
12
10
 
13
- # A partir desse horário, os dados consolidados (SPR/PR) já estão disponíveis.
14
- HORA_INICIO_CONSOLIDADO = dt.time(19, 0)
15
-
16
- logger = logging.getLogger(__name__)
17
-
18
11
 
19
12
  def futures(
20
13
  date: DateLike | ArrayLike,
21
14
  contract_code: str | list[str],
22
- full_report: bool = False,
23
15
  ) -> pl.DataFrame:
24
16
  """Busca dados de um contrato futuro da B3 para a data de referência.
25
17
 
18
+ Dados obtidos do dataset PR cacheado no GitHub (disponível desde 2018).
19
+ Para dados do pregão corrente, use ``futures_intraday``.
20
+
26
21
  Args:
27
22
  date: Data de referência para consulta ou coleção de datas.
28
23
  Quando uma coleção é fornecida, os dados são buscados para cada
29
24
  data individualmente e concatenados. Datas inválidas (feriados,
30
25
  fins de semana, futuras) são silenciosamente ignoradas.
31
26
  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:
27
+ códigos. Contratos disponíveis no cache histórico:
35
28
  - Juros: DI1, DDI, FRC, FRO, DAP
36
29
  - Moedas: DOL, WDO
37
30
  - Í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 —
45
- indicado para processos batch noturnos.
46
31
 
47
32
  Returns:
48
33
  DataFrame Polars com os dados do contrato informado.
@@ -84,26 +69,21 @@ def futures(
84
69
  if is_collection(date):
85
70
  # date é ArrayLike neste branch
86
71
  datas: ArrayLike = date # type: ignore[assignment]
87
- return _buscar_varias_datas(datas, codigos_contrato, full_report)
72
+ return _buscar_varias_datas(datas, codigos_contrato)
88
73
 
89
74
  # date é escalar (DateLike) neste branch
90
75
  data_negociacao: dt.date = cv.converter_datas(date) # type: ignore[assignment]
91
76
  if not data_negociacao_valida(data_negociacao):
92
77
  return pl.DataFrame()
93
78
 
94
- return _buscar_por_fonte(data_negociacao, codigos_contrato, full_report)
79
+ return historical.historical(data_negociacao, codigos_contrato)
95
80
 
96
81
 
97
82
  def _buscar_varias_datas(
98
83
  datas: ArrayLike,
99
84
  codigos: list[str],
100
- full_report: bool,
101
85
  ) -> pl.DataFrame:
102
- """Busca dados para múltiplas datas e concatena os resultados.
103
-
104
- Prioriza o dataset PR cacheado (bulk). Para datas ausentes no cache,
105
- busca individualmente via _buscar_por_fonte.
106
- """
86
+ """Busca dados para múltiplas datas do dataset PR cacheado."""
107
87
  serie_datas = cv.converter_datas(datas)
108
88
  datas_validas = [
109
89
  d for d in serie_datas if d is not None and data_negociacao_valida(d)
@@ -111,52 +91,65 @@ def _buscar_varias_datas(
111
91
  if not datas_validas:
112
92
  return pl.DataFrame()
113
93
 
114
- # Bulk: carrega todas as datas de uma vez do cache, por contrato
115
- resultados = []
116
- for codigo in codigos:
117
- df_cache = historical._obter_futuros_pr(datas_validas, codigo)
118
- if not df_cache.is_empty():
119
- resultados.append(df_cache)
120
-
121
- # Identifica datas que não vieram do cache
122
- datas_no_cache: set[dt.date] = set()
123
- for df in resultados:
124
- datas_no_cache.update(df["data_referencia"].unique().to_list())
125
- datas_faltantes = [d for d in datas_validas if d not in datas_no_cache]
126
-
127
- # Fallback individual apenas para datas faltantes
128
- for data in datas_faltantes:
129
- df = _buscar_por_fonte(data, codigos, full_report)
130
- if not df.is_empty():
131
- resultados.append(df)
94
+ resultados = [
95
+ df
96
+ for codigo in codigos
97
+ if not (df := historical._obter_futuros_pr(datas_validas, codigo)).is_empty()
98
+ ]
132
99
 
133
100
  if not resultados:
134
101
  return pl.DataFrame()
135
102
  return pl.concat(resultados, how="diagonal_relaxed")
136
103
 
137
104
 
138
- def _buscar_por_fonte(
139
- data: dt.date,
140
- codigos: list[str],
141
- full_report: bool,
105
+ def futures_intraday(
106
+ contract_code: str | list[str],
142
107
  ) -> pl.DataFrame:
143
- """Seleciona a fonte de dados com base na data e horário.
108
+ """Busca dados intraday de contratos futuros da B3.
109
+
110
+ Retorna os dados mais recentes do pregão corrente, com atraso
111
+ aproximado de 15 minutos. Para dados históricos consolidados,
112
+ use ``futures``.
113
+
114
+ Args:
115
+ contract_code: Código do contrato futuro na B3 ou lista de
116
+ códigos (ex.: 'DI1', ['DI1', 'DAP']).
144
117
 
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).
118
+ Returns:
119
+ DataFrame Polars com dados intraday. Retorna DataFrame vazio
120
+ fora do horário de pregão.
121
+
122
+ Output Columns:
123
+ * data_referencia (Date): data de negociação.
124
+ * atualizado_as (Datetime): horário a que o dado se refere
125
+ (com atraso de ~15 min).
126
+ * codigo_negociacao (String): código de negociação na B3.
127
+ * data_vencimento (Date): data de vencimento do contrato.
128
+ * dias_uteis (Int64): dias úteis até o vencimento.
129
+ * dias_corridos (Int64): dias corridos até o vencimento.
130
+ * contratos_abertos (Int64): contratos em aberto.
131
+ * numero_negocios (Int64): número de negócios.
132
+ * volume_negociado (Int64): quantidade de contratos negociados.
133
+ * volume_financeiro (Float64): volume financeiro bruto.
134
+ * dv01 (Float64): variação no preço para 1bp (apenas DI1).
135
+ * preco_ultimo (Float64): último preço (apenas DI1/DAP).
136
+ * taxa_ajuste_anterior (Float64): taxa de ajuste do dia anterior.
137
+ * taxa_limite_minimo (Float64): limite mínimo de variação.
138
+ * taxa_limite_maximo (Float64): limite máximo de variação.
139
+ * taxa_abertura (Float64): taxa de abertura.
140
+ * taxa_minima (Float64): taxa mínima negociada.
141
+ * taxa_media (Float64): taxa média negociada.
142
+ * taxa_maxima (Float64): taxa máxima negociada.
143
+ * taxa_oferta_compra (Float64): melhor oferta de compra.
144
+ * taxa_oferta_venda (Float64): melhor oferta de venda.
145
+ * taxa_ultima (Float64): última taxa negociada.
146
+ * taxa_forward (Float64): taxa a termo (apenas DI1/DAP).
150
147
  """
151
- if data != clock.today():
152
- return historical.historical(data, codigos, full_report)
148
+ codigos = normalizar_codigos_contrato(contract_code)
149
+ if not codigos:
150
+ return pl.DataFrame()
153
151
 
154
- horario = clock.now().time()
155
- if horario >= HORA_INICIO_CONSOLIDADO:
156
- return historical.historical(data, codigos, full_report)
157
- if horario >= HORA_INICIO_INTRADAY:
158
- return intraday.intraday(codigos)
159
- return pl.DataFrame()
152
+ return intraday.intraday(codigos)
160
153
 
161
154
 
162
155
  def available_dates(contract_code: str) -> pl.Series:
@@ -182,4 +175,4 @@ def available_dates(contract_code: str) -> pl.Series:
182
175
  return historical.listar_datas_disponiveis(contract_code)
183
176
 
184
177
 
185
- __all__ = ["available_dates", "futures"]
178
+ __all__ = ["available_dates", "futures", "futures_intraday"]
@@ -6,7 +6,6 @@ from pyield import bday
6
6
  from pyield._internal.data_cache import obter_dataset_cacheado
7
7
  from pyield.b3._contracts import normalizar_codigos_contrato
8
8
  from pyield.b3.futures.common import adicionar_vencimento, expr_dv01
9
- from pyield.b3.price_report import fetch_price_report
10
9
  from pyield.fwd import forwards
11
10
 
12
11
  # Lista de contratos que negociam por taxa (juros/cupom).
@@ -63,15 +62,12 @@ def _obter_pr_normalizado() -> pl.DataFrame:
63
62
  def historical(
64
63
  data: dt.date,
65
64
  codigo_contrato: str | list[str],
66
- full_report: bool = False,
67
65
  ) -> pl.DataFrame:
68
- """Busca histórico de futuros priorizando o dataset PR cacheado.
66
+ """Busca histórico de futuros no dataset PR cacheado.
69
67
 
70
68
  Args:
71
69
  data: Data de negociação.
72
70
  codigo_contrato: Código(s) do contrato futuro na B3.
73
- full_report: Se False (padrão), tenta SPR primeiro e PR como
74
- fallback. Se True, usa apenas o PR completo (~2 MB).
75
71
 
76
72
  Returns:
77
73
  DataFrame Polars com dados históricos de futuros.
@@ -114,6 +110,9 @@ def historical(
114
110
  * taxa_forward (Float64): taxa a termo (apenas DI1/DAP).
115
111
 
116
112
  Notes:
113
+ Usa exclusivamente o dataset PR cacheado no GitHub. Contratos
114
+ disponíveis: DI1, DDI, FRC, FRO, DAP, DOL, WDO, IND, WIN.
115
+
117
116
  As colunas com prefixo ``preco_`` aparecem para contratos cotados por
118
117
  preço (ex.: DOL, IND). As com prefixo ``taxa_`` aparecem para contratos
119
118
  cotados por taxa (ex.: DI1, DAP, DDI, FRC, FRO). Nem todas as colunas
@@ -130,28 +129,11 @@ def historical(
130
129
  if not codigos:
131
130
  return pl.DataFrame()
132
131
 
133
- dataframes: list[pl.DataFrame] = []
134
- codigos_sem_cache: list[str] = []
135
-
136
- for codigo in codigos:
137
- df_cache = _obter_futuros_pr([data], codigo)
138
- if df_cache.is_empty():
139
- codigos_sem_cache.append(codigo)
140
- else:
141
- dataframes.append(df_cache)
142
-
143
- if codigos_sem_cache:
144
- for codigo in codigos_sem_cache:
145
- df_bruto = _buscar_price_report(data, codigo, full_report)
146
- if df_bruto.is_empty():
147
- continue
148
-
149
- df_bruto = adicionar_vencimento(df_bruto, codigo, "codigo_negociacao")
150
- df = _enriquecer_dados(df_bruto, codigo)
151
- df_saida = _selecionar_colunas_saida(df)
152
- if "data_vencimento" in df_saida.columns:
153
- df_saida = df_saida.sort("data_vencimento")
154
- dataframes.append(df_saida)
132
+ dataframes = [
133
+ df
134
+ for codigo in codigos
135
+ if not (df := _obter_futuros_pr([data], codigo)).is_empty()
136
+ ]
155
137
 
156
138
  if not dataframes:
157
139
  return pl.DataFrame()
@@ -201,28 +183,6 @@ def listar_datas_disponiveis(codigo_contrato: str) -> pl.Series:
201
183
  )
202
184
 
203
185
 
204
- def _buscar_price_report(data: dt.date, codigo: str, full_report: bool) -> pl.DataFrame:
205
- """Busca o price report da B3, com fallback SPR→PR.
206
-
207
- Se full_report é True, usa apenas o PR (completo).
208
- Se False, tenta o SPR (leve) primeiro e faz fallback para o PR.
209
- """
210
- if full_report:
211
- return _normalizar_colunas_pr(
212
- fetch_price_report(date=data, contract_code=codigo, full_report=True)
213
- )
214
-
215
- # SPR (leve) primeiro; PR (pesado) como fallback
216
- df = _normalizar_colunas_pr(
217
- fetch_price_report(date=data, contract_code=codigo, full_report=False)
218
- )
219
- if not df.is_empty():
220
- return df
221
- return _normalizar_colunas_pr(
222
- fetch_price_report(date=data, contract_code=codigo, full_report=True)
223
- )
224
-
225
-
226
186
  def _filtrar_e_renomear(
227
187
  df: pl.DataFrame, datas: list[dt.date], codigo_contrato: str
228
188
  ) -> pl.DataFrame:
@@ -1 +0,0 @@
1
- __version__ = "0.46.8"
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