pyield 0.53.0__tar.gz → 0.53.1__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 (70) hide show
  1. {pyield-0.53.0 → pyield-0.53.1}/PKG-INFO +1 -1
  2. pyield-0.53.1/pyield/tpf/secundario/__init__.py +19 -0
  3. pyield-0.53.1/pyield/tpf/secundario/_intradia.py +139 -0
  4. pyield-0.53.0/pyield/tpf/secundario.py → pyield-0.53.1/pyield/tpf/secundario/_mensal.py +46 -146
  5. {pyield-0.53.0 → pyield-0.53.1}/pyproject.toml +1 -1
  6. {pyield-0.53.0 → pyield-0.53.1}/LICENSE +0 -0
  7. {pyield-0.53.0 → pyield-0.53.1}/README.md +0 -0
  8. {pyield-0.53.0 → pyield-0.53.1}/pyield/__init__.py +0 -0
  9. {pyield-0.53.0 → pyield-0.53.1}/pyield/_internal/__init__.py +0 -0
  10. {pyield-0.53.0 → pyield-0.53.1}/pyield/_internal/br_numbers.py +0 -0
  11. {pyield-0.53.0 → pyield-0.53.1}/pyield/_internal/cache.py +0 -0
  12. {pyield-0.53.0 → pyield-0.53.1}/pyield/_internal/converters.py +0 -0
  13. {pyield-0.53.0 → pyield-0.53.1}/pyield/_internal/data_cache.py +0 -0
  14. {pyield-0.53.0 → pyield-0.53.1}/pyield/_internal/retry.py +0 -0
  15. {pyield-0.53.0 → pyield-0.53.1}/pyield/_internal/types.py +0 -0
  16. {pyield-0.53.0 → pyield-0.53.1}/pyield/anbima/__init__.py +0 -0
  17. {pyield-0.53.0 → pyield-0.53.1}/pyield/anbima/imaq.py +0 -0
  18. {pyield-0.53.0 → pyield-0.53.1}/pyield/anbima/mercado_secundario.py +0 -0
  19. {pyield-0.53.0 → pyield-0.53.1}/pyield/b3/__init__.py +0 -0
  20. {pyield-0.53.0 → pyield-0.53.1}/pyield/b3/_contratos.py +0 -0
  21. {pyield-0.53.0 → pyield-0.53.1}/pyield/b3/_validar_pregao.py +0 -0
  22. {pyield-0.53.0 → pyield-0.53.1}/pyield/b3/boletim.py +0 -0
  23. {pyield-0.53.0 → pyield-0.53.1}/pyield/b3/derivativos_intradia.py +0 -0
  24. {pyield-0.53.0 → pyield-0.53.1}/pyield/b3/di_over.py +0 -0
  25. {pyield-0.53.0 → pyield-0.53.1}/pyield/bc/__init__.py +0 -0
  26. {pyield-0.53.0 → pyield-0.53.1}/pyield/bc/_olinda.py +0 -0
  27. {pyield-0.53.0 → pyield-0.53.1}/pyield/bc/leiloes.py +0 -0
  28. {pyield-0.53.0 → pyield-0.53.1}/pyield/bc/lft.py +0 -0
  29. {pyield-0.53.0 → pyield-0.53.1}/pyield/bc/sgs.py +0 -0
  30. {pyield-0.53.0 → pyield-0.53.1}/pyield/du/__init__.py +0 -0
  31. {pyield-0.53.0 → pyield-0.53.1}/pyield/du/core.py +0 -0
  32. {pyield-0.53.0 → pyield-0.53.1}/pyield/du/feriados/__init__.py +0 -0
  33. {pyield-0.53.0 → pyield-0.53.1}/pyield/du/feriados/feriados_antigos_br.txt +0 -0
  34. {pyield-0.53.0 → pyield-0.53.1}/pyield/du/feriados/feriados_br.py +0 -0
  35. {pyield-0.53.0 → pyield-0.53.1}/pyield/du/feriados/feriados_novos_br.txt +0 -0
  36. {pyield-0.53.0 → pyield-0.53.1}/pyield/futuro/__init__.py +0 -0
  37. {pyield-0.53.0 → pyield-0.53.1}/pyield/futuro/contratos.py +0 -0
  38. {pyield-0.53.0 → pyield-0.53.1}/pyield/futuro/di1.py +0 -0
  39. {pyield-0.53.0 → pyield-0.53.1}/pyield/futuro/historico.py +0 -0
  40. {pyield-0.53.0 → pyield-0.53.1}/pyield/futuro/intradia.py +0 -0
  41. {pyield-0.53.0 → pyield-0.53.1}/pyield/fwd.py +0 -0
  42. {pyield-0.53.0 → pyield-0.53.1}/pyield/interpolador.py +0 -0
  43. {pyield-0.53.0 → pyield-0.53.1}/pyield/ipca/__init__.py +0 -0
  44. {pyield-0.53.0 → pyield-0.53.1}/pyield/ipca/historico.py +0 -0
  45. {pyield-0.53.0 → pyield-0.53.1}/pyield/ipca/projetado.py +0 -0
  46. {pyield-0.53.0 → pyield-0.53.1}/pyield/py.typed +0 -0
  47. {pyield-0.53.0 → pyield-0.53.1}/pyield/relogio.py +0 -0
  48. {pyield-0.53.0 → pyield-0.53.1}/pyield/selic/__init__.py +0 -0
  49. {pyield-0.53.0 → pyield-0.53.1}/pyield/selic/compromissada.py +0 -0
  50. {pyield-0.53.0 → pyield-0.53.1}/pyield/selic/copom.py +0 -0
  51. {pyield-0.53.0 → pyield-0.53.1}/pyield/selic/cpm.py +0 -0
  52. {pyield-0.53.0 → pyield-0.53.1}/pyield/selic/probabilities.py +0 -0
  53. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/__init__.py +0 -0
  54. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/__init__.py +0 -0
  55. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/lft.py +0 -0
  56. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/ltn.py +0 -0
  57. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/ntnb.py +0 -0
  58. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/ntnb1.py +0 -0
  59. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/ntnbprinc.py +0 -0
  60. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/ntnc.py +0 -0
  61. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/_titulos/ntnf.py +0 -0
  62. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/benchmark.py +0 -0
  63. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/leiloes.py +0 -0
  64. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/pre.py +0 -0
  65. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/rmd/__init__.py +0 -0
  66. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/rmd/_aba_1_3.py +0 -0
  67. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/rmd/_aba_2_1.py +0 -0
  68. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/rmd/_common.py +0 -0
  69. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/rmd/_download.py +0 -0
  70. {pyield-0.53.0 → pyield-0.53.1}/pyield/tpf/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyield
