PYield 0.9.4__tar.gz → 0.9.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 (33) hide show
  1. {pyield-0.9.4 → pyield-0.9.6}/PKG-INFO +22 -3
  2. {pyield-0.9.4 → pyield-0.9.6}/README.md +21 -2
  3. pyield-0.9.6/pyield/__about__.py +1 -0
  4. {pyield-0.9.4 → pyield-0.9.6}/pyield/__init__.py +2 -2
  5. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/anbima.py +3 -3
  6. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/futures/intraday.py +3 -2
  7. pyield-0.9.6/pyield/interpolator.py +138 -0
  8. {pyield-0.9.4 → pyield-0.9.6}/pyield/ntnb.py +37 -54
  9. {pyield-0.9.4 → pyield-0.9.6}/pyield/spreads.py +1 -1
  10. {pyield-0.9.4 → pyield-0.9.6}/pyproject.toml +1 -1
  11. pyield-0.9.4/pyield/__about__.py +0 -1
  12. pyield-0.9.4/pyield/interpolators.py +0 -91
  13. {pyield-0.9.4 → pyield-0.9.6}/LICENSE +0 -0
  14. {pyield-0.9.4 → pyield-0.9.6}/pyield/bday.py +0 -0
  15. {pyield-0.9.4 → pyield-0.9.6}/pyield/date_validator.py +0 -0
  16. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/__init__.py +0 -0
  17. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/futures/__init__.py +0 -0
  18. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/futures/common.py +0 -0
  19. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/futures/historical.py +0 -0
  20. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/futures/xml.py +0 -0
  21. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/indicators.py +0 -0
  22. {pyield-0.9.4 → pyield-0.9.6}/pyield/fetchers/projections.py +0 -0
  23. {pyield-0.9.4 → pyield-0.9.6}/pyield/holidays/__init__.py +0 -0
  24. {pyield-0.9.4 → pyield-0.9.6}/pyield/holidays/br_holidays_new.txt +0 -0
  25. {pyield-0.9.4 → pyield-0.9.6}/pyield/holidays/br_holidays_old.txt +0 -0
  26. {pyield-0.9.4 → pyield-0.9.6}/pyield/holidays/holidays_manager.py +0 -0
  27. {pyield-0.9.4 → pyield-0.9.6}/pyield/py.typed +0 -0
  28. {pyield-0.9.4 → pyield-0.9.6}/tests/__init__.py +0 -0
  29. {pyield-0.9.4 → pyield-0.9.6}/tests/data/SPRD231222.zip +0 -0
  30. {pyield-0.9.4 → pyield-0.9.6}/tests/data/SPRD240426.zip +0 -0
  31. {pyield-0.9.4 → pyield-0.9.6}/tests/test_bday.py +0 -0
  32. {pyield-0.9.4 → pyield-0.9.6}/tests/test_futures.py +0 -0
  33. {pyield-0.9.4 → pyield-0.9.6}/tests/test_futures_xml.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PYield
3
- Version: 0.9.4
3
+ Version: 0.9.6
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>
@@ -85,7 +85,7 @@ Timestamp('2024-01-02 00:00:00')
85
85
  >>> yd.bday.offset(dates="30-12-2023", offset=0)
86
86
  Timestamp('2024-01-02 00:00:00')
87
87
 
88
- # Since 2023-12-29 is a business day, it returns the same date (offset=0)
88
+ # Since 29-12-2023 is a business day, it returns the same date (offset=0)
89
89
  >>> yd.bday.offset(dates="29-12-2023", offset=0)
90
90
  Timestamp('2023-12-29 00:00:00')
91
91
 
@@ -127,7 +127,7 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
127
127
  # Fetch a DataFrame with the NTN-B data from ANBIMA
128
128
  # Anbima data is available for the last 5 working days
129
129
  # Obs: Anbima members have access to the full history
130
- >>> yd.anbima(reference_date='12-04-2024', bond_type='NTN-B')
130
+ >>> yd.anbima(bond_type='NTN-B', reference_date='12-04-2024')
131
131
 
132
132
  BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate Price
133
133
  NTN-B 2024-04-12 2024-08-15 0.07540 0.07504 0.07523 4,271.43565
