PYield 0.31.0__tar.gz → 0.31.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {pyield-0.31.0 → pyield-0.31.2}/PKG-INFO +47 -44
  2. {pyield-0.31.0 → pyield-0.31.2}/README.md +46 -43
  3. pyield-0.31.2/pyield/__about__.py +1 -0
  4. {pyield-0.31.0 → pyield-0.31.2}/pyield/__init__.py +2 -1
  5. {pyield-0.31.0 → pyield-0.31.2}/pyield/anbima/__init__.py +2 -1
  6. {pyield-0.31.0 → pyield-0.31.2}/pyield/anbima/ettj.py +58 -25
  7. {pyield-0.31.0 → pyield-0.31.2}/pyield/anbima/tpf.py +2 -1
  8. {pyield-0.31.0 → pyield-0.31.2}/pyield/tpf/lft.py +7 -6
  9. {pyield-0.31.0 → pyield-0.31.2}/pyield/tpf/ltn.py +16 -10
  10. {pyield-0.31.0 → pyield-0.31.2}/pyield/tpf/ntnb.py +36 -15
  11. pyield-0.31.2/pyield/tpf/ntnc.py +276 -0
  12. {pyield-0.31.0 → pyield-0.31.2}/pyield/tpf/ntnf.py +27 -25
  13. {pyield-0.31.0 → pyield-0.31.2}/pyproject.toml +1 -0
  14. pyield-0.31.0/pyield/__about__.py +0 -1
  15. {pyield-0.31.0 → pyield-0.31.2}/.gitignore +0 -0
  16. {pyield-0.31.0 → pyield-0.31.2}/LICENSE +0 -0
  17. {pyield-0.31.0 → pyield-0.31.2}/pyield/anbima/ima.py +0 -0
  18. {pyield-0.31.0 → pyield-0.31.2}/pyield/anbima/imaq.py +0 -0
  19. {pyield-0.31.0 → pyield-0.31.2}/pyield/anbima/ipca.py +0 -0
  20. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/__init__.py +0 -0
  21. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/di.py +0 -0
  22. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/di_over.py +0 -0
  23. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/futures/__init__.py +0 -0
  24. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/futures/common.py +0 -0
  25. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/futures/historical.py +0 -0
  26. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/futures/intraday.py +0 -0
  27. {pyield-0.31.0 → pyield-0.31.2}/pyield/b3/futures/xml.py +0 -0
  28. {pyield-0.31.0 → pyield-0.31.2}/pyield/bc/__init__.py +0 -0
  29. {pyield-0.31.0 → pyield-0.31.2}/pyield/bc/auction.py +0 -0
  30. {pyield-0.31.0 → pyield-0.31.2}/pyield/bc/bcdata.py +0 -0
  31. {pyield-0.31.0 → pyield-0.31.2}/pyield/bc/ptax.py +0 -0
  32. {pyield-0.31.0 → pyield-0.31.2}/pyield/bc/repo.py +0 -0
  33. {pyield-0.31.0 → pyield-0.31.2}/pyield/bc/trade.py +0 -0
  34. {pyield-0.31.0 → pyield-0.31.2}/pyield/bc/vna.py +0 -0
  35. {pyield-0.31.0 → pyield-0.31.2}/pyield/bday.py +0 -0
  36. {pyield-0.31.0 → pyield-0.31.2}/pyield/conftest.py +0 -0
  37. {pyield-0.31.0 → pyield-0.31.2}/pyield/data_cache.py +0 -0
  38. {pyield-0.31.0 → pyield-0.31.2}/pyield/date_converter.py +0 -0
  39. {pyield-0.31.0 → pyield-0.31.2}/pyield/forwards.py +0 -0
  40. {pyield-0.31.0 → pyield-0.31.2}/pyield/holidays/__init__.py +0 -0
  41. {pyield-0.31.0 → pyield-0.31.2}/pyield/holidays/br_holidays_new.txt +0 -0
  42. {pyield-0.31.0 → pyield-0.31.2}/pyield/holidays/br_holidays_old.txt +0 -0
  43. {pyield-0.31.0 → pyield-0.31.2}/pyield/holidays/brholidays.py +0 -0
  44. {pyield-0.31.0 → pyield-0.31.2}/pyield/ibge/__init__.py +0 -0
  45. {pyield-0.31.0 → pyield-0.31.2}/pyield/ibge/ipca.py +0 -0
  46. {pyield-0.31.0 → pyield-0.31.2}/pyield/interpolator.py +0 -0
  47. {pyield-0.31.0 → pyield-0.31.2}/pyield/py.typed +0 -0
  48. {pyield-0.31.0 → pyield-0.31.2}/pyield/retry.py +0 -0
  49. {pyield-0.31.0 → pyield-0.31.2}/pyield/tpf/__init__.py +0 -0
  50. {pyield-0.31.0 → pyield-0.31.2}/pyield/tpf/tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PYield
3
- Version: 0.31.0
3
+ Version: 0.31.2
4
4
  Summary: A Python library for analysis of fixed income instruments in Brazil
5
5
  Project-URL: Source, https://github.com/crdcj/PYield
6
6
  Author-email: Carlos Carvalho <cr.cj@outlook.com>
@@ -49,8 +49,6 @@ PYield is a Python library designed for the analysis of Brazilian fixed income i
49
49
 