3
- Version: 0.53.0
3
+ Version: 0.53.1
4
4
  Summary: Polars-powered toolkit for Brazilian fixed income analysis
5
5
  Keywords: fixed-income,brazil,finance,analysis,bonds
6
6
  Author: Carlos Carvalho
@@ -0,0 +1,19 @@
1
+ """Negociações do mercado secundário de TPFs no sistema Selic do BCB."""
2
+
3
+ from pyield.tpf.secundario._intradia import intradia as intradia
4
+ from pyield.tpf.secundario._mensal import baixar_zip as baixar_zip
5
+ from pyield.tpf.secundario._mensal import ler_zip as ler_zip
6
+ from pyield.tpf.secundario._mensal import mensal as mensal
7
+ from pyield.tpf.secundario._mensal import (
8
+ nome_arquivo_mensal as nome_arquivo_mensal,
9
+ )
10
+ from pyield.tpf.secundario._mensal import zip_para_silver as zip_para_silver
11
+
12
+ __all__ = [
13
+ "baixar_zip",
14
+ "intradia",
15
+ "ler_zip",
16
+ "mensal",
17
+ "nome_arquivo_mensal",
18
+ "zip_para_silver",
19
+ ]
@@ -0,0 +1,139 @@
1
+ """Dados intradia do mercado secundário de TPFs no sistema Selic do BCB."""
2
+
3
+ import datetime as dt
4
+
5
+ import polars as pl
6
+ import requests
7
+
8
+ from pyield import du, relogio
9
+ from pyield._internal.br_numbers import float_br, inteiro_br, taxa_br
10
+ from pyield._internal.cache import ttl_cache
11
+ from pyield._internal.retry import retry_padrao
12
+
13
+ URL_BASE_TEMPO_REAL = (
14
+ "https://www3.bcb.gov.br/novoselic/rest/precosNegociacao/pub/download/estatisticas/"
15
+ )
16
+
17
+ HORA_INICIO_TEMPO_REAL = dt.time(9, 0, 0)
18
+ HORA_FIM_TEMPO_REAL = dt.time(22, 0, 0)
19
+
20
+
21
+ @ttl_cache()
22
+ @retry_padrao
23
+ def _buscar_csv_intradia() -> bytes:
24
+ hoje = relogio.hoje()
25
+ data_formatada = hoje.strftime("%d-%m-%Y")
26
+ url = f"{URL_BASE_TEMPO_REAL}{data_formatada}"
27
+ resposta = requests.get(url, timeout=30) # API costuma levar ~10s
28
+ resposta.raise_for_status()
29
+ return resposta.content
30
+
31
+
32
+ def _parsear_csv_intradia(dados: bytes) -> pl.DataFrame:
33
+ return pl.read_csv(
34
+ dados,
35
+ separator=";",
36
+ infer_schema=False,
37
+ null_values="-",
38
+ ).rename(lambda c: c.strip())
39
+
40
+
41
+ def _processar_df_intradia(df: pl.DataFrame) -> pl.DataFrame:
42
+ agora = relogio.agora()
43
+ return df.filter(pl.col("//1") == "1").select(
44
+ data_hora_consulta=agora,
45
+ data_liquidacao=agora.date(),
46
+ titulo=pl.col("sigla").str.strip_chars(),
47
+ codigo_selic=inteiro_br("código título"),
48
+ data_vencimento=pl.col("data vencimento").str.to_date("%d/%m/%Y"),
49
+ pu_minimo=float_br("pu mínimo"),
50
+ pu_medio=float_br("pu médio"),
51
+ pu_maximo=float_br("pu máximo"),
52
+ pu_ultimo=float_br("mercado à vista pu último"),
53
+ taxa_minima=taxa_br("tx mínimo"),
54
+ taxa_media=taxa_br("tx médio"),
55
+ taxa_maxima=taxa_br("tx máximo"),
56
+ taxa_ultima=taxa_br("tx último"),
57
+ operacoes=inteiro_br("totais liquidados operações"),
58
+ quantidade=inteiro_br("títulos"),
59
+ financeiro=float_br("financeiro"),
60
+ operacoes_corretagem=inteiro_br("corretagem liquidados operações"),
61
+ quantidade_corretagem=inteiro_br("corretagem títulos"),
62
+ termo_pu_minimo=float_br("pu mínimo_duplicated_0"),
63
+ termo_pu_medio=float_br("pu médio_duplicated_0"),
64
+ termo_pu_ultimo=float_br("mercado a termo pu último"),
65
+ termo_pu_maximo=float_br("pu máximo_duplicated_0"),
66
+ termo_taxa_ultima=taxa_br("tx último_duplicated_0"),
67
+ termo_taxa_minima=taxa_br("tx mínimo_duplicated_0"),
68
+ termo_taxa_media=taxa_br("tx médio_duplicated_0"),
69
+ termo_taxa_maxima=taxa_br("tx máximo_duplicated_0"),
70
+ termo_operacoes=inteiro_br("totais contratados operações"),
71
+ termo_quantidade=inteiro_br("títulos_duplicated_0"),
72
+ termo_financeiro=float_br("financeiro_duplicated_0"),
73
+ termo_operacoes_corretagem=inteiro_br("corretagem contratados operações"),
74
+ termo_quantidade_corretagem=inteiro_br("corretagem títulos_duplicated_0"),
75
+ )
76
+
77
+
78
+ def _mercado_selic_aberto() -> bool:
79
+ agora = relogio.agora()
80
+ hoje = agora.date()
81
+ hora = agora.time()
82
+ eh_dia_util = du.eh_dia_util(hoje)
83
+ eh_horario = HORA_INICIO_TEMPO_REAL <= hora <= HORA_FIM_TEMPO_REAL
84
+
85
+ return eh_dia_util and eh_horario
86
+
87
+
88
+ def intradia() -> pl.DataFrame:
89
+ """Busca dados intradia do mercado secundário de TPFs.
90
+
91
+ Fonte: Banco Central do Brasil, sistema SELIC. Os dados ficam disponíveis
92
+ apenas durante o horário do SELIC (09:00-22:00 BRT) em dias úteis.
93
+
94
+ Returns:
95
+ DataFrame Polars com negociações intradia do mercado secundário.
96
+ Retorna DataFrame vazio fora do horário do SELIC.
97
+
98
+ Output Columns:
99
+ * data_hora_consulta (Datetime): data e hora da consulta.
100
+ * data_liquidacao (Date): data de liquidação à vista.
101
+ * titulo (String): sigla do título público.
102
+ * codigo_selic (Int64): código SELIC do título.
103
+ * data_vencimento (Date): data de vencimento do título.
104
+ * pu_minimo (Float64): menor preço negociado.
105
+ * pu_medio (Float64): preço médio negociado.
106
+ * pu_maximo (Float64): maior preço negociado.
107
+ * pu_ultimo (Float64): último preço negociado.
108
+ * taxa_minima (Float64): menor taxa negociada.
109
+ * taxa_media (Float64): taxa média negociada.
110
+ * taxa_maxima (Float64): maior taxa negociada.
111
+ * taxa_ultima (Float64): última taxa negociada.
112
+ * operacoes (Int64): total de operações liquidadas.
113
+ * quantidade (Int64): quantidade total de títulos negociados.
114
+ * financeiro (Float64): valor financeiro total negociado.
115
+ * operacoes_corretagem (Int64): operações via corretagem.
116
+ * quantidade_corretagem (Int64): títulos via corretagem.
117
+ * termo_pu_minimo (Float64): menor preço a termo negociado.
118
+ * termo_pu_medio (Float64): preço médio a termo negociado.
119
+ * termo_pu_ultimo (Float64): último preço a termo negociado.
120
+ * termo_pu_maximo (Float64): maior preço a termo negociado.
121
+ * termo_taxa_ultima (Float64): última taxa a termo negociada.
122
+ * termo_taxa_minima (Float64): menor taxa a termo negociada.
123
+ * termo_taxa_media (Float64): taxa média a termo negociada.
124
+ * termo_taxa_maxima (Float64): maior taxa a termo negociada.
125
+ * termo_operacoes (Int64): total de operações a termo.
126
+ * termo_quantidade (Int64): total de títulos a termo negociados.
127
+ * termo_financeiro (Float64): valor financeiro total a termo.
128
+ * termo_operacoes_corretagem (Int64): operações a termo via corretagem.
129
+ * termo_quantidade_corretagem (Int64): títulos a termo via corretagem.
130
+
131
+ Examples:
132
+ >>> df = yd.tpf.secundario.intradia() # doctest: +SKIP
133
+ """
134
+ if not _mercado_selic_aberto():
135
+ return pl.DataFrame()
136
+
137
+ texto_bruto = _buscar_csv_intradia()
138
+ df = _parsear_csv_intradia(texto_bruto)
139
+ return _processar_df_intradia(df)
@@ -1,4 +1,4 @@
1
- """Negociações do mercado secundário de TPFs no sistema Selic do BCB."""
1
+ """Dados mensais do mercado secundário de TPFs no sistema Selic do BCB."""
2
2
 
3
3
  import datetime as dt
4
4
  import io
@@ -10,33 +10,19 @@ import polars as pl
10
10
  import polars.selectors as ps
11
11
  import requests
12
12
 
13
- from pyield import du, relogio
14
- from pyield._internal.br_numbers import float_br, inteiro_br, taxa_br
13
+ from pyield import relogio
14
+ from pyield._internal.br_numbers import float_br
15
15
  from pyield._internal.cache import ttl_cache
16
16
  from pyield._internal.converters import converter_datas
17
17
  from pyield._internal.retry import retry_padrao
18
18
  from pyield._internal.types import DateLike, any_is_empty
19
19
 
20
20
  URL_BASE_MENSAL = "https://www4.bcb.gov.br/pom/demab/negociacoes/download"
21
- URL_BASE_TEMPO_REAL = (
22
- "https://www3.bcb.gov.br/novoselic/rest/precosNegociacao/pub/download/estatisticas/"
23
- )
24
-
25
- HORA_INICIO_TEMPO_REAL = dt.time(9, 0, 0)
26
- HORA_FIM_TEMPO_REAL = dt.time(22, 0, 0)
27
21
  CHAVES_ORDENACAO = ["data_liquidacao", "titulo", "data_vencimento"]
28
22
  COLUNAS_MINIMAS_CSV = 2