@@ -184,3 +184,22 @@ IndicatorProjection(
184
184
  0.0035 # 0.35%
185
185
  ```
186
186
 
187
+ ### Interpolation Tools
188
+ ```python
189
+
190
+ # Interpolate interest rates for specific business days using the Interpolator class.
191
+
192
+ # Initialize the Interpolator with known business days and interest rates.
193
+ >>> known_bdays = [30, 60, 90]
194
+ >>> known_rates = [0.045, 0.05, 0.055]
195
+ >>> linear_itp = yd.Interpolator("linear", known_bdays, known_rates)
196
+
197
+ # Interpolate the interest rate for a given number of business days.
198
+ >>> linear_itp.interpolate(45)
199
+ 0.0475
200
+
201
+ # Use the flat forward method for interpolation.
202
+ >>> ff_itp = yd.Interpolator("flat_forward", known_bdays, known_rates)
203
+ >>> ff_itp.interpolate(45)
204
+ 0.04833068080970859
205
+ ```
@@ -42,7 +42,7 @@ Timestamp('2024-01-02 00:00:00')
42
42
  >>> yd.bday.offset(dates="30-12-2023", offset=0)
43
43
  Timestamp('2024-01-02 00:00:00')
44
44
 
45
- # Since 2023-12-29 is a business day, it returns the same date (offset=0)
45
+ # Since 29-12-2023 is a business day, it returns the same date (offset=0)
46
46
  >>> yd.bday.offset(dates="29-12-2023", offset=0)
47
47
  Timestamp('2023-12-29 00:00:00')
48
48
 
@@ -84,7 +84,7 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
84
84
  # Fetch a DataFrame with the NTN-B data from ANBIMA
85
85
  # Anbima data is available for the last 5 working days
86
86
  # Obs: Anbima members have access to the full history
87
- >>> yd.anbima(reference_date='12-04-2024', bond_type='NTN-B')
87
+ >>> yd.anbima(bond_type='NTN-B', reference_date='12-04-2024')
88
88
 
89
89
  BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate Price
90
90
  NTN-B 2024-04-12 2024-08-15 0.07540 0.07504 0.07523 4,271.43565
@@ -141,3 +141,22 @@ IndicatorProjection(
141
141
  0.0035 # 0.35%
142
142
  ```
143
143
 
144
+ ### Interpolation Tools
145
+ ```python
146
+
147
+ # Interpolate interest rates for specific business days using the Interpolator class.
148
+
149
+ # Initialize the Interpolator with known business days and interest rates.
150
+ >>> known_bdays = [30, 60, 90]
151
+ >>> known_rates = [0.045, 0.05, 0.055]
152
+ >>> linear_itp = yd.Interpolator("linear", known_bdays, known_rates)
153
+
154
+ # Interpolate the interest rate for a given number of business days.
155
+ >>> linear_itp.interpolate(45)
156
+ 0.0475
157
+
158
+ # Use the flat forward method for interpolation.
159
+ >>> ff_itp = yd.Interpolator("flat_forward", known_bdays, known_rates)
160
+ >>> ff_itp.interpolate(45)
161
+ 0.04833068080970859
162
+ ```
@@ -0,0 +1 @@
1
+ __version__ = "0.9.6"
@@ -1,4 +1,4 @@
1
- from . import bday, interpolators, ntnb
1
+ from . import bday, interpolator, ntnb
2
2
  from .__about__ import __version__
3
3
  from .fetchers.anbima import anbima
4
4
  from .fetchers.futures import futures
@@ -15,6 +15,6 @@ __all__ = [
15
15
  "projection",
16
16
  "spread",
17
17
  "futures",
18
- "interpolators",
18
+ "interpolator",
19
19
  "spread",
20
20
  ]
@@ -90,8 +90,8 @@ def _process_raw_df(df_raw: pd.DataFrame) -> pd.DataFrame:
90
90
 
91
91
 
92
92
  def anbima(
93
- reference_date: str | pd.Timestamp | None = None,
94
93
  bond_type: str | list[str] | None = None,
94
+ reference_date: str | pd.Timestamp | None = None,
95
95
  ) -> pd.DataFrame:
96
96
  """
97
97
  Fetches indicative treasury rates from ANBIMA for a specified reference date.
@@ -100,10 +100,10 @@ def anbima(
100
100
  ANBIMA, processing them into a structured pandas DataFrame.
101
101
 
102
102
  Args:
103
+ bond_type (str, optional): The type of bond to filter by. Defaults to None.
103
104
  reference_date (str | pd.Timestamp | None, optional): The date for which to
104
105
  fetch the indicative rates. If a string is provided, it should be in the
105
106
  format 'dd-mm-yyyy'. Defaults last business day if None.
106
- bond_type (str, optional): The type of bond to filter by. Defaults to None.
107
107
 
108
108
  Returns:
109
109
  pd.DataFrame: A DataFrame containing the processed indicative rates for the
@@ -117,7 +117,7 @@ def anbima(
117
117
  # Fetch ANBIMA data for all bonds using the last business day available
118
118
  >>> yd.anbima("18-06-2024")
119
119
  # Fetch ANBIMA data for NTN-B bonds using a specific reference date
120
- >>> yd.anbima("18-06-2024", "NTN-B")
120
+ >>> yd.anbima("NTN-B", "18-06-2024")
121
121
  """
122
122
  # Normalize the reference date
123
123
  normalized_date = dv.normalize_date(reference_date)
@@ -167,8 +167,9 @@ def fetch_intraday_df(future_code: str) -> pd.DataFrame:
167
167
  pd.DataFrame: A Pandas pd.DataFrame containing the latest DI futures data.
168
168
  """
169
169
  raw_df = _fetch_b3_df(future_code)
170
- if raw_df.empty:
171
- return raw_df
170
+ if "buyOffer" not in raw_df.columns:
171
+ # Return an empty DataFrame if the data is not available
172
+ return pd.DataFrame()
172
173
  df = _process_df(raw_df)
173
174
  df = _select_and_reorder_columns(df)
174
175
  return df
@@ -0,0 +1,138 @@
1
+ import bisect
2
+ from typing import Literal
3
+
4
+ import numpy as np
5
+ import pandas as pd
6
+
7
+
8
+ class Interpolator:
9
+ def __init__(
10
+ self,
11
+ method: Literal["flat_forward", "linear"],
12
+ known_bdays: pd.Series | list,
13
+ known_rates: pd.Series | list,
14
+ ):
15
+ """
16
+ Initialize the Interpolator with given atributes.
17
+
18
+ Args:
19
+ method (Literal["flat_forward", "linear"]): Interpolation method.
20
+ known_bdays (pd.Series): Series of known business days.
21
+ known_rates (pd.Series): Series of known interest rates.
22
+
23
+ Raises:
24
+ ValueError: If known_bdays and known_rates do not have the same length.
25
+ ValueError: If the interpolation method is not recognized
26
+
27
+ Returns:
28
+ Interpolator: An instance of the Interpolator
29
+
30
+ Examples:
31
+ >>> known_bdays = [30, 60, 90]
32
+ >>> known_rates = [0.045, 0.05, 0.055]
33
+ >>> interpolator = Interpolator("linear", known_bdays, known_rates)
34
+ """
35
+ self.known_bdays, self.known_rates = self._process_known_data(
36
+ known_bdays, known_rates
37
+ )
38
+ self.method = self._validate_method(method)
39
+
40
+ @staticmethod
41
+ def _validate_method(method: str) -> str:
42
+ """
43
+ Validate the interpolation method.
44
+
45
+ Args:
46
+ method (str): Interpolation method to validate.
47
+
48
+ Returns:
49
+ str: Validated interpolation method.
50
+ """
51
+ valid_methods = ["flat_forward", "linear"]
52
+ if method not in valid_methods:
53
+ raise ValueError(f"Unknown interpolation method: {method}.")
54
+ return method
55
+
56
+ @staticmethod
57
+ def _process_known_data(
58
+ known_bdays: pd.Series | list, known_rates: pd.Series | list
59
+ ) -> tuple[list, list]:
60
+ """
61
+ Process and validate known business days and interest rates.
62
+
63
+ Args:
64
+ known_bdays (pd.Series): Series of known business days.
65
+ known_rates (pd.Series): Series of known interest rates.
66
+
67
+ Returns:
68
+ tuple: Processed lists of business days and interest rates.
69
+ """
70
+ if len(known_bdays) != len(known_rates):
71
+ raise ValueError("known_bdays and known_rates must have the same length.")
72
+
73
+ df = pd.DataFrame({"bday": known_bdays, "rate": known_rates})
74
+ df = df.dropna().drop_duplicates(subset="bday").sort_values("bday")
75
+
76
+ return df["bday"].to_list(), df["rate"].to_list()
77
+
78
+ def _flat_forward(self, bday: int) -> float:
79
+ """Performs the interest rate interpolation using the flat forward method."""
80
+
81
+ # Find i such that known_bdays[i-1] < bday < known_bdays[i]
82
+ i = bisect.bisect_left(self.known_bdays, bday)
83
+
84
+ # Get previous and next known rates and business days
85
+ prev_rate = self.known_rates[i - 1]
86
+ prev_bday = self.known_bdays[i - 1]
87
+ next_rate = self.known_rates[i]
88
+ next_bday = self.known_bdays[i]
89
+
90
+ # Perform flat forward interpolation
91
+ a = (1 + prev_rate) ** (prev_bday / 252)
92
+ b = (1 + next_rate) ** (next_bday / 252)
93
+ c = (bday - prev_bday) / (next_bday - prev_bday)
94
+ return (a * (b / a) ** c) ** (252 / bday) - 1
95
+
96
+ def _linear(self, bday: int) -> float:
97
+ """Performs linear interpolation."""
98
+ np_float = np.interp(bday, self.known_bdays, self.known_rates)
99
+ return float(np_float)
100
+
101
+ def interpolate(self, bday: int) -> float:
102
+ """
103
+ Finds the appropriate interpolation point and returns the interest rate
104
+ interpolated by the specified method from that point.
105
+
106
+ Args:
107
+ bday (int): Number of business days for which the interest rate is to be
108
+ calculated.
109
+
110
+ Returns:
111
+ float: The interest rate interpolated by the specified method for the given
112
+ number of business days.
113
+
114
+ Examples:
115
+ >>> known_bdays = [30, 60, 90]
116
+ >>> known_rates = [0.045, 0.05, 0.055]
117
+ >>> linear = Interpolator("linear", known_bdays, known_rates)
118
+ >>> linear.interpolate(45)
119
+ 0.0475
120
+ >>> ffwd = Interpolator("flat_forward", known_bdays, known_rates)
121
+ >>> ffwd.interpolate(45)
122
+ 0.04833068080970859
123
+ """
124
+ known_bdays = self.known_bdays
125
+ known_rates = self.known_rates
126
+
127
+ # Special cases
128
+ if bday < known_bdays[0]:
129
+ return known_rates[0]
130
+ elif bday > known_bdays[-1]:
131
+ return known_rates[-1]
132
+ elif bday in known_bdays:
133
+ return known_rates[known_bdays.index(bday)]
134
+
135
+ if self.method == "flat_forward":
136
+ return self._flat_forward(bday)
137
+ elif self.method == "linear":
138
+ return self._linear(bday)
@@ -3,9 +3,9 @@ import pandas as pd
3
3
 
4
4
  from . import bday
5
5
  from . import date_validator as dv
6
- from . import interpolators as ip
7
6
  from .fetchers.anbima import anbima
8
7
  from .fetchers.futures import futures
8
+ from .interpolator import Interpolator
9
9
  from .spreads import spread
10
10
 
11
11
  # 6% per year compounded semi-annually and rounded to 8 decimal places
@@ -35,7 +35,7 @@ def ytm_rates(reference_date: str | pd.Timestamp) -> pd.DataFrame:
35
35
  Returns:
36
36
  pd.DataFrame: A DataFrame containing the maturity dates and corresponding rates.
37
37
  """
38
- df = anbima(reference_date, bond_type="NTN-B")
38
+ df = anbima("NTN-B", reference_date)
39
39
 
40
40
  # Keep only the relevant columns for the output
41
41
  keep_columns = ["ReferenceDate", "BondType", "MaturityDate", "IndicativeRate"]
@@ -188,30 +188,6 @@ def quotation(
188
188
  return _truncate(dcf.sum(), 4)
189
189
 
190
190
 
191
- def _prepare_interpolation_data(
192
- reference_date: pd.Timestamp, maturity_dates: pd.Series, rates: pd.Series
193
- ) -> tuple:
194
- """
195
- Prepare the data needed for interpolation by sorting the YTM rates by the number of
196
- business days.
197
-
198
- Args:
199
- reference_date (str | pd.Timestamp): The reference date for calculating the
200
- number of business days.
201
- maturity_dates (pd.Series): Series of maturity dates for the bonds.
202
- rates (pd.Series): Series of rates corresponding to the maturity dates.
203
-
204
- Returns:
205
- tuple: Two lists containing the ordered business days and YTM rates.
206
- """
207
- bdays = bday.count(reference_date, maturity_dates)
208
- df = pd.DataFrame({"BDays": bdays, "Rates": rates})
209
- df.sort_values(by="BDays", ignore_index=True, inplace=True)
210
- ordered_bdays = df["BDays"].to_list()
211
- ordered_rates = df["Rates"].to_list()
212
- return ordered_bdays, ordered_rates
213
-
214
-
215
191
  def spot_rates(
216
192
  settlement_date: str | pd.Timestamp,
217
193
  maturity_dates: pd.Series,
@@ -223,37 +199,44 @@ def spot_rates(
223
199
 
224
200
  Args:
225
201
  settlement_date (str | pd.Timestamp): The reference date for settlement.
226
- maturity_dates (pd.Series): Series of maturity dates for the bonds.
227
- ytm_rates (pd.Series): Series of Yield to Maturity rates corresponding to the
202
+ maturity_dates (pd.Series): Series of maturity dates for the bonds. ytm_rates
203
+ (pd.Series): Series of Yield to Maturity rates corresponding to the
228
204
  maturity dates.
229
205
 
230
206
  Returns:
231
- pd.DataFrame: DataFrame containing the maturity dates and corresponding spot
232
- rates.
207
+ pd.DataFrame: DataFrame containing the maturity dates and corresponding real
208
+ spot rates (RSR).
233
209
 
234
210
  Notes:
235
211
  The calculation of the spot rates for NTN-B bonds considers the following steps:
236
212
  - Map all all possible payment dates up to the longest maturity date.
237
213
  - Interpolate the YTM rates in the intermediate payment dates.
238
214
  - Calculate the NTN-B quotation for each maturity date.
239
- - Calculate the spot rates for each maturity date.
215
+ - Calculate the real spot rates (RSR) for each maturity date.
240
216
  """
241
217
  # COUPON = (1.06) ** 0.5 - 1 # Coupon without rounding
242
218
  # Validate and normalize the settlement date
243
219
  settlement_date = dv.normalize_date(settlement_date)
244
220
 
245
- # Prepare the data for interpolation
246
- ordered_bdays, ordered_ytms = _prepare_interpolation_data(
247
- settlement_date, maturity_dates, ytm_rates
221
+ # Create the interpolator object
222
+ flat_fwd = Interpolator(
223
+ method="flat_forward",
224
+ known_bdays=bday.count(settlement_date, maturity_dates),
225
+ known_rates=ytm_rates,
226
+ )
227
+
228
+ # Generate coupon dates up to the longest maturity date
229
+ all_coupon_dates = coupon_dates_map(
230
+ start=settlement_date,
231
+ end=maturity_dates.max(),
248
232
  )
249
- # Generate coupon dates and initialize the main DataFrame
250
- longest_ntnb = maturity_dates.max()
251
- coupon_dates_all = coupon_dates_map(settlement_date, longest_ntnb)
252
- df = pd.DataFrame(coupon_dates_all, columns=["MaturityDate"])
233
+
234
+ # Create a DataFrame with all coupon dates
235
+ df = pd.DataFrame(all_coupon_dates, columns=["MaturityDate"])
253
236
 
254
237
  # Add auxiliary columns for calculations
255
238
  df["BDays"] = bday.count(settlement_date, df["MaturityDate"])
256
- df["YTM"] = 0.0
239
+ df["YTM"] = df["BDays"].apply(flat_fwd.interpolate)
257
240
  df["RSR"] = 0.0
258
241
 
259
242
  # Main loop to calculate spot rates
@@ -273,15 +256,12 @@ def spot_rates(
273
256
  # Calculate the present value of the cash flows (discounted cash flows)
274
257
  dcfs = cfs / (1 + spot_rates) ** periods
275
258
 
276
- # Interpolate YTM and calculate spot rate
259
+ # Calculate the real spot rate (RSR) for the bond
277
260
  bd = df.at[index, "BDays"]
278
- ytm = ip.find_and_interpolate_flat_forward(bd, ordered_bdays, ordered_ytms)
261
+ ytm = df.at[index, "YTM"]
279
262
  ntnb_quotation = quotation(settlement_date, maturity_date, ytm) / 100
280
- spot_rate = ((COUPON + 1) / (ntnb_quotation - dcfs.sum())) ** (252 / bd) - 1
281
-
282
- # Update DataFrame with calculated values
283
- df.at[index, "RSR"] = spot_rate
284
- df.at[index, "YTM"] = ytm
263
+ rsr = ((COUPON + 1) / (ntnb_quotation - dcfs.sum())) ** (252 / bd) - 1
264
+ df.at[index, "RSR"] = rsr
285
265
 
286
266
  # Drop the BDays column, remove intermediate cupon dates and reset the index.
287
267
  return (
@@ -383,25 +363,28 @@ def bei_rates(
383
363
 
384
364
  # Fetch Nominal Spot Rate (NSR) data
385
365
  df_nsr = _get_nsr_df(reference_date)
386
- known_bdays = df_nsr["BDaysToExp"].to_list()
387
- known_rates = df_nsr["NSR_DI"].to_list()
388
366
 
367
+ ffwd = Interpolator(
368
+ method="flat_forward",
369
+ known_bdays=df_nsr["BDaysToExp"],
370
+ known_rates=df_nsr["NSR_DI"],
371
+ )
389
372
  # Calculate Real Spot Rate (RSR)
390
373
  df = spot_rates(settlement_date, maturity_dates, ytm_rates)
391
374
  df = df.rename(columns={"RSR": "RSR"})
392
375
  df["BDays"] = bday.count(reference_date, df["MaturityDate"])
393
- df["NSR_DI"] = df["BDays"].apply(
394
- lambda x: ip.find_and_interpolate_flat_forward(x, known_bdays, known_rates)
395
- )
376
+ df["NSR_DI"] = df["BDays"].apply(ffwd.interpolate)
396
377
 
397
378
  # Calculate Breakeven Inflation Rate (BIR)
398
379
  df["BIR_DI"] = ((df["NSR_DI"] + 1) / (df["RSR"] + 1)) - 1
399
380
 
400
381
  # Adjust BEI for DI spread in prefixed bonds
401
- known_rates = df_nsr["NSR_PRE"].to_list()
402
- df["NSR_PRE"] = df["BDays"].apply(
403
- lambda x: ip.find_and_interpolate_flat_forward(x, known_bdays, known_rates)
382
+ ffwd = Interpolator(
383
+ method="flat_forward",
384
+ known_bdays=df_nsr["BDaysToExp"],
385
+ known_rates=df_nsr["NSR_PRE"],
404
386
  )
387
+ df["NSR_PRE"] = df["BDays"].apply(ffwd.interpolate)
405
388
  df["BIR_PRE"] = ((df["NSR_PRE"] + 1) / (df["RSR"] + 1)) - 1
406
389
 
407
390
  cols_reordered = [
@@ -76,7 +76,7 @@ def di_pre(reference_date: pd.Timestamp) -> pd.DataFrame:
76
76
  df_di["MaturityDate"] = df_di["MaturityDate"].dt.to_period("M").dt.to_timestamp()
77
77
 
78
78
  # Fetch bond rates, filtering for LTN and NTN-F types
79
- df_anbima = anbima(reference_date, ["LTN", "NTN-F"])
79
+ df_anbima = anbima(["LTN", "NTN-F"], reference_date)
80
80
  # Keep only the relevant columns for the output
81
81
  keep_columns = ["ReferenceDate", "BondType", "MaturityDate", "IndicativeRate"]
82
82
  df_anbima = df_anbima[keep_columns].copy()
@@ -32,7 +32,7 @@ dependencies = [
32
32
  "requests>=2.31.0",
33
33
  ]
34
34
  dynamic = []
35
- version = "0.9.4"
35
+ version = "0.9.6"
36
36
 
37
37
  [project.license]
38
38
  file = "LICENSE"
@@ -1 +0,0 @@
1
- __version__ = "0.9.4"
@@ -1,91 +0,0 @@
1
- import bisect
2
-
3
-
4
- def interpolate_flat_forward(
5
- prev_rate: float, prev_bdays: int, next_rate: float, next_bdays: int, bdays: int
6
- ) -> float:
7
- """Performs interest rate interpolation using the flat forward interpolation method
8
- considering a base of 252 business days.
9
-
10
- The interpolation is done between two known pairs of vertices (prev_rate,
11
- prev_business_days) and (next_rate, next_business_days), for a third vertex defined
12
- by the number of business days 'business_days' where 'prev_business_days <
13
- business_days < next_business_days'. This third vertex is the point in time for
14
- which the interest rate is being calculated.
15
-
16
- Args:
17
- - prev_rate (float): Interest rate of the previous vertex.
18
- - prev_bdays (int): Number of business days of the previous vertex.
19
- - next_rate (float): Interest rate of the next vertex.
20
- - next_bdays (int): Number of business days of the next vertex.
21
- - bdays (int): Number of business days for which the interest rate is to be
22
- interpolated.
23
-
24
- Example:
25
- interpolated_rate = interpolate_flat_forward(0.045, 30, 0.05, 60, 45)
26
-
27
- Returns:
28
- float: The interpolated interest rate at the given `business_days`.
29
- """
30
- a = (1 + prev_rate) ** (prev_bdays / 252)
31
- b = (1 + next_rate) ** (next_bdays / 252)
32
- c = (bdays - prev_bdays) / (next_bdays - prev_bdays)
33
-
34
- return (a * (b / a) ** c) ** (252 / bdays) - 1
35
-
36
-
37
- def find_and_interpolate_flat_forward(
38
- bdays: int,
39
- known_bdays: list[int],
40
- known_rates: list[float],
41
- ) -> float:
42
- """
43
- Finds the appropriate interpolation point and returns the interest rate
44
- interpolated by the flat forward method from that point. Uses the `bisect` module
45
- for binary search in ordered lists.
46
-
47
-
48
- Args:
49
- business_days (int): Number of business days for which the flat forward interest
50
- rate is to be calculated.
51
- known_business_days (List[int]): List of business days where interest rates are
52
- known.
53
- known_rates (List[float]): List of known interest rates.
54
-
55
- Notes:
56
- - It is assumed that `known_business_days` and `known_rates` are sorted and have
57
- the same size.
58
- - The method uses 252 business days per year in the interpolation, which is the
59
- standard in the Brazilian market.
60
- - Special cases are handled for situations where `business_days` is less than
61
- the first known business day, greater than the last known business day, or
62
- exactly equal to a known business day, avoiding the need for interpolation.
63
-
64
- Example:
65
- known_bdays = [30, 60, 90]
66
- known_rates = [0.045, 0.05, 0.055]
67
- interpolated_rate = find_and_interpolate_flat_forward(45, known_bdays, known_rates)
68
-
69
- Returns:
70
- float: The interest rate interpolated by the flat forward method for the given
71
- number of business days.
72
- """
73
- # Special cases
74
- if bdays <= known_bdays[0]:
75
- return known_rates[0]
76
- elif bdays >= known_bdays[-1]:
77
- return known_rates[-1]
78
- # Do not interpolate vertex whose rate is known
79
- elif bdays in known_bdays:
80
- return known_rates[known_bdays.index(bdays)]
81
-
82
- # Find i such that known_business_days[i-1] < business_days < known_business_days[i]
83
- i = bisect.bisect_left(known_bdays, bdays)
84
-
85
- return interpolate_flat_forward(
86
- known_rates[i - 1],
87
- known_bdays[i - 1],
88
- known_rates[i],
89
- known_bdays[i],
90
- bdays,
91
- )
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