PYield 0.40.4__tar.gz → 0.40.6__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 (62) hide show
  1. {pyield-0.40.4 → pyield-0.40.6}/PKG-INFO +157 -156
  2. pyield-0.40.6/README.md +268 -0
  3. pyield-0.40.6/pyield/__about__.py +1 -0
  4. {pyield-0.40.4 → pyield-0.40.6}/pyield/anbima/difusao.py +13 -11
  5. {pyield-0.40.4 → pyield-0.40.6}/pyield/anbima/ima.py +1 -1
  6. {pyield-0.40.4 → pyield-0.40.6}/pyield/anbima/imaq.py +35 -22
  7. {pyield-0.40.4 → pyield-0.40.6}/pyield/anbima/tpf.py +21 -36
  8. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/di1.py +19 -18
  9. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/di_over.py +5 -5
  10. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/futures/__init__.py +11 -17
  11. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/futures/xml.py +3 -3
  12. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/auction.py +7 -7
  13. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/ptax_api.py +7 -7
  14. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/rates.py +21 -21
  15. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/repo.py +4 -4
  16. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/trades_monthly.py +5 -7
  17. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/vna.py +6 -6
  18. {pyield-0.40.4 → pyield-0.40.6}/pyield/bday/core.py +97 -81
  19. pyield-0.40.6/pyield/converters.py +76 -0
  20. {pyield-0.40.4 → pyield-0.40.6}/pyield/fwd.py +7 -7
  21. {pyield-0.40.4 → pyield-0.40.6}/pyield/interpolator.py +5 -5
  22. {pyield-0.40.4 → pyield-0.40.6}/pyield/ipca/historical.py +9 -9
  23. {pyield-0.40.4 → pyield-0.40.6}/pyield/ipca/projected.py +2 -2
  24. pyield-0.40.6/pyield/retry.py +62 -0
  25. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/auctions.py +5 -5
  26. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/benchmark.py +3 -3
  27. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/lft.py +16 -18
  28. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/ltn.py +25 -28
  29. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/ntnb.py +59 -78
  30. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/ntnc.py +28 -35
  31. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/ntnf.py +87 -86
  32. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/pre.py +6 -6
  33. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/tools.py +26 -12
  34. {pyield-0.40.4 → pyield-0.40.6}/pyield/types.py +33 -20
  35. {pyield-0.40.4 → pyield-0.40.6}/pyproject.toml +0 -1
  36. pyield-0.40.4/README.md +0 -267
  37. pyield-0.40.4/pyield/__about__.py +0 -1
  38. pyield-0.40.4/pyield/converters.py +0 -97
  39. pyield-0.40.4/pyield/retry.py +0 -98
  40. {pyield-0.40.4 → pyield-0.40.6}/.gitignore +0 -0
  41. {pyield-0.40.4 → pyield-0.40.6}/LICENSE +0 -0
  42. {pyield-0.40.4 → pyield-0.40.6}/pyield/__init__.py +0 -0
  43. {pyield-0.40.4 → pyield-0.40.6}/pyield/anbima/__init__.py +0 -0
  44. {pyield-0.40.4 → pyield-0.40.6}/pyield/anbima/ettj_intraday.py +0 -0
  45. {pyield-0.40.4 → pyield-0.40.6}/pyield/anbima/ettj_last.py +0 -0
  46. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/__init__.py +0 -0
  47. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/futures/common.py +0 -0
  48. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/futures/historical.py +0 -0
  49. {pyield-0.40.4 → pyield-0.40.6}/pyield/b3/futures/intraday.py +0 -0
  50. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/__init__.py +0 -0
  51. {pyield-0.40.4 → pyield-0.40.6}/pyield/bc/trades_intraday.py +0 -0
  52. {pyield-0.40.4 → pyield-0.40.6}/pyield/bday/__init__.py +0 -0
  53. {pyield-0.40.4 → pyield-0.40.6}/pyield/bday/holidays/__init__.py +0 -0
  54. {pyield-0.40.4 → pyield-0.40.6}/pyield/bday/holidays/br_holidays_new.txt +0 -0
  55. {pyield-0.40.4 → pyield-0.40.6}/pyield/bday/holidays/br_holidays_old.txt +0 -0
  56. {pyield-0.40.4 → pyield-0.40.6}/pyield/bday/holidays/brholidays.py +0 -0
  57. {pyield-0.40.4 → pyield-0.40.6}/pyield/config.py +0 -0
  58. {pyield-0.40.4 → pyield-0.40.6}/pyield/conftest.py +0 -0
  59. {pyield-0.40.4 → pyield-0.40.6}/pyield/data_cache.py +0 -0
  60. {pyield-0.40.4 → pyield-0.40.6}/pyield/ipca/__init__.py +0 -0
  61. {pyield-0.40.4 → pyield-0.40.6}/pyield/py.typed +0 -0
  62. {pyield-0.40.4 → pyield-0.40.6}/pyield/tn/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PYield