29
23
 
30
24
  type CaminhoArquivo = str | os.PathLike[str]
31
25
 
32
- __all__ = [
33
- "baixar_zip",
34
- "intradia",
35
- "ler_zip",
36
- "mensal",
37
- "zip_para_silver",
38
- ]
39
-
40
26
 
41
27
  def _tipo_arquivo(extragrupo: bool) -> str:
42
28
  return "E" if extragrupo else "T"
@@ -50,7 +36,22 @@ def _data_mensal(data: DateLike) -> dt.date:
50
36
  return data_alvo
51
37
 
52
38
 
53
- def _nome_arquivo(data: DateLike, extragrupo: bool = False) -> str:
39
+ def nome_arquivo_mensal(data: DateLike, extragrupo: bool = False) -> str:
40
+ """Retorna o nome do arquivo ZIP mensal do secundário no BCB/SELIC.
41
+
42
+ Args:
43
+ data: Data de referência. Apenas ano e mês definem o arquivo.
44
+ extragrupo: Se verdadeiro, retorna o nome do arquivo extragrupo.
45
+
46
+ Returns:
47
+ Nome do arquivo ZIP mensal publicado pelo BCB.
48
+
49
+ Examples:
50
+ >>> yd.tpf.secundario.nome_arquivo_mensal("07-06-2026")
51
+ 'NegT202606.ZIP'
52
+ >>> yd.tpf.secundario.nome_arquivo_mensal("07-01-2025", extragrupo=True)
53
+ 'NegE202501.ZIP'
54
+ """
54
55
  data_alvo = _data_mensal(data)
55
56
  return f"Neg{_tipo_arquivo(extragrupo)}{data_alvo:%Y%m}.ZIP"
56
57
 
@@ -88,7 +89,7 @@ def baixar_zip(data: DateLike, extragrupo: bool = False) -> bytes:
88
89
  Examples:
89
90
  >>> conteudo = yd.tpf.secundario.baixar_zip("07-01-2025") # doctest: +SKIP
90
91
  """
91
- arquivo = _nome_arquivo(data, extragrupo)
92
+ arquivo = nome_arquivo_mensal(data, extragrupo)
92
93
  conteudo_zip = _baixar_url_zip(f"{URL_BASE_MENSAL}/{arquivo}")
93
94
  _validar_zip(conteudo_zip, arquivo)
94
95
  return conteudo_zip
@@ -147,6 +148,17 @@ def _parsear_csv_mensal(conteudo_csv: bytes) -> pl.DataFrame:
147
148
 
148
149
 
149
150
  def _processar_df_mensal(df: pl.DataFrame) -> pl.DataFrame:
151
+ operacoes_corretagem = (
152
+ pl.col("NUM OPER COM CORRETAGEM").cast(pl.Int64)
153
+ if "NUM OPER COM CORRETAGEM" in df.columns
154
+ else pl.lit(None, dtype=pl.Int64)
155
+ )
156
+ quantidade_corretagem = (
157
+ pl.col("QUANT NEG COM CORRETAGEM").cast(pl.Int64)
158
+ if "QUANT NEG COM CORRETAGEM" in df.columns
159
+ else pl.lit(None, dtype=pl.Int64)
160
+ )
161
+
150
162
  return (
151
163
  df.with_columns(ps.string().str.strip_chars())
152
164
  .with_columns(
@@ -162,7 +174,6 @@ def _processar_df_mensal(df: pl.DataFrame) -> pl.DataFrame:
162
174
  data_vencimento=pl.col("VENCIMENTO").str.to_date("%d/%m/%Y", strict=False),
163
175
  operacoes=pl.col("NUM DE OPER").cast(pl.Int64),
164
176
  quantidade=pl.col("quantidade"),
165
- financeiro=(pl.col("quantidade") * pl.col("pu_medio")).round(2),
166
177
  pu_minimo=float_br("PU MIN"),
167
178
  pu_medio=pl.col("pu_medio"),
168
179
  pu_maximo=float_br("PU MAX"),
@@ -171,8 +182,8 @@ def _processar_df_mensal(df: pl.DataFrame) -> pl.DataFrame:
171
182
  taxa_minima=float_br("TAXA MIN"),
172
183
  taxa_media=float_br("TAXA MED"),
173
184
  taxa_maxima=float_br("TAXA MAX"),
174
- operacoes_corretagem=pl.col("NUM OPER COM CORRETAGEM").cast(pl.Int64),
175
- quantidade_corretagem=pl.col("QUANT NEG COM CORRETAGEM").cast(pl.Int64),
185
+ operacoes_corretagem=operacoes_corretagem,
186
+ quantidade_corretagem=quantidade_corretagem,
176
187
  )
177
188
  .sort(CHAVES_ORDENACAO)
178
189
  )
@@ -201,7 +212,6 @@ def zip_para_silver(conteudo_zip: bytes) -> pl.DataFrame:
201
212
  * data_vencimento (Date): data de vencimento do título.
202
213
  * operacoes (Int64): número total de operações.
203
214
  * quantidade (Int64): quantidade total negociada.
204
- * financeiro (Float64): valor financeiro negociado.
205
215
  * pu_minimo (Float64): preço unitário mínimo.
206
216
  * pu_medio (Float64): preço unitário médio.
207
217
  * pu_maximo (Float64): preço unitário máximo.
@@ -213,6 +223,11 @@ def zip_para_silver(conteudo_zip: bytes) -> pl.DataFrame:
213
223
  * operacoes_corretagem (Int64): operações com corretagem.
214
224
  * quantidade_corretagem (Int64): quantidade com corretagem.
215
225
 
226
+ Notes:
227
+ O schema silver é estável para concatenação entre meses. Em layouts
228
+ antigos da fonte que não trazem corretagem, ``operacoes_corretagem`` e
229
+ ``quantidade_corretagem`` são retornadas como nulas.
230
+
216
231
  Examples:
217
232
  >>> conteudo = yd.tpf.secundario.baixar_zip("07-01-2025") # doctest: +SKIP
218
233
  >>> df = yd.tpf.secundario.zip_para_silver(conteudo) # doctest: +SKIP
@@ -244,7 +259,7 @@ def mensal(data: DateLike, extragrupo: bool = False) -> pl.DataFrame:
244
259
  """Busca dados mensais do mercado secundário de TPFs.
