PYield 0.19.2__tar.gz → 0.20.0__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.19.2 → pyield-0.20.0}/PKG-INFO +4 -8
- {pyield-0.19.2 → pyield-0.20.0}/README.md +3 -7
- pyield-0.20.0/pyield/__about__.py +1 -0
- pyield-0.20.0/pyield/__init__.py +23 -0
- {pyield-0.19.2/pyield/data_sources → pyield-0.20.0/pyield}/anbima.py +6 -6
- {pyield-0.19.2/pyield/data_sources/futures_data → pyield-0.20.0/pyield/b3_futures}/__init__.py +2 -2
- {pyield-0.19.2/pyield/data_sources/futures_data → pyield-0.20.0/pyield/b3_futures}/common.py +1 -1
- {pyield-0.19.2/pyield/data_sources/futures_data → pyield-0.20.0/pyield/b3_futures}/historical.py +2 -2
- {pyield-0.19.2/pyield/data_sources/futures_data → pyield-0.20.0/pyield/b3_futures}/intraday.py +1 -1
- {pyield-0.19.2/pyield/data_sources/futures_data → pyield-0.20.0/pyield/b3_futures}/xml.py +3 -4
- {pyield-0.19.2 → pyield-0.20.0}/pyield/bday.py +18 -58
- {pyield-0.19.2 → pyield-0.20.0}/pyield/bonds/bond_tools.py +3 -3
- {pyield-0.19.2 → pyield-0.20.0}/pyield/bonds/lft.py +8 -9
- {pyield-0.19.2 → pyield-0.20.0}/pyield/bonds/ltn.py +17 -12
- {pyield-0.19.2 → pyield-0.20.0}/pyield/bonds/ntnb.py +35 -22
- {pyield-0.19.2 → pyield-0.20.0}/pyield/bonds/ntnf.py +63 -30
- pyield-0.20.0/pyield/conftest.py +8 -0
- {pyield-0.19.2/pyield/data_sources → pyield-0.20.0/pyield}/data_cache.py +1 -1
- pyield-0.20.0/pyield/date_converter.py +82 -0
- {pyield-0.19.2/pyield/data_sources → pyield-0.20.0/pyield}/di.py +9 -9
- pyield-0.20.0/pyield/holidays/__init__.py +3 -0
- {pyield-0.19.2/pyield/data_sources → pyield-0.20.0/pyield}/indicators.py +68 -61
- {pyield-0.19.2 → pyield-0.20.0}/pyield/interpolator.py +3 -0
- {pyield-0.19.2/pyield/data_sources → pyield-0.20.0/pyield}/projections.py +28 -27
- {pyield-0.19.2 → pyield-0.20.0}/pyproject.toml +1 -1
- pyield-0.19.2/pyield/__about__.py +0 -1
- pyield-0.19.2/pyield/__init__.py +0 -21
- pyield-0.19.2/pyield/data_sources/__init__.py +0 -6
- pyield-0.19.2/pyield/date_converter.py +0 -65
- pyield-0.19.2/pyield/holidays/__init__.py +0 -3
- {pyield-0.19.2 → pyield-0.20.0}/LICENSE +0 -0
- {pyield-0.19.2 → pyield-0.20.0}/pyield/bonds/__init__.py +0 -0
- {pyield-0.19.2 → pyield-0.20.0}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.19.2 → pyield-0.20.0}/pyield/holidays/br_holidays_old.txt +0 -0
- /pyield-0.19.2/pyield/holidays/holidays_manager.py → /pyield-0.20.0/pyield/holidays/brholidays.py +0 -0
- {pyield-0.19.2 → pyield-0.20.0}/pyield/py.typed +0 -0
- /pyield-0.19.2/pyield/calculators.py → /pyield-0.20.0/pyield/tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PYield
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.0
|
|
4
4
|
Summary: A Python library for analysis of fixed income instruments in Brazil
|
|
5
5
|
Keywords: fixed-income, brazil, finance, analysis, bonds
|
|
6
6
|
Author-Email: Carlos Carvalho <cr.cj@outlook.com>
|
|
@@ -179,16 +179,12 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
|
|
|
179
179
|
```python
|
|
180
180
|
>>> import pyield as yd
|
|
181
181
|
# Fetch the SELIC target rate from the Central Bank of Brazil
|
|
182
|
-
>>> yd.indicator(indicator_code="
|
|
182
|
+
>>> yd.indicator(indicator_code="SELIC_TARGET", reference_date='12-04-2024')
|
|
183
183
|
0.1075 # 10.75%
|
|
184
184
|
|
|
185
185
|
# Fetch the IPCA monthly inflation rate from IBGE
|
|
186
|
-
>>> yd.indicator(indicator_code="
|
|
187
|
-
0.
|
|
188
|
-
|
|
189
|
-
# If no data is yet available for the indicator, the function returns None
|
|
190
|
-
>>> yd.indicator(indicator_code="IPCA", reference_date='10-04-2024')
|
|
191
|
-
None
|
|
186
|
+
>>> yd.indicator(indicator_code="IPCA_MR", reference_date='18-03-2024')
|
|
187
|
+
0.0016 # 0.16%
|
|
192
188
|
```
|
|
193
189
|
|
|
194
190
|
### Projections Data
|
|
@@ -135,16 +135,12 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
|
|
|
135
135
|
```python
|
|
136
136
|
>>> import pyield as yd
|
|
137
137
|
# Fetch the SELIC target rate from the Central Bank of Brazil
|
|
138
|
-
>>> yd.indicator(indicator_code="
|
|
138
|
+
>>> yd.indicator(indicator_code="SELIC_TARGET", reference_date='12-04-2024')
|
|
139
139
|
0.1075 # 10.75%
|
|
140
140
|
|
|
141
141
|
# Fetch the IPCA monthly inflation rate from IBGE
|
|
142
|
-
>>> yd.indicator(indicator_code="
|
|
143
|
-
0.
|
|
144
|
-
|
|
145
|
-
# If no data is yet available for the indicator, the function returns None
|
|
146
|
-
>>> yd.indicator(indicator_code="IPCA", reference_date='10-04-2024')
|
|
147
|
-
None
|
|
142
|
+
>>> yd.indicator(indicator_code="IPCA_MR", reference_date='18-03-2024')
|
|
143
|
+
0.0016 # 0.16%
|
|
148
144
|
```
|
|
149
145
|
|
|
150
146
|
### Projections Data
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.20.0"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from pyield import anbima, bday, di, tools
|
|
2
|
+
from pyield.__about__ import __version__
|
|
3
|
+
from pyield.b3_futures import futures
|
|
4
|
+
from pyield.bonds import lft, ltn, ntnb, ntnf
|
|
5
|
+
from pyield.indicators import indicator
|
|
6
|
+
from pyield.interpolator import Interpolator
|
|
7
|
+
from pyield.projections import projection
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"__version__",
|
|
11
|
+
"anbima",
|
|
12
|
+
"bday",
|
|
13
|
+
"futures",
|
|
14
|
+
"indicator",
|
|
15
|
+
"ntnb",
|
|
16
|
+
"ntnf",
|
|
17
|
+
"ltn",
|
|
18
|
+
"lft",
|
|
19
|
+
"di",
|
|
20
|
+
"projection",
|
|
21
|
+
"Interpolator",
|
|
22
|
+
"tools",
|
|
23
|
+
]
|
|
@@ -5,9 +5,9 @@ import zipfile as zp
|
|
|
5
5
|
import pandas as pd
|
|
6
6
|
import requests
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from .data_cache import get_anbima_dataframe
|
|
8
|
+
from pyield import bday
|
|
9
|
+
from pyield import date_converter as dc
|
|
10
|
+
from pyield.data_cache import get_anbima_dataframe
|
|
11
11
|
|
|
12
12
|
# URL Constants
|
|
13
13
|
ANBIMA_URL = "https://www.anbima.com.br/informacoes/merc-sec/arqs"
|
|
@@ -110,7 +110,7 @@ def data(
|
|
|
110
110
|
bond_type: str | None = None,
|
|
111
111
|
) -> pd.DataFrame:
|
|
112
112
|
# Normalize the reference date
|
|
113
|
-
reference_date = dc.
|
|
113
|
+
reference_date = dc.convert_input_dates(reference_date)
|
|
114
114
|
file_content = _get_file_content(reference_date)
|
|
115
115
|
|
|
116
116
|
if not file_content:
|
|
@@ -134,7 +134,7 @@ def rates(
|
|
|
134
134
|
) -> pd.DataFrame:
|
|
135
135
|
df = get_anbima_dataframe()
|
|
136
136
|
|
|
137
|
-
reference_date = dc.
|
|
137
|
+
reference_date = dc.convert_input_dates(reference_date)
|
|
138
138
|
df.query("ReferenceDate == @reference_date", inplace=True)
|
|
139
139
|
|
|
140
140
|
if df.empty:
|
|
@@ -159,7 +159,7 @@ def pre_maturities(
|
|
|
159
159
|
reference_date: str | pd.Timestamp,
|
|
160
160
|
) -> pd.Series:
|
|
161
161
|
df = get_anbima_dataframe()
|
|
162
|
-
reference_date = dc.
|
|
162
|
+
reference_date = dc.convert_input_dates(reference_date)
|
|
163
163
|
df.query("ReferenceDate == @reference_date", inplace=True)
|
|
164
164
|
df.query("BondType in ['LTN', 'NTN-F']", inplace=True)
|
|
165
165
|
maturity_dates = df["MaturityDate"].drop_duplicates()
|
{pyield-0.19.2/pyield/data_sources/futures_data → pyield-0.20.0/pyield/b3_futures}/__init__.py
RENAMED
|
@@ -3,7 +3,7 @@ import datetime as dt
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
from pytz import timezone
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from .. import date_converter as dc
|
|
7
7
|
from .historical import fetch_historical_df
|
|
8
8
|
from .intraday import fetch_intraday_df
|
|
9
9
|
|
|
@@ -47,7 +47,7 @@ def futures(
|
|
|
47
47
|
if contract_code not in SUPPORTED_FUTURES:
|
|
48
48
|
raise ValueError("Futures contract not supported.")
|
|
49
49
|
|
|
50
|
-
trade_date = dc.
|
|
50
|
+
trade_date = dc.convert_input_dates(trade_date)
|
|
51
51
|
|
|
52
52
|
# First, try to fetch historical data for the specified date
|
|
53
53
|
df = fetch_historical_df(contract_code, trade_date)
|
|
@@ -7,9 +7,8 @@ import pandas as pd
|
|
|
7
7
|
import requests
|
|
8
8
|
from lxml import etree
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from . import common
|
|
10
|
+
from pyield import bday
|
|
11
|
+
from pyield.b3_futures import common
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
def _get_file_from_path(file_path: Path) -> io.BytesIO:
|
|
@@ -201,7 +200,7 @@ def _process_df(df_raw: pd.DataFrame) -> pd.DataFrame:
|
|
|
201
200
|
# Remove expired contracts
|
|
202
201
|
df.query("DaysToExp > 0", inplace=True)
|
|
203
202
|
|
|
204
|
-
df["BDaysToExp"] =
|
|
203
|
+
df["BDaysToExp"] = bday.count(df["TradeDate"], df["ExpirationDate"])
|
|
205
204
|
|
|
206
205
|
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
207
206
|
# Remove % and round to 5 (3 in %) dec. places in rate columns
|
|
@@ -1,58 +1,17 @@
|
|
|
1
|
-
import datetime as dt
|
|
2
1
|
from typing import Literal, overload
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
5
4
|
import pandas as pd
|
|
6
5
|
|
|
7
|
-
from
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type PandasArrayDateTypes = pd.Series | pd.DatetimeIndex | pd.Index
|
|
11
|
-
type ArrayDateTypes = PandasArrayDateTypes | np.ndarray | list | tuple
|
|
6
|
+
from pyield import date_converter as dc
|
|
7
|
+
from pyield.date_converter import ArrayDateTypes, ScalarDateTypes
|
|
8
|
+
from pyield.holidays import BrHolidays
|
|
12
9
|
|
|
13
10
|
type ArrayIntTypes = np.ndarray | pd.Series | list | tuple
|
|
14
11
|
type ScalarIntTypes = int | np.integer
|
|
15
12
|
|
|
16
13
|
# Initialize the BrHolidays class
|
|
17
|
-
br_holidays =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@overload
|
|
21
|
-
def _convert_input_dates(dates: ScalarDateTypes) -> pd.Timestamp: ...
|
|
22
|
-
@overload
|
|
23
|
-
def _convert_input_dates(dates: ArrayDateTypes) -> pd.Series: ...
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _convert_input_dates(
|
|
27
|
-
dates: ScalarDateTypes | ArrayDateTypes,
|
|
28
|
-
) -> pd.Timestamp | pd.Series:
|
|
29
|
-
result = pd.to_datetime(dates, dayfirst=True)
|
|
30
|
-
if isinstance(result, (pd.Timestamp, dt.date, dt.datetime, np.datetime64)):
|
|
31
|
-
result = pd.Timestamp(result).normalize()
|
|
32
|
-
elif isinstance(result, (pd.Series, pd.DatetimeIndex)):
|
|
33
|
-
result = pd.Series(result).astype("datetime64[ns]")
|
|
34
|
-
else:
|
|
35
|
-
raise ValueError("Invalid date input type.")
|
|
36
|
-
|
|
37
|
-
return result
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def _convert_to_numpy_date(
|
|
41
|
-
dates: pd.Timestamp | pd.Series,
|
|
42
|
-
) -> np.datetime64 | np.ndarray:
|
|
43
|
-
"""
|
|
44
|
-
Converts the input dates to a numpy datetime64[D] format.
|
|
45
|
-
|
|
46
|
-
Args:
|
|
47
|
-
dates (Timestamp | Series): A single date or a Series of dates.
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
np.datetime64 | np.ndarray: The input dates in a numpy datetime64[D] format.
|
|
51
|
-
"""
|
|
52
|
-
if isinstance(dates, pd.Timestamp):
|
|
53
|
-
return np.datetime64(dates, "D")
|
|
54
|
-
else:
|
|
55
|
-
return dates.to_numpy().astype("datetime64[D]")
|
|
14
|
+
br_holidays = BrHolidays()
|
|
56
15
|
|
|
57
16
|
|
|
58
17
|
@overload
|
|
@@ -188,14 +147,14 @@ def offset(
|
|
|
188
147
|
information on error handling and behavior, refer to the `numpy.busday_offset`
|
|
189
148
|
documentation: https://numpy.org/doc/stable/reference/generated/numpy.busday_offset.html
|
|
190
149
|
"""
|
|
191
|
-
|
|
150
|
+
converted_dates = dc.convert_input_dates(dates)
|
|
192
151
|
|
|
193
152
|
selected_holidays = br_holidays.get_applicable_holidays(
|
|
194
|
-
|
|
153
|
+
converted_dates, holiday_list
|
|
195
154
|
)
|
|
196
|
-
selected_holidays_np =
|
|
155
|
+
selected_holidays_np = dc.convert_to_numpy_date(selected_holidays)
|
|
197
156
|
|
|
198
|
-
dates_np =
|
|
157
|
+
dates_np = dc.convert_to_numpy_date(converted_dates)
|
|
199
158
|
offsetted_dates_np = np.busday_offset(
|
|
200
159
|
dates_np, offsets=offset, roll=roll, holidays=selected_holidays_np
|
|
201
160
|
)
|
|
@@ -304,18 +263,18 @@ def count(
|
|
|
304
263
|
1 19
|
|
305
264
|
dtype: Int64
|
|
306
265
|
"""
|
|
307
|
-
|
|
308
|
-
|
|
266
|
+
converted_start = dc.convert_input_dates(start)
|
|
267
|
+
converted_end = dc.convert_input_dates(end)
|
|
309
268
|
|
|
310
269
|
# Determine which list of holidays to use
|
|
311
270
|
selected_holidays = br_holidays.get_applicable_holidays(
|
|
312
|
-
|
|
271
|
+
converted_start, holiday_list
|
|
313
272
|
)
|
|
314
|
-
selected_holidays_np =
|
|
273
|
+
selected_holidays_np = dc.convert_to_numpy_date(selected_holidays)
|
|
315
274
|
|
|
316
275
|
# Convert inputs to numpy datetime64[D] before calling numpy.busday_count
|
|
317
|
-
start_np =
|
|
318
|
-
end_np =
|
|
276
|
+
start_np = dc.convert_to_numpy_date(converted_start)
|
|
277
|
+
end_np = dc.convert_to_numpy_date(converted_end)
|
|
319
278
|
|
|
320
279
|
result_np = np.busday_count(start_np, end_np, holidays=selected_holidays_np)
|
|
321
280
|
if isinstance(result_np, np.integer):
|
|
@@ -371,11 +330,12 @@ def generate(
|
|
|
371
330
|
https://pandas.pydata.org/docs/reference/api/pandas.bdate_range.html.
|
|
372
331
|
"""
|
|
373
332
|
if start:
|
|
374
|
-
converted_start =
|
|
333
|
+
converted_start = dc.convert_input_dates(start)
|
|
375
334
|
else:
|
|
376
335
|
converted_start = pd.Timestamp.today()
|
|
336
|
+
|
|
377
337
|
if end:
|
|
378
|
-
converted_end =
|
|
338
|
+
converted_end = dc.convert_input_dates(end)
|
|
379
339
|
else:
|
|
380
340
|
converted_end = pd.Timestamp.today()
|
|
381
341
|
|
|
@@ -410,6 +370,6 @@ def is_business_day(date: ScalarDateTypes) -> bool:
|
|
|
410
370
|
>>> bday.is_business_day("25-12-2023") # Christmas
|
|
411
371
|
False
|
|
412
372
|
"""
|
|
413
|
-
converted_date =
|
|
373
|
+
converted_date = dc.convert_input_dates(date)
|
|
414
374
|
shifted_date = offset(converted_date, 0) # Shift the date if it is not a bus. day
|
|
415
375
|
return converted_date == shifted_date
|
|
@@ -3,8 +3,8 @@ from typing import overload
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pandas as pd
|
|
5
5
|
|
|
6
|
-
from
|
|
7
|
-
from
|
|
6
|
+
from pyield import anbima, di
|
|
7
|
+
from pyield import date_converter as dc
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@overload
|
|
@@ -77,7 +77,7 @@ def di_spreads(reference_date: str | pd.Timestamp) -> pd.DataFrame:
|
|
|
77
77
|
bond type and maturity date.
|
|
78
78
|
"""
|
|
79
79
|
# Fetch DI rates for the reference date
|
|
80
|
-
reference_date = dc.
|
|
80
|
+
reference_date = dc.convert_input_dates(reference_date)
|
|
81
81
|
df_di = di.data(reference_date, adj_expirations=True)
|
|
82
82
|
if "SettlementRate" not in df_di.columns:
|
|
83
83
|
raise ValueError("DI rates data is missing the 'SettlementRate' column.")
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from . import bond_tools as bt
|
|
3
|
+
from pyield import anbima, bday
|
|
4
|
+
from pyield import date_converter as dc
|
|
5
|
+
from pyield.bonds import bond_tools as bt
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
def rates(reference_date: str | pd.Timestamp) -> pd.DataFrame:
|
|
@@ -54,7 +53,7 @@ def quotation(
|
|
|
54
53
|
|
|
55
54
|
Examples:
|
|
56
55
|
Calculate the quotation of a LFT bond with a 0.02 yield rate:
|
|
57
|
-
>>> lft.quotation(
|
|
56
|
+
>>> yd.lft.quotation(
|
|
58
57
|
... settlement="24-07-2024",
|
|
59
58
|
... maturity="01-09-2030",
|
|
60
59
|
... rate=0.001717, # 0.1717%
|
|
@@ -62,8 +61,8 @@ def quotation(
|
|
|
62
61
|
98.9645
|
|
63
62
|
"""
|
|
64
63
|
# Validate and normalize dates
|
|
65
|
-
settlement = dc.
|
|
66
|
-
maturity = dc.
|
|
64
|
+
settlement = dc.convert_input_dates(settlement)
|
|
65
|
+
maturity = dc.convert_input_dates(maturity)
|
|
67
66
|
|
|
68
67
|
# The number of bdays between settlement (inclusive) and the maturity (exclusive)
|
|
69
68
|
bdays = bday.count(settlement, maturity)
|
|
@@ -92,8 +91,8 @@ def premium(lft_rate: float, selic_over: float) -> float:
|
|
|
92
91
|
Calculate the premium of a LFT bond with a 0.02 yield rate over the Selic rate:
|
|
93
92
|
>>> lft_rate = 0.1695 / 100 # 0.1695%
|
|
94
93
|
>>> selic_over = 10.40 / 100 # 10.40%
|
|
95
|
-
>>> lft.premium(lft_rate, selic_over)
|
|
96
|
-
1.017121
|
|
94
|
+
>>> yd.lft.premium(lft_rate, selic_over)
|
|
95
|
+
1.017121
|
|
97
96
|
"""
|
|
98
97
|
adjusted_lft_rate = (lft_rate + 1) * (selic_over + 1) - 1
|
|
99
98
|
f1 = (adjusted_lft_rate + 1) ** (1 / 252) - 1
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from . import bond_tools as bt
|
|
3
|
+
from pyield import anbima, bday, di
|
|
4
|
+
from pyield import date_converter as dc
|
|
5
|
+
from pyield.bonds import bond_tools as bt
|
|
7
6
|
|
|
8
7
|
FACE_VALUE = 1000
|
|
9
8
|
|
|
@@ -61,13 +60,13 @@ def price(
|
|
|
61
60
|
- https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
|
|
62
61
|
|
|
63
62
|
Examples:
|
|
64
|
-
>>> price("05-07-2024", "01-01-2030", 0.12145)
|
|
63
|
+
>>> yd.ltn.price("05-07-2024", "01-01-2030", 0.12145)
|
|
65
64
|
535.279902
|
|
66
65
|
"""
|
|
67
66
|
|
|
68
67
|
# Validate and normalize dates
|
|
69
|
-
settlement = dc.
|
|
70
|
-
maturity = dc.
|
|
68
|
+
settlement = dc.convert_input_dates(settlement)
|
|
69
|
+
maturity = dc.convert_input_dates(maturity)
|
|
71
70
|
|
|
72
71
|
# Calculate the number of business days between settlement and cash flow dates
|
|
73
72
|
bdays = bday.count(settlement, maturity)
|
|
@@ -90,11 +89,10 @@ def di_spreads(reference_date: str | pd.Timestamp) -> pd.DataFrame:
|
|
|
90
89
|
|
|
91
90
|
Parameters:
|
|
92
91
|
reference_date (str | pd.Timestamp, optional): The reference date for the
|
|
93
|
-
spread calculation.
|
|
94
|
-
business day according to the Brazilian calendar.
|
|
92
|
+
spread calculation.
|
|
95
93
|
|
|
96
94
|
Returns:
|
|
97
|
-
pd.DataFrame: DataFrame with the columns "MaturityDate" and "DISpread".
|
|
95
|
+
pd.DataFrame: DataFrame with the columns "MaturityDate" and "DISpread" (in bps).
|
|
98
96
|
"""
|
|
99
97
|
# Fetch DI Spreads for the reference date
|
|
100
98
|
df = bt.di_spreads(reference_date)
|
|
@@ -113,6 +111,13 @@ def premium(ltn_rate: float, di_rate: float) -> float:
|
|
|
113
111
|
|
|
114
112
|
Returns:
|
|
115
113
|
float: The premium of the LTN bond over the DI Future rate.
|
|
114
|
+
|
|
115
|
+
Examples:
|
|
116
|
+
Reference date: 22-08-2024
|
|
117
|
+
LTN rate for 01-01-2030: 0.118746
|
|
118
|
+
DI (JAN30) Settlement rate: 0.11725
|
|
119
|
+
>>> yd.ltn.premium(0.118746, 0.11725)
|
|
120
|
+
1.012072
|
|
116
121
|
"""
|
|
117
122
|
# Cálculo das taxas diárias
|
|
118
123
|
ltn_factor = (1 + ltn_rate) ** (1 / 252)
|
|
@@ -138,8 +143,8 @@ def historical_premium(
|
|
|
138
143
|
If the data is not available, returns NaN.
|
|
139
144
|
"""
|
|
140
145
|
# Convert input dates to a consistent format
|
|
141
|
-
reference_date = dc.
|
|
142
|
-
maturity = dc.
|
|
146
|
+
reference_date = dc.convert_input_dates(reference_date)
|
|
147
|
+
maturity = dc.convert_input_dates(maturity)
|
|
143
148
|
|
|
144
149
|
# Retrieve LTN rates for the reference date
|
|
145
150
|
df_anbima = rates(reference_date)
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import pandas as pd
|
|
3
3
|
|
|
4
|
-
from
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from . import bond_tools as bt
|
|
4
|
+
from pyield import anbima, bday
|
|
5
|
+
from pyield import date_converter as dc
|
|
6
|
+
from pyield.bonds import bond_tools as bt
|
|
7
|
+
from pyield.interpolator import Interpolator
|
|
9
8
|
|
|
10
9
|
"""
|
|
11
10
|
Constants calculated as per Anbima Rules and in base 100
|
|
@@ -99,8 +98,8 @@ def _generate_coupon_dates_map(
|
|
|
99
98
|
pd.Series: Series of coupon dates within the specified range.
|
|
100
99
|
"""
|
|
101
100
|
# Validate and normalize dates
|
|
102
|
-
start = dc.
|
|
103
|
-
end = dc.
|
|
101
|
+
start = dc.convert_input_dates(start)
|
|
102
|
+
end = dc.convert_input_dates(end)
|
|
104
103
|
|
|
105
104
|
# Initialize the first coupon date based on the reference date
|
|
106
105
|
reference_year = start.year
|
|
@@ -136,10 +135,17 @@ def payment_dates(
|
|
|
136
135
|
|
|
137
136
|
Returns:
|
|
138
137
|
pd.Series: Series of coupon dates within the specified range.
|
|
138
|
+
|
|
139
|
+
Examples:
|
|
140
|
+
>>> yd.ntnb.payment_dates("10-05-2024", "15-05-2025")
|
|
141
|
+
0 2024-05-15
|
|
142
|
+
1 2024-11-15
|
|
143
|
+
2 2025-05-15
|
|
144
|
+
dtype: datetime64[ns]
|
|
139
145
|
"""
|
|
140
146
|
# Validate and normalize dates
|
|
141
|
-
settlement = dc.
|
|
142
|
-
maturity = dc.
|
|
147
|
+
settlement = dc.convert_input_dates(settlement)
|
|
148
|
+
maturity = dc.convert_input_dates(maturity)
|
|
143
149
|
_check_maturities(maturity)
|
|
144
150
|
|
|
145
151
|
# Check if maturity date is after the start date
|
|
@@ -178,10 +184,17 @@ def cash_flows(
|
|
|
178
184
|
Returned columns:
|
|
179
185
|
- PaymentDate: The payment date of the cash flow
|
|
180
186
|
- CashFlow: Cash flow value for the bond
|
|
187
|
+
|
|
188
|
+
Examples:
|
|
189
|
+
>>> yd.ntnb.cash_flows("10-05-2024", "15-05-2025")
|
|
190
|
+
PaymentDate CashFlow
|
|
191
|
+
0 2024-05-15 2.956301
|
|
192
|
+
1 2024-11-15 2.956301
|
|
193
|
+
2 2025-05-15 102.956301
|
|
181
194
|
"""
|
|
182
195
|
# Validate and normalize dates
|
|
183
|
-
settlement = dc.
|
|
184
|
-
maturity = dc.
|
|
196
|
+
settlement = dc.convert_input_dates(settlement)
|
|
197
|
+
maturity = dc.convert_input_dates(maturity)
|
|
185
198
|
|
|
186
199
|
# Get the coupon dates between the settlement and maturity dates
|
|
187
200
|
p_dates = payment_dates(settlement, maturity)
|
|
@@ -219,14 +232,14 @@ def quotation(
|
|
|
219
232
|
Anbima rules.
|
|
220
233
|
|
|
221
234
|
Examples:
|
|
222
|
-
>>> ntnb.quotation("31-05-2024", "15-05-2035", 0.061490)
|
|
235
|
+
>>> yd.ntnb.quotation("31-05-2024", "15-05-2035", 0.061490)
|
|
223
236
|
99.3651
|
|
224
|
-
>>> ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
|
|
237
|
+
>>> yd.ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
|
|
225
238
|
99.5341
|
|
226
239
|
"""
|
|
227
240
|
# Validate and normalize dates
|
|
228
|
-
settlement = dc.
|
|
229
|
-
maturity = dc.
|
|
241
|
+
settlement = dc.convert_input_dates(settlement)
|
|
242
|
+
maturity = dc.convert_input_dates(maturity)
|
|
230
243
|
_check_maturities(maturity)
|
|
231
244
|
|
|
232
245
|
cf_df = cash_flows(settlement, maturity)
|
|
@@ -266,7 +279,7 @@ def price(
|
|
|
266
279
|
- https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
|
|
267
280
|
|
|
268
281
|
Examples:
|
|
269
|
-
>>> ntnb.price(4299.160173, 99.3651)
|
|
282
|
+
>>> yd.ntnb.price(4299.160173, 99.3651)
|
|
270
283
|
4271.864805
|
|
271
284
|
"""
|
|
272
285
|
return bt.truncate(vna * quotation / 100, 6)
|
|
@@ -306,12 +319,12 @@ def spot_rates(
|
|
|
306
319
|
- SpotRate: The real spot rate for the bond.
|
|
307
320
|
"""
|
|
308
321
|
# Process and validate the input data
|
|
309
|
-
settlement = dc.
|
|
322
|
+
settlement = dc.convert_input_dates(settlement)
|
|
310
323
|
maturities = pd.to_datetime(maturities, errors="raise", dayfirst=True)
|
|
311
324
|
_check_maturities(maturities)
|
|
312
325
|
|
|
313
326
|
# Create the interpolator object
|
|
314
|
-
ff_interpolator =
|
|
327
|
+
ff_interpolator = Interpolator(
|
|
315
328
|
method="flat_forward",
|
|
316
329
|
known_bdays=bday.count(settlement, maturities),
|
|
317
330
|
known_rates=rates,
|
|
@@ -401,7 +414,7 @@ def bei_rates(
|
|
|
401
414
|
settlement date to the bond's maturity.
|
|
402
415
|
"""
|
|
403
416
|
# Normalize input dates
|
|
404
|
-
settlement = dc.
|
|
417
|
+
settlement = dc.convert_input_dates(settlement)
|
|
405
418
|
ntnb_maturities = pd.to_datetime(ntnb_maturities, errors="coerce", dayfirst=True)
|
|
406
419
|
|
|
407
420
|
# Calculate Real Interest Rate (RIR)
|
|
@@ -409,7 +422,7 @@ def bei_rates(
|
|
|
409
422
|
df["BDays"] = bday.count(settlement, df["MaturityDate"])
|
|
410
423
|
df = df.rename(columns={"SpotRate": "RIR"})
|
|
411
424
|
|
|
412
|
-
nir_interplator =
|
|
425
|
+
nir_interplator = Interpolator(
|
|
413
426
|
method="flat_forward",
|
|
414
427
|
known_bdays=bday.count(settlement, nominal_maturities),
|
|
415
428
|
known_rates=nominal_rates,
|
|
@@ -434,8 +447,8 @@ def duration(
|
|
|
434
447
|
maturity: str | pd.Timestamp,
|
|
435
448
|
rate: float,
|
|
436
449
|
) -> float:
|
|
437
|
-
settlement = dc.
|
|
438
|
-
maturity = dc.
|
|
450
|
+
settlement = dc.convert_input_dates(settlement)
|
|
451
|
+
maturity = dc.convert_input_dates(maturity)
|
|
439
452
|
|
|
440
453
|
df = cash_flows(settlement, maturity)
|
|
441
454
|
df["BY"] = bday.count(settlement, df["PaymentDate"]) / 252
|