PYield 0.40.7__tar.gz → 0.41.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.
Files changed (61) hide show
  1. {pyield-0.40.7 → pyield-0.41.0}/PKG-INFO +1 -1
  2. pyield-0.41.0/pyield/__about__.py +1 -0
  3. {pyield-0.40.7 → pyield-0.41.0}/pyield/__init__.py +3 -1
  4. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/lft.py +24 -0
  5. pyield-0.41.0/pyield/tn/ntnb1.py +345 -0
  6. pyield-0.41.0/pyield/tn/ntnbprinc.py +80 -0
  7. pyield-0.40.7/pyield/__about__.py +0 -1
  8. {pyield-0.40.7 → pyield-0.41.0}/.gitignore +0 -0
  9. {pyield-0.40.7 → pyield-0.41.0}/LICENSE +0 -0
  10. {pyield-0.40.7 → pyield-0.41.0}/README.md +0 -0
  11. {pyield-0.40.7 → pyield-0.41.0}/pyield/anbima/__init__.py +0 -0
  12. {pyield-0.40.7 → pyield-0.41.0}/pyield/anbima/difusao.py +0 -0
  13. {pyield-0.40.7 → pyield-0.41.0}/pyield/anbima/ettj_intraday.py +0 -0
  14. {pyield-0.40.7 → pyield-0.41.0}/pyield/anbima/ettj_last.py +0 -0
  15. {pyield-0.40.7 → pyield-0.41.0}/pyield/anbima/ima.py +0 -0
  16. {pyield-0.40.7 → pyield-0.41.0}/pyield/anbima/imaq.py +0 -0
  17. {pyield-0.40.7 → pyield-0.41.0}/pyield/anbima/tpf.py +0 -0
  18. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/__init__.py +0 -0
  19. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/di1.py +0 -0
  20. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/di_over.py +0 -0
  21. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/futures/__init__.py +0 -0
  22. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/futures/common.py +0 -0
  23. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/futures/historical.py +0 -0
  24. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/futures/intraday.py +0 -0
  25. {pyield-0.40.7 → pyield-0.41.0}/pyield/b3/futures/xml.py +0 -0
  26. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/__init__.py +0 -0
  27. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/auction.py +0 -0
  28. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/ptax_api.py +0 -0
  29. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/rates.py +0 -0
  30. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/repo.py +0 -0
  31. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/trades_intraday.py +0 -0
  32. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/trades_monthly.py +0 -0
  33. {pyield-0.40.7 → pyield-0.41.0}/pyield/bc/vna.py +0 -0
  34. {pyield-0.40.7 → pyield-0.41.0}/pyield/bday/__init__.py +0 -0
  35. {pyield-0.40.7 → pyield-0.41.0}/pyield/bday/core.py +0 -0
  36. {pyield-0.40.7 → pyield-0.41.0}/pyield/bday/holidays/__init__.py +0 -0
  37. {pyield-0.40.7 → pyield-0.41.0}/pyield/bday/holidays/br_holidays_new.txt +0 -0
  38. {pyield-0.40.7 → pyield-0.41.0}/pyield/bday/holidays/br_holidays_old.txt +0 -0
  39. {pyield-0.40.7 → pyield-0.41.0}/pyield/bday/holidays/brholidays.py +0 -0
  40. {pyield-0.40.7 → pyield-0.41.0}/pyield/config.py +0 -0
  41. {pyield-0.40.7 → pyield-0.41.0}/pyield/conftest.py +0 -0
  42. {pyield-0.40.7 → pyield-0.41.0}/pyield/converters.py +0 -0
  43. {pyield-0.40.7 → pyield-0.41.0}/pyield/data_cache.py +0 -0
  44. {pyield-0.40.7 → pyield-0.41.0}/pyield/fwd.py +0 -0
  45. {pyield-0.40.7 → pyield-0.41.0}/pyield/interpolator.py +0 -0
  46. {pyield-0.40.7 → pyield-0.41.0}/pyield/ipca/__init__.py +0 -0
  47. {pyield-0.40.7 → pyield-0.41.0}/pyield/ipca/historical.py +0 -0
  48. {pyield-0.40.7 → pyield-0.41.0}/pyield/ipca/projected.py +0 -0
  49. {pyield-0.40.7 → pyield-0.41.0}/pyield/py.typed +0 -0
  50. {pyield-0.40.7 → pyield-0.41.0}/pyield/retry.py +0 -0
  51. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/__init__.py +0 -0
  52. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/auctions.py +0 -0
  53. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/benchmark.py +0 -0
  54. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/ltn.py +0 -0
  55. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/ntnb.py +0 -0
  56. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/ntnc.py +0 -0
  57. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/ntnf.py +0 -0
  58. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/pre.py +0 -0
  59. {pyield-0.40.7 → pyield-0.41.0}/pyield/tn/tools.py +0 -0
  60. {pyield-0.40.7 → pyield-0.41.0}/pyield/types.py +0 -0
  61. {pyield-0.40.7 → pyield-0.41.0}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PYield