50
50
  Documentation: [https://crdcj.github.io/PYield/](https://crdcj.github.io/PYield/)
51
51
 
52
- Source Code: [https://github.com/crdcj/PYield](https://github.com/crdcj/PYield)
53
-
54
52
  ## Key Features
55
53
 
56
54
  - **Data Collection**: Automated fetching of data from ANBIMA and B3.
@@ -103,38 +101,39 @@ date = pd.to_datetime("05-31-2024", format="%m-%d-%Y")
103
101
  ```python
104
102
  >>> from pyield import ntnb, ntnf, ltn
105
103
 
104
+ # Get ANBIMA data for a given date
105
+ >>> ltn.data("23-08-2024")
106
+ ReferenceDate BondType MaturityDate IndicativeRate Price
107
+ 0 2024-08-23 LTN 2024-10-01 0.104416 989.415342
108
+ 1 2024-08-23 LTN 2025-01-01 0.107171 964.293046
109
+ 2 2024-08-23 LTN 2025-04-01 0.110866 938.943013
110
+ 3 2024-08-23 LTN 2025-07-01 0.113032 913.849158
111
+ 4 2024-08-23 LTN 2025-10-01 0.114374 887.394285
112
+ 5 2024-08-23 LTN 2026-01-01 0.114654 863.026594
113
+ 6 2024-08-23 LTN 2026-04-01 0.114997 840.232741
114
+ 7 2024-08-23 LTN 2026-07-01 0.115265 818.020491
115
+ 8 2024-08-23 LTN 2026-10-01 0.115357 795.185488
116
+ 9 2024-08-23 LTN 2027-07-01 0.115335 733.981131
117
+ 10 2024-08-23 LTN 2028-01-01 0.115694 693.647778
118
+ 11 2024-08-23 LTN 2028-07-01 0.116417 655.6398
119
+ 12 2024-08-23 LTN 2030-01-01 0.117436 554.331151
120
+
106
121
  # Calculate the quotation of a NTN-B bond as per ANBIMA's rules
107
122
  >>> ntnb.quotation("31-05-2024", "15-05-2035", 0.061490)
108
123
  99.3651
109
124
  >>> ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
110
125
  99.5341
111
126
 
112
- # Calculate the DI Spread of NTN-F bonds in a given date
113
- >>> ntnf.di_spreads("17-07-2024")
114
- 2025-01-01 -2.31
115
- 2027-01-01 -1.88
116
- 2029-01-01 -3.26
117
- 2031-01-01 3.61
118
- 2033-01-01 -3.12
119
- 2035-01-01 -1.00
120
- Name: DISpread, dtype: Float64
121
-
122
- # Get ANBIMA's indicative rates for LTN bonds
123
- >>> ltn.anbima_rates("17-07-2024")
124
- 2024-10-01 0.104236
125
- 2025-01-01 0.105400
126
- 2025-04-01 0.107454
127
- 2025-07-01 0.108924
128
- 2025-10-01 0.110751
129
- 2026-01-01 0.111753
130
- 2026-04-01 0.112980
131
- 2026-07-01 0.113870
132
- 2026-10-01 0.114592
133
- 2027-07-01 0.116090
134
- 2028-01-01 0.117160
135
- 2028-07-01 0.118335
136
- 2030-01-01 0.120090
137
- Name: IndicativeRate, dtype: Float64
127
+ # Calculate the DI Spread of NTN-F and LTN bonds in a given date
128
+ >>> ntnf.di_spreads("23-08-2024")
129
+ MaturityDate DISpread
130
+ 0 2025-01-01 -5.38
131
+ 1 2027-01-01 4.39
132
+ 2 2029-01-01 7.37
133
+ 3 2031-01-01 12.58
134
+ 4 2033-01-01 7.67
135
+ 5 2035-01-01 12.76
136
+
138
137
  ```
139
138
 
140
139
  ### Business Days Tools (Brazilian holidays are automatically considered)
@@ -162,22 +161,11 @@ Timestamp('2023-12-29 00:00:00')
162
161
  0 2023-12-29
163
162
  1 2024-01-02
164
163
  2 2024-01-03
165
- dtype: datetime64[ns]
166
164
  ```
167
165
 
168
166
  ### Futures Data
169
167
  ```python
170
168
  >>> import pyield as yd
171
- # Fetch current DI Futures data from B3 (15 minutes delay)
172
- >>> yd.futures(contract_code="DI1")
173
- LastUpdatee TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
174
- 2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
175
- 2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
176
- 2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
177
- ... ... ... ... ... ... ... ... ...
178
- 2024-04-21 13:37:39 DI1F37 2037-01-02 3183 ... <NA> <NA> 0.11600 <NA>
179
- 2024-04-21 13:37:39 DI1F38 2038-01-04 3432 ... <NA> <NA> 0.11600 <NA>
180
- 2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
181
169
 
182
170
  # Fetch historical DI Futures data from B3
183
171
  >>> yd.futures(contract_code="DI1", date='08-03-2024')
@@ -189,20 +177,35 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
189
177
  2024-03-08 DI1F37 2037-01-02 3213 ... <NA> <NA> <NA> 10.859
190
178
  2024-03-08 DI1F38 2038-01-04 3462 ... <NA> <NA> <NA> 10.859
191
179
  2024-03-08 DI1F39 2039-01-03 3713 ... <NA> <NA> <NA> 10.85
180
+
181
+ # Fetch current DI Futures data from B3 (15 minutes delay)
182
+ >>> yd.futures(contract_code="DI1", date="21-03-2024") # when the date used is the current date and market is open
183
+ LastUpdatee TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
184
+ 2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
185
+ 2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
186
+ 2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
187
+ ... ... ... ... ... ... ... ... ...
188
+ 2024-04-21 13:37:39 DI1F37 2037-01-02 3183 ... <NA> <NA> 0.11600 <NA>
189
+ 2024-04-21 13:37:39 DI1F38 2038-01-04 3432 ... <NA> <NA> 0.11600 <NA>
190
+ 2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
192
191
  ```
193
192
 
194
193
  ### Indicators Data
195
194
  ```python
196
195
  >>> from pyield import bc
197
- # Fetch the SELIC target rate from the Central Bank of Brazil
198
- >>> bc.selic_over("26-01-2025") # No data on 26-01-2025 (sunday)
196
+
197
+ # Fetch the SELIC target rates from the Central Bank of Brazil
198
+ >>> bc.selic_over_series("26-01-2025", "30-01-2025") # No data on 26-01-2025 (sunday)
199
199
  Date Value
200
200
  0 2025-01-27 0.1215
201
201
  1 2025-01-28 0.1215
202
202
  2 2025-01-29 0.1215
203
203
  3 2025-01-30 0.1315
204
- 4 2025-01-31 0.1315
205
- ...
204
+
205
+ # Fetch the SELIC target rate for a specific date
206
+ >>> bc.selic_over("27-01-2025")
207
+ Date Value
208
+ 0.1215 # 12.15%
206
209
  ```
207
210
 
208
211
  ### Projections Data
@@ -8,8 +8,6 @@ PYield is a Python library designed for the analysis of Brazilian fixed income i
8
8
 
9
9
  Documentation: [https://crdcj.github.io/PYield/](https://crdcj.github.io/PYield/)
10
10
 
11
- Source Code: [https://github.com/crdcj/PYield](https://github.com/crdcj/PYield)
12
-
13
11
  ## Key Features
14
12
 
15
13
  - **Data Collection**: Automated fetching of data from ANBIMA and B3.
@@ -62,38 +60,39 @@ date = pd.to_datetime("05-31-2024", format="%m-%d-%Y")
62
60
  ```python
63
61
  >>> from pyield import ntnb, ntnf, ltn
64
62
 
63
+ # Get ANBIMA data for a given date
64
+ >>> ltn.data("23-08-2024")
65
+ ReferenceDate BondType MaturityDate IndicativeRate Price
66
+ 0 2024-08-23 LTN 2024-10-01 0.104416 989.415342
67
+ 1 2024-08-23 LTN 2025-01-01 0.107171 964.293046
68
+ 2 2024-08-23 LTN 2025-04-01 0.110866 938.943013
69
+ 3 2024-08-23 LTN 2025-07-01 0.113032 913.849158
70
+ 4 2024-08-23 LTN 2025-10-01 0.114374 887.394285
71
+ 5 2024-08-23 LTN 2026-01-01 0.114654 863.026594
72
+ 6 2024-08-23 LTN 2026-04-01 0.114997 840.232741
73
+ 7 2024-08-23 LTN 2026-07-01 0.115265 818.020491
74
+ 8 2024-08-23 LTN 2026-10-01 0.115357 795.185488
75
+ 9 2024-08-23 LTN 2027-07-01 0.115335 733.981131
76
+ 10 2024-08-23 LTN 2028-01-01 0.115694 693.647778
77
+ 11 2024-08-23 LTN 2028-07-01 0.116417 655.6398
78
+ 12 2024-08-23 LTN 2030-01-01 0.117436 554.331151
79
+
65
80
  # Calculate the quotation of a NTN-B bond as per ANBIMA's rules
66
81
  >>> ntnb.quotation("31-05-2024", "15-05-2035", 0.061490)
67
82
  99.3651
68
83
  >>> ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
69
84
  99.5341
70
85
 
71
- # Calculate the DI Spread of NTN-F bonds in a given date
72
- >>> ntnf.di_spreads("17-07-2024")
73
- 2025-01-01 -2.31
74
- 2027-01-01 -1.88
75
- 2029-01-01 -3.26
76
- 2031-01-01 3.61
77
- 2033-01-01 -3.12
78
- 2035-01-01 -1.00
79
- Name: DISpread, dtype: Float64
80
-
81
- # Get ANBIMA's indicative rates for LTN bonds
82
- >>> ltn.anbima_rates("17-07-2024")
83
- 2024-10-01 0.104236
84
- 2025-01-01 0.105400
85
- 2025-04-01 0.107454
86
- 2025-07-01 0.108924
87
- 2025-10-01 0.110751
88
- 2026-01-01 0.111753
89
- 2026-04-01 0.112980
90
- 2026-07-01 0.113870
91
- 2026-10-01 0.114592
92
- 2027-07-01 0.116090
93
- 2028-01-01 0.117160
94
- 2028-07-01 0.118335
95
- 2030-01-01 0.120090
96
- Name: IndicativeRate, dtype: Float64
86
+ # Calculate the DI Spread of NTN-F and LTN bonds in a given date
87
+ >>> ntnf.di_spreads("23-08-2024")
88
+ MaturityDate DISpread
89
+ 0 2025-01-01 -5.38
90
+ 1 2027-01-01 4.39
91
+ 2 2029-01-01 7.37
92
+ 3 2031-01-01 12.58
93
+ 4 2033-01-01 7.67
94
+ 5 2035-01-01 12.76
95
+
97
96
  ```
98
97
 
99
98
  ### Business Days Tools (Brazilian holidays are automatically considered)
@@ -121,22 +120,11 @@ Timestamp('2023-12-29 00:00:00')
121
120
  0 2023-12-29
122
121
  1 2024-01-02
123
122
  2 2024-01-03
124
- dtype: datetime64[ns]
125
123
  ```
126
124
 
127
125
  ### Futures Data
128
126
  ```python
129
127
  >>> import pyield as yd
130
- # Fetch current DI Futures data from B3 (15 minutes delay)
131
- >>> yd.futures(contract_code="DI1")
132
- LastUpdatee TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
133
- 2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
134
- 2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
135
- 2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
136
- ... ... ... ... ... ... ... ... ...
137
- 2024-04-21 13:37:39 DI1F37 2037-01-02 3183 ... <NA> <NA> 0.11600 <NA>
138
- 2024-04-21 13:37:39 DI1F38 2038-01-04 3432 ... <NA> <NA> 0.11600 <NA>
139
- 2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
140
128
 
141
129
  # Fetch historical DI Futures data from B3
142
130
  >>> yd.futures(contract_code="DI1", date='08-03-2024')
@@ -148,20 +136,35 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
148
136
  2024-03-08 DI1F37 2037-01-02 3213 ... <NA> <NA> <NA> 10.859
149
137
  2024-03-08 DI1F38 2038-01-04 3462 ... <NA> <NA> <NA> 10.859
150
138
  2024-03-08 DI1F39 2039-01-03 3713 ... <NA> <NA> <NA> 10.85
139
+
140
+ # Fetch current DI Futures data from B3 (15 minutes delay)
141
+ >>> yd.futures(contract_code="DI1", date="21-03-2024") # when the date used is the current date and market is open
142
+ LastUpdatee TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
143
+ 2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
144
+ 2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
145
+ 2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
146
+ ... ... ... ... ... ... ... ... ...
147
+ 2024-04-21 13:37:39 DI1F37 2037-01-02 3183 ... <NA> <NA> 0.11600 <NA>
148
+ 2024-04-21 13:37:39 DI1F38 2038-01-04 3432 ... <NA> <NA> 0.11600 <NA>
149
+ 2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
151
150
  ```
152
151
 
153
152
  ### Indicators Data
154
153
  ```python
155
154
  >>> from pyield import bc
156
- # Fetch the SELIC target rate from the Central Bank of Brazil
157
- >>> bc.selic_over("26-01-2025") # No data on 26-01-2025 (sunday)
155
+
156
+ # Fetch the SELIC target rates from the Central Bank of Brazil
157
+ >>> bc.selic_over_series("26-01-2025", "30-01-2025") # No data on 26-01-2025 (sunday)
158
158
  Date Value
159
159
  0 2025-01-27 0.1215
160
160
  1 2025-01-28 0.1215
161
161
  2 2025-01-29 0.1215
162
162
  3 2025-01-30 0.1315
163
- 4 2025-01-31 0.1315
164
- ...
163
+
164
+ # Fetch the SELIC target rate for a specific date
165
+ >>> bc.selic_over("27-01-2025")
166
+ Date Value
167
+ 0.1215 # 12.15%
165
168
  ```
166
169
 
167
170
  ### Projections Data
@@ -0,0 +1 @@
1
+ __version__ = "0.31.2"
@@ -6,7 +6,7 @@ from pyield.b3 import futures
6
6
  from pyield.b3.di import DIFutures
7
7
  from pyield.forwards import forward_rates
8
8
  from pyield.interpolator import Interpolator
9
- from pyield.tpf import lft, ltn, ntnb, ntnf
9
+ from pyield.tpf import lft, ltn, ntnb, ntnc, ntnf
10
10
 
11
11
  __all__ = [
12
12
  "__version__",
@@ -20,6 +20,7 @@ __all__ = [
20
20
  "lft",
21
21
  "ltn",
22
22
  "ntnb",
23
+ "ntnc",
23
24
  "ntnf",
24
25
  "bc",
25
26
  "b3",
@@ -1,4 +1,4 @@
1
- from pyield.anbima.ettj import last_ettj
1
+ from pyield.anbima.ettj import intraday_ettj, last_ettj
2
2
  from pyield.anbima.ima import last_ima
3
3
  from pyield.anbima.imaq import imaq
4
4
  from pyield.anbima.ipca import ipca_projection
@@ -12,4 +12,5 @@ __all__ = [
12
12
  "tpf_data",
13
13
  "tpf_fixed_rate_maturities",
14
14
  "last_ettj",
15
+ "intraday_ettj",
15
16
  ]
@@ -4,11 +4,13 @@ from io import StringIO
4
4
  import pandas as pd
5
5
  import requests
6
6
 
7
- from pyield.forwards import forward_rates
8
7
  from pyield.retry import default_retry
9
8
 
10
9
  logger = logging.getLogger(__name__)
11
10
  LAST_ETTJ_URL = "https://www.anbima.com.br/informacoes/est-termo/CZ-down.asp"
11
+ INTRADAY_ETTJ_URL = (
12
+ "https://www.anbima.com.br/informacoes/curvas-intradiarias/cIntra-down.asp"
13
+ )
12
14
 
13
15
  # Anbima ETTJ data has 4 decimal places in percentage values
14
16
  # We will round to 6 decimal places to avoid floating point errors
@@ -76,31 +78,12 @@ def _process_df(df: pd.DataFrame) -> pd.DataFrame:
76
78
  df["nominal_rate"] = (df["nominal_rate"] / 100).round(ROUND_DIGITS)
77
79
  df["implied_inflation"] = (df["implied_inflation"] / 100).round(ROUND_DIGITS)
78
80
 
79
- df["real_rate_fwd"] = forward_rates(
80
- business_days=df["vertex"],
81
- zero_rates=df["real_rate"],
82
- groupby_dates=df["date"],
83
- )
84
- df["nominal_rate_fwd"] = forward_rates(
85
- business_days=df["vertex"],
86
- zero_rates=df["nominal_rate"],
87
- groupby_dates=df["date"],
88
- )
89
- df["implied_inflation_fwd"] = forward_rates(
90
- business_days=df["vertex"],
91
- zero_rates=df["implied_inflation"],
92
- groupby_dates=df["date"],
93
- )
94
-
95
81
  column_order = [
96
82
  "date",
97
83
  "vertex",
98
84
  "nominal_rate",
99
85
  "real_rate",
100
86
  "implied_inflation",
101
- "nominal_rate_fwd",
102
- "real_rate_fwd",
103
- "implied_inflation_fwd",
104
87
  ]
105
88
  df = df[column_order].copy()
106
89
 
@@ -113,8 +96,7 @@ def last_ettj() -> pd.DataFrame:
113
96
 
114
97
  This function fetches the most recent yield curve data published by ANBIMA,
115
98
  containing real rates (IPCA-indexed), nominal rates, and implied inflation
116
- at various vertices (time points). Both spot rates and forward rates are
117
- calculated and included in the returned DataFrame.
99
+ at various vertices (time points).
118
100
 
119
101
  Returns:
120
102
  pd.DataFrame: A DataFrame containing the latest ETTJ data.
@@ -125,9 +107,6 @@ def last_ettj() -> pd.DataFrame:
125
107
  - nominal_rate: Zero-coupon nominal interest rate
126
108
  - real_rate: Zero-coupon real interest rate (IPCA-indexed)
127
109
  - implied_inflation: Implied inflation rate (break-even inflation)
128
- - nominal_rate_fwd: Forward nominal interest rate
129
- - real_rate_fwd: Forward real interest rate
130
- - implied_inflation_fwd: Forward implied inflation rate
131
110
 
132
111
  Note:
133
112
  All rates are expressed in decimal format (e.g., 0.12 for 12%).
@@ -135,3 +114,57 @@ def last_ettj() -> pd.DataFrame:
135
114
  text = _get_last_content()
136
115
  df = _convert_text_to_df(text)
137
116
  return _process_df(df)
117
+
118
+
119
+ def intraday_ettj() -> pd.DataFrame:
120
+ """
121
+ Retrieves and processes the intraday Brazilian yield curve data from ANBIMA.
122
+
123
+ This function fetches the most recent intraday yield curve data published by ANBIMA,
124
+ containing real rates (IPCA-indexed), nominal rates, and implied inflation
125
+ at various vertices (time points). The curve is published at around 12:30 PM BRT.
126
+
127
+ Returns:
128
+ pd.DataFrame: A DataFrame containing the intraday ETTJ data.
129
+
130
+ DataFrame columns:
131
+ - date: Reference date of the yield curve
132
+ - vertex: Time point in business days
133
+ - nominal_rate: Zero-coupon nominal interest rate
134
+ - real_rate: Zero-coupon real interest rate (IPCA-indexed)
135
+ - implied_inflation: Implied inflation rate (break-even inflation)
136
+
137
+ Note:
138
+ All rates are expressed in decimal format (e.g., 0.12 for 12%).
139
+ """
140
+ text = requests.get(INTRADAY_ETTJ_URL).text
141
+ text_parts = text.split("ETTJ IPCA (%a.a./252)")
142
+
143
+ nominal_text = text_parts[0]
144
+ lines = nominal_text.splitlines()
145
+ date_str = lines[1]
146
+ date = pd.to_datetime(date_str, format="%d/%m/%Y")
147
+ df_text = "\n".join(lines[2:])
148
+ df_nominal = pd.read_csv(StringIO(df_text), sep=";", decimal=",", thousands=".")
149
+ df_nominal = df_nominal.drop(columns=["Fechamento D -1"])
150
+ df_nominal = df_nominal.rename(columns={"D0": "nominal_rate"})
151
+
152
+ real_text = text_parts[1]
153
+ lines = real_text.splitlines()
154
+ df_text = "\n".join(lines[2:])
155
+ df_real = pd.read_csv(StringIO(df_text), sep=";", decimal=",", thousands=".")
156
+ df_real = df_real.drop(columns=["Fechamento D -1"])
157
+ df_real = df_real.rename(columns={"D0": "real_rate"})
158
+
159
+ df = pd.merge(df_nominal, df_real, on="Vertices", how="right")
160
+ df = df.rename(columns={"Vertices": "vertex"})
161
+
162
+ # Divide float columns by 100 and round to 6 decimal places
163
+ df["real_rate"] = (df["real_rate"] / 100).round(ROUND_DIGITS)
164
+ df["nominal_rate"] = (df["nominal_rate"] / 100).round(ROUND_DIGITS)
165
+ df["implied_inflation"] = (df["nominal_rate"] + 1) / (df["real_rate"] + 1) - 1
166
+ df["implied_inflation"] = df["implied_inflation"].round(ROUND_DIGITS)
167
+
168
+ df["date"] = date
169
+ column_order = ["date", "vertex", "nominal_rate", "real_rate", "implied_inflation"]
170
+ return df[column_order].copy()
@@ -81,7 +81,8 @@ def _process_raw_df(df_raw: pd.DataFrame) -> pd.DataFrame:
81
81
  def tpf_web_data(
82
82
  date: DateScalar, bond_type: str | BOND_TYPES | None = None
83
83
  ) -> pd.DataFrame:
84
- """Fetch and process TPF secondary market data from ANBIMA website.
84
+ """Fetch and process TPF secondary market data directly from the ANBIMA website.
85
+ Only the last 5 days of data are available in the ANBIMA website.
85
86
 
86
87
  This function retrieves bond market data from the ANBIMA website for a
87
88
  specified reference date. It handles different file formats based on the date
@@ -3,7 +3,7 @@ import pandas as pd
3
3
  from pyield import anbima, bday
4
4
  from pyield import date_converter as dc
5
5
  from pyield.date_converter import DateScalar
6
- from pyield.tpf import tools as tt
6
+ from pyield.tpf import tools
7
7
 
8
8
 
9
9
  def data(date: DateScalar) -> pd.DataFrame:
@@ -22,8 +22,8 @@ def data(date: DateScalar) -> pd.DataFrame:
22
22
  - Price: The price of the LFT bond.
23
23
 
24
24
  Examples:
25
-
26
- >>> yd.lft.data("23-08-2024")
25
+ >>> from pyield import lft
26
+ >>> lft.data("23-08-2024")
27
27
  ReferenceDate BondType MaturityDate IndicativeRate Price
28
28
  0 2024-08-23 LFT 2024-09-01 0.000272 15252.158852
29
29
  1 2024-08-23 LFT 2025-03-01 -0.000418 15255.605864
@@ -61,7 +61,8 @@ def quotation(
61
61
 
62
62
  Examples:
63
63
  Calculate the quotation of a LFT bond with a 0.02 yield rate:
64
- >>> yd.lft.quotation(
64
+ >>> from pyield import lft
65
+ >>> lft.quotation(
65
66
  ... settlement="24-07-2024",
66
67
  ... maturity="01-09-2030",
67
68
  ... rate=0.001717, # 0.1717%
@@ -76,11 +77,11 @@ def quotation(
76
77
  bdays = bday.count(settlement, maturity)
77
78
 
78
79
  # Calculate the number of periods truncated as per Anbima rules
79
- num_of_years = tt.truncate(bdays / 252, 14)
80
+ num_of_years = tools.truncate(bdays / 252, 14)
80
81
 
81
82
  discount_factor = 1 / (1 + rate) ** num_of_years
82
83
 
83
- return tt.truncate(100 * discount_factor, 4)
84
+ return tools.truncate(100 * discount_factor, 4)
84
85
 
85
86
 
86
87
  def premium(lft_rate: float, selic_over: float) -> float:
@@ -4,7 +4,7 @@ from pyield import anbima, bday
4
4
  from pyield import date_converter as dc
5
5
  from pyield.b3 import di
6
6
  from pyield.date_converter import DateScalar
7
- from pyield.tpf import tools as tt
7
+ from pyield.tpf import tools
8
8
 
9
9
  FACE_VALUE = 1000
10
10
 
@@ -20,7 +20,8 @@ def data(date: DateScalar) -> pd.DataFrame:
20
20
  pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
21
21
 
22
22
  Examples:
23
- >>> yd.ltn.data("23-08-2024")
23
+ >>> from pyield import ltn
24
+ >>> ltn.data("23-08-2024")
24
25
  ReferenceDate BondType MaturityDate IndicativeRate Price
25
26
  0 2024-08-23 LTN 2024-10-01 0.104416 989.415342
26
27
  1 2024-08-23 LTN 2025-01-01 0.107171 964.293046
@@ -51,7 +52,8 @@ def maturities(date: DateScalar) -> pd.Series:
51
52
  pd.Series: A Series of bond maturities available for the reference date.
52
53
 
53
54
  Examples:
54
- >>> yd.ltn.maturities("22-08-2024")
55
+ >>> from pyield import ltn
56
+ >>> ltn.maturities("22-08-2024")
55
57
  0 2024-10-01
56
58
  1 2025-01-01
57
59
  2 2025-04-01
@@ -97,7 +99,8 @@ def price(
97
99
  - https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
98
100
 
99
101
  Examples:
100
- >>> yd.ltn.price("05-07-2024", "01-01-2030", 0.12145)
102
+ >>> from pyield import ltn
103
+ >>> ltn.price("05-07-2024", "01-01-2030", 0.12145)
101
104
  535.279902
102
105
  """
103
106
 
@@ -109,12 +112,12 @@ def price(
109
112
  bdays = bday.count(settlement, maturity)
110
113
 
111
114
  # Calculate the number of periods truncated as per Anbima rule
112
- num_of_years = tt.truncate(bdays / 252, 14)
115
+ num_of_years = tools.truncate(bdays / 252, 14)
113
116
 
114
117
  discount_factor = (1 + rate) ** num_of_years
115
118
 
116
119
  # Truncate the price to 6 decimal places as per Anbima rules
117
- return tt.truncate(FACE_VALUE / discount_factor, 6)
120
+ return tools.truncate(FACE_VALUE / discount_factor, 6)
118
121
 
119
122
 
120
123
  def di_spreads(date: DateScalar) -> pd.DataFrame:
@@ -132,7 +135,8 @@ def di_spreads(date: DateScalar) -> pd.DataFrame:
132
135
  pd.DataFrame: DataFrame with the columns "MaturityDate" and "DISpread" (in bps).
133
136
 
134
137
  Examples:
135
- >>> yd.ltn.di_spreads("22-08-2024")
138
+ >>> from pyield import ltn
139
+ >>> ltn.di_spreads("22-08-2024")
136
140
  MaturityDate DISpread
137
141
  0 2024-10-01 -3.06
138
142
  1 2025-01-01 -9.95
@@ -149,7 +153,7 @@ def di_spreads(date: DateScalar) -> pd.DataFrame:
149
153
  12 2030-01-01 14.96
150
154
  """
151
155
  # Fetch DI Spreads for the reference date
152
- df = tt.pre_spreads(date)
156
+ df = tools.pre_spreads(date)
153
157
  df.query("BondType == 'LTN'", inplace=True)
154
158
  df.sort_values(["MaturityDate"], ignore_index=True, inplace=True)
155
159
  return df[["MaturityDate", "DISpread"]]
@@ -170,7 +174,8 @@ def premium(ltn_rate: float, di_rate: float) -> float:
170
174
  Reference date: 22-08-2024
171
175
  LTN rate for 01-01-2030: 0.118746
172
176
  DI (JAN30) Settlement rate: 0.11725
173
- >>> yd.ltn.premium(0.118746, 0.11725)
177
+ >>> from pyield import ltn
178
+ >>> ltn.premium(0.118746, 0.11725)
174
179
  1.0120718007994287
175
180
  """
176
181
  # Cálculo das taxas diárias
@@ -197,7 +202,8 @@ def historical_premium(
197
202
  If the data is not available, returns NaN.
198
203
 
199
204
  Examples:
200
- >>> yd.ltn.historical_premium("22-08-2024", "01-01-2030")
205
+ >>> from pyield import ltn
206
+ >>> ltn.historical_premium("22-08-2024", "01-01-2030")
201
207
  1.0120718007994287
202
208
 
203
209
  """
@@ -34,7 +34,8 @@ def data(date: DateScalar) -> pd.DataFrame:
34
34
  - IndicativeRate: The indicative rate for the bond.
35
35
 
36
36
  Examples:
37
- >>> yd.ntnb.data("23-08-2024")
37
+ >>> from pyield import ntnb
38
+ >>> ntnb.data("23-08-2024")
38
39
  ReferenceDate BondType MaturityDate IndicativeRate Price
39
40
  0 2024-08-23 NTN-B 2025-05-15 0.063804 4377.008543
40
41
  1 2024-08-23 NTN-B 2026-08-15 0.065795 4278.316344
@@ -66,8 +67,8 @@ def maturities(date: DateScalar) -> pd.Series:
66
67
  pd.Series: Series containing the maturity dates for the NTN-B bonds.
67
68
 
68
69
  Examples:
69
-
70
- >>> yd.ntnb.maturities("16-08-2024")
70
+ >>> from pyield import ntnb
71
+ >>> ntnb.maturities("16-08-2024")
71
72
  0 2025-05-15
72
73
  1 2026-08-15
73
74
  2 2027-05-15
@@ -147,7 +148,8 @@ def payment_dates(
147
148
  pd.Series: Series of coupon dates within the specified range.
148
149
 
149
150
  Examples:
150
- >>> yd.ntnb.payment_dates("10-05-2024", "15-05-2025")
151
+ >>> from pyield import ntnb
152
+ >>> ntnb.payment_dates("10-05-2024", "15-05-2025")
151
153
  0 2024-05-15
152
154
  1 2024-11-15
153
155
  2 2025-05-15
@@ -194,7 +196,8 @@ def cash_flows(
194
196
  - CashFlow: Cash flow value for the bond
195
197
 
196
198
  Examples:
197
- >>> yd.ntnb.cash_flows("10-05-2024", "15-05-2025")
199
+ >>> from pyield import ntnb
200
+ >>> ntnb.cash_flows("10-05-2024", "15-05-2025")
198
201
  PaymentDate CashFlow
199
202
  0 2024-05-15 2.956301
200
203
  1 2024-11-15 2.956301
@@ -238,11 +241,12 @@ def quotation(
238
241
  Anbima rules.
239
242
 
240
243
  Examples:
241
- >>> yd.ntnb.quotation("31-05-2024", "15-05-2035", 0.061490)
244
+ >>> from pyield import ntnb
245
+ >>> ntnb.quotation("31-05-2024", "15-05-2035", 0.061490)
242
246
  99.3651
243
- >>> yd.ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
247
+ >>> ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
244
248
  99.5341
245
- >>> yd.ntnb.quotation("15-08-2024", "15-08-2032", 0.05929)
249
+ >>> ntnb.quotation("15-08-2024", "15-08-2032", 0.05929)
246
250
  100.6409
247
251
  """
248
252
  # Validate and normalize dates
@@ -286,9 +290,10 @@ def price(
286
290
  - https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
287
291
 
288
292
  Examples:
289
- >>> yd.ntnb.price(4299.160173, 99.3651)
293
+ >>> from pyield import ntnb
294
+ >>> ntnb.price(4299.160173, 99.3651)
290
295
  4271.864805
291
- >>> yd.ntnb.price(4315.498383, 100.6409)
296
+ >>> ntnb.price(4315.498383, 100.6409)
292
297
  4343.156412
293
298
  """
294
299
  return bt.truncate(vna * quotation / 100, 6)
@@ -319,11 +324,11 @@ def spot_rates(
319
324
  pd.DataFrame: DataFrame with columns "MaturityDate", "SpotRate".
320
325
 
321
326
  Examples:
322
- # Get the NTN-B rates for a specific reference date
323
- >>> df = yd.ntnb.data("16-08-2024")
324
-
325
- # Calculate the spot rates considering the settlement at the reference date
326
- >>> yd.ntnb.spot_rates(
327
+ >>> from pyield import ntnb
328
+ >>> # Get the NTN-B rates for a specific reference date
329
+ >>> df = ntnb.data("16-08-2024")
330
+ >>> # Calculate the spot rates considering the settlement at the reference date
331
+ >>> ntnb.spot_rates(
327
332
  ... settlement="16-08-2024",
328
333
  ... maturities=df["MaturityDate"],
329
334
  ... rates=df["IndicativeRate"],
@@ -521,6 +526,22 @@ def duration(
521
526
  maturity: DateScalar,
522
527
  rate: float,
523
528
  ) -> float:
529
+ """
530
+ Calculate the Macaulay duration of the NTN-B bond in business years.
531
+
532
+ Args:
533
+ settlement (DateScalar): The settlement date of the operation.
534
+ maturity (DateScalar): The maturity date of the NTN-B bond.
535
+ rate (float): The discount rate used to calculate the duration.
536
+
537
+ Returns:
538
+ float: The Macaulay duration of the NTN-B bond in business years.
539
+
540
+ Examples:
541
+ >>> from pyield import ntnb
542
+ >>> ntnb.duration("23-08-2024", "15-08-2060", 0.061005)
543
+ 15.083054313130464
544
+ """
524
545
  settlement = dc.convert_input_dates(settlement)
525
546
  maturity = dc.convert_input_dates(maturity)
526
547
 
@@ -0,0 +1,276 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+ import pyield.date_converter as dc
5
+ import pyield.tpf.tools as bt
6
+ from pyield import anbima, bday
7
+ from pyield.date_converter import DateScalar
8
+
9
+ """
10
+ Constants calculated as per Anbima Rules and in base 100
11
+ Valid for NTN-C bonds with maturity date 01-01-2031:
12
+ PRINCIPAL = 100
13
+ COUPON_RATE = (0.12 + 1) ** 0.5 - 1 # 12% annual rate compounded semi-annually
14
+ COUPON_PMT = round(100 * COUPON_RATE, 6) -> 5.830052
15
+ FINAL_PMT = principal + last coupon payment = 100 + COUPON_PMT = 105.830052
16
+
17
+ All other NTN-C bonds will have different values for COUPON_PMT and FINAL_PMT:
18
+ COUPON_RATE = (0.06 + 1) ** 0.5 - 1 # 6% annual rate compounded semi-annually
19
+ COUPON_PMT = round(100 * COUPON_RATE, 6) -> 2.956301
20
+ FINAL_PMT = principal + last coupon payment = 100 + 2.956301
21
+
22
+ """
23
+ COUPON_DAY = 1
24
+ COUPON_PMT_2031 = 5.830052
25
+ FINAL_PMT_2031 = 105.830052
26
+
27
+ COUPON_PMT = 2.956301
28
+ FINAL_PMT = 102.956301
29
+
30
+
31
+ def _get_coupon_pmt(maturity: pd.Timestamp) -> float:
32
+ if maturity.year == 2031: # noqa
33
+ return COUPON_PMT_2031
34
+ return COUPON_PMT
35
+
36
+
37
+ def _get_final_pmt(maturity: pd.Timestamp) -> float:
38
+ if maturity.year == 2031: # noqa
39
+ return FINAL_PMT_2031
40
+ return FINAL_PMT
41
+
42
+
43
+ def data(date: DateScalar) -> pd.DataFrame:
44
+ """
45
+ Fetch the LTN Anbima indicative rates for the given reference date.
46
+
47
+ Args:
48
+ date (DateScalar): The reference date for fetching the data.
49
+
50
+ Returns:
51
+ pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
52
+
53
+ Examples:
54
+ >>> from pyield import ntnc
55
+ >>> ntnc.data("21-03-2025")
56
+ ReferenceDate BondType MaturityDate IndicativeRate Price
57
+ 0 2025-03-21 NTN-C 2031-01-01 0.067626 8347.348705
58
+ """
59
+ return anbima.tpf_data(date, "NTN-C")
60
+
61
+
62
+ def payment_dates(
63
+ settlement: DateScalar,
64
+ maturity: DateScalar,
65
+ ) -> pd.Series:
66
+ """
67
+ Generate all remaining coupon dates between a given date and the maturity date.
68
+ The dates are inclusive. The NTN-C bond is determined by its maturity date.
69
+
70
+ Args:
71
+ settlement (DateScalar): The settlement date (exlusive) to start generating
72
+ the coupon dates.
73
+ maturity (DateScalar): The maturity date.
74
+
75
+ Returns:
76
+ pd.Series: Series of coupon dates within the specified range.
77
+
78
+ Examples:
79
+ >>> from pyield import ntnc
80
+ >>> ntnc.payment_dates("21-03-2025", "01-01-2031")
81
+ 0 2025-07-01
82
+ 1 2026-01-01
83
+ 2 2026-07-01
84
+ 3 2027-01-01
85
+ 4 2027-07-01
86
+ 5 2028-01-01
87
+ 6 2028-07-01
88
+ 7 2029-01-01
89
+ 8 2029-07-01
90
+ 9 2030-01-01
91
+ 10 2030-07-01
92
+ 11 2031-01-01
93
+ dtype: datetime64[ns]
94
+ """
95
+ # Validate and normalize dates
96
+ settlement = dc.convert_input_dates(settlement)
97
+ maturity = dc.convert_input_dates(maturity)
98
+
99
+ # Check if maturity date is after the start date
100
+ if maturity < settlement:
101
+ raise ValueError("Maturity date must be after the start date.")
102
+
103
+ # Initialize loop variables
104
+ coupon_dates = maturity
105
+ cp_dates = []
106
+
107
+ # Iterate backwards from the maturity date to the settlement date
108
+ while coupon_dates > settlement:
109
+ cp_dates.append(coupon_dates)
110
+ # Move the coupon date back 6 months
111
+ coupon_dates -= pd.DateOffset(months=6)
112
+
113
+ return pd.Series(cp_dates).sort_values(ignore_index=True)
114
+
115
+
116
+ def cash_flows(
117
+ settlement: DateScalar,
118
+ maturity: DateScalar,
119
+ ) -> pd.DataFrame:
120
+ """
121
+ Generate the cash flows for NTN-C bonds between the settlement and maturity dates.
122
+
123
+ Args:
124
+ settlement (DateScalar): The settlement date (exclusive) to start generating
125
+ the cash flows.
126
+ maturity (DateScalar): The maturity date of the bond.
127
+
128
+ Returns:
129
+ pd.DataFrame: DataFrame with columns "PaymentDate" and "CashFlow".
130
+
131
+ Returned columns:
132
+ - PaymentDate: The payment date of the cash flow
133
+ - CashFlow: Cash flow value for the bond
134
+
135
+ Examples:
136
+ >>> from pyield import ntnc
137
+ >>> ntnc.cash_flows("21-03-2025", "01-01-2031")
138
+ PaymentDate CashFlow
139
+ 0 2025-07-01 5.830052
140
+ 1 2026-01-01 5.830052
141
+ 2 2026-07-01 5.830052
142
+ 3 2027-01-01 5.830052
143
+ 4 2027-07-01 5.830052
144
+ 5 2028-01-01 5.830052
145
+ 6 2028-07-01 5.830052
146
+ 7 2029-01-01 5.830052
147
+ 8 2029-07-01 5.830052
148
+ 9 2030-01-01 5.830052
149
+ 10 2030-07-01 5.830052
150
+ 11 2031-01-01 105.830052
151
+ """
152
+ # Validate and normalize dates
153
+ settlement = dc.convert_input_dates(settlement)
154
+ maturity = dc.convert_input_dates(maturity)
155
+
156
+ # Get the coupon dates between the settlement and maturity dates
157
+ p_dates = payment_dates(settlement, maturity)
158
+
159
+ # Get the right coupon payment and final payment values
160
+ coupon_pmt = _get_coupon_pmt(maturity)
161
+ final_pmt = _get_final_pmt(maturity)
162
+
163
+ # Set the cash flow at maturity to FINAL_PMT and the others to COUPON_PMT
164
+ cfs = np.where(p_dates == maturity, final_pmt, coupon_pmt).tolist()
165
+
166
+ # Return a dataframe with the payment dates and cash flows
167
+ return pd.DataFrame(data={"PaymentDate": p_dates, "CashFlow": cfs})
168
+
169
+
170
+ def quotation(
171
+ settlement: DateScalar,
172
+ maturity: DateScalar,
173
+ rate: float,
174
+ ) -> float:
175
+ """
176
+ Calculate the NTN-C quotation in base 100 using Anbima rules.
177
+
178
+ Args:
179
+ settlement (DateScalar): The settlement date of the operation.
180
+ maturity (DateScalar): The maturity date of the NTN-C bond.
181
+ rate (float): The discount rate used to calculate the present value of
182
+ the cash flows, which is the yield to maturity (YTM) of the NTN-C.
183
+
184
+ Returns:
185
+ float: The NTN-C quotation truncated to 4 decimal places.
186
+
187
+ References:
188
+ - https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
189
+ - The semi-annual coupon is set to 2.956301, which represents a 6% annual
190
+ coupon rate compounded semi-annually and rounded to 6 decimal places as per
191
+ Anbima rules.
192
+
193
+ Examples:
194
+ >>> from pyield import ntnc
195
+ >>> ntnc.quotation("21-03-2025", "01-01-2031", 0.067626)
196
+ 126.4958
197
+ """
198
+ # Validate and normalize dates
199
+ settlement = dc.convert_input_dates(settlement)
200
+ maturity = dc.convert_input_dates(maturity)
201
+
202
+ cf_df = cash_flows(settlement, maturity)
203
+ cf_dates = cf_df["PaymentDate"]
204
+ cf_values = cf_df["CashFlow"]
205
+
206
+ # Calculate the number of business days between settlement and cash flow dates
207
+ bdays = bday.count(settlement, cf_dates)
208
+
209
+ # Calculate the number of periods truncated as per Anbima rules
210
+ num_of_years = bt.truncate(bdays / 252, 14)
211
+
212
+ discount_factor = (1 + rate) ** num_of_years
213
+
214
+ # Calculate the present value of each cash flow (DCF) rounded as per Anbima rules
215
+ cf_present_value = (cf_values / discount_factor).round(10)
216
+
217
+ # Return the quotation (the dcf sum) truncated as per Anbima rules
218
+ return bt.truncate(cf_present_value.sum(), 4)
219
+
220
+
221
+ def price(
222
+ vna: float,
223
+ quotation: float,
224
+ ) -> float:
225
+ """
226
+ Calculate the NTN-C price using Anbima rules.
227
+
228
+ price = VNA * quotation / 100
229
+
230
+ Args:
231
+ vna (float): The nominal value of the NTN-C bond.
232
+ quotation (float): The NTN-C quotation in base 100.
233
+
234
+ Returns:
235
+ float: The NTN-C price truncated to 6 decimal places.
236
+
237
+ References:
238
+ - https://www.anbima.com.br/data/files/A0/02/CC/70/8FEFC8104606BDC8B82BA2A8/Metodologias%20ANBIMA%20de%20Precificacao%20Titulos%20Publicos.pdf
239
+
240
+ Examples:
241
+ >>> from pyield import ntnc
242
+ >>> ntnc.price(6598.913723, 126.4958)
243
+ 8347.348705
244
+ """
245
+ return bt.truncate(vna * quotation / 100, 6)
246
+
247
+
248
+ def duration(
249
+ settlement: DateScalar,
250
+ maturity: DateScalar,
251
+ rate: float,
252
+ ) -> float:
253
+ """
254
+ Calculate the Macaulay duration of the NTN-C bond in business years.
255
+
256
+ Args:
257
+ settlement (DateScalar): The settlement date of the operation.
258
+ maturity (DateScalar): The maturity date of the NTN-C bond.
259
+ rate (float): The discount rate used to calculate the duration.
260
+
261
+ Returns:
262
+ float: The Macaulay duration of the NTN-C bond in business years.
263
+
264
+ Examples:
265
+ >>> from pyield import ntnc
266
+ >>> ntnc.duration("21-03-2025", "01-01-2031", 0.067626)
267
+ 4.405363320448003
268
+ """
269
+ settlement = dc.convert_input_dates(settlement)
270
+ maturity = dc.convert_input_dates(maturity)
271
+
272
+ df = cash_flows(settlement, maturity)
273
+ df["BY"] = bday.count(settlement, df["PaymentDate"]) / 252
274
+ df["DCF"] = df["CashFlow"] / (1 + rate) ** df["BY"]
275
+ np_duration = (df["DCF"] * df["BY"]).sum() / df["DCF"].sum()
276
+ return float(np_duration)
@@ -8,7 +8,7 @@ from pyield import date_converter as dc
8
8
  from pyield import interpolator as ip
9
9
  from pyield.b3 import di
10
10
  from pyield.date_converter import DateScalar
11
- from pyield.tpf import tools as tt
11
+ from pyield.tpf import tools
12
12
 
13
13
  """
14
14
  Constants calculated as per Anbima Rules
@@ -34,7 +34,8 @@ def data(date: DateScalar) -> pd.DataFrame:
34
34
  pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
35
35
 
36
36
  Examples:
37
- >>> yd.ntnf.data("23-08-2024")
37
+ >>> from pyield import ntnf
38
+ >>> ntnf.data("23-08-2024")
38
39
  ReferenceDate BondType MaturityDate IndicativeRate Price
39
40
  0 2024-08-23 NTN-F 2025-01-01 0.107692 1011.189166
40
41
  1 2024-08-23 NTN-F 2027-01-01 0.115109 985.834842
@@ -57,7 +58,8 @@ def maturities(date: DateScalar) -> pd.Series:
57
58
  pd.Series: A Series of NTN-F bond maturities available for the reference date.
58
59
 
59
60
  Examples:
60
- >>> yd.ntnf.maturities("23-08-2024")
61
+ >>> from pyield import ntnf
62
+ >>> ntnf.maturities("23-08-2024")
61
63
  0 2025-01-01
62
64
  1 2027-01-01
63
65
  2 2029-01-01
@@ -65,7 +67,6 @@ def maturities(date: DateScalar) -> pd.Series:
65
67
  4 2033-01-01
66
68
  5 2035-01-01
67
69
  dtype: datetime64[ns]
68
-
69
70
  """
70
71
  df_rates = data(date)
71
72
  s_maturities = df_rates["MaturityDate"]
@@ -106,8 +107,8 @@ def payment_dates(
106
107
  (exclusive) and maturity (inclusive) dates.
107
108
 
108
109
  Examples:
109
-
110
- >>> yd.ntnf.payment_dates("15-05-2024", "01-01-2025")
110
+ >>> from pyield import ntnf
111
+ >>> ntnf.payment_dates("15-05-2024", "01-01-2025")
111
112
  0 2024-07-01
112
113
  1 2025-01-01
113
114
  dtype: datetime64[ns]
@@ -157,7 +158,8 @@ def cash_flows(
157
158
  pd.DataFrame: DataFrame with columns "PaymentDate" and "CashFlow".
158
159
 
159
160
  Examples:
160
- >>> yd.ntnf.cash_flows("15-05-2024", "01-01-2025")
161
+ >>> from pyield import ntnf
162
+ >>> ntnf.cash_flows("15-05-2024", "01-01-2025")
161
163
  PaymentDate CashFlow
162
164
  0 2024-07-01 48.80885
163
165
  1 2025-01-01 1048.80885
@@ -206,18 +208,19 @@ def price(
206
208
  Anbima rules.
207
209
 
208
210
  Examples:
209
- >>> yd.ntnf.price("05-07-2024", "01-01-2035", 0.11921)
211
+ >>> from pyield import ntnf
212
+ >>> ntnf.price("05-07-2024", "01-01-2035", 0.11921)
210
213
  895.359254
211
214
  """
212
215
  cf_df = cash_flows(settlement, maturity)
213
216
  cf_values = cf_df["CashFlow"]
214
217
  bdays = bday.count(settlement, cf_df["PaymentDate"])
215
- byears = tt.truncate(bdays / 252, 14)
218
+ byears = tools.truncate(bdays / 252, 14)
216
219
  discount_factors = (1 + rate) ** byears
217
220
  # Calculate the present value of each cash flow (DCF) rounded as per Anbima rules
218
221
  dcf = (cf_values / discount_factors).round(9)
219
222
  # Return the sum of the discounted cash flows truncated as per Anbima rules
220
- return tt.truncate(dcf.sum(), 6)
223
+ return tools.truncate(dcf.sum(), 6)
221
224
 
222
225
 
223
226
  def spot_rates( # noqa
@@ -254,9 +257,10 @@ def spot_rates( # noqa
254
257
  "BDToMat" is the business days from the settlement date to the maturities.
255
258
 
256
259
  Examples:
257
- >>> df_ltn = yd.ltn.data("03-09-2024")
258
- >>> df_ntnf = yd.ntnf.data("03-09-2024")
259
- >>> yd.ntnf.spot_rates(
260
+ >>> from pyield import ntnf, ltn
261
+ >>> df_ltn = ltn.data("03-09-2024")
262
+ >>> df_ntnf = ntnf.data("03-09-2024")
263
+ >>> ntnf.spot_rates(
260
264
  ... settlement="03-09-2024",
261
265
  ... ltn_maturities=df_ltn["MaturityDate"],
262
266
  ... ltn_rates=df_ltn["IndicativeRate"],
@@ -306,7 +310,7 @@ def spot_rates( # noqa
306
310
  # Calculate the present value of the coupon payments
307
311
  cf_dates = payment_dates(settlement, row["MaturityDate"])[:-1] # noqa
308
312
  cf_df = df.query("MaturityDate in @cf_dates").reset_index(drop=True)
309
- cf_present_value = tt.calculate_present_value(
313
+ cf_present_value = tools.calculate_present_value(
310
314
  cash_flows=cf_df["Coupon"],
311
315
  rates=cf_df["SpotRate"],
312
316
  periods=cf_df["BDToMat"] / 252,
@@ -339,7 +343,8 @@ def di_spreads(date: DateScalar) -> pd.DataFrame:
339
343
  pd.DataFrame: DataFrame with columns "MaturityDate", "DISpread".
340
344
 
341
345
  Examples:
342
- >>> yd.ntnf.di_spreads("23-08-2024")
346
+ >>> from pyield import ntnf
347
+ >>> ntnf.di_spreads("23-08-2024")
343
348
  MaturityDate DISpread
344
349
  0 2025-01-01 -5.38
345
350
  1 2027-01-01 4.39
@@ -350,7 +355,7 @@ def di_spreads(date: DateScalar) -> pd.DataFrame:
350
355
 
351
356
  """
352
357
  # Fetch DI Spreads for the reference date
353
- df = tt.pre_spreads(date)
358
+ df = tools.pre_spreads(date)
354
359
  df = (
355
360
  df.query("BondType == 'NTN-F'")
356
361
  .sort_values(["MaturityDate"])
@@ -550,7 +555,7 @@ def premium(
550
555
  df["DIRate"] = df["BDToMat"].apply(ff_interpolator)
551
556
 
552
557
  # Calculate the present value of the cash flows using the DI rate
553
- bond_price = tt.calculate_present_value(
558
+ bond_price = tools.calculate_present_value(
554
559
  cash_flows=df["CashFlow"],
555
560
  rates=df["DIRate"],
556
561
  periods=df["BDToMat"] / 252,
@@ -599,7 +604,7 @@ def historical_premium(
599
604
  )
600
605
 
601
606
  # Calculate the present value of the cash flows using the DI rate
602
- bond_price = tt.calculate_present_value(
607
+ bond_price = tools.calculate_present_value(
603
608
  cash_flows=df["CashFlow"],
604
609
  rates=df["DIRate"],
605
610
  periods=df["BDToMat"] / 252,
@@ -625,11 +630,7 @@ def duration(
625
630
  rate: float,
626
631
  ) -> float:
627
632
  """
628
- Calculate the Macaulay duration for an NTN-F bond.
629
-
630
- The Macaulay duration is a weighted average of the times until each payment is
631
- received, with the weights proportional to the present value of the cash flows.
632
- It measures the bond's sensitivity to interest rate changes.
633
+ Calculate the Macaulay duration for an NTN-F bond in business years.
633
634
 
634
635
  Args:
635
636
  settlement (DateScalar): The settlement date to calculate the duration.
@@ -637,10 +638,11 @@ def duration(
637
638
  rate (float): The yield to maturity (YTM) used to discount the cash flows.
638
639
 
639
640
  Returns:
640
- float: The Macaulay duration in years.
641
+ float: The Macaulay duration in business business years.
641
642
 
642
643
  Examples:
643
- >>> yd.ntnf.duration("02-09-2024", "01-01-2035", 0.121785)
644
+ >>> from pyield import ntnf
645
+ >>> ntnf.duration("02-09-2024", "01-01-2035", 0.121785)
644
646
  6.32854218039796
645
647
  """
646
648
  settlement = dc.convert_input_dates(settlement)
@@ -36,6 +36,7 @@ dev = [
36
36
  "types-requests",
37
37
  "pandas-stubs",
38
38
  "lxml-stubs",
39
+ "ruff",
39
40
  ]
40
41
 
41
42
  [build-system]
@@ -1 +0,0 @@
1
- __version__ = "0.31.0"
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