pyield 0.48.6__tar.gz → 0.48.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.
- {pyield-0.48.6 → pyield-0.48.8}/PKG-INFO +1 -1
- pyield-0.48.8/pyield/__about__.py +1 -0
- pyield-0.48.8/pyield/anbima/__init__.py +9 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/boletim.py +6 -13
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/di1.py +1 -3
- pyield-0.48.8/pyield/bc/_olinda.py +33 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/compromissada.py +38 -69
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/leiloes.py +26 -54
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/sgs.py +1 -1
- pyield-0.48.8/pyield/tn/__init__.py +20 -0
- pyield-0.48.6/pyield/__about__.py +0 -1
- pyield-0.48.6/pyield/anbima/__init__.py +0 -15
- pyield-0.48.6/pyield/anbima/ettj_intradia.py +0 -83
- pyield-0.48.6/pyield/anbima/ettj_ultima.py +0 -76
- pyield-0.48.6/pyield/anbima/ima_ultimo.py +0 -129
- pyield-0.48.6/pyield/tn/__init__.py +0 -7
- {pyield-0.48.6 → pyield-0.48.8}/.gitignore +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/LICENSE +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/README.md +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/__init__.py +1 -1
- {pyield-0.48.6 → pyield-0.48.8}/pyield/_internal/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/_internal/br_numbers.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/_internal/cache.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/_internal/converters.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/_internal/data_cache.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/_internal/retry.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/_internal/types.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/anbima/imaq.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/anbima/tpf.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/_contratos.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/_validar_pregao.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/derivativos_intradia.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/di_over.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/futuro/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/futuro/contratos.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/futuro/historico.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/b3/futuro/intradia.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/copom.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/tpf_intradia.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/tpf_mensal.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/bc/vna.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/du/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/du/core.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/du/feriados/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/du/feriados/feriados_antigos_br.txt +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/du/feriados/feriados_br.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/du/feriados/feriados_novos_br.txt +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/fwd.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/interpolador.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/ipca/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/ipca/historico.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/ipca/projetado.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/py.typed +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/relogio.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/selic/__init__.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/selic/cpm.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/selic/probabilities.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/benchmark.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/leiloes.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/lft.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/ltn.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/ntnb.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/ntnb1.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/ntnbprinc.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/ntnc.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/ntnf.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/pre.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/rmd.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyield/tn/utils.py +0 -0
- {pyield-0.48.6 → pyield-0.48.8}/pyproject.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyield
|
|
3
|
-
Version: 0.48.
|
|
3
|
+
Version: 0.48.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.48.8"
|
|
@@ -215,19 +215,12 @@ def _parsear_xml_registros(xml_bytes: bytes) -> list[dict]:
|
|
|
215
215
|
|
|
216
216
|
|
|
217
217
|
def _converter_para_df(registros: list[dict]) -> pl.DataFrame:
|
|
218
|
-
|
|
219
|
-
#
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
nome: pl.lit(None).cast(tipo)
|
|
225
|
-
for nome, tipo in SCHEMA_PRICE_REPORT.items()
|
|
226
|
-
if nome not in df.columns
|
|
227
|
-
}
|
|
228
|
-
if colunas_faltantes:
|
|
229
|
-
df = df.with_columns(**colunas_faltantes)
|
|
230
|
-
return df.select(SCHEMA_PRICE_REPORT.keys())
|
|
218
|
+
# Schema explícito garante que todas as colunas existam no DataFrame,
|
|
219
|
+
# mesmo que os primeiros registros não tenham todas as chaves.
|
|
220
|
+
# (pl.DataFrame infere colunas de ~50 primeiras linhas por padrão.)
|
|
221
|
+
schema_str = {nome: pl.String for nome in SCHEMA_PRICE_REPORT}
|
|
222
|
+
df = pl.DataFrame(registros, schema=schema_str)
|
|
223
|
+
return df.cast(SCHEMA_PRICE_REPORT, strict=False) # type: ignore
|
|
231
224
|
|
|
232
225
|
|
|
233
226
|
def _processar_xml_extraido(xml_bytes: bytes) -> pl.DataFrame:
|
|
@@ -236,11 +236,9 @@ def interpolar_taxas(
|
|
|
236
236
|
extrapolar=extrapolar,
|
|
237
237
|
)
|
|
238
238
|
|
|
239
|
-
# 4. A mágica: map_batches passa a Series inteira para o interpolador
|
|
240
|
-
# O interpolador retorna uma Series, que o Polars alinha perfeitamente
|
|
241
239
|
df_parcial = df_parcial.with_columns(
|
|
242
240
|
pl.col("dias_uteis")
|
|
243
|
-
.
|
|
241
|
+
.map_elements(interpolador_du, return_dtype=pl.Float64)
|
|
244
242
|
.alias("taxa_interpolada")
|
|
245
243
|
)
|
|
246
244
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Helpers compartilhados para acesso à API OData do BCB (olinda.bcb.gov.br)."""
|
|
2
|
+
|
|
3
|
+
import polars as pl
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
from pyield._internal.retry import retry_padrao
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def montar_url(url_base: str, parametros: dict[str, str]) -> str:
|
|
10
|
+
"""Monta URL OData com parâmetros opcionais e formato CSV.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
url_base: URL base do endpoint OData (com '?' no final).
|
|
14
|
+
parametros: Dicionário ``{nome_param: valor}`` já formatado.
|
|
15
|
+
Parâmetros com valor vazio são ignorados.
|
|
16
|
+
"""
|
|
17
|
+
partes = [f"@{k}='{v}'" for k, v in parametros.items() if v]
|
|
18
|
+
return url_base + "&".join(partes) + "&$format=text/csv"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@retry_padrao
|
|
22
|
+
def buscar_csv(url: str) -> bytes:
|
|
23
|
+
"""Busca CSV da API OData do BCB com retry automático."""
|
|
24
|
+
r = requests.get(url, timeout=10)
|
|
25
|
+
r.raise_for_status()
|
|
26
|
+
return r.content
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def parsear_csv(dados: bytes) -> pl.DataFrame:
|
|
30
|
+
"""Lê CSV OData como DataFrame sem inferência de tipos."""
|
|
31
|
+
if not dados.strip():
|
|
32
|
+
return pl.DataFrame()
|
|
33
|
+
return pl.read_csv(dados, infer_schema=False, null_values=["null", ""])
|
|
@@ -13,63 +13,27 @@ ac1b013d13d6fb1d9d9e251b8000121e, 2025-08-21 , 12:00 , TodoMercado
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
import polars as pl
|
|
16
|
-
import requests
|
|
17
16
|
|
|
18
17
|
import pyield._internal.converters as cv
|
|
19
18
|
from pyield import du
|
|
20
19
|
from pyield._internal.br_numbers import float_br, taxa_br
|
|
21
|
-
from pyield._internal.retry import retry_padrao
|
|
22
20
|
from pyield._internal.types import DateLike
|
|
21
|
+
from pyield.bc._olinda import buscar_csv, montar_url, parsear_csv
|
|
23
22
|
|
|
24
23
|
URL_BASE_API = "https://olinda.bcb.gov.br/olinda/servico/leiloes_selic/versao/v1/odata/leiloes_compromissadas(dataLancamentoInicio=@dataLancamentoInicio,dataLancamentoFim=@dataLancamentoFim,horaInicio=@horaInicio,dataLiquidacao=@dataLiquidacao,dataRetorno=@dataRetorno,publicoPermitidoLeilao=@publicoPermitidoLeilao,nomeTipoOferta=@nomeTipoOferta)?"
|
|
25
24
|
|
|
26
25
|
|
|
27
|
-
def
|
|
26
|
+
def _montar_parametros(
|
|
28
27
|
inicio: DateLike | None,
|
|
29
28
|
fim: DateLike | None,
|
|
30
|
-
) -> str:
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
Regras da API:
|
|
34
|
-
- Apenas inicio: retorna de inicio até o fim da série.
|
|
35
|
-
- Apenas fim: retorna do início da série até fim.
|
|
36
|
-
- Ambos ausentes: retorna a série completa.
|
|
37
|
-
"""
|
|
38
|
-
url = URL_BASE_API
|
|
29
|
+
) -> dict[str, str]:
|
|
30
|
+
"""Converte parâmetros opcionais de período em dicionário para a URL."""
|
|
31
|
+
params: dict[str, str] = {}
|
|
39
32
|
if inicio:
|
|
40
|
-
|
|
41
|
-
inicio_str = inicio_dt.strftime("%Y-%m-%d")
|
|
42
|
-
url += f"@dataLancamentoInicio='{inicio_str}'"
|
|
43
|
-
|
|
33
|
+
params["dataLancamentoInicio"] = cv.converter_datas(inicio).strftime("%Y-%m-%d")
|
|
44
34
|
if fim:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
url += f"&@dataLancamentoFim='{fim_str}'"
|
|
48
|
-
|
|
49
|
-
url += "&$format=text/csv" # Adiciona o formato CSV ao final
|
|
50
|
-
|
|
51
|
-
return url
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@retry_padrao
|
|
55
|
-
def _buscar_csv_api(url: str) -> bytes:
|
|
56
|
-
"""Executa requisição HTTP e retorna o corpo CSV como string.
|
|
57
|
-
|
|
58
|
-
Decorado com ``retry_padrao`` para resiliência a falhas transitórias.
|
|
59
|
-
Levanta exceções de status HTTP para tratamento a montante.
|
|
60
|
-
"""
|
|
61
|
-
r = requests.get(url, timeout=10)
|
|
62
|
-
r.raise_for_status()
|
|
63
|
-
return r.content
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def _ler_csv(csv_bytes: bytes) -> pl.DataFrame:
|
|
67
|
-
"""Lê o CSV (bytes) em um DataFrame Polars sem inferência de tipos."""
|
|
68
|
-
return pl.read_csv(
|
|
69
|
-
csv_bytes,
|
|
70
|
-
infer_schema=False,
|
|
71
|
-
null_values=["null", ""],
|
|
72
|
-
)
|
|
35
|
+
params["dataLancamentoFim"] = cv.converter_datas(fim).strftime("%Y-%m-%d")
|
|
36
|
+
return params
|
|
73
37
|
|
|
74
38
|
|
|
75
39
|
def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
@@ -80,14 +44,14 @@ def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
|
80
44
|
data_liquidacao=pl.col("dataLiquidacao").str.to_date("%Y-%m-%d"),
|
|
81
45
|
data_retorno=pl.col("dataRetorno").str.to_date("%Y-%m-%d"),
|
|
82
46
|
hora_inicio=pl.col("horaInicio").str.to_time("%H:%M"),
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
47
|
+
prazo_dc=pl.col("prazoDiasCorridos").cast(pl.Int64),
|
|
48
|
+
prazo_du=du.contar_expr("dataLiquidacao", "dataRetorno"),
|
|
49
|
+
comunicado=pl.col("numeroComunicado").cast(pl.Int64),
|
|
86
50
|
tipo_oferta=pl.col("nomeTipoOferta"),
|
|
87
|
-
|
|
88
|
-
|
|
51
|
+
publico=pl.col("publicoPermitidoLeilao"),
|
|
52
|
+
financeiro_aceito=1000 * pl.col("volumeAceito").cast(pl.Float64),
|
|
89
53
|
taxa_corte=pl.when(vol_zero).then(None).otherwise(taxa_br("taxaCorte")),
|
|
90
|
-
|
|
54
|
+
pct_aceito=pl.when(vol_zero)
|
|
91
55
|
.then(0.0)
|
|
92
56
|
.otherwise(100 - float_br("percentualCorte")),
|
|
93
57
|
).sort("data_leilao", "hora_inicio", "tipo_oferta")
|
|
@@ -117,36 +81,41 @@ def compromissadas(
|
|
|
117
81
|
- data_liquidacao (Date): data de liquidação (início da operação).
|
|
118
82
|
- data_retorno (Date): data de recompra / término da operação.
|
|
119
83
|
- hora_inicio (Time): horário de início do leilão.
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- numero_comunicado (Int64): número do comunicado/aviso do BC (pode ser nulo).
|
|
84
|
+
- prazo_dc (Int64): dias corridos até a data de retorno.
|
|
85
|
+
- prazo_du (Int64): dias úteis entre liquidação e retorno.
|
|
86
|
+
- comunicado (Int64): número do comunicado/aviso do BC (pode ser nulo).
|
|
124
87
|
- tipo_oferta (String): classif. do tipo de oferta (ex: Tomador, Compromissada 1047).
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
- taxa_corte (Float64): taxa de corte (ex. 0.1490 = 14,90%). Nula se
|
|
128
|
-
-
|
|
88
|
+
- publico (String): público permitido no leilão (SomenteDealer, TodoMercado).
|
|
89
|
+
- financeiro_aceito (Float64): financeiro aceito no leilão em reais (convertido de milhares).
|
|
90
|
+
- taxa_corte (Float64): taxa de corte (ex. 0.1490 = 14,90%). Nula se financeiro_aceito = 0.
|
|
91
|
+
- pct_aceito (Float64): percentual do volume ofertado efetivamente aceito (0-100).
|
|
129
92
|
100 = nenhuma rejeição. 0 indica nada aceito (volume_aceito = 0).
|
|
130
93
|
|
|
131
94
|
Notes:
|
|
132
95
|
- Dados ordenados por: data_leilao, hora_inicio, tipo_oferta.
|
|
133
96
|
|
|
134
97
|
Examples:
|
|
98
|
+
>>> import polars as pl
|
|
99
|
+
>>> _ = pl.Config.set_tbl_width_chars(210)
|
|
100
|
+
>>> _ = pl.Config.set_tbl_cols(-1)
|
|
135
101
|
>>> from pyield import bc
|
|
136
102
|
>>> bc.compromissadas(inicio="21-08-2025", fim="21-08-2025")
|
|
137
103
|
shape: (2, 12)
|
|
138
|
-
|
|
139
|
-
│ data_leilao ┆ data_liquidacao ┆ data_retorno ┆ hora_inicio ┆
|
|
140
|
-
│ --- ┆ --- ┆ --- ┆ --- ┆
|
|
141
|
-
│ date ┆ date ┆ date ┆ time ┆
|
|
142
|
-
|
|
143
|
-
│ 2025-08-21 ┆ 2025-08-21 ┆ 2025-08-22 ┆ 09:00:00 ┆
|
|
144
|
-
│ 2025-08-21 ┆ 2025-08-22 ┆ 2025-11-21 ┆ 12:00:00 ┆
|
|
145
|
-
|
|
104
|
+
┌─────────────┬─────────────────┬──────────────┬─────────────┬──────────┬──────────┬────────────┬────────────────────┬───────────────┬───────────────────┬────────────┬────────────┐
|
|
105
|
+
│ data_leilao ┆ data_liquidacao ┆ data_retorno ┆ hora_inicio ┆ prazo_dc ┆ prazo_du ┆ comunicado ┆ tipo_oferta ┆ publico ┆ financeiro_aceito ┆ taxa_corte ┆ pct_aceito │
|
|
106
|
+
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
107
|
+
│ date ┆ date ┆ date ┆ time ┆ i64 ┆ i64 ┆ i64 ┆ str ┆ str ┆ f64 ┆ f64 ┆ f64 │
|
|
108
|
+
╞═════════════╪═════════════════╪══════════════╪═════════════╪══════════╪══════════╪════════════╪════════════════════╪═══════════════╪═══════════════════╪════════════╪════════════╡
|
|
109
|
+
│ 2025-08-21 ┆ 2025-08-21 ┆ 2025-08-22 ┆ 09:00:00 ┆ 1 ┆ 1 ┆ null ┆ Tomador ┆ SomenteDealer ┆ 6.4771e11 ┆ 0.149 ┆ 100.0 │
|
|
110
|
+
│ 2025-08-21 ┆ 2025-08-22 ┆ 2025-11-21 ┆ 12:00:00 ┆ 91 ┆ 64 ┆ 43716 ┆ Compromissada 1047 ┆ TodoMercado ┆ 5.0000e9 ┆ 0.9978 ┆ 35.87 │
|
|
111
|
+
└─────────────┴─────────────────┴──────────────┴─────────────┴──────────┴──────────┴────────────┴────────────────────┴───────────────┴───────────────────┴────────────┴────────────┘
|
|
112
|
+
>>> _ = pl.Config.restore_defaults()
|
|
113
|
+
>>> _ = pl.Config.set_tbl_width_chars(150)
|
|
146
114
|
"""
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
115
|
+
params = _montar_parametros(inicio, fim)
|
|
116
|
+
url = montar_url(URL_BASE_API, params)
|
|
117
|
+
dados = buscar_csv(url)
|
|
118
|
+
df = parsear_csv(dados)
|
|
150
119
|
if df.is_empty():
|
|
151
120
|
return pl.DataFrame()
|
|
152
121
|
return _processar_df(df)
|
|
@@ -12,13 +12,12 @@ from typing import Literal
|
|
|
12
12
|
|
|
13
13
|
import polars as pl
|
|
14
14
|
import polars.selectors as cs
|
|
15
|
-
import requests
|
|
16
15
|
|
|
17
16
|
import pyield._internal.converters as cv
|
|
18
17
|
from pyield import du
|
|
19
18
|
from pyield._internal.br_numbers import float_br, taxa_br
|
|
20
|
-
from pyield._internal.retry import retry_padrao
|
|
21
19
|
from pyield._internal.types import DateLike
|
|
20
|
+
from pyield.bc._olinda import buscar_csv, montar_url, parsear_csv
|
|
22
21
|
from pyield.bc.sgs import ptax_serie
|
|
23
22
|
from pyield.tn.ntnb import duration as duration_b
|
|
24
23
|
from pyield.tn.ntnf import duration as duration_f
|
|
@@ -74,39 +73,17 @@ CHAVES_ORDENACAO = ["data_leilao", "tipo_leilao", "titulo", "data_vencimento"]
|
|
|
74
73
|
URL_BASE_API = "https://olinda.bcb.gov.br/olinda/servico/leiloes_selic/versao/v1/odata/leiloesTitulosPublicos(dataMovimentoInicio=@dataMovimentoInicio,dataMovimentoFim=@dataMovimentoFim,dataLiquidacao=@dataLiquidacao,codigoTitulo=@codigoTitulo,dataVencimento=@dataVencimento,edital=@edital,tipoPublico=@tipoPublico,tipoOferta=@tipoOferta)?"
|
|
75
74
|
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def _montar_url(
|
|
76
|
+
def _montar_parametros(
|
|
81
77
|
inicio: DateLike | None = None,
|
|
82
78
|
fim: DateLike | None = None,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
) -> dict[str, str]:
|
|
80
|
+
"""Converte parâmetros opcionais de período em dicionário para a URL."""
|
|
81
|
+
params: dict[str, str] = {}
|
|
86
82
|
if inicio:
|
|
87
|
-
|
|
88
|
-
url += f"@dataMovimentoInicio='{inicio:%Y-%m-%d}'"
|
|
83
|
+
params["dataMovimentoInicio"] = cv.converter_datas(inicio).strftime("%Y-%m-%d")
|
|
89
84
|
if fim:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if tipo_leilao:
|
|
93
|
-
url += f"&@tipoOferta='{MAPA_TIPO_LEILAO[tipo_leilao.lower()]}'"
|
|
94
|
-
url += "&$format=text/csv"
|
|
95
|
-
return url
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
@retry_padrao
|
|
99
|
-
def _buscar_csv(url: str) -> bytes:
|
|
100
|
-
resposta = requests.get(url, timeout=10)
|
|
101
|
-
resposta.raise_for_status()
|
|
102
|
-
return resposta.content
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def _parsear_df(dados: bytes) -> pl.DataFrame:
|
|
106
|
-
"""Lê CSV como strings."""
|
|
107
|
-
if not dados.strip():
|
|
108
|
-
return pl.DataFrame()
|
|
109
|
-
return pl.read_csv(dados, infer_schema=False, null_values=["null"])
|
|
85
|
+
params["dataMovimentoFim"] = cv.converter_datas(fim).strftime("%Y-%m-%d")
|
|
86
|
+
return params
|
|
110
87
|
|
|
111
88
|
|
|
112
89
|
def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
@@ -147,9 +124,7 @@ def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
|
147
124
|
pu_corte=float_br("cotacaoCorte"),
|
|
148
125
|
taxa_media=taxa_br("taxaMedia"),
|
|
149
126
|
taxa_corte=taxa_br("taxaCorte"),
|
|
150
|
-
financeiro_total=
|
|
151
|
-
.round(0)
|
|
152
|
-
.cast(pl.Int64),
|
|
127
|
+
financeiro_total=float_br("financeiro") * 1_000_000,
|
|
153
128
|
quantidade_ofertada_1v=pl.col("quantidadeOfertada").cast(pl.Int64),
|
|
154
129
|
quantidade_aceita_1v=pl.col("quantidadeAceita").cast(pl.Int64),
|
|
155
130
|
quantidade_liquidada_1v=pl.col("quantidadeLiquidada").cast(pl.Int64),
|
|
@@ -182,9 +157,7 @@ def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
|
182
157
|
(pl.col("quantidade_aceita_1v") / pl.col("quantidade_aceita_total"))
|
|
183
158
|
* pl.col("financeiro_total")
|
|
184
159
|
)
|
|
185
|
-
.otherwise(0)
|
|
186
|
-
.round(0)
|
|
187
|
-
.cast(pl.Int64),
|
|
160
|
+
.otherwise(0.0),
|
|
188
161
|
)
|
|
189
162
|
.with_columns(
|
|
190
163
|
financeiro_2v=pl.col("financeiro_total") - pl.col("financeiro_1v"),
|
|
@@ -319,9 +292,9 @@ def leiloes(
|
|
|
319
292
|
* quantidade_aceita_1v (Int64): qtd aceita 1ª volta.
|
|
320
293
|
* quantidade_aceita_2v (Int64): qtd aceita 2ª volta.
|
|
321
294
|
* quantidade_aceita_total (Int64): qtd total aceita.
|
|
322
|
-
* financeiro_1v (
|
|
323
|
-
* financeiro_2v (
|
|
324
|
-
* financeiro_total (
|
|
295
|
+
* financeiro_1v (Float64): financeiro 1ª volta em R$.
|
|
296
|
+
* financeiro_2v (Float64): financeiro 2ª volta em R$.
|
|
297
|
+
* financeiro_total (Float64): financeiro total em R$.
|
|
325
298
|
|
|
326
299
|
Notes:
|
|
327
300
|
1v = primeira volta (rodada), 2v = segunda volta.
|
|
@@ -333,24 +306,23 @@ def leiloes(
|
|
|
333
306
|
┌─────────────┬─────────────────┬─────────────┬───────────────┬───┬─────────────────────────┬───────────────┬───────────────┬──────────────────┐
|
|
334
307
|
│ data_leilao ┆ data_liquidacao ┆ tipo_leilao ┆ numero_edital ┆ … ┆ quantidade_aceita_total ┆ financeiro_1v ┆ financeiro_2v ┆ financeiro_total │
|
|
335
308
|
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
|
|
336
|
-
│ date ┆ date ┆ str ┆ i64 ┆ ┆ i64 ┆
|
|
309
|
+
│ date ┆ date ┆ str ┆ i64 ┆ ┆ i64 ┆ f64 ┆ f64 ┆ f64 │
|
|
337
310
|
╞═════════════╪═════════════════╪═════════════╪═══════════════╪═══╪═════════════════════════╪═══════════════╪═══════════════╪══════════════════╡
|
|
338
|
-
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 192 ┆ … ┆ 150000 ┆
|
|
339
|
-
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 192 ┆ … ┆ 751003 ┆
|
|
340
|
-
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 193 ┆ … ┆ 300759 ┆
|
|
341
|
-
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 194 ┆ … ┆ 500542 ┆
|
|
342
|
-
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 194 ┆ … ┆ 500000 ┆
|
|
311
|
+
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 192 ┆ … ┆ 150000 ┆ 2.5724e9 ┆ 0.0 ┆ 2.5724e9 │
|
|
312
|
+
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 192 ┆ … ┆ 751003 ┆ 1.2804e10 ┆ 1.7124e7 ┆ 1.2822e10 │
|
|
313
|
+
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 193 ┆ … ┆ 300759 ┆ 1.2899e9 ┆ 3.2635e6 ┆ 1.2932e9 │
|
|
314
|
+
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 194 ┆ … ┆ 500542 ┆ 2.0717e9 ┆ 2.2457e6 ┆ 2.0739e9 │
|
|
315
|
+
│ 2025-08-19 ┆ 2025-08-20 ┆ Venda ┆ 194 ┆ … ┆ 500000 ┆ 2.0107e9 ┆ 0.0 ┆ 2.0107e9 │
|
|
343
316
|
└─────────────┴─────────────────┴─────────────┴───────────────┴───┴─────────────────────────┴───────────────┴───────────────┴──────────────────┘
|
|
344
317
|
"""
|
|
345
|
-
url =
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
tipo_leilao=tipo_leilao,
|
|
349
|
-
)
|
|
350
|
-
dados = _buscar_csv(url)
|
|
351
|
-
df = _parsear_df(dados)
|
|
318
|
+
url = montar_url(URL_BASE_API, _montar_parametros(inicio, fim))
|
|
319
|
+
dados = buscar_csv(url)
|
|
320
|
+
df = parsear_csv(dados)
|
|
352
321
|
if df.is_empty():
|
|
353
322
|
return pl.DataFrame()
|
|
354
323
|
df = _processar_df(df)
|
|
355
324
|
df = _adicionar_dv01_usd(df)
|
|
356
|
-
|
|
325
|
+
df = df.select(ORDEM_COLUNAS_FINAL).sort(CHAVES_ORDENACAO)
|
|
326
|
+
if tipo_leilao:
|
|
327
|
+
df = df.filter(pl.col("tipo_leilao").str.to_lowercase() == tipo_leilao.lower())
|
|
328
|
+
return df
|
|
@@ -59,7 +59,7 @@ class SerieSGS(Enum):
|
|
|
59
59
|
@ttl_cache()
|
|
60
60
|
@retry_padrao
|
|
61
61
|
def _chamar_api(url_api: str) -> list[dict[str, str]]:
|
|
62
|
-
resposta = requests.get(url_api, timeout=
|
|
62
|
+
resposta = requests.get(url_api, timeout=30)
|
|
63
63
|
resposta.raise_for_status()
|
|
64
64
|
return resposta.json()
|
|
65
65
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from pyield.tn import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf, pre
|
|
2
|
+
from pyield.tn.benchmark import benchmarks
|
|
3
|
+
from pyield.tn.leiloes import leilao
|
|
4
|
+
from pyield.tn.rmd import rmd
|
|
5
|
+
from pyield.tn.utils import premio_pre
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"benchmarks",
|
|
9
|
+
"leilao",
|
|
10
|
+
"lft",
|
|
11
|
+
"ltn",
|
|
12
|
+
"ntnb",
|
|
13
|
+
"ntnb1",
|
|
14
|
+
"ntnbprinc",
|
|
15
|
+
"ntnc",
|
|
16
|
+
"ntnf",
|
|
17
|
+
"pre",
|
|
18
|
+
"premio_pre",
|
|
19
|
+
"rmd",
|
|
20
|
+
]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.48.6"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from pyield.anbima.ettj_intradia import ettj_intradia
|
|
2
|
-
from pyield.anbima.ettj_ultima import ettj_ultima
|
|
3
|
-
from pyield.anbima.ima_ultimo import ima_ultimo
|
|
4
|
-
from pyield.anbima.imaq import imaq
|
|
5
|
-
from pyield.anbima.tpf import tpf, tpf_fonte, tpf_vencimentos
|
|
6
|
-
|
|
7
|
-
__all__ = [
|
|
8
|
-
"ima_ultimo",
|
|
9
|
-
"imaq",
|
|
10
|
-
"tpf",
|
|
11
|
-
"tpf_vencimentos",
|
|
12
|
-
"tpf_fonte",
|
|
13
|
-
"ettj_ultima",
|
|
14
|
-
"ettj_intradia",
|
|
15
|
-
]
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import datetime as dt
|
|
2
|
-
|
|
3
|
-
import polars as pl
|
|
4
|
-
import requests
|
|
5
|
-
|
|
6
|
-
from pyield._internal.br_numbers import float_br, taxa_br
|
|
7
|
-
from pyield._internal.cache import ttl_cache
|
|
8
|
-
from pyield._internal.retry import retry_padrao
|
|
9
|
-
|
|
10
|
-
URL_ETTJ_INTRADIA = (
|
|
11
|
-
"https://www.anbima.com.br/informacoes/curvas-intradiarias/cIntra-down.asp"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
# Dados ETTJ: taxas com 4 casas decimais em percentual (ex.: 14,2644%).
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@ttl_cache()
|
|
18
|
-
@retry_padrao
|
|
19
|
-
def _buscar_texto_intradia() -> str:
|
|
20
|
-
carga_requisicao = {"Dt_Ref": "", "saida": "csv"}
|
|
21
|
-
resposta = requests.post(URL_ETTJ_INTRADIA, data=carga_requisicao, timeout=10)
|
|
22
|
-
resposta.raise_for_status()
|
|
23
|
-
resposta.encoding = "latin1"
|
|
24
|
-
return resposta.text
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def _extrair_data_e_tabelas(texto: str) -> tuple[dt.date, str, str]:
|
|
28
|
-
"""Separa o texto bruto em data de referência e as duas tabelas CSV."""
|
|
29
|
-
# Cada seção (PREFIXADOS e IPCA) é separada por linha em branco
|
|
30
|
-
secao_pre, secao_ipca = texto.strip().replace("\r\n", "\n").split("\n\n")
|
|
31
|
-
|
|
32
|
-
# Estrutura de cada seção: título, data, header+dados
|
|
33
|
-
linhas_pre = secao_pre.splitlines()
|
|
34
|
-
data_ref = dt.datetime.strptime(linhas_pre[1], "%d/%m/%Y").date()
|
|
35
|
-
tabela_pre = "\n".join(linhas_pre[2:])
|
|
36
|
-
|
|
37
|
-
linhas_ipca = secao_ipca.splitlines()
|
|
38
|
-
tabela_ipca = "\n".join(linhas_ipca[2:])
|
|
39
|
-
|
|
40
|
-
return data_ref, tabela_pre, tabela_ipca
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def _parsear_tabela_intradia(texto: str, nome_taxa: str) -> pl.DataFrame:
|
|
44
|
-
return pl.read_csv(texto.encode(), separator=";", infer_schema=False).select(
|
|
45
|
-
vertice=float_br("Vertices").cast(pl.Int64),
|
|
46
|
-
**{nome_taxa: taxa_br("D0")},
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def ettj_intradia() -> pl.DataFrame:
|
|
51
|
-
"""Obtém e processa a curva de juros intradiária da ANBIMA.
|
|
52
|
-
|
|
53
|
-
Busca os dados mais recentes da curva de juros intradiária publicada pela
|
|
54
|
-
ANBIMA, contendo taxas reais (indexadas ao IPCA), taxas nominais e inflação
|
|
55
|
-
implícita em diversos vértices. A curva é publicada por volta das 12h30 BRT.
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
pl.DataFrame: DataFrame com os dados intradiários da ETTJ.
|
|
59
|
-
|
|
60
|
-
Output Columns:
|
|
61
|
-
- data_referencia (Date): data de referência da curva de juros.
|
|
62
|
-
- vertice (Int64): vértice em dias úteis.
|
|
63
|
-
- taxa_nominal (Float64): taxa de juros nominal zero-cupom.
|
|
64
|
-
- taxa_real (Float64): taxa de juros real zero-cupom (indexada ao IPCA).
|
|
65
|
-
- inflacao_implicita (Float64): taxa de inflação implícita (breakeven).
|
|
66
|
-
|
|
67
|
-
Notes:
|
|
68
|
-
Todas as taxas são expressas em formato decimal (ex: 0.12 para 12%).
|
|
69
|
-
"""
|
|
70
|
-
texto_api = _buscar_texto_intradia()
|
|
71
|
-
|
|
72
|
-
data_ref, tabela_pre, tabela_ipca = _extrair_data_e_tabelas(texto_api)
|
|
73
|
-
|
|
74
|
-
df_pre = _parsear_tabela_intradia(tabela_pre, "taxa_nominal")
|
|
75
|
-
df_ipca = _parsear_tabela_intradia(tabela_ipca, "taxa_real")
|
|
76
|
-
expr_inflacao_impl = (pl.col("taxa_nominal") + 1) / (pl.col("taxa_real") + 1) - 1
|
|
77
|
-
df = df_pre.join(df_ipca, on="vertice", how="right").with_columns(
|
|
78
|
-
data_referencia=data_ref,
|
|
79
|
-
inflacao_implicita=expr_inflacao_impl.round(6),
|
|
80
|
-
)
|
|
81
|
-
return df.select(
|
|
82
|
-
"data_referencia", "vertice", "taxa_nominal", "taxa_real", "inflacao_implicita"
|
|
83
|
-
)
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import datetime as dt
|
|
2
|
-
|
|
3
|
-
import polars as pl
|
|
4
|
-
import requests
|
|
5
|
-
|
|
6
|
-
from pyield._internal.br_numbers import float_br, taxa_br
|
|
7
|
-
from pyield._internal.cache import ttl_cache
|
|
8
|
-
from pyield._internal.retry import retry_padrao
|
|
9
|
-
|
|
10
|
-
URL_ETTJ_ULTIMA = "https://www.anbima.com.br/informacoes/est-termo/CZ-down.asp"
|
|
11
|
-
|
|
12
|
-
# Dados ETTJ: taxas com 4 casas decimais em percentual (ex.: 14,2644%).
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@ttl_cache()
|
|
16
|
-
@retry_padrao
|
|
17
|
-
def _buscar_texto_ettj_ultima() -> str:
|
|
18
|
-
"""Busca o texto bruto da curva de juros na ANBIMA."""
|
|
19
|
-
carga_requisicao = {
|
|
20
|
-
"Idioma": "PT",
|
|
21
|
-
"Dt_Ref": "",
|
|
22
|
-
"saida": "csv",
|
|
23
|
-
}
|
|
24
|
-
resposta = requests.post(URL_ETTJ_ULTIMA, data=carga_requisicao, timeout=10)
|
|
25
|
-
resposta.raise_for_status()
|
|
26
|
-
resposta.encoding = "latin1"
|
|
27
|
-
return resposta.text
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def _extrair_data_e_tabela(texto: str) -> tuple[dt.date, str]:
|
|
31
|
-
"""Separa o texto bruto em data de referência e a tabela CSV principal."""
|
|
32
|
-
# Seções separadas por linha em branco: betas, ETTJ, circular, erros
|
|
33
|
-
secoes = texto.strip().replace("\r\n", "\n").split("\n\n")
|
|
34
|
-
# A data está na primeira linha da primeira seção (ex.: "20/03/2026;Beta 1;...")
|
|
35
|
-
data_str = secoes[0].splitlines()[0][:10]
|
|
36
|
-
data_ref = dt.datetime.strptime(data_str, "%d/%m/%Y").date()
|
|
37
|
-
# A tabela ETTJ é a segunda seção; pular o título (primeira linha)
|
|
38
|
-
linhas_ettj = secoes[1].splitlines()
|
|
39
|
-
tabela = "\n".join(linhas_ettj[1:])
|
|
40
|
-
return data_ref, tabela
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def _processar_tabela(texto: str, data_referencia: dt.date) -> pl.DataFrame:
|
|
44
|
-
"""Lê o CSV e converte para DataFrame com taxas decimais."""
|
|
45
|
-
return pl.read_csv(texto.encode(), separator=";", infer_schema=False).select(
|
|
46
|
-
data_referencia=data_referencia,
|
|
47
|
-
vertice=float_br("Vertices").cast(pl.Int64),
|
|
48
|
-
taxa_nominal=taxa_br("ETTJ PREF"),
|
|
49
|
-
taxa_real=taxa_br("ETTJ IPCA"),
|
|
50
|
-
inflacao_implicita=taxa_br("Inflação Implícita"),
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def ettj_ultima() -> pl.DataFrame:
|
|
55
|
-
"""Obtém e processa a última curva de juros (ETTJ) publicada pela ANBIMA.
|
|
56
|
-
|
|
57
|
-
Busca os dados mais recentes da curva de juros de fechamento publicada pela
|
|
58
|
-
ANBIMA, contendo taxas reais (indexadas ao IPCA), taxas nominais e inflação
|
|
59
|
-
implícita em diversos vértices.
|
|
60
|
-
|
|
61
|
-
Returns:
|
|
62
|
-
pl.DataFrame: DataFrame com os dados da ETTJ de fechamento.
|
|
63
|
-
|
|
64
|
-
Output Columns:
|
|
65
|
-
- data_referencia (Date): data de referência da curva de juros.
|
|
66
|
-
- vertice (Int64): vértice em dias úteis.
|
|
67
|
-
- taxa_nominal (Float64): taxa de juros nominal zero-cupom.
|
|
68
|
-
- taxa_real (Float64): taxa de juros real zero-cupom (indexada ao IPCA).
|
|
69
|
-
- inflacao_implicita (Float64): taxa de inflação implícita (breakeven).
|
|
70
|
-
|
|
71
|
-
Notes:
|
|
72
|
-
Todas as taxas são expressas em formato decimal (ex: 0.12 para 12%).
|
|
73
|
-
"""
|
|
74
|
-
texto = _buscar_texto_ettj_ultima()
|
|
75
|
-
data_ref, tabela = _extrair_data_e_tabela(texto)
|
|
76
|
-
return _processar_tabela(tabela, data_ref)
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
from typing import Literal
|
|
2
|
-
|
|
3
|
-
import polars as pl
|
|
4
|
-
import requests
|
|
5
|
-
|
|
6
|
-
from pyield._internal.br_numbers import float_br, inteiro_m, taxa_br
|
|
7
|
-
from pyield._internal.cache import ttl_cache
|
|
8
|
-
from pyield._internal.retry import retry_padrao
|
|
9
|
-
|
|
10
|
-
TiposIMA = Literal[
|
|
11
|
-
"IRF-M 1",
|
|
12
|
-
"IRF-M 1+",
|
|
13
|
-
"IRF-M",
|
|
14
|
-
"IMA-B 5",
|
|
15
|
-
"IMA-B 5+",
|
|
16
|
-
"IMA-B",
|
|
17
|
-
"IMA-S",
|
|
18
|
-
"IMA-GERAL-EX-C",
|
|
19
|
-
"IMA-GERAL",
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
URL_IMA_ULTIMO = "https://www.anbima.com.br/informacoes/ima/arqs/ima_completo.txt"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@ttl_cache()
|
|
27
|
-
@retry_padrao
|
|
28
|
-
def _buscar_texto_ima_ultimo() -> str:
|
|
29
|
-
resposta = requests.get(URL_IMA_ULTIMO, timeout=3)
|
|
30
|
-
resposta.raise_for_status()
|
|
31
|
-
resposta.encoding = "latin1"
|
|
32
|
-
return resposta.text
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def _parsear_df(texto: str) -> pl.DataFrame:
|
|
36
|
-
texto_csv = texto.split("2@COMPOSIÇÃO DE CARTEIRA")[1].strip()
|
|
37
|
-
return pl.read_csv(
|
|
38
|
-
texto_csv.encode(),
|
|
39
|
-
separator="@",
|
|
40
|
-
infer_schema=False,
|
|
41
|
-
null_values="--",
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _processar_df(df: pl.DataFrame) -> pl.DataFrame:
|
|
46
|
-
mduration_expr = pl.col("duration") / (1 + pl.col("taxa_indicativa"))
|
|
47
|
-
dv01_mercado_expr = pl.col("dv01") * pl.col("quantidade_mercado")
|
|
48
|
-
df = (
|
|
49
|
-
df.with_columns(
|
|
50
|
-
pu=float_br("PU (R$)"),
|
|
51
|
-
duration=pl.col("Duration (d.u.)").cast(pl.Int64).truediv(252),
|
|
52
|
-
taxa_indicativa=taxa_br("Taxa Indicativa (% a.a.)", 4),
|
|
53
|
-
quantidade_mercado=inteiro_m("Quantidade (1.000 títulos)"),
|
|
54
|
-
)
|
|
55
|
-
.with_columns(dv01=0.0001 * pl.col("pu") * mduration_expr)
|
|
56
|
-
.select(
|
|
57
|
-
data_referencia=pl.col("Data de Referência").str.to_date("%d/%m/%Y"),
|
|
58
|
-
indice=pl.col("INDICE"),
|
|
59
|
-
titulo=pl.col("Títulos"),
|
|
60
|
-
data_vencimento=pl.col("Data de Vencimento").str.to_date("%d/%m/%Y"),
|
|
61
|
-
codigo_selic=pl.col("Código SELIC").cast(pl.Int64),
|
|
62
|
-
isin=pl.col("Código ISIN"),
|
|
63
|
-
dias_uteis=pl.col("Prazo (d.u.)").cast(pl.Int64),
|
|
64
|
-
duration=pl.col("duration"),
|
|
65
|
-
taxa_indicativa=pl.col("taxa_indicativa"),
|
|
66
|
-
pu=pl.col("pu"),
|
|
67
|
-
pu_juros=float_br("PU de Juros (R$)"),
|
|
68
|
-
dv01=pl.col("dv01"),
|
|
69
|
-
pmr=float_br("PMR"),
|
|
70
|
-
peso=float_br("Peso (%)"),
|
|
71
|
-
convexidade=float_br("Convexidade"),
|
|
72
|
-
quantidade_teorica=float_br("Quantidade Teórica (1.000 títulos)"),
|
|
73
|
-
operacoes=pl.col("Número de Operações *").cast(pl.Int64),
|
|
74
|
-
quantidade_negociada=inteiro_m("Quant. Negociada (1.000 títulos) *"),
|
|
75
|
-
valor_negociado=inteiro_m("Valor Negociado (R$ mil) *"),
|
|
76
|
-
dv01_mercado=dv01_mercado_expr.round(0).cast(pl.Int64),
|
|
77
|
-
quantidade_mercado=pl.col("quantidade_mercado"),
|
|
78
|
-
valor_mercado=inteiro_m("Carteira a Mercado (R$ mil)"),
|
|
79
|
-
)
|
|
80
|
-
)
|
|
81
|
-
return df
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def ima_ultimo(indice: TiposIMA | None = None) -> pl.DataFrame:
|
|
85
|
-
"""Obtém os últimos dados de composição de carteira IMA disponíveis na ANBIMA.
|
|
86
|
-
|
|
87
|
-
Busca e processa os dados do arquivo IMA completo publicado pela ANBIMA,
|
|
88
|
-
retornando um DataFrame estruturado.
|
|
89
|
-
|
|
90
|
-
Args:
|
|
91
|
-
indice (str, optional): Tipo de índice IMA para filtrar os dados.
|
|
92
|
-
Se None, retorna todos os índices. Padrão é None.
|
|
93
|
-
|
|
94
|
-
Returns:
|
|
95
|
-
pl.DataFrame: DataFrame com os dados do IMA.
|
|
96
|
-
|
|
97
|
-
Output Columns:
|
|
98
|
-
- data_referencia (Date): data de referência.
|
|
99
|
-
- indice (String): índice IMA (ex: 'IMA-B', 'IRF-M').
|
|
100
|
-
- titulo (String): título (ex: 'LTN', 'NTN-B').
|
|
101
|
-
- data_vencimento (Date): data de vencimento do título.
|
|
102
|
-
- codigo_selic (Int64): código do título no sistema SELIC.
|
|
103
|
-
- isin (String): código ISIN.
|
|
104
|
-
- dias_uteis (Int64): dias úteis até o vencimento.
|
|
105
|
-
- duration (Float64): duration do título em anos úteis (252 d.u./ano).
|
|
106
|
-
- taxa_indicativa (Float64): taxa indicativa em decimal (ex: 0.10 para 10%).
|
|
107
|
-
- pu (Float64): preço unitário (PU) em R$.
|
|
108
|
-
- pu_juros (Float64): PU de juros em R$.
|
|
109
|
-
- dv01 (Float64): DV01 em R$.
|
|
110
|
-
- pmr (Float64): prazo médio de repactuação.
|
|
111
|
-
- peso (Float64): peso do título no índice (%).
|
|
112
|
-
- convexidade (Float64): convexidade do título.
|
|
113
|
-
- quantidade_teorica (Float64): quantidade teórica (em 1.000 títulos).
|
|
114
|
-
- operacoes (Int64): número de operações.
|
|
115
|
-
- quantidade_negociada (Int64): quantidade negociada (unidades).
|
|
116
|
-
- valor_negociado (Int64): valor negociado em R$.
|
|
117
|
-
- dv01_mercado (Int64): DV01 de mercado em R$.
|
|
118
|
-
- quantidade_mercado (Int64): quantidade em carteira (unidades).
|
|
119
|
-
- valor_mercado (Int64): valor de mercado em R$.
|
|
120
|
-
|
|
121
|
-
Examples:
|
|
122
|
-
>>> yd.anbima.ima_ultimo("IMA-B") # doctest: +SKIP
|
|
123
|
-
"""
|
|
124
|
-
texto_ima = _buscar_texto_ima_ultimo()
|
|
125
|
-
df = _parsear_df(texto_ima)
|
|
126
|
-
df = _processar_df(df)
|
|
127
|
-
if indice:
|
|
128
|
-
df = df.filter(pl.col("indice") == indice)
|
|
129
|
-
return df.sort("indice", "titulo", "data_vencimento")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -10,7 +10,6 @@ from pyield.selic.cpm import data as copom_options
|
|
|
10
10
|
from pyield.tn import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
|
-
"Interpolador",
|
|
14
13
|
"__version__",
|
|
15
14
|
"agora",
|
|
16
15
|
"anbima",
|
|
@@ -22,6 +21,7 @@ __all__ = [
|
|
|
22
21
|
"forward",
|
|
23
22
|
"forwards",
|
|
24
23
|
"hoje",
|
|
24
|
+
"Interpolador",
|
|
25
25
|
"ipca",
|
|
26
26
|
"lft",
|
|
27
27
|
"ltn",
|
|
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
|