3
- Version: 0.40.7
3
+ Version: 0.41.0
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.41.0"
@@ -5,7 +5,7 @@ from pyield.__about__ import __version__
5
5
  from pyield.b3 import di1, futures
6
6
  from pyield.fwd import forward, forwards
7
7
  from pyield.interpolator import Interpolator
8
- from pyield.tn import lft, ltn, ntnb, ntnc, ntnf, pre
8
+ from pyield.tn import lft, ltn, ntnb, ntnb1, ntnbprinc, ntnc, ntnf, pre
9
9
 
10
10
  __all__ = [
11
11
  "__version__",
@@ -23,6 +23,8 @@ __all__ = [
23
23
  "lft",
24
24
  "ltn",
25
25
  "ntnb",
26
+ "ntnbprinc",
27
+ "ntnb1",
26
28
  "ntnc",
27
29
  "ntnf",
28
30
  "pre",
@@ -146,3 +146,27 @@ def premium(lft_rate: float, di_rate: float) -> float:
146
146
  ltt_factor = (lft_rate + 1) ** (1 / 252)
147
147
  di_factor = (di_rate + 1) ** (1 / 252)
148
148
  return (ltt_factor * di_factor - 1) / (di_factor - 1)
149
+
150
+
151
+ def price(
152
+ vna: float,
153
+ quotation: float,
154
+ ) -> float:
155
+ """
156
+ Calculate the LFT price using Brazilian Treasury rules.
157
+
158
+ Args:
159
+ vna (float): The nominal value of the LFT bond.
160
+ quotation (float): The LFT quotation in base 100.
161
+ Returns:
162
+ float: The LFT price truncated to 6 decimal places.
163
+
164
+ References:
165
+ - SEI Proccess 17944.005214/2024-09
166
+
167
+ Examples:
168
+ >>> from pyield import lft
169
+ >>> lft.price(15785.324502, 99.9291)
170
+ 15774.132706
171
+ """
172
+ return tools.truncate(vna * quotation / 100, 6)
@@ -0,0 +1,345 @@
1
+ from enum import Enum
2
+
3
+ import pandas as pd
4
+ import polars as pl
5
+
6
+ import pyield.converters as cv
7
+ import pyield.tn.tools as bt
8
+ from pyield import bday
9
+ from pyield.types import DateLike, has_nullable_args
10
+
11
+ """
12
+ Global parameters for NTN-B1 bonds calculations.
13
+ These parameters are used to define the cash flows and payment structure of the bonds,
14
+ according to Commercial Name.
15
+ The parameters are initialized based on the commercial name of the NTN-B1 bond.
16
+
17
+ """
18
+ AMORTIZATION_PAYMENT = 0
19
+ FINAL_AMORTIZATION_PAYMENT = 0
20
+ NUMBER_OF_AMORTIZATIONS = 0
21
+
22
+
23
+ class CommercialName(Enum):
24
+ """
25
+ Commercial Name Enum used to identify the kind of used NTN-B1 in the scope of the
26
+ calculation (Renda+ or Educa+).
27
+ """
28
+
29
+ RENDA_MAIS = "Renda+"
30
+ EDUCA_MAIS = "Educa+"
31
+
32
+
33
+ # Mapeamento estático do número de meses
34
+ # Isso é uma constante real (não muda durante a execução)
35
+ PARAMS_MAP = {
36
+ CommercialName.RENDA_MAIS: 240,
37
+ CommercialName.EDUCA_MAIS: 60,
38
+ }
39
+
40
+
41
+ def _get_bond_parameters(commercial_name: CommercialName) -> tuple[float, float, int]:
42
+ """
43
+ Returns amortization parameters based on commercial name.
44
+ Returns: (amortization_payment, final_amortization_payment, number_of_amortizations)
45
+ """
46
+ try:
47
+ n_amortizations = PARAMS_MAP[commercial_name]
48
+ except KeyError:
49
+ raise ValueError(f"Invalid commercial name: {commercial_name}")
50
+
51
+ amortization_payment = 1 / n_amortizations
52
+ final_amortization_payment = 1 - (amortization_payment * (n_amortizations - 1))
53
+
54
+ return amortization_payment, final_amortization_payment, n_amortizations
55
+
56
+
57
+ def payment_dates(
58
+ settlement: DateLike, maturity: DateLike, commercial_name: CommercialName
59
+ ) -> pl.Series:
60
+ """
61
+ Generate all remaining amortization dates between a given date and the maturity
62
+ date.
63
+ The dates are inclusive. Payments are made from January 15th of the year of
64
+ conversion to December 15 of maturity year.
65
+
66
+ Args:
67
+ settlement (DateLike): The settlement date (exclusive) to start generating
68
+ the amortization dates.
69
+ maturity (DateLike): The maturity date.
70
+ commercial_name (CommercialName): The commercial name of the NTN-B1 bond
71
+ (Renda+ or Educa+).
72
+
73
+ Returns:
74
+ pl.Series: Series of coupon dates within the specified range.
75
+
76
+ Examples:
77
+ >>> from pyield import ntnb1
78
+ >>> r_mais = ntnb1.CommercialName.RENDA_MAIS
79
+ >>> ntnb1.payment_dates("10-05-2024", "15-12-2050", r_mais)
80
+ shape: (240,)
81
+ Series: 'payment_dates' [date]
82
+ [
83
+ 2031-01-15
84
+ 2031-02-15
85
+ 2031-03-15
86
+ 2031-04-15
87
+ 2031-05-15
88
+ …
89
+ 2050-08-15
90
+ 2050-09-15
91
+ 2050-10-15
92
+ 2050-11-15
93
+ 2050-12-15
94
+ ]
95
+ """
96
+ if has_nullable_args(settlement, maturity, commercial_name):
97
+ return pl.Series("payment_dates", dtype=pl.Date)
98
+
99
+ # Validate and normalize dates
100
+ settlement = cv.convert_dates(settlement)
101
+ maturity = cv.convert_dates(maturity)
102
+
103
+ if maturity <= settlement:
104
+ raise ValueError("Maturity date must be after the settlement date.")
105
+
106
+ maturity = maturity.replace(day=15)
107
+
108
+ # Get bond parameters
109
+ _, _, n_amortizations = _get_bond_parameters(commercial_name)
110
+
111
+ amtz_dates = [maturity - pd.DateOffset(months=i) for i in range(n_amortizations)]
112
+
113
+ if len(amtz_dates) == 0:
114
+ raise ValueError("No amortization dates found after settlement date.")
115
+
116
+ s_pmt_dates = pl.Series(name="payment_dates", values=amtz_dates).cast(pl.Date)
117
+
118
+ return s_pmt_dates.filter(s_pmt_dates > settlement).sort()
119
+
120
+
121
+ def cash_flows(
122
+ settlement: DateLike, maturity: DateLike, commercial_name: CommercialName
123
+ ) -> pl.DataFrame:
124
+ """
125
+ Generate the cash flows for NTN-B1 bonds between the settlement and maturity dates.
126
+
127
+ Args:
128
+ settlement (DateScalar): The settlement date (exclusive) to start generating
129
+ the cash flows.
130
+ maturity (DateScalar): The maturity date of the bond.
131
+ commercial_name (CommercialName): The commercial name of the NTN-B1 bond
132
+ (Renda+ or Educa+).
133
+
134
+ Returns:
135
+ pd.DataFrame: DataFrame with columns "PaymentDate" and "CashFlow".
136
+
137
+ Returned columns:
138
+ - PaymentDate: The payment date of the cash flow
139
+ - CashFlow: Cash flow value for the bond
140
+
141
+ Examples:
142
+ >>> from pyield import ntnb1
143
+ >>> r_mais = ntnb1.CommercialName.RENDA_MAIS
144
+ >>> ntnb1.cash_flows("10-05-2024", "15-12-2060", r_mais)
145
+ shape: (240, 2)
146
+ ┌─────────────┬──────────┐
147
+ │ PaymentDate ┆ CashFlow │
148
+ │ --- ┆ --- │
149
+ │ date ┆ f64 │
150
+ ╞═════════════╪══════════╡
151
+ │ 2041-01-15 ┆ 0.004167 │
152
+ │ 2041-02-15 ┆ 0.004167 │
153
+ │ 2041-03-15 ┆ 0.004167 │
154
+ │ 2041-04-15 ┆ 0.004167 │
155
+ │ 2041-05-15 ┆ 0.004167 │
156
+ │ … ┆ … │
157
+ │ 2060-08-15 ┆ 0.004167 │
158
+ │ 2060-09-15 ┆ 0.004167 │
159
+ │ 2060-10-15 ┆ 0.004167 │
160
+ │ 2060-11-15 ┆ 0.004167 │
161
+ │ 2060-12-15 ┆ 0.004167 │
162
+ └─────────────┴──────────┘
163
+
164
+ """
165
+ if has_nullable_args(settlement, maturity, commercial_name):
166
+ return pl.DataFrame({"PaymentDate": [], "CashFlow": []})
167
+
168
+ # Validate and normalize dates
169
+ settlement = cv.convert_dates(settlement)
170
+ maturity = cv.convert_dates(maturity)
171
+
172
+ # Get the coupon dates between the settlement and maturity dates
173
+ p_dates = payment_dates(settlement, maturity, commercial_name)
174
+ df = pl.DataFrame({"PaymentDate": p_dates})
175
+
176
+ # Get bond parameters
177
+ amort_payment, final_amort_payment, _ = _get_bond_parameters(commercial_name)
178
+
179
+ # Set the cash flow at maturity to FINAL_PMT and the others to COUPON_PMT
180
+ df = df.with_columns(
181
+ pl.when(pl.col("PaymentDate") == maturity)
182
+ .then(final_amort_payment)
183
+ .otherwise(amort_payment)
184
+ .alias("CashFlow")
185
+ )
186
+
187
+ # Return a dataframe with the payment dates and cash flows
188
+ return df
189
+
190
+
191
+ def quotation(
192
+ settlement: DateLike,
193
+ maturity: DateLike,
194
+ rate: float,
195
+ commercial_name: CommercialName,
196
+ ) -> float:
197
+ """
198
+ Calculate the NTN-B quotation in base 100 using Anbima rules.
199
+
200
+ Args:
201
+ settlement (DateScalar): The settlement date of the operation.
202
+ maturity (DateScalar): The maturity date of the NTN-B bond.
203
+ rate (float): The discount rate used to calculate the present value of
204
+ the cash flows, which is the yield to maturity (YTM) of the NTN-B.
205
+ commercial_name (CommercialName): The commercial name of the NTN-B1 bond
206
+ (Renda+ or Educa+).
207
+
208
+ Returns:
209
+ float: The NTN-B quotation truncated to 6 decimal places.
210
+
211
+ References:
212
+ - https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
213
+
214
+ Examples:
215
+ >>> from pyield import ntnb1
216
+ >>> r_mais = ntnb1.CommercialName.RENDA_MAIS
217
+ >>> ntnb1.quotation("18-06-2025", "15-12-2084", 0.07010, r_mais)
218
+ 0.038332
219
+ """
220
+ cf_df = cash_flows(settlement, maturity, commercial_name)
221
+ cf_dates = cf_df["PaymentDate"]
222
+ cf_values = cf_df["CashFlow"]
223
+
224
+ # Calculate the number of business days between settlement and cash flow dates
225
+ b_days = bday.count(settlement, cf_dates)
226
+
227
+ # Calculate the number of periods truncated as per Anbima rules
228
+ num_of_years = bt.truncate(b_days / 252, 14)
229
+
230
+ discount_factor = (1 + rate) ** num_of_years
231
+
232
+ # Calculate the present value of each cash flow (DCF) rounded as per Anbima rules
233
+ cf_present_value = (cf_values / discount_factor).round(10)
234
+
235
+ # Return the quotation (the dcf sum) truncated as per Anbima rules
236
+ return bt.truncate(cf_present_value.sum(), 6)
237
+
238
+
239
+ def price(
240
+ vna: float,
241
+ quotation: float,
242
+ ) -> float:
243
+ """
244
+ Calculate the NTN-B1 price using Brazilian Treasury rules.
245
+
246
+ Args:
247
+ vna (float): The nominal value of the NTN-B bond.
248
+ quotation (float): The NTN-B quotation in base 100.
249
+
250
+ Returns:
251
+ float: The NTN-B1 price truncated to 6 decimal places.
252
+
253
+ References:
254
+ - SEI Proccess 17944.005214/2024-09
255
+
256
+ Examples:
257
+ >>> from pyield import ntnb1
258
+ >>> ntnb1.price(4299.160173, 99.3651 / 100)
259
+ 4271.864805
260
+ >>> ntnb1.price(4315.498383, 100.6409 / 100)
261
+ 4343.156412
262
+ """
263
+ if has_nullable_args(vna, quotation):
264
+ return float("nan")
265
+ return bt.truncate(vna * quotation, 6)
266
+
267
+
268
+ def duration(
269
+ settlement: DateLike,
270
+ maturity: DateLike,
271
+ rate: float,
272
+ commercial_name: CommercialName,
273
+ ) -> float:
274
+ """
275
+ Calculate the Macaulay duration of the NTN-B bond in business years.
276
+
277
+ Args:
278
+ settlement (DateScalar): The settlement date of the operation.
279
+ maturity (DateScalar): The maturity date of the NTN-B bond.
280
+ rate (float): The discount rate used to calculate the duration.
281
+ commercial_name (CommercialName): The commercial name of the NTN-B1 bond
282
+ (Renda+ or Educa+).
283
+
284
+ Returns:
285
+ float: The Macaulay duration of the NTN-B bond in business years.
286
+
287
+ Examples:
288
+ >>> from pyield import ntnb1
289
+ >>> r_mais = ntnb1.CommercialName.RENDA_MAIS
290
+ >>> ntnb1.duration("23-06-2025", "15-12-2084", 0.0686, r_mais)
291
+ 47.10493458167134
292
+ """
293
+ # Return NaN if any input is nullable
294
+ if has_nullable_args(settlement, maturity, rate, commercial_name):
295
+ return float("nan")
296
+
297
+ df = cash_flows(settlement, maturity, commercial_name)
298
+ s_byears = bday.count(settlement, df["PaymentDate"]) / 252
299
+ s_dcf = df["CashFlow"] / (1 + rate) ** s_byears
300
+ duration = (s_dcf * s_byears).sum() / s_dcf.sum()
301
+
302
+ # Truncate duration to 14 decimal places for result reproducibility
303
+ return bt.truncate(duration, 14)
304
+
305
+
306
+ def dv01(
307
+ settlement: DateLike,
308
+ maturity: DateLike,
309
+ rate: float,
310
+ vna: float,
311
+ commercial_name: CommercialName = CommercialName.RENDA_MAIS,
312
+ ) -> float:
313
+ """
314
+ Calculate the DV01 (Dollar Value of 01) for an NTN-B1 in R$.
315
+
316
+ Represents the price change in R$ for a 1 basis point (0.01%) increase in yield.
317
+
318
+ Args:
319
+ settlement (DateScalar): The settlement date in 'DD-MM-YYYY' format
320
+ or a pandas Timestamp.
321
+ maturity (DateScalar): The maturity date in 'DD-MM-YYYY' format or
322
+ a pandas Timestamp.
323
+ rate (float): The discount rate used to calculate the present value of
324
+ the cash flows, which is the yield to maturity (YTM) of the NTN-B.
325
+ vna (float): The nominal value of the NTN-B bond.
326
+ commercial_name (CommercialName): The commercial name of the NTN-B1 bond
327
+
328
+ Returns:
329
+ float: The DV01 value, representing the price change for a 1 basis point
330
+ increase in yield.
331
+
332
+ Examples:
333
+ >>> from pyield import ntnb1
334
+ >>> r_mais = ntnb1.CommercialName.RENDA_MAIS
335
+ >>> ntnb1.dv01("23-06-2025", "15-12-2084", 0.0686, 4299.160173, r_mais)
336
+ 0.7738490000000127
337
+ """
338
+ if has_nullable_args(settlement, maturity, rate, vna, commercial_name):
339
+ return float("nan")
340
+
341
+ quotation1 = quotation(settlement, maturity, rate, commercial_name)
342
+ quotation2 = quotation(settlement, maturity, rate + 0.0001, commercial_name)
343
+ price1 = price(vna, quotation1)
344
+ price2 = price(vna, quotation2)
345
+ return price1 - price2
@@ -0,0 +1,80 @@
1
+ from pyield import bday
2
+ from pyield.tn import tools
3
+ from pyield.types import DateLike, has_nullable_args
4
+
5
+
6
+ def price(
7
+ settlement: DateLike,
8
+ maturity: DateLike,
9
+ rate: float,
10
+ face_value: float,
11
+ ) -> float:
12
+ """
13
+ Calculate the NTN-B PRINCIPAL price using Anbima rules.
14
+
15
+ Args:
16
+ settlement (DateScalar): The settlement date in 'DD-MM-YYYY' format
17
+ or a pandas Timestamp.
18
+ maturity (DateScalar): The maturity date in 'DD-MM-YYYY' format or
19
+ a pandas Timestamp.
20
+ rate (float): The discount rate used to calculate the present value of
21
+ the cash flows, which is the yield to maturity (YTM) of the NTN-F.
22
+ face_value (float): The face value of the bond (VNA).
23
+ Returns:
24
+ float: The NTN-B PRINCIPAL price using Anbima rules.
25
+
26
+ References:
27
+ - https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
28
+
29
+ Examples:
30
+ >>> from pyield import ntnbprinc
31
+ >>> ntnbprinc.price("02-12-2025", "15-05-2029", 0.0777, 4567.033825)
32
+ 3537.763157
33
+ """
34
+ if has_nullable_args(settlement, maturity, rate, face_value):
35
+ return float("nan")
36
+
37
+ # Calculate the number of business days between settlement and cash flow dates
38
+ bdays = bday.count(settlement, maturity)
39
+
40
+ # Calculate the number of periods truncated as per Anbima rule
41
+ num_of_years = tools.truncate(bdays / 252, 14)
42
+
43
+ discount_factor = (1 + rate) ** num_of_years
44
+
45
+ # Truncate the price to 6 decimal places as per Anbima rules
46
+ return tools.truncate(face_value / discount_factor, 6)
47
+
48
+
49
+ def dv01(
50
+ settlement: DateLike,
51
+ maturity: DateLike,
52
+ rate: float,
53
+ face_value: float,
54
+ ) -> float:
55
+ """
56
+ Calculate the DV01 (Dollar Value of 01) for an LTN in R$.
57
+
58
+ Represents the price change in R$ for a 1 basis point (0.01%) increase in yield.
59
+
60
+ Args:
61
+ settlement (DateScalar): The settlement date in 'DD-MM-YYYY' format
62
+ or a pandas Timestamp.
63
+ maturity (DateScalar): The maturity date in 'DD-MM-YYYY' format or
64
+ a pandas Timestamp.
65
+ rate (float): The discount rate used to calculate the present value of
66
+ the cash flows, which is the yield to maturity (YTM) of the LTN.
67
+ face_value (float): The face value of the bond (VNA).
68
+
69
+ Returns:
70
+ float: The DV01 value, representing the price change for a 1 basis point
71
+ increase in yield.
72
+
73
+ Examples:
74
+ >>> from pyield import ntnbprinc as bp
75
+ >>> bp.dv01("02-12-2025", "15-05-2029", 0.0777, 4567.033825)
76
+ 1.1200559999997495
77
+ """
78
+ price1 = price(settlement, maturity, rate, face_value)
79
+ price2 = price(settlement, maturity, rate + 0.0001, face_value)
80
+ return price1 - price2
@@ -1 +0,0 @@
1
- __version__ = "0.40.7"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes