PYield 0.36.0__tar.gz → 0.36.2__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 (54) hide show
  1. {pyield-0.36.0 → pyield-0.36.2}/.gitignore +3 -1
  2. {pyield-0.36.0 → pyield-0.36.2}/PKG-INFO +1 -1
  3. pyield-0.36.2/pyield/__about__.py +1 -0
  4. {pyield-0.36.0 → pyield-0.36.2}/pyield/anbima/imaq.py +9 -2
  5. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/auction.py +72 -29
  6. pyield-0.36.2/pyield/tn/__init__.py +3 -0
  7. pyield-0.36.0/pyield/tn/auction.py → pyield-0.36.2/pyield/tn/benchmark.py +17 -11
  8. {pyield-0.36.0 → pyield-0.36.2}/pyproject.toml +4 -19
  9. pyield-0.36.0/pyield/__about__.py +0 -1
  10. pyield-0.36.0/pyield/tn/__init__.py +0 -3
  11. {pyield-0.36.0 → pyield-0.36.2}/LICENSE +0 -0
  12. {pyield-0.36.0 → pyield-0.36.2}/README.md +0 -0
  13. {pyield-0.36.0 → pyield-0.36.2}/pyield/__init__.py +0 -0
  14. {pyield-0.36.0 → pyield-0.36.2}/pyield/anbima/__init__.py +0 -0
  15. {pyield-0.36.0 → pyield-0.36.2}/pyield/anbima/ettj.py +0 -0
  16. {pyield-0.36.0 → pyield-0.36.2}/pyield/anbima/ima.py +0 -0
  17. {pyield-0.36.0 → pyield-0.36.2}/pyield/anbima/ipca.py +0 -0
  18. {pyield-0.36.0 → pyield-0.36.2}/pyield/anbima/tpf.py +0 -0
  19. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/__init__.py +0 -0
  20. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/di1.py +0 -0
  21. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/di_over.py +0 -0
  22. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/futures/__init__.py +0 -0
  23. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/futures/common.py +0 -0
  24. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/futures/historical.py +0 -0
  25. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/futures/intraday.py +0 -0
  26. {pyield-0.36.0 → pyield-0.36.2}/pyield/b3/futures/xml.py +0 -0
  27. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/__init__.py +0 -0
  28. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/bcdata.py +0 -0
  29. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/ptax.py +0 -0
  30. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/repo.py +0 -0
  31. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/trades_intraday.py +0 -0
  32. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/trades_monthly.py +0 -0
  33. {pyield-0.36.0 → pyield-0.36.2}/pyield/bc/vna.py +0 -0
  34. {pyield-0.36.0 → pyield-0.36.2}/pyield/bday.py +0 -0
  35. {pyield-0.36.0 → pyield-0.36.2}/pyield/conftest.py +0 -0
  36. {pyield-0.36.0 → pyield-0.36.2}/pyield/data_cache.py +0 -0
  37. {pyield-0.36.0 → pyield-0.36.2}/pyield/date_converter.py +0 -0
  38. {pyield-0.36.0 → pyield-0.36.2}/pyield/fwd.py +0 -0
  39. {pyield-0.36.0 → pyield-0.36.2}/pyield/holidays/__init__.py +0 -0
  40. {pyield-0.36.0 → pyield-0.36.2}/pyield/holidays/br_holidays_new.txt +0 -0
  41. {pyield-0.36.0 → pyield-0.36.2}/pyield/holidays/br_holidays_old.txt +0 -0
  42. {pyield-0.36.0 → pyield-0.36.2}/pyield/holidays/brholidays.py +0 -0
  43. {pyield-0.36.0 → pyield-0.36.2}/pyield/ibge/__init__.py +0 -0
  44. {pyield-0.36.0 → pyield-0.36.2}/pyield/ibge/ipca.py +0 -0
  45. {pyield-0.36.0 → pyield-0.36.2}/pyield/interpolator.py +0 -0
  46. {pyield-0.36.0 → pyield-0.36.2}/pyield/py.typed +0 -0
  47. {pyield-0.36.0 → pyield-0.36.2}/pyield/retry.py +0 -0
  48. {pyield-0.36.0 → pyield-0.36.2}/pyield/tn/lft.py +0 -0
  49. {pyield-0.36.0 → pyield-0.36.2}/pyield/tn/ltn.py +0 -0
  50. {pyield-0.36.0 → pyield-0.36.2}/pyield/tn/ntnb.py +0 -0
  51. {pyield-0.36.0 → pyield-0.36.2}/pyield/tn/ntnc.py +0 -0
  52. {pyield-0.36.0 → pyield-0.36.2}/pyield/tn/ntnf.py +0 -0
  53. {pyield-0.36.0 → pyield-0.36.2}/pyield/tn/pre.py +0 -0
  54. {pyield-0.36.0 → pyield-0.36.2}/pyield/tn/tools.py +0 -0
@@ -36,4 +36,6 @@ ENV/
36
36
  *.ipynb
37
37
 
38
38
  # Dev folder
39
- dev/
39
+ dev/
40
+
41
+ site/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PYield
3
- Version: 0.36.0
3
+ Version: 0.36.2
4
4
  Summary: A Python library for analysis of fixed income instruments in Brazil
5
5
  Project-URL: Source, https://github.com/crdcj/PYield
6
6
  Author-email: Carlos Carvalho <cr.cj@outlook.com>
@@ -0,0 +1 @@
1
+ __version__ = "0.36.2"
@@ -60,6 +60,7 @@ def _fetch_url_tables(target_date: pd.Timestamp) -> pd.DataFrame:
60
60
  decimal=",",
61
61
  displayed_only=True,
62
62
  dtype_backend="numpy_nullable",
63
+ na_values="--",
63
64
  )
64
65
 
65
66
  df = (
@@ -95,9 +96,15 @@ def _fetch_url_tables(target_date: pd.Timestamp) -> pd.DataFrame:
95
96
  def _process_df(df: pd.DataFrame) -> pd.DataFrame:
96
97
  df = df.rename(columns=COLUMN_MAPPING)[COLUMN_MAPPING.values()]
97
98
  df["Maturity"] = pd.to_datetime(df["Maturity"], format="%d/%m/%Y")
98
- # Remove the thousands unit from numeric columns
99
+
99
100
  for col in ["MarketQuantity", "MarketValue", "QuantityVariation"]:
100
- df[col] = (1000 * df[col]).astype("Int64")
101
+ # Fallback to string conversion in case conversion failed during read_csv
102
+ if df[col].dtype == "string" or df[col].dtype == "object":
103
+ df[col] = df[col].str.replace(".", "", regex=False).replace(",", ".")
104
+ df[col] = pd.to_numeric(df[col], errors="coerce")
105
+
106
+ # Remove the thousands unit from numeric columns
107
+ df[col] *= (1000 * df[col]).astype("Int64")
101
108
 
102
109
  return df
103
110
 
@@ -14,6 +14,7 @@ import requests
14
14
 
15
15
  from pyield import bday
16
16
  from pyield import date_converter as dc
17
+ from pyield.bc import ptax
17
18
  from pyield.date_converter import DateScalar
18
19
  from pyield.retry import default_retry
19
20
  from pyield.tn.ntnb import duration as duration_b
@@ -176,7 +177,7 @@ def _add_dv01(df: pd.DataFrame) -> pd.DataFrame:
176
177
  df["DV01SR"] = dv01 * df["AcceptedQuantitySR"]
177
178
 
178
179
  for col in ["DV01", "DV01FR", "DV01SR"]:
179
- # Definiri DV01 nulos do leilão como 0
180
+ # Definrir DV01 nulos do leilão como 0
180
181
  df[col] = df[col].fillna(0).round(2)
181
182
 
182
183
  # Forçar 0 nas LFT, pois não há DV01
@@ -185,6 +186,24 @@ def _add_dv01(df: pd.DataFrame) -> pd.DataFrame:
185
186
  return df
186
187
 
187
188
 
189
+ def _get_ptax_df(start_date: pd.Timestamp | None = None) -> pd.DataFrame:
190
+ # A série de leilões começa em 2007
191
+ df = ptax.ptax_series(start=start_date)[["Date", "MidRate"]]
192
+ df = df.rename(columns={"MidRate": "PTAX"})
193
+ return df
194
+
195
+
196
+ def _add_usd_dv01(df: pd.DataFrame) -> pd.DataFrame:
197
+ ptax_start_date = df["Date"].min()
198
+ df_ptax = _get_ptax_df(start_date=ptax_start_date)
199
+ df = pd.merge_asof(left=df, right=df_ptax)
200
+ dv01_cols = [c for c in df.columns if c.startswith("DV01")]
201
+ for col in dv01_cols:
202
+ df[f"{col}USD"] = df[col] / df["PTAX"]
203
+
204
+ return df.drop(columns=["PTAX"])
205
+
206
+
188
207
  def _add_avg_maturity(df: pd.DataFrame) -> pd.DataFrame:
189
208
  # Na metodolgia do Tesouro Nacional, a maturidade média é a mesma que a duração
190
209
  df["AvgMaturity"] = df["Duration"]
@@ -221,6 +240,9 @@ def _sort_and_reorder_columns(df: pd.DataFrame) -> pd.DataFrame:
221
240
  "DV01",
222
241
  "DV01FR",
223
242
  "DV01SR",
243
+ "DV01USD",
244
+ "DV01FRUSD",
245
+ "DV01SRUSD",
224
246
  "AvgPrice",
225
247
  "CutPrice",
226
248
  "AvgRate",
@@ -242,6 +264,7 @@ def _fetch_df_from_url(url: str) -> pd.DataFrame:
242
264
  df = _process_df(df)
243
265
  df = _add_duration(df)
244
266
  df = _add_dv01(df)
267
+ df = _add_usd_dv01(df)
245
268
  df = _add_avg_maturity(df)
246
269
  df = _sort_and_reorder_columns(df)
247
270
  return df
@@ -304,38 +327,57 @@ def auctions(
304
327
  especificados. Em caso de erro ao buscar os dados, um DataFrame vazio
305
328
  é retornado e uma mensagem de erro é registrada no log.
306
329
 
330
+ Examples:
331
+ >>> import pandas as pd
332
+ >>> from pyield import bc
333
+ >>> df = bc.auctions(start="03-06-2025", end="03-06-2025")
334
+ >>> df
335
+ Date Settlement AuctionType ... CutPrice AvgRate CutRate
336
+ 0 2025-06-03 2025-06-04 Venda ... 16653.010815 0.000589 0.000589
337
+ 1 2025-06-03 2025-06-04 Venda ... 16572.063672 0.00109 0.00109
338
+ 2 2025-06-03 2025-06-04 Venda ... 4314.142451 0.07569 0.07569
339
+ 3 2025-06-03 2025-06-04 Venda ... 4140.47255 0.07312 0.07312
340
+ 4 2025-06-03 2025-06-04 Venda ... 3960.619508 0.07157 0.07157
341
+ ...
342
+
307
343
  Notes:
308
344
  FR = First Round (Primeira Rodada)
345
+
309
346
  SR = Second Round (Segunda Rodada)
310
347
 
311
- O DataFrame possui as seguintes colunas:
312
- - Date: Data do leilão.
313
- - Settlement: Data de liquidação do leilão.
314
- - AuctionType: Tipo de leilão (ex: "Sell" ou "Buy").
315
- - Ordinance: Edital normativo associado ao leilão.
316
- - Buyer: Categoria do comprador (ex: "TodoMercado", "SomenteDealerApto").
317
- - BondType: Categoria do título (ex: "LTN", "LFT", "NTN-B", "NTN-F").
318
- - SelicCode: Código do título no sistema Selic.
319
- - Maturity: Data de vencimento do título.
320
- - DV01: Valor do DV01 total do leilão em R$.
321
- - DV01FR: DV01 da Primeira Rodada (FR) em R$.
322
- - DV01SR: DV01 da Segunda Rodada (SR) em R$.
323
- - AvgMaturity: Maturidade média do título (em anos).
324
- - Value: Valor total do leilão em R$ (FR + SR).
325
- - ValueFR: Valor da primeira rodada (FR) do leilão em R$.
326
- - ValueSR: Valor da segunda rodada (SR) em R$.
327
- - OfferedQuantity: Quantidade total ofertada no leilão (FR + SR).
328
- - OfferedQuantityFR: Quantidade ofertada na primeira rodada (FR).
329
- - OfferedQuantitySR: Quantidade ofertada na segunda rodada (SR).
330
- - AcceptedQuantity: Quantidade total aceita no leilão (FR + SR).
331
- - AcceptedQuantityFR: Quantidade aceita na primeira rodada (FR).
332
- - AcceptedQuantitySR: Quantidade aceita na segunda rodada (SR).
333
- - AvgPrice: Preço médio no leilão.
334
- - CutPrice: Preço de corte.
335
- - AvgRate: Taxa de juros média.
336
- - CutRate: Taxa de corte.
337
- - BDToMat: Dias úteis até o vencimento.
338
- - Duration: Duration (Duração) do título.
348
+ DataFrame Columns:
349
+ - Date: Data do leilão.
350
+ - Settlement: Data de liquidação do leilão.
351
+ - AuctionType: Tipo de leilão (ex: "Sell" ou "Buy").
352
+ - Ordinance: Edital normativo associado ao leilão.
353
+ - Buyer: Categoria do comprador (ex: "TodoMercado", "SomenteDealerApto").
354
+ - BondType: Categoria do título (ex: "LTN", "LFT", "NTN-B", "NTN-F").
355
+ - SelicCode: Código do título no sistema Selic.
356
+ - Maturity: Data de vencimento do título.
357
+ - DV01: Valor do DV01 total do leilão em R$.
358
+ - DV01FR: DV01 da Primeira Rodada (FR) em R$.
359
+ - DV01SR: DV01 da Segunda Rodada (SR) em R$.
360
+ - DV01USD: DV01 total do leilão em dólares (USD).
361
+ - DV01FRUSD: DV01 da Primeira Rodada (FR) em dólares (USD).
362
+ - DV01SRUSD: DV01 da Segunda Rodada (SR) em dólares (USD).
363
+ - AvgMaturity: Maturidade média do título (em anos).
364
+ - Value: Valor total do leilão em R$ (FR + SR).
365
+ - ValueFR: Valor da primeira rodada (FR) do leilão em R$.
366
+ - ValueSR: Valor da segunda rodada (SR) em R$.
367
+ - OfferedQuantity: Quantidade total ofertada no leilão (FR + SR).
368
+ - OfferedQuantityFR: Quantidade ofertada na primeira rodada (FR).
369
+ - OfferedQuantitySR: Quantidade ofertada na segunda rodada (SR).
370
+ - AcceptedQuantity: Quantidade total aceita no leilão (FR + SR).
371
+ - AcceptedQuantityFR: Quantidade aceita na primeira rodada (FR).
372
+ - AcceptedQuantitySR: Quantidade aceita na segunda rodada (SR).
373
+ - AvgPrice: Preço médio no leilão.
374
+ - CutPrice: Preço de corte.
375
+ - AvgRate: Taxa de juros média.
376
+ - CutRate: Taxa de corte.
377
+ - BDToMat: Dias úteis entre a data de liquidação da 1R e a data de
378
+ vencimento do título.
379
+ - Duration: Duration (Duração) calculada com base na data de
380
+ liquidação da 1R e na data de vencimento do título.
339
381
  """
340
382
  url = BASE_API_URL
341
383
  if start:
@@ -351,6 +393,7 @@ def auctions(
351
393
  # Mapeamento do auction_type para o valor esperado pela API
352
394
  auction_type_mapping = {"sell": "Venda", "buy": "Compra"}
353
395
  if auction_type:
396
+ auction_type = str(auction_type).lower()
354
397
  auction_type_api_value = auction_type_mapping[auction_type]
355
398
  # Adiciona o parâmetro tipoOferta à URL se auction_type for fornecido
356
399
  url += f"&@tipoOferta='{auction_type_api_value}'"
@@ -0,0 +1,3 @@
1
+ from pyield.tn.benchmark import benchmarks
2
+
3
+ __all__ = ["benchmarks"]
@@ -9,12 +9,12 @@ logger = logging.getLogger(__name__)
9
9
 
10
10
  TIMEZONE_BZ = ZoneInfo("America/Sao_Paulo")
11
11
 
12
- BENCHMARKS_COLUMN_MAPPING = {
13
- "BENCHMARK": "Benchmark",
14
- "VENCIMENTO": "MaturityDate",
15
- "TÍTULO": "BondType",
12
+ COLUMN_MAPPING = {
16
13
  "INÍCIO": "StartDate",
17
14
  "TERMINO": "EndDate",
15
+ "TÍTULO": "BondType",
16
+ "VENCIMENTO": "MaturityDate",
17
+ "BENCHMARK": "Benchmark",
18
18
  }
19
19
 
20
20
 
@@ -61,12 +61,12 @@ def benchmarks(include_history: bool = False) -> pd.DataFrame:
61
61
  >>> # Get historical benchmarks
62
62
  >>> df_history = tn.benchmarks(include_history=True)
63
63
  >>> df_history.head()
64
- Benchmark MaturityDate BondType StartDate EndDate
65
- 0 LFT 6 anos 2020-03-01 LFT 2014-01-01 2014-06-30
66
- 1 LFT 6 anos 2020-09-01 LFT 2014-07-01 2014-12-31
67
- 2 LFT 6 anos 2021-03-01 LFT 2015-01-01 2015-04-30
68
- 3 LFT 6 anos 2021-09-01 LFT 2015-05-01 2015-12-31
69
- 4 LFT 6 anos 2022-03-01 LFT 2016-01-01 2016-06-30
64
+ StartDate EndDate BondType MaturityDate Benchmark
65
+ 0 2014-01-01 2014-06-30 LFT 2020-03-01 LFT 6 anos
66
+ 1 2014-01-01 2014-06-01 LTN 2014-10-01 LTN 6 meses
67
+ 2 2014-01-01 2014-06-30 LTN 2015-04-01 LTN 12 meses
68
+ 3 2014-01-01 2014-06-30 LTN 2016-04-01 LTN 24 meses
69
+ 4 2014-01-01 2014-06-30 LTN 2018-01-01 LTN 48 meses
70
70
  """
71
71
  session = requests.Session()
72
72
  include_history_param_value = "S" if include_history else "N"
@@ -127,4 +127,10 @@ def benchmarks(include_history: bool = False) -> pd.DataFrame:
127
127
  "No current benchmark data found after filtering by active period."
128
128
  )
129
129
 
130
- return df.rename(columns=BENCHMARKS_COLUMN_MAPPING)
130
+ column_order = [c for c in COLUMN_MAPPING if c in df.columns]
131
+ return (
132
+ df[column_order]
133
+ .rename(columns=COLUMN_MAPPING)
134
+ .sort_values(["StartDate", "BondType", "MaturityDate"])
135
+ .reset_index(drop=True)
136
+ )
@@ -15,7 +15,7 @@ classifiers = [
15
15
  ]
16
16
  dependencies = [
17
17
  "pandas[html, parquet]>=2.0.0",
18
- "numpy>=2.0.0",
18
+ "numpy>=2.0.0",
19
19
  "requests>=2.31.0",
20
20
  "tenacity>=9.0.0",
21
21
  ]
@@ -32,8 +32,8 @@ dev = [
32
32
  "mkdocs",
33
33
  "mkdocs-material",
34
34
  "mkdocstrings[python]",
35
- "mkdocs-autorefs",
36
- "types-requests",
35
+ "mkdocs-autorefs",
36
+ "types-requests",
37
37
  "pandas-stubs",
38
38
  "lxml-stubs",
39
39
  "ruff",
@@ -50,19 +50,4 @@ path = "pyield/__about__.py"
50
50
  only-include = ["pyield"]
51
51
 
52
52
  [tool.uv]
53
- package = true
54
-
55
- [tool.ruff]
56
- line-length = 88
57
- indent-width = 4
58
- target-version = "py312"
59
- extend-include = ["*.ipynb"]
60
-
61
- [tool.ruff.lint]
62
- preview = true
63
- select = ["I", "F", "E", "W", "PL", "PT"]
64
-
65
- [tool.ruff.format]
66
- docstring-code-format = true
67
- docstring-code-line-length = 88
68
-
53
+ package = true
@@ -1 +0,0 @@
1
- __version__ = "0.36.0"
@@ -1,3 +0,0 @@
1
- from pyield.tn.auction import benchmarks
2
-
3
- __all__ = ["benchmarks"]
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