245
260
 
246
261
  Fonte: Banco Central do Brasil, sistema SELIC. Baixa o ZIP mensal de
247
- negociações secundárias, valida o bronze bruto e retorna o DataFrame silver.
262
+ negociações secundárias, valida o bronze bruto e retorna o DataFrame ouro.
248
263
  Apenas o ano e o mês de ``data`` são usados para identificar o arquivo.
249
264
 
250
265
  Args:
@@ -263,7 +278,6 @@ def mensal(data: DateLike, extragrupo: bool = False) -> pl.DataFrame:
263
278
  * data_vencimento (Date): data de vencimento do título.
264
279
  * operacoes (Int64): número total de operações.
265
280
  * quantidade (Int64): quantidade total negociada.
266
- * financeiro (Float64): valor financeiro negociado.
267
281
  * pu_minimo (Float64): preço unitário mínimo.
268
282
  * pu_medio (Float64): preço unitário médio.
269
283
  * pu_maximo (Float64): preço unitário máximo.
@@ -274,6 +288,11 @@ def mensal(data: DateLike, extragrupo: bool = False) -> pl.DataFrame:
274
288
  * taxa_maxima (Float64): taxa máxima.
275
289
  * operacoes_corretagem (Int64): operações com corretagem.
276
290
  * quantidade_corretagem (Int64): quantidade com corretagem.
291
+ * financeiro (Float64): valor financeiro negociado.
292
+
293
+ Notes:
294
+ Esta é a camada ouro mensal: retorna o schema de ``zip_para_silver``
295
+ acrescido de ``financeiro = quantidade * pu_medio``.
277
296
 
278
297
  Examples:
279
298
  >>> df = yd.tpf.secundario.mensal("07-01-2025", extragrupo=True)
@@ -286,125 +305,6 @@ def mensal(data: DateLike, extragrupo: bool = False) -> pl.DataFrame:
286
305
  if (data_alvo.year, data_alvo.month) > (hoje.year, hoje.month):
287
306
  return pl.DataFrame()
288
307
 
289
- return zip_para_silver(baixar_zip(data_alvo, extragrupo))
290
-
291
-
292
- @ttl_cache()
293
- @retry_padrao
294
- def _buscar_csv_intradia() -> bytes:
295
- hoje = relogio.hoje()
296
- data_formatada = hoje.strftime("%d-%m-%Y")
297
- url = f"{URL_BASE_TEMPO_REAL}{data_formatada}"
298
- resposta = requests.get(url, timeout=30) # API costuma levar ~10s
299
- resposta.raise_for_status()
300
- return resposta.content
301
-
302
-
303
- def _parsear_csv_intradia(dados: bytes) -> pl.DataFrame:
304
- return pl.read_csv(
305
- dados,
306
- separator=";",
307
- infer_schema=False,
308
- null_values="-",
309
- ).rename(lambda c: c.strip())
310
-
311
-
312
- def _processar_df_intradia(df: pl.DataFrame) -> pl.DataFrame:
313
- agora = relogio.agora()
314
- return df.filter(pl.col("//1") == "1").select(
315
- data_hora_consulta=agora,
316
- data_liquidacao=agora.date(),
317
- titulo=pl.col("sigla").str.strip_chars(),
318
- codigo_selic=inteiro_br("código título"),
319
- data_vencimento=pl.col("data vencimento").str.to_date("%d/%m/%Y"),
320
- pu_minimo=float_br("pu mínimo"),
321
- pu_medio=float_br("pu médio"),
322
- pu_maximo=float_br("pu máximo"),
323
- pu_ultimo=float_br("mercado à vista pu último"),
324
- taxa_minima=taxa_br("tx mínimo"),
325
- taxa_media=taxa_br("tx médio"),
326
- taxa_maxima=taxa_br("tx máximo"),
327
- taxa_ultima=taxa_br("tx último"),
328
- operacoes=inteiro_br("totais liquidados operações"),
329
- quantidade=inteiro_br("títulos"),
330
- financeiro=float_br("financeiro"),
331
- operacoes_corretagem=inteiro_br("corretagem liquidados operações"),
332
- quantidade_corretagem=inteiro_br("corretagem títulos"),
333
- termo_pu_minimo=float_br("pu mínimo_duplicated_0"),
334
- termo_pu_medio=float_br("pu médio_duplicated_0"),
335
- termo_pu_ultimo=float_br("mercado a termo pu último"),
336
- termo_pu_maximo=float_br("pu máximo_duplicated_0"),
337
- termo_taxa_ultima=taxa_br("tx último_duplicated_0"),
338
- termo_taxa_minima=taxa_br("tx mínimo_duplicated_0"),
339
- termo_taxa_media=taxa_br("tx médio_duplicated_0"),
340
- termo_taxa_maxima=taxa_br("tx máximo_duplicated_0"),
341
- termo_operacoes=inteiro_br("totais contratados operações"),
342
- termo_quantidade=inteiro_br("títulos_duplicated_0"),
343
- termo_financeiro=float_br("financeiro_duplicated_0"),
344
- termo_operacoes_corretagem=inteiro_br("corretagem contratados operações"),
345
- termo_quantidade_corretagem=inteiro_br("corretagem títulos_duplicated_0"),
308
+ return zip_para_silver(baixar_zip(data_alvo, extragrupo)).with_columns(
309
+ financeiro=(pl.col("quantidade") * pl.col("pu_medio")).round(2),
346
310
  )
347
-
348
-
349
- def _mercado_selic_aberto() -> bool:
350
- agora = relogio.agora()
351
- hoje = agora.date()
352
- hora = agora.time()
353
- eh_dia_util = du.eh_dia_util(hoje)
354
- eh_horario = HORA_INICIO_TEMPO_REAL <= hora <= HORA_FIM_TEMPO_REAL
355
-
356
- return eh_dia_util and eh_horario
357
-
358
-
359
- def intradia() -> pl.DataFrame:
360
- """Busca dados intradia do mercado secundário de TPFs.
361
-
362
- Fonte: Banco Central do Brasil, sistema SELIC. Os dados ficam disponíveis
363
- apenas durante o horário do SELIC (09:00-22:00 BRT) em dias úteis.
364
-
365
- Returns:
366
- DataFrame Polars com negociações intradia do mercado secundário.
367
- Retorna DataFrame vazio fora do horário do SELIC.
368
-
369
- Output Columns:
370
- * data_hora_consulta (Datetime): data e hora da consulta.
371
- * data_liquidacao (Date): data de liquidação à vista.
372
- * titulo (String): sigla do título público.
373
- * codigo_selic (Int64): código SELIC do título.
374
- * data_vencimento (Date): data de vencimento do título.
375
- * pu_minimo (Float64): menor preço negociado.
376
- * pu_medio (Float64): preço médio negociado.
377
- * pu_maximo (Float64): maior preço negociado.
378
- * pu_ultimo (Float64): último preço negociado.
379
- * taxa_minima (Float64): menor taxa negociada.
380
- * taxa_media (Float64): taxa média negociada.
381
- * taxa_maxima (Float64): maior taxa negociada.
382
- * taxa_ultima (Float64): última taxa negociada.
383
- * operacoes (Int64): total de operações liquidadas.
384
- * quantidade (Int64): quantidade total de títulos negociados.
385
- * financeiro (Float64): valor financeiro total negociado.
386
- * operacoes_corretagem (Int64): operações via corretagem.
387
- * quantidade_corretagem (Int64): títulos via corretagem.
388
- * termo_pu_minimo (Float64): menor preço a termo negociado.
389
- * termo_pu_medio (Float64): preço médio a termo negociado.
390
- * termo_pu_ultimo (Float64): último preço a termo negociado.
391
- * termo_pu_maximo (Float64): maior preço a termo negociado.
392
- * termo_taxa_ultima (Float64): última taxa a termo negociada.
393
- * termo_taxa_minima (Float64): menor taxa a termo negociada.
394
- * termo_taxa_media (Float64): taxa média a termo negociada.
395
- * termo_taxa_maxima (Float64): maior taxa a termo negociada.
396
- * termo_operacoes (Int64): total de operações a termo.
397
- * termo_quantidade (Int64): total de títulos a termo negociados.
398
- * termo_financeiro (Float64): valor financeiro total a termo.
399
- * termo_operacoes_corretagem (Int64): operações a termo via corretagem.
400
- * termo_quantidade_corretagem (Int64): títulos a termo via corretagem.
401
-
402
- Examples:
403
- >>> df = yd.tpf.secundario.intradia() # doctest: +SKIP
404
- """
405
- if not _mercado_selic_aberto():
406
- return pl.DataFrame()
407
-
408
- texto_bruto = _buscar_csv_intradia()
409
- df = _parsear_csv_intradia(texto_bruto)
410
- return _processar_df_intradia(df)
@@ -19,7 +19,7 @@ dependencies = [
19
19
  "fastexcel>=0.19.0",
20
20
  "tzdata>=2024.1; platform_system == 'Windows'",
21
21
  ]
22
- version = "0.53.0"
22
+ version = "0.53.1"
23
23
 
24
24
  [project.urls]
25
25
  Homepage = "https://github.com/crdcj/PYield"
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