3
- Version: 0.40.4
3
+ Version: 0.40.6
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>
@@ -72,96 +72,70 @@ Visit the [full documentation for PYield](https://crdcj.github.io/PYield/).
72
72
  - **Easy Integration**: Seamless integration with pandas data analysis workflows.
73
73
  - **Type Hints**: Full support for static type checking, enhancing development experience and code quality.
74
74
 
75
- ## Installation
76
-
77
- You can install PYield using pip:
78
- ```sh
79
- pip install pyield
80
- ```
81
- ## Custom Types
82
-
83
- ### DateScalar
84
- `DateScalar` and `DateArray` are internal type unions used across PYield to accept flexible date inputs. Supported scalar Python / library date types:
85
-
86
- - `str` (formats: `DD-MM-YYYY`, `DD/MM/YYYY`, `YYYY-MM-DD`)
87
- - `datetime.date`
88
- - `datetime.datetime`
89
- - `pandas.Timestamp`
90
- - `numpy.datetime64`
91
-
92
- ### DateArray
93
- Accepted collection types (homogeneous date-like values):
94
-
95
- - `list[DateScalar]`
96
- - `tuple[DateScalar, ...]`
97
- - `pandas.Series`
98
- - `pandas.DatetimeIndex`
99
- - `numpy.ndarray`
100
- - `polars.Series`
101
-
102
- Other helper unions:
103
-
104
- `FloatArray`:
105
- - `list[float]` | `tuple[float, ...]` | `numpy.ndarray` | `pandas.Series` | `polars.Series`
106
-
107
- `IntegerScalar`:
108
- - `int` | `numpy.integer`
109
-
110
- `IntegerArray`:
111
- - `list[int]` | `tuple[int, ...]` | `numpy.ndarray` | `pandas.Series` | `polars.Series`
112
-
113
- Referencing these unions in function docstrings means you can pass any of the listed types interchangeably; conversion is handled internally.
75
+ ## Overview & Navigation
76
+
77
+ PYield is split into focused namespaces. Each function and class has a rich docstring (the online site is generated from them via MkDocs). The quickest learning path is: open a Python shell, import a namespace, call `help()`.
78
+
79
+ ### Top-Level Namespace (Cheat Sheet)
80
+ Symbols exported directly by `pyield.__all__` (available via `from pyield import ...`). Prefer these first:
81
+
82
+ | Symbol | Kind | Purpose |
83
+ |--------|------|---------|
84
+ | `bday` | module | Business day calendar (count, offset, generate). |
85
+ | `anbima` | module | ANBIMA diffusion & curve endpoints. |
86
+ | `bc` | module | BCB indicators (SELIC Over, PTAX, repo rates). |
87
+ | `b3` | module | B3 domain (futures submodules). |
88
+ | `di1` | module | DI1 futures data & analytics. |
89
+ | `futures` | function | Fetch futures (see `help(futures)`). |
90
+ | `forward` | function | Single period forward rate from spot curve. |
91
+ | `forwards` | function | Vectorized forward rate construction. |
92
+ | `Interpolator` | class | Rate interpolation (linear / flat_forward). |
93
+ | `ltn` | module | LTN bond data & analytics. |
94
+ | `ntnb` | module | NTN-B pricing, spot, forward, BEI. |
95
+ | `ntnc` | module | NTN-C (if available in current dataset). |
96
+ | `ntnf` | module | NTN-F DI spreads & related analytics. |
97
+ | `lft` | module | LFT bond tools. |
98
+ | `pre` | module | Zero-coupon (pré-fixado) helpers. |
99
+ | `ipca` | module | Inflation historical & projections. |
100
+
101
+
102
+ ### Learning Path
103
+ 1. Install: `pip install pyield`.
104
+ 2. Choose a domain: e.g. bonds (`from pyield import ntnb`).
105
+ 3. Inspect: `dir(ntnb)` then `help(ntnb.quotation)`.
106
+ 4. Reproduce the docstring example verbatim.
107
+ 5. Chain outputs (Polars DataFrames / Series) into your pipeline; convert to pandas only if unavoidable.
108
+
109
+ ### Minimal Quick Start
110
+ ```python
111
+ from pyield import bday, ntnb, bc
114
112
 
115
- ### Date String Formats
116
- Accepted string date formats:
113
+ # Calendar
114
+ business_days = bday.count("02-01-2025", "15-01-2025")
117
115
 
118
- - Day-first (Brazilian): `DD-MM-YYYY` (e.g., `31-05-2024`)
119
- - Day-first (slash): `DD/MM/YYYY` (e.g., `31/05/2024`)
120
- - ISO: `YYYY-MM-DD` (e.g., `2024-05-31`)
116
+ # Bond quotation (base 100)
117
+ q = ntnb.quotation("31-05-2024", "15-05-2035", 0.06149)
121
118
 
122
- Rules:
123
- - No ambiguous autodetection: `2024-05-06` is always interpreted as ISO (`YYYY-MM-DD`).
124
- - A collection of strings must not mix different styles; the first non-null value defines the format.
125
- - Nulls are preserved; empty collections are not allowed.
119
+ # SELIC Over single day
120
+ selic = bc.selic_over("31-05-2024")
126
121
 
127
- Recommendation:
128
- Always parse external inputs explicitly when constructing your own pipelines:
129
- ```python
130
- import pandas as pd
131
- dt_val = pd.to_datetime("31-05-2024", format="%d-%m-%Y")
132
- iso_val = pd.to_datetime("2024-05-31", format="%Y-%m-%d")
122
+ print(business_days, q, selic)
133
123
  ```
134
124
 
135
- ### Null & Empty Input Handling
125
+ ### Docstrings = Source of Truth
126
+ If any README description conflicts with behavior, prefer the docstring. It documents:
127
+ * Parameters & types
128
+ * Edge cases / null semantics
129
+ * References (e.g. ANBIMA methodology PDFs)
130
+ * Examples guaranteed to run (CI checks)
136
131
 
137
- PYield uses an internal helper (`has_null_args`) for early detection of missing inputs. The default propagation policy is: return **`None`** for missing scalar inputs and preserve nulls inside collections. This avoids implicit imputation and makes failure modes explicit.
132
+ See also: [Custom Types & Data Handling](#custom-types--data-handling) for input normalization rules.
138
133
 
139
- Summary:
140
- - Scalar functions (dates, prices, quotations, spreads, durations): return `None` when any required argument is missing or empty.
141
- - Collection (vectorized) functions: if the entire relevant input is missing/empty, return an empty Polars `DataFrame`/`Series` (or `None` for purely scalar semantics). Individual null elements propagate as `null` values in the resulting Polars Series/DataFrame.
142
- - Empty collections where a shape is mandatory (e.g. an empty date array for conversion) raise `ValueError` rather than returning a silently empty result.
143
- - Date string collections must share a single format; the first non-null defines it.
144
- - Numeric computations only produce `NaN` when an internal arithmetic step yields an undefined value (rare — typical missing input short-circuits to `None`).
145
-
146
- Examples:
147
- ```python
148
- >>> from pyield import ntnb, bday
149
- # Missing settlement -> None
150
- >>> ntnb.quotation(None, "15-05-2035", 0.06149)
151
- None
152
-
153
- # Null start date in business day count -> None
154
- >>> bday.count(None, "01-01-2025")
155
- None
134
+ ## Installation
156
135
 
157
- # Null in array input propagates element-wise
158
- >>> bday.count(["01-01-2024", None], "01-02-2024")
159
- shape: (2,)
160
- Series: 'bdays' [i64]
161
- [
162
- 22
163
- null
164
- ]
136
+ You can install PYield using pip:
137
+ ```sh
138
+ pip install pyield
165
139
  ```
166
140
  ## How to use PYield
167
141
  ### Brazilian Treasury Bonds Tools
@@ -222,88 +196,115 @@ datetime.date(2024, 1, 2)
222
196
  # Returns same date if already business day (offset=0)
223
197
  >>> bday.offset("29-12-2023", 0)
224
198
  datetime.date(2023, 12, 29)
225
-
226
- # Generate business day series
227
- >>> bday.generate(start="22-12-2023", end="02-01-2024")
228
- shape: (6,)
229
- Series: '' [date]
230
- [
231
- 2023-12-22
232
- 2023-12-26
233
- 2023-12-27
234
- 2023-12-28
235
- 2023-12-29
236
- 2024-01-02
237
- ]
238
199
  ```
239
200
 
240
- ### Futures Data
241
- ```python
242
- >>> from pyield.b3.futures import futures
243
-
244
- # Fetch DI1 futures (historical)
245
- >>> futures("DI1", "31-05-2024")
246
- shape: (40, 20)
247
- ┌────────────┬──────────────┬───────────────┬────────────┬───┬──────────────┬──────────┬───────────────┬─────────────┐
248
- │ TradeDate ┆ TickerSymbol ┆ ExpirationDate┆ BDaysToExp ┆ … ┆ CloseBidRate ┆ CloseRate┆ SettlementRate┆ ForwardRate │
249
- │ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
250
- │ date ┆ str ┆ date ┆ i64 ┆ ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
251
- ├────────────┼──────────────┼───────────────┼────────────┼───┼──────────────┼──────────┼───────────────┼─────────────┤
252
- │ 2024-05-31 ┆ DI1M24 ┆ 2024-06-03 ┆ 1 ┆ … ┆ 0.10404 ┆ 0.10404 ┆ 0.10399 ┆ 0.10399 │
253
- │ 2024-05-31 ┆ DI1N24 ┆ 2024-07-01 ┆ 21 ┆ … ┆ 0.1039 ┆ 0.10386 ┆ 0.1039 ┆ 0.103896 │
254
- │ 2024-05-31 ┆ DI1Q24 ┆ 2024-08-01 ┆ 44 ┆ … ┆ 0.10374 ┆ 0.10374 ┆ 0.1037 ┆ 0.103517 │
255
- │ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │
256
- └────────────┴──────────────┴───────────────┴────────────┴───┴──────────────┴──────────┴───────────────┴─────────────┘
257
- ```
201
+ ## Custom Types & Data Handling
202
+
203
+ This section documents the internal typing and data normalization rules adopted across PYield so users can rely on predictable inputs/outputs and null semantics.
204
+
205
+ ### DateLike (scalar inputs)
206
+ `DateLike` is a union used anywhere a single date is accepted:
207
+
208
+ * `str` (accepted formats below)
209
+ * `datetime.date`
210
+ * `datetime.datetime`
211
+ * `pandas.Timestamp`
212
+ * `numpy.datetime64`
213
+
214
+ Returned scalar dates are normalized to `datetime.date` (no timezone).
215
+
216
+ ### ArrayLike (collection inputs)
217
+ `ArrayLike` covers any homogeneous collection of values accepted by vectorized functions:
218
+
219
+ * `Sequence[Any]` (e.g. `list`, `tuple`)
220
+ * `pandas.Series`
221
+ * `polars.Series`
222
+ * `numpy.ndarray`
223
+
224
+ Internally collections of date-like values are converted to a `polars.Series` with dtype `Date`.
225
+
226
+ ### Supported Date String Formats
258
227
 
259
- ### Indicators Data
228
+ * Brazilian day‑first (dash): `DD-MM-YYYY` (e.g. `31-05-2024`)
229
+ * Brazilian day‑first (slash): `DD/MM/YYYY` (e.g. `31/05/2024`)
230
+ * ISO: `YYYY-MM-DD` (e.g. `2024-05-31`)
231
+
232
+ Rules:
233
+ 1. No ambiguous inference: `2024-05-06` is always ISO (`YYYY-MM-DD`).
234
+ 2. Collections: the first non-null/non-empty string determines the format for the entire collection.
235
+ 3. Strings not matching that inferred format become `null` (instead of raising) to keep vectorization robust.
236
+ 4. A collection containing only null/empty strings becomes a `Date` Series of all nulls.
237
+
238
+ Recommendation (defensive pipelines):
260
239
  ```python
261
- >>> from pyield import bc
262
-
263
- # SELIC Over series (no data on Sunday)
264
- >>> bc.selic_over_series("26-01-2025").head(5)
265
- shape: (5, 2)
266
- ┌────────────┬────────┐
267
- │ Date ┆ Value │
268
- │ --- ┆ --- │
269
- │ date ┆ f64 │
270
- ├────────────┼────────┤
271
- │ 2025-01-27 ┆ 0.1215 │
272
- │ 2025-01-28 ┆ 0.1215 │
273
- │ 2025-01-29 ┆ 0.1215 │
274
- │ 2025-01-30 ┆ 0.1315 │
275
- │ 2025-01-31 ┆ 0.1315 │
276
- └────────────┴────────┘
277
-
278
- # SELIC Over for a single date
279
- >>> bc.selic_over("31-05-2024")
280
- 0.104 # 10.40%
240
+ import pandas as pd
241
+ dt_val = pd.to_datetime("31-05-2024", format="%d-%m-%Y")
242
+ iso_val = pd.to_datetime("2024-05-31", format="%Y-%m-%d")
281
243
  ```
282
244
 
283
- ### Projections Data
245
+ ### Conversion Summary
246
+
247
+ | Input | Output Normalization |
248
+ |-------------------------------------|--------------------------------------|
249
+ | "31-05-2024" | datetime.date(2024, 5, 31) |
250
+ | ["31-05-2024", "01-06-2024"] | polars.Series<Date>[2024-05-31,…] |
251
+ | ["31-05-2024", None] | polars.Series<Date>[2024-05-31,null] |
252
+ | ["31-05-2024", "2024-06-01"] | second -> null (mismatched format) |
253
+ | [] (where shape mandatory) | ValueError (function-dependent) |
254
+
255
+ ### Nullability & Early Short-Circuit
256
+
257
+ The internal helper `has_nullable_args(*args)` returns `True` if any argument is considered "nullable". An argument is nullable when it is:
258
+
259
+ * `None`
260
+ * `NaN` (float)
261
+ * Empty string `""`
262
+ * Empty collection: `[]`, `()`, `{}`
263
+ * Empty pandas `DataFrame` / `Series` / `Index`
264
+ * Empty polars `DataFrame` / `Series`
265
+ * NumPy `ndarray` with `size == 0`
266
+
267
+ Policy:
268
+ * Scalar-style functions:
269
+ * Pure date counters/adjusters may return `None` when a required scalar date is missing.
270
+ * Valuation / rate functions (`quotation`, `price`, `duration`, `dv01`) return `float('nan')` when inputs are nullable or a cash-flow schedule cannot be built.
271
+ * Vectorized functions: an entirely missing/empty driving input yields an empty `DataFrame`/`Series` (or `None` if semantics are purely scalar); element-level nulls propagate.
272
+ * Arithmetic emits `NaN` only for truly undefined operations—most missing cases short-circuit sooner (or return `nan` as above for valuation functions).
273
+
274
+ ### Practical Examples
284
275
  ```python
285
- >>> from pyield import ipca
286
- # Fetch current month projection for IPCA
287
- >>> proj = ipca.projected_rate()
288
- >>> proj
289
- IndicatorProjection(last_updated=..., reference_period=..., projected_value=...)
290
- >>> proj.projected_value
291
- 0.0035 # 0.35%
276
+ >>> from pyield import ntnb, bday
277
+
278
+ # Missing settlement -> nan (empty cash-flow schedule)
279
+ >>> ntnb.quotation(None, "15-05-2035", 0.06149)
280
+ nan
281
+
282
+ # Date output with null start date -> None
283
+ >>> bday.count(None, "01-01-2025")
284
+ None
285
+
286
+ # Element-level null propagation
287
+ >>> bday.count(["01-01-2024", None], "01-02-2024")
288
+ shape: (2,)
289
+ Series: 'bdays' [i64]
290
+ [
291
+ 22
292
+ null
293
+ ]
292
294
  ```
293
295
 
294
- ### Interpolation Tools
295
- Interpolate interest rates for specific business days using the Interpolator class.
296
+ ### Pandas Interop
297
+ Polars objects are the canonical return types. Convert explicitly when you need pandas:
296
298
  ```python
297
- >>> from pyield import Interpolator
298
- # Initialize the Interpolator with known business days and interest rates.
299
- >>> known_bdays = [30, 60, 90]
300
- >>> known_rates = [0.045, 0.05, 0.055]
301
- >>> linear_interpolator = Interpolator("linear", known_bdays, known_rates)
302
- >>> linear_interpolator(45) # Interpolate the interest rate for a given number of business days.
303
- 0.0475
304
-
305
- # Use the flat forward method for interpolation.
306
- >>> ff_interpolator = Interpolator("flat_forward", known_bdays, known_rates)
307
- >>> ff_interpolator(45)
308
- 0.04833068080970859
299
+ df_pandas = df.to_pandas(use_pyarrow_extension_array=True)
300
+ series_pandas = s.to_pandas(use_pyarrow_extension_array=True)
309
301
  ```
302
+
303
+ ### Rationale
304
+ Using Polars + Arrow dtypes provides:
305
+ * Deterministic schema & faster IO
306
+ * Efficient vectorized date casting
307
+ * Clear null vs. missing semantics
308
+ * Reduced overhead vs. repeated Pandas conversions
309
+
310
+ These conventions keep public APIs flexible on input while consistent on output.
@@ -0,0 +1,268 @@
1
+ [![PyPI version](https://img.shields.io/pypi/v/pyield.svg)](https://pypi.python.org/pypi/pyield)
2
+ [![Made with Python](https://img.shields.io/badge/Python->=3.12-blue?logo=python&logoColor=white)](https://python.org "Go to Python homepage")
3
+ [![License](https://img.shields.io/badge/License-MIT-blue)](https://github.com/crdcj/PYield/blob/main/LICENSE)
4
+
5
+ # PYield: Brazilian Fixed Income Toolkit
6
+
7
+ PYield is a Python library designed for the analysis of Brazilian fixed income instruments. Leveraging the power of popular Python libraries like Polars, Pandas, Numpy and Requests, PYield simplifies the process of obtaining and processing data from key sources such as ANBIMA, BCB, IBGE and B3.
8
+
9
+ ---
10
+ ### ✅ Polars migration from version 0.40.0 onwards:
11
+
12
+ All public functions now return **Polars DataFrames or Series** as the canonical format. This provides stronger typing, faster execution and more reliable date/rate handling. The last version to return Pandas objects by default was **0.39.xx**.
13
+
14
+ Need Pandas? Convert explicitly:
15
+ ```python
16
+ df_pandas = df.to_pandas(use_pyarrow_extension_array=True)
17
+ series_pandas = s.to_pandas(use_pyarrow_extension_array=True)
18
+ ```
19
+ The internal typing relies on PyArrow-backed dtypes for consistency across numeric and date operations.
20
+
21
+ ## Documentation
22
+
23
+ Visit the [full documentation for PYield](https://crdcj.github.io/PYield/).
24
+
25
+ ## Key Features
26
+
27
+ - **Data Collection**: Automated fetching of data from ANBIMA and B3.
28
+ - **Data Processing**: Efficient processing and normalization of fixed income data.
29
+ - **Analysis Tools**: Built-in functions for common analysis tasks in fixed income markets.
30
+ - **Easy Integration**: Seamless integration with pandas data analysis workflows.
31
+ - **Type Hints**: Full support for static type checking, enhancing development experience and code quality.
32
+
33
+ ## Overview & Navigation
34
+
35
+ PYield is split into focused namespaces. Each function and class has a rich docstring (the online site is generated from them via MkDocs). The quickest learning path is: open a Python shell, import a namespace, call `help()`.
36
+
37
+ ### Top-Level Namespace (Cheat Sheet)
38
+ Symbols exported directly by `pyield.__all__` (available via `from pyield import ...`). Prefer these first:
39
+
40
+ | Symbol | Kind | Purpose |
41
+ |--------|------|---------|
42
+ | `bday` | module | Business day calendar (count, offset, generate). |
43
+ | `anbima` | module | ANBIMA diffusion & curve endpoints. |
44
+ | `bc` | module | BCB indicators (SELIC Over, PTAX, repo rates). |
45
+ | `b3` | module | B3 domain (futures submodules). |
46
+ | `di1` | module | DI1 futures data & analytics. |
47
+ | `futures` | function | Fetch futures (see `help(futures)`). |
48
+ | `forward` | function | Single period forward rate from spot curve. |
49
+ | `forwards` | function | Vectorized forward rate construction. |
50
+ | `Interpolator` | class | Rate interpolation (linear / flat_forward). |
51
+ | `ltn` | module | LTN bond data & analytics. |
52
+ | `ntnb` | module | NTN-B pricing, spot, forward, BEI. |
53
+ | `ntnc` | module | NTN-C (if available in current dataset). |
54
+ | `ntnf` | module | NTN-F DI spreads & related analytics. |
55
+ | `lft` | module | LFT bond tools. |
56
+ | `pre` | module | Zero-coupon (pré-fixado) helpers. |
57
+ | `ipca` | module | Inflation historical & projections. |
58
+
59
+
60
+ ### Learning Path
61
+ 1. Install: `pip install pyield`.
62
+ 2. Choose a domain: e.g. bonds (`from pyield import ntnb`).
63
+ 3. Inspect: `dir(ntnb)` then `help(ntnb.quotation)`.
64
+ 4. Reproduce the docstring example verbatim.
65
+ 5. Chain outputs (Polars DataFrames / Series) into your pipeline; convert to pandas only if unavoidable.
66
+
67
+ ### Minimal Quick Start
68
+ ```python
69
+ from pyield import bday, ntnb, bc
70
+
71
+ # Calendar
72
+ business_days = bday.count("02-01-2025", "15-01-2025")
73
+
74
+ # Bond quotation (base 100)
75
+ q = ntnb.quotation("31-05-2024", "15-05-2035", 0.06149)
76
+
77
+ # SELIC Over single day
78
+ selic = bc.selic_over("31-05-2024")
79
+
80
+ print(business_days, q, selic)
81
+ ```
82
+
83
+ ### Docstrings = Source of Truth
84
+ If any README description conflicts with behavior, prefer the docstring. It documents:
85
+ * Parameters & types
86
+ * Edge cases / null semantics
87
+ * References (e.g. ANBIMA methodology PDFs)
88
+ * Examples guaranteed to run (CI checks)
89
+
90
+ See also: [Custom Types & Data Handling](#custom-types--data-handling) for input normalization rules.
91
+
92
+ ## Installation
93
+
94
+ You can install PYield using pip:
95
+ ```sh
96
+ pip install pyield
97
+ ```
98
+ ## How to use PYield
99
+ ### Brazilian Treasury Bonds Tools
100
+ ```python
101
+ >>> from pyield import ltn, ntnb, ntnf
102
+
103
+ # Get ANBIMA LTN data for a given date
104
+ >>> ltn.data("23-08-2024")
105
+ shape: (13, 14)
106
+ ┌──────────────┬─────────┬──────────┬──────────────┬───┬─────────┬─────────┬───────────────┬────────┐
107
+ │ ReferenceDate│ BondType│ SelicCode│ IssueBaseDate│ … │ BidRate │ AskRate │ IndicativeRate│ DIRate │
108
+ │ --- │ --- │ --- │ --- │ │ --- │ --- │ --- │ --- │
109
+ │ date │ str │ i64 │ date │ │ f64 │ f64 │ f64 │ f64 │
110
+ ├──────────────┼─────────┼──────────┼──────────────┼───┼─────────┼─────────┼───────────────┼────────┤
111
+ │ 2024-08-23 │ LTN │ 100000 │ 2022-07-08 │ … │ 0.10459 │ 0.104252│ 0.104416 │ 0.10472│
112
+ │ 2024-08-23 │ LTN │ 100000 │ 2018-02-01 │ … │ 0.107366│ 0.107016│ 0.107171 │ 0.10823│
113
+ │ 2024-08-23 │ LTN │ 100000 │ 2023-01-06 │ … │ 0.110992│ 0.110746│ 0.110866 │ 0.11179│
114
+ │ … │ … │ … │ … │ … │ … │ … │ … │ … │
115
+ └──────────────┴─────────┴──────────┴──────────────┴───┴─────────┴─────────┴───────────────┴────────┘
116
+
117
+ # Calculate the quotation of an NTN-B bond (base 100, truncated to 4 decimals)
118
+ >>> ntnb.quotation("31-05-2024", "15-05-2035", 0.061490)
119
+ 99.3651
120
+ >>> ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
121
+ 99.5341
122
+
123
+ # DI Spreads: IndicativeRate - SettlementRate (bps=True multiplies by 10_000)
124
+ >>> ntnf.di_spreads("30-05-2025", bps=True)
125
+ shape: (5, 3)
126
+ ┌─────────┬─────────────┬──────────┐
127
+ │ BondType│ MaturityDate│ DISpread │
128
+ │ --- │ --- │ --- │
129
+ │ str │ date │ f64 │
130
+ ├─────────┼─────────────┼──────────┤
131
+ │ NTN-F │ 2027-01-01 │ -3.31 │
132
+ │ NTN-F │ 2029-01-01 │ 14.21 │
133
+ │ NTN-F │ 2031-01-01 │ 21.61 │
134
+ │ NTN-F │ 2033-01-01 │ 11.51 │
135
+ │ NTN-F │ 2035-01-01 │ 22.0 │
136
+ └─────────┴─────────────┴──────────┘
137
+ ```
138
+
139
+ ### Business Days Tools (Brazilian holidays automatically considered)
140
+ ```python
141
+ >>> from pyield import bday
142
+ # Count business days (start inclusive, end exclusive)
143
+ >>> bday.count("29-12-2023", "02-01-2024")
144
+ 1
145
+
146
+ # Next business day after given date (offset=1)
147
+ >>> bday.offset("29-12-2023", 1)
148
+ datetime.date(2024, 1, 2)
149
+
150
+ # Adjust to next business day when not a business day (offset=0)
151
+ >>> bday.offset("30-12-2023", 0)
152
+ datetime.date(2024, 1, 2)
153
+
154
+ # Returns same date if already business day (offset=0)
155
+ >>> bday.offset("29-12-2023", 0)
156
+ datetime.date(2023, 12, 29)
157
+ ```
158
+
159
+ ## Custom Types & Data Handling
160
+
161
+ This section documents the internal typing and data normalization rules adopted across PYield so users can rely on predictable inputs/outputs and null semantics.
162
+
163
+ ### DateLike (scalar inputs)
164
+ `DateLike` is a union used anywhere a single date is accepted:
165
+
166
+ * `str` (accepted formats below)
167
+ * `datetime.date`
168
+ * `datetime.datetime`
169
+ * `pandas.Timestamp`
170
+ * `numpy.datetime64`
171
+
172
+ Returned scalar dates are normalized to `datetime.date` (no timezone).
173
+
174
+ ### ArrayLike (collection inputs)
175
+ `ArrayLike` covers any homogeneous collection of values accepted by vectorized functions:
176
+
177
+ * `Sequence[Any]` (e.g. `list`, `tuple`)
178
+ * `pandas.Series`
179
+ * `polars.Series`
180
+ * `numpy.ndarray`
181
+
182
+ Internally collections of date-like values are converted to a `polars.Series` with dtype `Date`.
183
+
184
+ ### Supported Date String Formats
185
+
186
+ * Brazilian day‑first (dash): `DD-MM-YYYY` (e.g. `31-05-2024`)
187
+ * Brazilian day‑first (slash): `DD/MM/YYYY` (e.g. `31/05/2024`)
188
+ * ISO: `YYYY-MM-DD` (e.g. `2024-05-31`)
189
+
190
+ Rules:
191
+ 1. No ambiguous inference: `2024-05-06` is always ISO (`YYYY-MM-DD`).
192
+ 2. Collections: the first non-null/non-empty string determines the format for the entire collection.
193
+ 3. Strings not matching that inferred format become `null` (instead of raising) to keep vectorization robust.
194
+ 4. A collection containing only null/empty strings becomes a `Date` Series of all nulls.
195
+
196
+ Recommendation (defensive pipelines):
197
+ ```python
198
+ import pandas as pd
199
+ dt_val = pd.to_datetime("31-05-2024", format="%d-%m-%Y")
200
+ iso_val = pd.to_datetime("2024-05-31", format="%Y-%m-%d")
201
+ ```
202
+
203
+ ### Conversion Summary
204
+
205
+ | Input | Output Normalization |
206
+ |-------------------------------------|--------------------------------------|
207
+ | "31-05-2024" | datetime.date(2024, 5, 31) |
208
+ | ["31-05-2024", "01-06-2024"] | polars.Series<Date>[2024-05-31,…] |
209
+ | ["31-05-2024", None] | polars.Series<Date>[2024-05-31,null] |
210
+ | ["31-05-2024", "2024-06-01"] | second -> null (mismatched format) |
211
+ | [] (where shape mandatory) | ValueError (function-dependent) |
212
+
213
+ ### Nullability & Early Short-Circuit
214
+
215
+ The internal helper `has_nullable_args(*args)` returns `True` if any argument is considered "nullable". An argument is nullable when it is:
216
+
217
+ * `None`
218
+ * `NaN` (float)
219
+ * Empty string `""`
220
+ * Empty collection: `[]`, `()`, `{}`
221
+ * Empty pandas `DataFrame` / `Series` / `Index`
222
+ * Empty polars `DataFrame` / `Series`
223
+ * NumPy `ndarray` with `size == 0`
224
+
225
+ Policy:
226
+ * Scalar-style functions:
227
+ * Pure date counters/adjusters may return `None` when a required scalar date is missing.
228
+ * Valuation / rate functions (`quotation`, `price`, `duration`, `dv01`) return `float('nan')` when inputs are nullable or a cash-flow schedule cannot be built.
229
+ * Vectorized functions: an entirely missing/empty driving input yields an empty `DataFrame`/`Series` (or `None` if semantics are purely scalar); element-level nulls propagate.
230
+ * Arithmetic emits `NaN` only for truly undefined operations—most missing cases short-circuit sooner (or return `nan` as above for valuation functions).
231
+
232
+ ### Practical Examples
233
+ ```python
234
+ >>> from pyield import ntnb, bday
235
+
236
+ # Missing settlement -> nan (empty cash-flow schedule)
237
+ >>> ntnb.quotation(None, "15-05-2035", 0.06149)
238
+ nan
239
+
240
+ # Date output with null start date -> None
241
+ >>> bday.count(None, "01-01-2025")
242
+ None
243
+
244
+ # Element-level null propagation
245
+ >>> bday.count(["01-01-2024", None], "01-02-2024")
246
+ shape: (2,)
247
+ Series: 'bdays' [i64]
248
+ [
249
+ 22
250
+ null
251
+ ]
252
+ ```
253
+
254
+ ### Pandas Interop
255
+ Polars objects are the canonical return types. Convert explicitly when you need pandas:
256
+ ```python
257
+ df_pandas = df.to_pandas(use_pyarrow_extension_array=True)
258
+ series_pandas = s.to_pandas(use_pyarrow_extension_array=True)
259
+ ```
260
+
261
+ ### Rationale
262
+ Using Polars + Arrow dtypes provides:
263
+ * Deterministic schema & faster IO
264
+ * Efficient vectorized date casting
265
+ * Clear null vs. missing semantics
266
+ * Reduced overhead vs. repeated Pandas conversions
267
+
268
+ These conventions keep public APIs flexible on input while consistent on output.
@@ -0,0 +1 @@
1
+ __version__ = "0.40.6"