pyield 0.47.3__tar.gz → 0.47.4__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.
- {pyield-0.47.3 → pyield-0.47.4}/PKG-INFO +1 -1
- pyield-0.47.4/pyield/__about__.py +1 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/price_report.py +84 -50
- pyield-0.47.3/pyield/__about__.py +0 -1
- {pyield-0.47.3 → pyield-0.47.4}/.gitignore +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/LICENSE +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/README.md +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/_internal/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/_internal/br_numbers.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/_internal/cache.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/_internal/converters.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/_internal/data_cache.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/_internal/retry.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/_internal/types.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/anbima/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/anbima/ettj_intraday.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/anbima/ettj_last.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/anbima/ima.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/anbima/imaq.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/anbima/tpf.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/_contracts.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/_validar_pregao.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/derivatives_intraday.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/di1.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/di_over.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/futures/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/futures/common.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/futures/historical.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/b3/futures/intraday.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/auction.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/copom.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/ptax_api.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/rates.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/repo.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/trades_intraday.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/trades_monthly.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bc/vna.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bday/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bday/core.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bday/holidays/br_holidays_new.txt +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bday/holidays/br_holidays_old.txt +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/bday/holidays/brholidays.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/clock.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/fwd.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/interpolator.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/ipca/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/ipca/historical.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/ipca/projected.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/py.typed +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/rmd.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/selic/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/selic/cpm.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/selic/probabilities.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/__init__.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/auctions.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/benchmark.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/lft.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/ltn.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/ntnb.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/ntnb1.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/ntnbprinc.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/ntnc.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/ntnf.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/pre.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyield/tn/utils.py +0 -0
- {pyield-0.47.3 → pyield-0.47.4}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyield
|
|
3
|
-
Version: 0.47.
|
|
3
|
+
Version: 0.47.4
|
|
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.4"
|
|
@@ -1,5 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Exemplo de trecho do XML bruto da B3:
|
|
3
|
+
<PricRpt>
|
|
4
|
+
<TradDt>
|
|
5
|
+
<Dt>2026-04-01</Dt>
|
|
6
|
+
</TradDt>
|
|
7
|
+
<SctyId>
|
|
8
|
+
<TckrSymb>DI1F31</TckrSymb>
|
|
9
|
+
</SctyId>
|
|
10
|
+
<FinInstrmId>
|
|
11
|
+
<OthrId>
|
|
12
|
+
<Id>200000235664</Id>
|
|
13
|
+
<Tp>
|
|
14
|
+
<Prtry>8</Prtry>
|
|
15
|
+
</Tp>
|
|
16
|
+
</OthrId>
|
|
17
|
+
<PlcOfListg>
|
|
18
|
+
<MktIdrCd>BVMF</MktIdrCd>
|
|
19
|
+
</PlcOfListg>
|
|
20
|
+
</FinInstrmId>
|
|
21
|
+
<TradDtls>
|
|
22
|
+
<TradQty>29880</TradQty>
|
|
23
|
+
</TradDtls>
|
|
24
|
+
<FinInstrmAttrbts>
|
|
25
|
+
<MktDataStrmId>E</MktDataStrmId>
|
|
26
|
+
...
|
|
27
|
+
<MinTradLmt Ccy="BRL">12.87</MinTradLmt>
|
|
28
|
+
</FinInstrmAttrbts>
|
|
29
|
+
</PricRpt>
|
|
30
|
+
"""
|
|
31
|
+
|
|
1
32
|
import datetime as dt
|
|
2
33
|
import io
|
|
34
|
+
import re
|
|
3
35
|
import zipfile
|
|
4
36
|
|
|
5
37
|
import polars as pl
|
|
@@ -18,13 +50,9 @@ NAMESPACE_B3 = "urn:bvmf.217.01.xsd"
|
|
|
18
50
|
NAMESPACES = {"ns": NAMESPACE_B3}
|
|
19
51
|
# ZIP válido do price report ~2KB; 1KB detecta arquivos "sem dados"
|
|
20
52
|
MIN_TAMANHO_ZIP_BYTES = 1024
|
|
21
|
-
|
|
22
|
-
XPATH_DATA_NEGOCIACAO = ".//ns:TradDt/ns:Dt"
|
|
23
|
-
XPATH_ATRIBUTOS_INSTRUMENTO = ".//ns:FinInstrmAttrbts"
|
|
24
|
-
XPATH_DETALHES_NEGOCIO = ".//ns:TradDtls"
|
|
53
|
+
XPATH_PRICE_REPORT = "//ns:PricRpt"
|
|
25
54
|
|
|
26
55
|
# --- Mapeamento de Colunas ---
|
|
27
|
-
|
|
28
56
|
# Estrutura: (id_pdf, nome_xml, tipo_polars)
|
|
29
57
|
# Esta camada base preserva os nomes originais do XML da B3.
|
|
30
58
|
# https://www.b3.com.br/data/files/16/70/29/9C/6219D710C8F297D7AC094EA8/Catalogo_precos_v1.3.pdf
|
|
@@ -121,35 +149,48 @@ def price_report_extract(conteudo_zip: bytes) -> bytes:
|
|
|
121
149
|
return zip_interno.read(nomes_xml[-1])
|
|
122
150
|
|
|
123
151
|
|
|
124
|
-
def _extrair_dados_contrato(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if pai is None:
|
|
129
|
-
return None
|
|
130
|
-
registro_pregao = pai.getparent()
|
|
131
|
-
if registro_pregao is None:
|
|
132
|
-
return None
|
|
133
|
-
elemento_data = registro_pregao.find(XPATH_DATA_NEGOCIACAO, NAMESPACES)
|
|
134
|
-
if elemento_data is None:
|
|
135
|
-
return None
|
|
152
|
+
def _extrair_dados_contrato(pric_rpt: etree._Element) -> dict | None:
|
|
153
|
+
dados = {}
|
|
154
|
+
tem_ticker = False
|
|
155
|
+
tem_data = False
|
|
136
156
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
157
|
+
for elem in pric_rpt.iter():
|
|
158
|
+
text = elem.text
|
|
159
|
+
if not text:
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
tag = elem.tag
|
|
163
|
+
if tag[0] == "{":
|
|
164
|
+
tag = tag[tag.find("}") + 1 :]
|
|
141
165
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
166
|
+
# 🔑 obrigatórios primeiro
|
|
167
|
+
if tag == "TckrSymb":
|
|
168
|
+
dados["TckrSymb"] = text
|
|
169
|
+
tem_ticker = True
|
|
170
|
+
continue
|
|
145
171
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
dados_ticker[nome_tag] = detalhe.text
|
|
172
|
+
if tag == "Dt":
|
|
173
|
+
pai = elem.getparent()
|
|
174
|
+
if pai is None:
|
|
175
|
+
continue
|
|
151
176
|
|
|
152
|
-
|
|
177
|
+
parent = pai.tag
|
|
178
|
+
if parent[0] == "{":
|
|
179
|
+
parent = parent[parent.find("}") + 1 :]
|
|
180
|
+
|
|
181
|
+
if parent == "TradDt":
|
|
182
|
+
dados["TradDt"] = text
|
|
183
|
+
tem_data = True
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
# ⚡ resto
|
|
187
|
+
if tag in SCHEMA_PRICE_REPORT:
|
|
188
|
+
dados[tag] = text
|
|
189
|
+
|
|
190
|
+
if not tem_ticker or not tem_data:
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
return dados
|
|
153
194
|
|
|
154
195
|
|
|
155
196
|
def _parsear_xml_registros(xml_bytes: bytes) -> list[dict]:
|
|
@@ -163,16 +204,13 @@ def _parsear_xml_registros(xml_bytes: bytes) -> list[dict]:
|
|
|
163
204
|
load_dtd=False,
|
|
164
205
|
)
|
|
165
206
|
arvore = etree.parse(io.BytesIO(xml_bytes), parser=analisador)
|
|
166
|
-
|
|
167
|
-
elementos: list[etree._Element] =
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
dados_contrato = _extrair_dados_contrato(elemento)
|
|
174
|
-
if dados_contrato is not None:
|
|
175
|
-
registros.append(dados_contrato)
|
|
207
|
+
resultado = arvore.xpath(XPATH_PRICE_REPORT, namespaces=NAMESPACES)
|
|
208
|
+
elementos: list[etree._Element] = resultado # type: ignore[assignment]
|
|
209
|
+
registros = [
|
|
210
|
+
dados
|
|
211
|
+
for pric_rpt in elementos
|
|
212
|
+
if (dados := _extrair_dados_contrato(pric_rpt)) is not None
|
|
213
|
+
]
|
|
176
214
|
return registros
|
|
177
215
|
|
|
178
216
|
|
|
@@ -204,14 +242,12 @@ def _filtrar_df(
|
|
|
204
242
|
prefixos: list[str],
|
|
205
243
|
comprimento_ticker: int | None = None,
|
|
206
244
|
) -> pl.DataFrame:
|
|
245
|
+
ticker = pl.col("TckrSymb")
|
|
207
246
|
if comprimento_ticker:
|
|
208
|
-
df = df.filter(
|
|
209
|
-
|
|
247
|
+
df = df.filter(ticker.str.len_chars() == comprimento_ticker)
|
|
210
248
|
if prefixos:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
)
|
|
214
|
-
df = df.filter(filtro)
|
|
249
|
+
padrao = f"^({'|'.join(re.escape(prefixo) for prefixo in prefixos)})"
|
|
250
|
+
df = df.filter(ticker.str.contains(padrao))
|
|
215
251
|
return df.sort("TckrSymb")
|
|
216
252
|
|
|
217
253
|
|
|
@@ -278,10 +314,8 @@ def price_report_fetch(
|
|
|
278
314
|
* IntlFinVol (Float64): volume financeiro internacional.
|
|
279
315
|
* OpnIntrst (Int64): contratos em aberto.
|
|
280
316
|
* FinInstrmQty (Int64): quantidade negociada de instrumentos financeiros.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
* BestAskPric (Float64): ultima melhor oferta de venda no snapshot
|
|
284
|
-
diario; pode ser nulo.
|
|
317
|
+
* BestBidPric (Float64): ultima melhor oferta de compra no snapshot diario; pode ser nulo.
|
|
318
|
+
* BestAskPric (Float64): ultima melhor oferta de venda no snapshot diario; pode ser nulo. diario; pode ser nulo.
|
|
285
319
|
* FrstPric (Float64): preço de abertura.
|
|
286
320
|
* MinPric (Float64): preço mínimo negociado.
|
|
287
321
|
* MaxPric (Float64): preço máximo negociado.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.47.3"
|
|
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
|
|
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
|