PYield 0.28.0__tar.gz → 0.28.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 (40) hide show
  1. {pyield-0.28.0 → pyield-0.28.2}/PKG-INFO +5 -6
  2. {pyield-0.28.0 → pyield-0.28.2}/README.md +3 -3
  3. pyield-0.28.2/pyield/__about__.py +1 -0
  4. {pyield-0.28.0/pyield/b3_futures → pyield-0.28.2/pyield/anbima}/__init__.py +5 -5
  5. {pyield-0.28.0 → pyield-0.28.2}/pyield/anbima/tpf.py +16 -18
  6. {pyield-0.28.0/pyield/anbima → pyield-0.28.2/pyield/b3_futures}/__init__.py +5 -5
  7. {pyield-0.28.0 → pyield-0.28.2}/pyield/b3_futures/di.py +27 -27
  8. {pyield-0.28.0 → pyield-0.28.2}/pyield/b3_futures/historical.py +17 -19
  9. {pyield-0.28.0 → pyield-0.28.2}/pyield/b3_futures/xml.py +13 -11
  10. {pyield-0.28.0 → pyield-0.28.2}/pyield/indicators.py +19 -19
  11. {pyield-0.28.0 → pyield-0.28.2}/pyield/projections.py +9 -21
  12. {pyield-0.28.0 → pyield-0.28.2}/pyield/tpf/lft.py +6 -6
  13. {pyield-0.28.0 → pyield-0.28.2}/pyield/tpf/ltn.py +14 -14
  14. {pyield-0.28.0 → pyield-0.28.2}/pyield/tpf/ntnb.py +6 -6
  15. {pyield-0.28.0 → pyield-0.28.2}/pyield/tpf/ntnf.py +17 -28
  16. {pyield-0.28.0 → pyield-0.28.2}/pyield/tpf/tools.py +4 -4
  17. {pyield-0.28.0 → pyield-0.28.2}/pyproject.toml +2 -3
  18. pyield-0.28.0/pyield/__about__.py +0 -1
  19. {pyield-0.28.0 → pyield-0.28.2}/.gitignore +0 -0
  20. {pyield-0.28.0 → pyield-0.28.2}/LICENSE +0 -0
  21. {pyield-0.28.0 → pyield-0.28.2}/pyield/__init__.py +0 -0
  22. {pyield-0.28.0 → pyield-0.28.2}/pyield/anbima/ima.py +0 -0
  23. {pyield-0.28.0 → pyield-0.28.2}/pyield/anbima/imaq.py +0 -0
  24. {pyield-0.28.0 → pyield-0.28.2}/pyield/b3_futures/common.py +0 -0
  25. {pyield-0.28.0 → pyield-0.28.2}/pyield/b3_futures/intraday.py +0 -0
  26. {pyield-0.28.0 → pyield-0.28.2}/pyield/bc/auction.py +0 -0
  27. {pyield-0.28.0 → pyield-0.28.2}/pyield/bc/ptax.py +0 -0
  28. {pyield-0.28.0 → pyield-0.28.2}/pyield/bc/repos.py +0 -0
  29. {pyield-0.28.0 → pyield-0.28.2}/pyield/bday.py +0 -0
  30. {pyield-0.28.0 → pyield-0.28.2}/pyield/conftest.py +0 -0
  31. {pyield-0.28.0 → pyield-0.28.2}/pyield/data_cache.py +0 -0
  32. {pyield-0.28.0 → pyield-0.28.2}/pyield/date_converter.py +0 -0
  33. {pyield-0.28.0 → pyield-0.28.2}/pyield/holidays/__init__.py +0 -0
  34. {pyield-0.28.0 → pyield-0.28.2}/pyield/holidays/br_holidays_new.txt +0 -0
  35. {pyield-0.28.0 → pyield-0.28.2}/pyield/holidays/br_holidays_old.txt +0 -0
  36. {pyield-0.28.0 → pyield-0.28.2}/pyield/holidays/brholidays.py +0 -0
  37. {pyield-0.28.0 → pyield-0.28.2}/pyield/interpolator.py +0 -0
  38. {pyield-0.28.0 → pyield-0.28.2}/pyield/py.typed +0 -0
  39. {pyield-0.28.0 → pyield-0.28.2}/pyield/tools.py +0 -0
  40. {pyield-0.28.0 → pyield-0.28.2}/pyield/tpf/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PYield
3
- Version: 0.28.0
3
+ Version: 0.28.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>
@@ -34,8 +34,7 @@ Classifier: Programming Language :: Python :: 3
34
34
  Classifier: Topic :: Office/Business :: Financial :: Investment
35
35
  Requires-Python: >=3.11
36
36
  Requires-Dist: numpy>=2.0.0
37
- Requires-Dist: pandas[html,parquet]>=2.0.0
38
- Requires-Dist: python-calamine>=0.2.0
37
+ Requires-Dist: pandas[excel,html,parquet]>=2.0.0
39
38
  Requires-Dist: requests>=2.31.0
40
39
  Description-Content-Type: text/markdown
41
40
 
@@ -180,7 +179,7 @@ LastUpdatee TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate
180
179
  2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
181
180
 
182
181
  # Fetch historical DI Futures data from B3
183
- >>> yd.futures(contract_code="DI1", reference_date='08-03-2024')
182
+ >>> yd.futures(contract_code="DI1", date='08-03-2024')
184
183
  TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastBidRate SettlementRate
185
184
  2024-03-08 DI1J24 2024-04-01 15 ... 10.952 10.952 10.956 10.956
186
185
  2024-03-08 DI1K24 2024-05-02 37 ... 10.776 10.774 10.780 10.777
@@ -195,11 +194,11 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
195
194
  ```python
196
195
  >>> import pyield as yd
197
196
  # Fetch the SELIC target rate from the Central Bank of Brazil
198
- >>> yd.indicator(indicator_code="SELIC_TARGET", reference_date='12-04-2024')
197
+ >>> yd.indicator(indicator_code="SELIC_TARGET", date='12-04-2024')
199
198
  0.1075 # 10.75%
200
199
 
201
200
  # Fetch the IPCA monthly inflation rate from IBGE
202
- >>> yd.indicator(indicator_code="IPCA_MR", reference_date='18-03-2024')
201
+ >>> yd.indicator(indicator_code="IPCA_MR", date='18-03-2024')
203
202
  0.0016 # 0.16%
204
203
  ```
205
204
 
@@ -139,7 +139,7 @@ LastUpdatee TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate
139
139
  2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
140
140
 
141
141
  # Fetch historical DI Futures data from B3
142
- >>> yd.futures(contract_code="DI1", reference_date='08-03-2024')
142
+ >>> yd.futures(contract_code="DI1", date='08-03-2024')
143
143
  TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastBidRate SettlementRate
144
144
  2024-03-08 DI1J24 2024-04-01 15 ... 10.952 10.952 10.956 10.956
145
145
  2024-03-08 DI1K24 2024-05-02 37 ... 10.776 10.774 10.780 10.777
@@ -154,11 +154,11 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
154
154
  ```python
155
155
  >>> import pyield as yd
156
156
  # Fetch the SELIC target rate from the Central Bank of Brazil
157
- >>> yd.indicator(indicator_code="SELIC_TARGET", reference_date='12-04-2024')
157
+ >>> yd.indicator(indicator_code="SELIC_TARGET", date='12-04-2024')
158
158
  0.1075 # 10.75%
159
159
 
160
160
  # Fetch the IPCA monthly inflation rate from IBGE
161
- >>> yd.indicator(indicator_code="IPCA_MR", reference_date='18-03-2024')
161
+ >>> yd.indicator(indicator_code="IPCA_MR", date='18-03-2024')
162
162
  0.0016 # 0.16%
163
163
  ```
164
164
 
@@ -0,0 +1 @@
1
+ __version__ = "0.28.2"
@@ -15,7 +15,7 @@ ContractOptions = Literal["DI1", "DDI", "FRC", "DAP", "DOL", "WDO", "IND", "WIN"
15
15
 
16
16
  def futures(
17
17
  contract_code: ContractOptions,
18
- trade_date: DateScalar,
18
+ date: DateScalar,
19
19
  ) -> pd.DataFrame:
20
20
  """
21
21
  Fetches data for a specified futures contract based on type and reference date.
@@ -31,7 +31,7 @@ def futures(
31
31
  - "WDO": Mini U.S. Dollar Futures from B3.
32
32
  - "IND": Ibovespa Futures from B3.
33
33
  - "WIN": Mini Ibovespa Futures from B3.
34
- trade_date (DateScalar): The date for which to fetch the data.
34
+ date (DateScalar): The date for which to fetch the data.
35
35
  If the reference date is a string, it should be in 'DD-MM-YYYY' format.
36
36
 
37
37
  Returns:
@@ -58,14 +58,14 @@ def futures(
58
58
  ...
59
59
  """
60
60
  selected_contract = str(contract_code).upper()
61
- converted_trade_date = dc.convert_input_dates(trade_date)
61
+ converted_date = dc.convert_input_dates(date)
62
62
 
63
63
  # First, try to fetch historical data for the specified date
64
- df = fetch_historical_df(selected_contract, converted_trade_date)
64
+ df = fetch_historical_df(selected_contract, converted_date)
65
65
 
66
66
  bz_today = dt.datetime.now(TIMEZONE_BZ).date()
67
67
  # If there is no historical data available, try to fetch intraday data
68
- if converted_trade_date.date() == bz_today and df.empty:
68
+ if converted_date.date() == bz_today and df.empty:
69
69
  df = fetch_intraday_df(selected_contract)
70
70
 
71
71
  return df
@@ -19,9 +19,9 @@ ANBIMA_MEMBER_URL = "http://www.anbima.associados.rtm/merc_sec/arqs"
19
19
  FORMAT_CHANGE_DATE = pd.to_datetime("13-05-2014", dayfirst=True)
20
20
 
21
21
 
22
- def _get_file_content(reference_date: pd.Timestamp) -> str:
23
- url_date = reference_date.strftime("%y%m%d")
24
- if reference_date < FORMAT_CHANGE_DATE:
22
+ def _get_file_content(date: pd.Timestamp) -> str:
23
+ url_date = date.strftime("%y%m%d")
24
+ if date < FORMAT_CHANGE_DATE:
25
25
  filename = f"ms{url_date}.exe"
26
26
  else:
27
27
  filename = f"ms{url_date}.txt"
@@ -41,7 +41,7 @@ def _get_file_content(reference_date: pd.Timestamp) -> str:
41
41
  # Checks if the response was successful (status code 200)
42
42
  r.raise_for_status()
43
43
 
44
- if reference_date < FORMAT_CHANGE_DATE:
44
+ if date < FORMAT_CHANGE_DATE:
45
45
  zip_file = zp.ZipFile(io.BytesIO(r.content))
46
46
  file_content = zip_file.read(zip_file.namelist()[0]).decode("latin-1")
47
47
  else:
@@ -106,9 +106,7 @@ def _process_raw_df(df_raw: pd.DataFrame) -> pd.DataFrame:
106
106
  return df.sort_values(["BondType", "MaturityDate"], ignore_index=True)
107
107
 
108
108
 
109
- def anbima_tpf_data(
110
- reference_date: DateScalar, bond_type: str | None = None
111
- ) -> pd.DataFrame:
109
+ def anbima_tpf_data(date: DateScalar, bond_type: str | None = None) -> pd.DataFrame:
112
110
  """Fetch and process TPF market data from ANBIMA.
113
111
 
114
112
  This function retrieves bond market data from the ANBIMA website for a
@@ -116,7 +114,7 @@ def anbima_tpf_data(
116
114
  and attempts to download the data from both member and non-member URLs.
117
115
 
118
116
  Args:
119
- reference_date (DateScalar): The reference date for the data.
117
+ date (DateScalar): The reference date for the data.
120
118
  bond_type (str, optional): Filter data by bond type.
121
119
  Defaults to None, which returns data for all bond types.
122
120
 
@@ -126,8 +124,8 @@ def anbima_tpf_data(
126
124
  specified date.
127
125
  """
128
126
  # Normalize the reference date
129
- reference_date = dc.convert_input_dates(reference_date)
130
- file_content = _get_file_content(reference_date)
127
+ date = dc.convert_input_dates(date)
128
+ file_content = _get_file_content(date)
131
129
 
132
130
  if not file_content:
133
131
  return pd.DataFrame()
@@ -144,7 +142,7 @@ def anbima_tpf_data(
144
142
 
145
143
 
146
144
  def anbima_tpf_rates(
147
- reference_date: DateScalar,
145
+ date: DateScalar,
148
146
  bond_type: str | None = None,
149
147
  adj_maturities: bool = False,
150
148
  ) -> pd.DataFrame:
@@ -156,7 +154,7 @@ def anbima_tpf_rates(
156
154
  website using the :func:`data` function.
157
155
 
158
156
  Args:
159
- reference_date (DateScalar): The reference date for the rates.
157
+ date (DateScalar): The reference date for the rates.
160
158
  bond_type (str, optional): Filter rates by bond type.
161
159
  Defaults to None, which returns rates for all bond types.
162
160
  adj_maturities (bool, optional): Adjust maturity dates to the next
@@ -169,12 +167,12 @@ def anbima_tpf_rates(
169
167
  """
170
168
  df = get_anbima_dataset()
171
169
 
172
- reference_date = dc.convert_input_dates(reference_date)
173
- df.query("ReferenceDate == @reference_date", inplace=True)
170
+ date = dc.convert_input_dates(date)
171
+ df.query("ReferenceDate == @date", inplace=True)
174
172
 
175
173
  if df.empty:
176
174
  # Try to fetch the data from the Anbima website
177
- df = anbima_tpf_data(reference_date)
175
+ df = anbima_tpf_data(date)
178
176
 
179
177
  if df.empty:
180
178
  # If the data is still empty, return an empty DataFrame
@@ -190,7 +188,7 @@ def anbima_tpf_rates(
190
188
  return df.sort_values(["BondType", "MaturityDate"], ignore_index=True)
191
189
 
192
190
 
193
- def tpf_pre_maturities(reference_date: DateScalar) -> pd.Series:
191
+ def tpf_pre_maturities(date: DateScalar) -> pd.Series:
194
192
  """Retrieve pre-defined maturity dates for LTN and NTN-F bonds.
195
193
 
196
194
  This function fetches pre-defined maturity dates for 'LTN' (prefixadas) and
@@ -198,14 +196,14 @@ def tpf_pre_maturities(reference_date: DateScalar) -> pd.Series:
198
196
  for a given reference date.
199
197
 
200
198
  Args:
201
- reference_date (DateScalar): The reference date for maturity dates.
199
+ date (DateScalar): The reference date for maturity dates.
202
200
 
203
201
  Returns:
204
202
  pd.Series: A Series containing unique maturity dates for 'LTN' and
205
203
  'NTN-F' bonds, sorted in ascending order.
206
204
  """
207
205
  maturity_dates = (
208
- anbima_tpf_rates(reference_date)
206
+ anbima_tpf_rates(date)
209
207
  .query("BondType in ['LTN', 'NTN-F']")["MaturityDate"]
210
208
  .drop_duplicates()
211
209
  .sort_values(ignore_index=True)
@@ -15,7 +15,7 @@ ContractOptions = Literal["DI1", "DDI", "FRC", "DAP", "DOL", "WDO", "IND", "WIN"
15
15
 
16
16
  def futures(
17
17
  contract_code: ContractOptions,
18
- trade_date: DateScalar,
18
+ date: DateScalar,
19
19
  ) -> pd.DataFrame:
20
20
  """
21
21
  Fetches data for a specified futures contract based on type and reference date.
@@ -31,7 +31,7 @@ def futures(
31
31
  - "WDO": Mini U.S. Dollar Futures from B3.
32
32
  - "IND": Ibovespa Futures from B3.
33
33
  - "WIN": Mini Ibovespa Futures from B3.
34
- trade_date (DateScalar): The date for which to fetch the data.
34
+ date (DateScalar): The date for which to fetch the data.
35
35
  If the reference date is a string, it should be in 'DD-MM-YYYY' format.
36
36
 
37
37
  Returns:
@@ -58,14 +58,14 @@ def futures(
58
58
  ...
59
59
  """
60
60
  selected_contract = str(contract_code).upper()
61
- converted_trade_date = dc.convert_input_dates(trade_date)
61
+ converted_date = dc.convert_input_dates(date)
62
62
 
63
63
  # First, try to fetch historical data for the specified date
64
- df = fetch_historical_df(selected_contract, converted_trade_date)
64
+ df = fetch_historical_df(selected_contract, converted_date)
65
65
 
66
66
  bz_today = dt.datetime.now(TIMEZONE_BZ).date()
67
67
  # If there is no historical data available, try to fetch intraday data
68
- if converted_trade_date.date() == bz_today and df.empty:
68
+ if converted_date.date() == bz_today and df.empty:
69
69
  df = fetch_intraday_df(selected_contract)
70
70
 
71
71
  return df
@@ -17,7 +17,7 @@ class DIFutures:
17
17
  NTN-F bond maturities.
18
18
 
19
19
  Args:
20
- trade_date (DateScalar | None): The trade date to retrieve the
20
+ date (DateScalar | None): The trade date to retrieve the
21
21
  DI contract data. If None, the latest available historical trade date is
22
22
  used.
23
23
  month_start (bool): If True, adjusts the expirations to the start of the month.
@@ -28,7 +28,7 @@ class DIFutures:
28
28
 
29
29
  Examples:
30
30
  To create a `DIFutures` instance and retrieve data:
31
- >>> dif = yd.DIFutures(trade_date="16-10-2024", month_start=True)
31
+ >>> dif = yd.DIFutures(date="16-10-2024", month_start=True)
32
32
  >>> df = dif.df # Retrieve DI contract dataframe for the specified date
33
33
  >>> df.iloc[:5, :5] # Show the first five rows and columns
34
34
  TradeDate ExpirationDate TickerSymbol BDaysToExp OpenContracts
@@ -48,7 +48,7 @@ class DIFutures:
48
48
  4 2024-10-16 2025-03-01 0.1157 0.12343
49
49
  """
50
50
 
51
- historical_trade_dates = (
51
+ historical_dates = (
52
52
  get_di_dataset()
53
53
  .drop_duplicates(subset=["TradeDate"])["TradeDate"]
54
54
  .sort_values(ascending=True)
@@ -62,7 +62,7 @@ class DIFutures:
62
62
 
63
63
  def __init__(
64
64
  self,
65
- trade_date: DateScalar | None = None,
65
+ date: DateScalar | None = None,
66
66
  month_start: bool = False,
67
67
  pre_filter: bool = False,
68
68
  all_columns: bool = True,
@@ -77,7 +77,7 @@ class DIFutures:
77
77
  self._df = pd.DataFrame()
78
78
  self._dirty = True # Attribute to track if the df needs updating
79
79
 
80
- self.trade_date = trade_date
80
+ self.date = date
81
81
  self.month_start = month_start
82
82
  self.pre_filter = pre_filter
83
83
  self.all_columns = all_columns
@@ -102,14 +102,14 @@ class DIFutures:
102
102
  def _update_df(self) -> pd.DataFrame:
103
103
  """Retrieve DI contract DataFrame for the initialized trade date."""
104
104
  bz_today = pd.Timestamp.today(tz="America/Sao_Paulo").normalize()
105
- if bz_today == self.trade_date:
105
+ if bz_today == self.date:
106
106
  # Try to get intraday data
107
- df = b3.futures(contract_code="DI1", trade_date=bz_today)
107
+ df = b3.futures(contract_code="DI1", date=bz_today)
108
108
  else:
109
109
  # Get historical data
110
110
  df = (
111
111
  get_di_dataset()
112
- .query("TradeDate == @self._trade_date")
112
+ .query("TradeDate == @self._date")
113
113
  .reset_index(drop=True)
114
114
  )
115
115
 
@@ -123,7 +123,7 @@ class DIFutures:
123
123
  df_pre = (
124
124
  get_anbima_dataset()
125
125
  .query("BondType in ['LTN', 'NTN-F']")
126
- .query("ReferenceDate == @self._trade_date")[
126
+ .query("ReferenceDate == @self._date")[
127
127
  ["ReferenceDate", "MaturityDate"]
128
128
  ]
129
129
  .drop_duplicates()
@@ -197,7 +197,7 @@ class DIFutures:
197
197
 
198
198
  @staticmethod
199
199
  def interpolate_rates(
200
- trade_dates: DateScalar | DateArray,
200
+ dates: DateScalar | DateArray,
201
201
  expirations: DateScalar | DateArray,
202
202
  extrapolate: bool = True,
203
203
  ) -> pd.Series:
@@ -209,12 +209,12 @@ class DIFutures:
209
209
  dates and maturities using a flat-forward interpolation method. If no DI
210
210
  rates are available for a reference date, the interpolated rate is set to NaN.
211
211
 
212
- If trade_dates is provided as a scalar and expirations as an array, the
212
+ If dates is provided as a scalar and expirations as an array, the
213
213
  method assumes the scalar value is the same for all maturities. The same logic
214
214
  applies when the maturities are scalar and the trade dates are an array.
215
215
 
216
216
  Args:
217
- trade_dates (DateScalar | DateArray): The trade dates for the rates.
217
+ dates (DateScalar | DateArray): The trade dates for the rates.
218
218
  expirations (DateScalar | DateArray): The expirations corresponding to the
219
219
  trade dates.
220
220
  extrapolate (bool): Whether to allow extrapolation beyond known DI rates.
@@ -223,29 +223,29 @@ class DIFutures:
223
223
  pd.Series: A Series containing the interpolated DI rates.
224
224
 
225
225
  Raises:
226
- ValueError: If `reference_dates` and `maturities` have different lengths.
226
+ ValueError: If `dates` and `maturities` have different lengths.
227
227
  """
228
228
  # Convert input dates to a consistent format
229
- trade_dates = dc.convert_input_dates(trade_dates)
229
+ dates = dc.convert_input_dates(dates)
230
230
  expirations = dc.convert_input_dates(expirations)
231
231
 
232
232
  # Ensure the lengths of input arrays are consistent
233
- match (trade_dates, expirations):
233
+ match (dates, expirations):
234
234
  case pd.Timestamp(), pd.Series():
235
235
  dfi = pd.DataFrame({"mat": expirations})
236
- dfi["tdate"] = trade_dates
236
+ dfi["tdate"] = dates
237
237
 
238
238
  case pd.Series(), pd.Timestamp():
239
- dfi = pd.DataFrame({"tdate": trade_dates})
239
+ dfi = pd.DataFrame({"tdate": dates})
240
240
  dfi["mat"] = expirations
241
241
 
242
242
  case pd.Series(), pd.Series():
243
- if len(trade_dates) != len(expirations):
243
+ if len(dates) != len(expirations):
244
244
  raise ValueError("Args. should have the same length.")
245
- dfi = pd.DataFrame({"tdate": trade_dates, "mat": expirations})
245
+ dfi = pd.DataFrame({"tdate": dates, "mat": expirations})
246
246
 
247
247
  case pd.Timestamp(), pd.Timestamp():
248
- dfi = pd.DataFrame({"tdate": [trade_dates], "mat": [expirations]})
248
+ dfi = pd.DataFrame({"tdate": [dates], "mat": [expirations]})
249
249
 
250
250
  # Compute business days between reference dates and maturities
251
251
  dfi["bdays"] = bday.count(dfi["tdate"], dfi["mat"])
@@ -332,11 +332,11 @@ class DIFutures:
332
332
  known_rates=df["SettlementRate"],
333
333
  extrapolate=extrapolate,
334
334
  )
335
- bd = bday.count(self._trade_date, expiration)
335
+ bd = bday.count(self._date, expiration)
336
336
  return ff_interp(bd)
337
337
 
338
338
  @property
339
- def trade_date(self) -> pd.Timestamp:
339
+ def date(self) -> pd.Timestamp:
340
340
  """
341
341
  The trade date to retrieve the DI contract data.
342
342
 
@@ -347,14 +347,14 @@ class DIFutures:
347
347
  pd.Timestamp: The trade date set for this instance.
348
348
  """
349
349
 
350
- return self._trade_date
350
+ return self._date
351
351
 
352
- @trade_date.setter
353
- def trade_date(self, value: DateScalar | None):
352
+ @date.setter
353
+ def date(self, value: DateScalar | None):
354
354
  if value:
355
- self._trade_date = dc.convert_input_dates(value)
355
+ self._date = dc.convert_input_dates(value)
356
356
  else:
357
- self._trade_date = self.historical_trade_dates.max()
357
+ self._date = self.historical_dates.max()
358
358
 
359
359
  self._dirty = True
360
360
 
@@ -18,9 +18,7 @@ COUNT_CONVENTIONS = {
18
18
  }
19
19
 
20
20
 
21
- def get_old_expiration_date(
22
- expiration_code: str, trade_date: pd.Timestamp
23
- ) -> pd.Timestamp:
21
+ def get_old_expiration_date(expiration_code: str, date: pd.Timestamp) -> pd.Timestamp:
24
22
  """
25
23
  Internal function to convert an old DI contract code into its ExpirationDate date.
26
24
  Valid for contract codes up to 21-05-2006.
@@ -29,7 +27,7 @@ def get_old_expiration_date(
29
27
  expiration_code (str): An old DI Expiration Code from B3, where the first three
30
28
  letters represent the month and the last digit represents the year.
31
29
  Example: "JAN3".
32
- trade_date (pd.Timestamp): The trade date for which the contract code is valid.
30
+ date (pd.Timestamp): The trade date for which the contract code is valid.
33
31
 
34
32
  Returns:
35
33
  pd.Timestamp
@@ -64,7 +62,7 @@ def get_old_expiration_date(
64
62
  month = month_codes[month_code]
65
63
 
66
64
  # Year codes must generated dynamically, since it depends on the trade date.
67
- reference_year = trade_date.year
65
+ reference_year = date.year
68
66
  year_codes = {}
69
67
  for year in range(reference_year, reference_year + 10):
70
68
  year_codes[str(year)[-1:]] = year
@@ -105,18 +103,18 @@ def _convert_prices_to_rates(
105
103
  return rates.round(5)
106
104
 
107
105
 
108
- def _fetch_raw_df(contract_code: str, trade_date: pd.Timestamp) -> pd.DataFrame:
106
+ def _fetch_raw_df(contract_code: str, date: pd.Timestamp) -> pd.DataFrame:
109
107
  """
110
108
  Fetch the historical futures data from B3 for a specific trade date. If the data is
111
109
  not available, an empty DataFrame is returned.
112
110
 
113
111
  Args:
114
- trade_date (pd.Timestamp): The trade date for which the data should be fetched.
112
+ date (pd.Timestamp): The trade date for which the data should be fetched.
115
113
 
116
114
  Returns:
117
115
  pd.DataFrame: Raw DI data as a Pandas pd.DataFrame.
118
116
  """
119
- url_date = trade_date.strftime("%d/%m/%Y")
117
+ url_date = date.strftime("%d/%m/%Y")
120
118
  # url example: https://www2.bmf.com.br/pages/portal/bmfbovespa/boletim1/SistemaPregao_excel1.asp?Data=05/10/2023&Mercadoria=DI1
121
119
  url = f"https://www2.bmf.com.br/pages/portal/bmfbovespa/boletim1/SistemaPregao_excel1.asp?Data={url_date}&Mercadoria={contract_code}&XLS=false"
122
120
  r = requests.get(url, timeout=10)
@@ -185,19 +183,19 @@ def _rename_columns(df: pd.DataFrame) -> pd.DataFrame:
185
183
 
186
184
 
187
185
  def process_df(
188
- input_df: pd.DataFrame, trade_date: pd.Timestamp, asset_code: str
186
+ input_df: pd.DataFrame, date: pd.Timestamp, asset_code: str
189
187
  ) -> pd.DataFrame:
190
188
  df = input_df.copy()
191
- df["TradeDate"] = trade_date
189
+ df["TradeDate"] = date
192
190
  # Convert to datetime64[ns] since it is pandas default type for timestamps
193
191
  df["TradeDate"] = df["TradeDate"].astype("datetime64[ns]")
194
192
 
195
193
  df["TickerSymbol"] = asset_code + df["ExpirationCode"]
196
194
 
197
195
  # Contract code format was changed in 22/05/2006
198
- if trade_date < pd.Timestamp("2006-05-22"):
196
+ if date < pd.Timestamp("2006-05-22"):
199
197
  df["ExpirationDate"] = df["ExpirationCode"].apply(
200
- get_old_expiration_date, args=(trade_date,)
198
+ get_old_expiration_date, args=(date,)
201
199
  )
202
200
  else:
203
201
  expiration_day = 15 if asset_code == "DAP" else 1
@@ -205,11 +203,11 @@ def process_df(
205
203
  common.get_expiration_date, args=(expiration_day,)
206
204
  )
207
205
 
208
- df["DaysToExp"] = (df["ExpirationDate"] - trade_date).dt.days
206
+ df["DaysToExp"] = (df["ExpirationDate"] - date).dt.days
209
207
  # Convert to nullable integer, since it is the default type in the library
210
208
  df["DaysToExp"] = df["DaysToExp"].astype("Int64")
211
209
 
212
- df["BDaysToExp"] = bday.count(trade_date, df["ExpirationDate"])
210
+ df["BDaysToExp"] = bday.count(date, df["ExpirationDate"])
213
211
 
214
212
  # Remove expired contracts
215
213
  df.query("DaysToExp > 0", inplace=True)
@@ -223,7 +221,7 @@ def process_df(
223
221
 
224
222
  rate_cols = [col for col in df.columns if "Rate" in col]
225
223
  # Prior to 17/01/2002 (inclusive), DI prices were not converted to rates
226
- if trade_date <= pd.Timestamp("2002-01-17") and asset_code == "DI1":
224
+ if date <= pd.Timestamp("2002-01-17") and asset_code == "DI1":
227
225
  df = _adjust_older_contracts_rates(df, rate_cols)
228
226
  else:
229
227
  # Remove % and round to 5 (3 in %) dec. places in rate columns
@@ -281,7 +279,7 @@ def _select_and_reorder_columns(df: pd.DataFrame):
281
279
  return df[reordered_columns]
282
280
 
283
281
 
284
- def fetch_historical_df(contract_code: str, trade_date: pd.Timestamp) -> pd.DataFrame:
282
+ def fetch_historical_df(contract_code: str, date: pd.Timestamp) -> pd.DataFrame:
285
283
  """
286
284
  Fetchs the futures data for a given date from B3.
287
285
 
@@ -290,7 +288,7 @@ def fetch_historical_df(contract_code: str, trade_date: pd.Timestamp) -> pd.Data
290
288
 
291
289
  Args:
292
290
  asset_code (str): The asset code to fetch the futures data.
293
- trade_date (pd.Timestamp): The trade date to fetch the futures data.
291
+ date (pd.Timestamp): The trade date to fetch the futures data.
294
292
  count_convention (int): The count convention for the DI futures contract.
295
293
  Can be 252 business days or 360 calendar days.
296
294
 
@@ -298,11 +296,11 @@ def fetch_historical_df(contract_code: str, trade_date: pd.Timestamp) -> pd.Data
298
296
  pd.DataFrame: A Pandas pd.DataFrame containing processed futures data. If
299
297
  the data is not available, an empty DataFrame is returned.
300
298
  """
301
- df_raw = _fetch_raw_df(contract_code, trade_date)
299
+ df_raw = _fetch_raw_df(contract_code, date)
302
300
  if df_raw.empty:
303
301
  return df_raw
304
302
 
305
303
  df = _rename_columns(df_raw)
306
- df = process_df(df, trade_date, contract_code)
304
+ df = process_df(df, date, contract_code)
307
305
  df = _select_and_reorder_columns(df)
308
306
  return df
@@ -22,7 +22,7 @@ def _get_file_from_path(file_path: Path) -> io.BytesIO:
22
22
  return io.BytesIO(content)
23
23
 
24
24
 
25
- def _get_file_from_url(trade_date: pd.Timestamp, source_type: str) -> io.BytesIO:
25
+ def _get_file_from_url(date: pd.Timestamp, source_type: str) -> io.BytesIO:
26
26
  """
27
27
  Types of XML files available:
28
28
  Full Price Report (all assets)
@@ -33,12 +33,14 @@ def _get_file_from_url(trade_date: pd.Timestamp, source_type: str) -> io.BytesIO
33
33
  url example: https://www.b3.com.br/pesquisapregao/download?filelist=SPRD240216.zip
34
34
  """
35
35
 
36
- trade_date_str = trade_date.strftime("%y%m%d")
36
+ date_str = date.strftime("%y%m%d")
37
37
 
38
38
  if source_type == "PR":
39
- url = f"https://www.b3.com.br/pesquisapregao/download?filelist=PR{trade_date_str}.zip"
39
+ url = f"https://www.b3.com.br/pesquisapregao/download?filelist=PR{date_str}.zip"
40
40
  elif source_type == "SPR":
41
- url = f"https://www.b3.com.br/pesquisapregao/download?filelist=SPRD{trade_date_str}.zip"
41
+ url = (
42
+ f"https://www.b3.com.br/pesquisapregao/download?filelist=SPRD{date_str}.zip"
43
+ )
42
44
  else:
43
45
  raise ValueError("Invalid source type. Must be either 'PR' or 'SPR'.")
44
46
 
@@ -46,8 +48,8 @@ def _get_file_from_url(trade_date: pd.Timestamp, source_type: str) -> io.BytesIO
46
48
 
47
49
  # File will be considered invalid if it is too small
48
50
  if response.status_code != 200 or len(response.content) < 1024:
49
- trade_date_str = trade_date.strftime("%Y-%m-%d")
50
- raise ValueError(f"There is no data available for {trade_date_str}.")
51
+ date_str = date.strftime("%Y-%m-%d")
52
+ raise ValueError(f"There is no data available for {date_str}.")
51
53
 
52
54
  return io.BytesIO(response.content)
53
55
 
@@ -112,12 +114,12 @@ def _extract_data_from_xml(xml_file: io.BytesIO, asset_code: str) -> list[dict]:
112
114
  continue
113
115
 
114
116
  # Extract the trade date
115
- trade_date = price_report.find(".//ns:TradDt/ns:Dt", namespaces)
116
- if trade_date is None:
117
+ date = price_report.find(".//ns:TradDt/ns:Dt", namespaces)
118
+ if date is None:
117
119
  continue
118
120
 
119
121
  # Store the data in a dictionary
120
- ticker_data = {"TradDt": trade_date.text, "TckrSymb": ticker.text}
122
+ ticker_data = {"TradDt": date.text, "TckrSymb": ticker.text}
121
123
 
122
124
  # Extract the FinInstrmAttrbts element
123
125
  fin_instrm_attrbts = price_report.find(".//ns:FinInstrmAttrbts", namespaces)
@@ -260,9 +262,9 @@ def process_zip_file(zip_file: io.BytesIO, asset_code: str) -> pd.DataFrame:
260
262
 
261
263
 
262
264
  def fetch_df(
263
- trade_date: pd.Timestamp, asset_code: str, source_type: Literal["PR", "SPR"]
265
+ date: pd.Timestamp, asset_code: str, source_type: Literal["PR", "SPR"]
264
266
  ) -> pd.DataFrame:
265
- zip_file = _get_file_from_url(trade_date, source_type)
267
+ zip_file = _get_file_from_url(date, source_type)
266
268
  df = process_zip_file(zip_file, asset_code)
267
269
  return df
268
270
 
@@ -19,7 +19,7 @@ MAX_ATTEMPTS = 10
19
19
 
20
20
  def indicator(
21
21
  indicator_code: Literal["IPCA_MR", "SELIC_TARGET", "SELIC_OVER", "DI", "VNA_LFT"],
22
- reference_date: DateScalar,
22
+ date: DateScalar,
23
23
  ) -> float:
24
24
  """
25
25
  Fetches the economic indicator value for a specified reference date.
@@ -37,7 +37,7 @@ def indicator(
37
37
  - "SELIC_OVER": SELIC Over (overnight) rate.
38
38
  - "DI": DI (interbank deposit rate).
39
39
  - "VNA_LFT": Valor Nominal Atualizado for LFT (Treasury Bills).
40
- reference_date (DateScalar): The date for which the indicator value is
40
+ date (DateScalar): The date for which the indicator value is
41
41
  fetched. If passed as a string, it should be in 'DD-MM-YYYY' format.
42
42
 
43
43
  Returns:
@@ -65,7 +65,7 @@ def indicator(
65
65
  0.104
66
66
 
67
67
  """
68
- converted_date = dc.convert_input_dates(reference_date)
68
+ converted_date = dc.convert_input_dates(date)
69
69
  selected_indicator_code = str(indicator_code).upper()
70
70
  match selected_indicator_code:
71
71
  case "IPCA_MR":
@@ -82,7 +82,7 @@ def indicator(
82
82
  raise ValueError("Invalid indicator code provided")
83
83
 
84
84
 
85
- def ipca_monthly_rate(reference_date: pd.Timestamp) -> float:
85
+ def ipca_monthly_rate(date: pd.Timestamp) -> float:
86
86
  """
87
87
  The function makes an API call to the IBGE's data portal to retrieve the data.
88
88
  An example of the API call: https://servicodados.ibge.gov.br/api/v3/agregados/6691/periodos/202403/variaveis/63?localidades=N1[all]
@@ -90,14 +90,14 @@ def ipca_monthly_rate(reference_date: pd.Timestamp) -> float:
90
90
  The API URL is constructed dynamically based on the reference date provided.
91
91
  """
92
92
  # Format the date as 'YYYYMM' for the API endpoint
93
- ipca_date = reference_date.strftime("%Y%m")
93
+ ipca_date = date.strftime("%Y%m")
94
94
 
95
95
  # Construct the API URL using the formatted date
96
96
  api_url = f"https://servicodados.ibge.gov.br/api/v3/agregados/6691/periodos/{ipca_date}/variaveis/63?localidades=N1[all]"
97
97
 
98
98
  def process_ipca_response(data):
99
99
  if not data:
100
- msg = f"No data available for IPCA Monthly Rate on {reference_date}"
100
+ msg = f"No data available for IPCA Monthly Rate on {date}"
101
101
  logger.warning(msg)
102
102
  return float("nan")
103
103
  ipca_str = data[0]["resultados"][0]["series"][0]["serie"][ipca_date]
@@ -106,28 +106,28 @@ def ipca_monthly_rate(reference_date: pd.Timestamp) -> float:
106
106
  return _fetch_with_retry(api_url, "IPCA Monthly Rate", process_ipca_response, True)
107
107
 
108
108
 
109
- def _selic_target(reference_date: pd.Timestamp) -> float:
109
+ def _selic_target(date: pd.Timestamp) -> float:
110
110
  """
111
111
  Fetches the SELIC Target rate for a specific reference date.
112
112
 
113
113
  The SELIC Target rate is the official rate set by the Central Bank of Brazil.
114
114
 
115
115
  Args:
116
- reference_date (pd.Timestamp): The date for which to fetch the SELIC Target.
116
+ date (pd.Timestamp): The date for which to fetch the SELIC Target.
117
117
 
118
118
  Returns:
119
119
  float: The SELIC Target rate as a float rounded to 4 decimal places or NaN if
120
120
  the rate is not available.
121
121
  """
122
122
  # https://api.bcb.gov.br/dados/serie/bcdata.sgs.432/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
123
- selic_date = reference_date.strftime("%d/%m/%Y")
123
+ selic_date = date.strftime("%d/%m/%Y")
124
124
  api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.432/dados?formato=csv&dataInicial={selic_date}&dataFinal={selic_date}"
125
125
 
126
126
  def process_selic_target_response(data):
127
127
  csv_data = io.StringIO(data)
128
128
  df = pd.read_csv(csv_data, sep=";", decimal=",")
129
129
  if df.empty or "valor" not in df.columns:
130
- msg = f"No data available for SELIC Target rate on {reference_date}"
130
+ msg = f"No data available for SELIC Target rate on {date}"
131
131
  logger.warning(msg)
132
132
  return float("nan")
133
133
  value = float(df["valor"].iloc[0] / 100) # SELIC Target rate
@@ -138,7 +138,7 @@ def _selic_target(reference_date: pd.Timestamp) -> float:
138
138
  )
139
139
 
140
140
 
141
- def _selic_over(reference_date: pd.Timestamp) -> float:
141
+ def _selic_over(date: pd.Timestamp) -> float:
142
142
  """
143
143
  Fetches the SELIC Over rate for a specific reference date.
144
144
 
@@ -146,14 +146,14 @@ def _selic_over(reference_date: pd.Timestamp) -> float:
146
146
  between banks in the interbank market, using public securities as collateral.
147
147
 
148
148
  Args:
149
- reference_date (pd.Timestamp): The date for which to fetch the SELIC Over rate.
149
+ date (pd.Timestamp): The date for which to fetch the SELIC Over rate.
150
150
 
151
151
  Returns:
152
152
  float: The SELIC Over rate as a float rounded to 4 decimal places or NaN if
153
153
  the rate is not available.
154
154
  """
155
155
 
156
- formatted_date = reference_date.strftime("%d/%m/%Y")
156
+ formatted_date = date.strftime("%d/%m/%Y")
157
157
  # https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
158
158
  api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=csv&dataInicial={formatted_date}&dataFinal={formatted_date}"
159
159
 
@@ -161,7 +161,7 @@ def _selic_over(reference_date: pd.Timestamp) -> float:
161
161
  csv_data = io.StringIO(data)
162
162
  df = pd.read_csv(csv_data, sep=";", decimal=",")
163
163
  if df.empty or "valor" not in df.columns:
164
- msg = f"No data available for SELIC Over rate on {reference_date}"
164
+ msg = f"No data available for SELIC Over rate on {date}"
165
165
  logger.warning(msg)
166
166
  return float("nan")
167
167
  value = float(df["valor"].iloc[0] / 100) # SELIC Over daily rate
@@ -170,16 +170,16 @@ def _selic_over(reference_date: pd.Timestamp) -> float:
170
170
  return _fetch_with_retry(api_url, "SELIC Over", process_selic_over_response, False)
171
171
 
172
172
 
173
- def _di(reference_date: pd.Timestamp) -> float:
173
+ def _di(date: pd.Timestamp) -> float:
174
174
  # https://api.bcb.gov.br/dados/serie/bcdata.sgs.11/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
175
- di_date = reference_date.strftime("%d/%m/%Y")
175
+ di_date = date.strftime("%d/%m/%Y")
176
176
  api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.11/dados?formato=csv&dataInicial={di_date}&dataFinal={di_date}"
177
177
 
178
178
  def process_di_response(data):
179
179
  csv_data = io.StringIO(data)
180
180
  df = pd.read_csv(csv_data, sep=";", decimal=",")
181
181
  if df.empty or "valor" not in df.columns:
182
- logger.warning(f"No data available for DI rate on {reference_date}")
182
+ logger.warning(f"No data available for DI rate on {date}")
183
183
  return float("nan")
184
184
  value = float(df["valor"].iloc[0] / 100) # DI daily rate
185
185
  return round((1 + value) ** 252 - 1, 4) # Annualize the daily rate
@@ -187,10 +187,10 @@ def _di(reference_date: pd.Timestamp) -> float:
187
187
  return _fetch_with_retry(api_url, "DI Over", process_di_response, False)
188
188
 
189
189
 
190
- def _vna_lft(reference_date: pd.Timestamp) -> float:
190
+ def _vna_lft(date: pd.Timestamp) -> float:
191
191
  # url example: https://www3.bcb.gov.br/novoselic/rest/arquivosDiarios/pub/download/3/20240418APC238
192
192
  url_base = "https://www3.bcb.gov.br/novoselic/rest/arquivosDiarios/pub/download/3/"
193
- url_file = f"{reference_date.strftime('%Y%m%d')}APC238"
193
+ url_file = f"{date.strftime('%Y%m%d')}APC238"
194
194
  url_vna = url_base + url_file
195
195
 
196
196
  def _process_vna_response(text: str) -> float:
@@ -1,11 +1,8 @@
1
- import io
2
1
  import locale
3
2
  from dataclasses import dataclass
4
3
  from typing import Literal
5
4
 
6
5
  import pandas as pd
7
- import python_calamine as pc
8
- import requests
9
6
 
10
7
 
11
8
  @dataclass
@@ -62,32 +59,23 @@ def ipca_current_month() -> IndicatorProjection:
62
59
  """
63
60
  # Define the URL and get the data
64
61
  url = "https://www.anbima.com.br/informacoes/indicadores/arqs/indicadores.xls"
65
- response = requests.get(url, timeout=10)
66
- excel_data = io.BytesIO(response.content)
62
+ df = pd.read_excel(url)
67
63
 
68
- # Load the workbook and select the first sheet
69
- workbook = pc.load_workbook(excel_data)
70
- first_sheet = workbook.sheet_names[0]
71
- data = workbook.get_sheet_by_name(first_sheet).to_python(skip_empty_area=True)
64
+ last_update_str = df.columns[0].split("Atualização:")[-1].strip()
72
65
 
73
- # Extract projection update date and time from the first row
74
- update_str = str(data[0][0])
75
- last_update_str = update_str.split("Atualização:")[-1].strip()
76
-
77
- # Find the text containing the IPCA projection and extract its data
78
- ipca_data = next(line for line in data if "IPCA1" in line)
79
- ipca_text = str(ipca_data[-1])
66
+ ipca_row = df[df.iloc[:, 0] == "IPCA1"]
67
+ ipca_date = ipca_row.iloc[0, 1]
68
+ ipca_value = ipca_row.iloc[0, 2]
80
69
 
81
70
  # Extract and format the reference month
82
- projection_text = str(ipca_data[1])
83
- month_str = projection_text.split("(")[-1].split(")")[0]
71
+ ipca_date = ipca_date.split("(")[-1].split(")")[0]
84
72
  locale.setlocale(locale.LC_TIME, "pt_BR.UTF-8")
85
- ipca_month_ts = pd.to_datetime(month_str, format="%b/%y")
86
- reference_period = ipca_month_ts.to_period("M")
73
+ ipca_date = pd.to_datetime(ipca_date, format="%b/%y")
74
+ reference_period = ipca_date.to_period("M")
87
75
  locale.setlocale(locale.LC_TIME, "") # Reset locale to default
88
76
 
89
77
  return IndicatorProjection(
90
78
  last_updated=pd.to_datetime(last_update_str, format="%d/%m/%Y - %H:%M h"),
91
79
  reference_period=reference_period,
92
- projected_value=round(float(ipca_text) / 100, 4),
80
+ projected_value=round(float(ipca_value) / 100, 4),
93
81
  )
@@ -7,33 +7,33 @@ from pyield.date_converter import DateScalar
7
7
  from pyield.tpf import tools as tt
8
8
 
9
9
 
10
- def rates(reference_date: DateScalar) -> pd.DataFrame:
10
+ def rates(date: DateScalar) -> pd.DataFrame:
11
11
  """
12
12
  Fetch the bond Anbima indicative rates for the given reference date.
13
13
 
14
14
  Args:
15
- reference_date (DateScalar): The reference date for fetching the data.
15
+ date (DateScalar): The reference date for fetching the data.
16
16
 
17
17
  Returns:
18
18
  pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
19
19
  """
20
- lft_rates = tpf.anbima_tpf_rates(reference_date, "LFT")
20
+ lft_rates = tpf.anbima_tpf_rates(date, "LFT")
21
21
  if lft_rates.empty:
22
22
  return pd.DataFrame()
23
23
  return lft_rates[["MaturityDate", "IndicativeRate"]]
24
24
 
25
25
 
26
- def maturities(reference_date: DateScalar) -> pd.Series:
26
+ def maturities(date: DateScalar) -> pd.Series:
27
27
  """
28
28
  Fetch the bond maturities available for the given reference date.
29
29
 
30
30
  Args:
31
- reference_date (DateScalar): The reference date for fetching the data.
31
+ date (DateScalar): The reference date for fetching the data.
32
32
 
33
33
  Returns:
34
34
  pd.Series: A Series of bond maturities available for the reference date.
35
35
  """
36
- df_rates = rates(reference_date)
36
+ df_rates = rates(date)
37
37
  return df_rates["MaturityDate"]
38
38
 
39
39
 
@@ -10,12 +10,12 @@ from pyield.tpf import tools as tt
10
10
  FACE_VALUE = 1000
11
11
 
12
12
 
13
- def rates(reference_date: DateScalar) -> pd.DataFrame:
13
+ def rates(date: DateScalar) -> pd.DataFrame:
14
14
  """
15
15
  Fetch the LTN Anbima indicative rates for the given reference date.
16
16
 
17
17
  Args:
18
- reference_date (DateScalar): The reference date for fetching the data.
18
+ date (DateScalar): The reference date for fetching the data.
19
19
 
20
20
  Returns:
21
21
  pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
@@ -38,18 +38,18 @@ def rates(reference_date: DateScalar) -> pd.DataFrame:
38
38
  12 2030-01-01 0.118746
39
39
 
40
40
  """
41
- ltn_rates = tpf.anbima_tpf_rates(reference_date, "LTN")
41
+ ltn_rates = tpf.anbima_tpf_rates(date, "LTN")
42
42
  if ltn_rates.empty:
43
43
  return pd.DataFrame()
44
44
  return ltn_rates[["MaturityDate", "IndicativeRate"]]
45
45
 
46
46
 
47
- def maturities(reference_date: DateScalar) -> pd.Series:
47
+ def maturities(date: DateScalar) -> pd.Series:
48
48
  """
49
49
  Fetch the bond maturities available for the given reference date.
50
50
 
51
51
  Args:
52
- reference_date (DateScalar): The reference date for fetching the data.
52
+ date (DateScalar): The reference date for fetching the data.
53
53
 
54
54
  Returns:
55
55
  pd.Series: A Series of bond maturities available for the reference date.
@@ -72,7 +72,7 @@ def maturities(reference_date: DateScalar) -> pd.Series:
72
72
  dtype: datetime64[ns]
73
73
 
74
74
  """
75
- df_rates = rates(reference_date)
75
+ df_rates = rates(date)
76
76
  s_maturities = df_rates["MaturityDate"]
77
77
  s_maturities.name = None
78
78
  return s_maturities
@@ -121,7 +121,7 @@ def price(
121
121
  return tt.truncate(FACE_VALUE / discount_factor, 6)
122
122
 
123
123
 
124
- def di_spreads(reference_date: DateScalar) -> pd.DataFrame:
124
+ def di_spreads(date: DateScalar) -> pd.DataFrame:
125
125
  """
126
126
  Calculates the DI spread for the LTN based on ANBIMA's indicative rates.
127
127
 
@@ -129,7 +129,7 @@ def di_spreads(reference_date: DateScalar) -> pd.DataFrame:
129
129
  rates and calculates the spread between these rates in basis points.
130
130
 
131
131
  Parameters:
132
- reference_date (DateScalar, optional): The reference date for the
132
+ date (DateScalar, optional): The reference date for the
133
133
  spread calculation.
134
134
 
135
135
  Returns:
@@ -153,7 +153,7 @@ def di_spreads(reference_date: DateScalar) -> pd.DataFrame:
153
153
  12 2030-01-01 14.96
154
154
  """
155
155
  # Fetch DI Spreads for the reference date
156
- df = tt.pre_spreads(reference_date)
156
+ df = tt.pre_spreads(date)
157
157
  df.query("BondType == 'LTN'", inplace=True)
158
158
  df.sort_values(["MaturityDate"], ignore_index=True, inplace=True)
159
159
  return df[["MaturityDate", "DISpread"]]
@@ -186,14 +186,14 @@ def premium(ltn_rate: float, di_rate: float) -> float:
186
186
 
187
187
 
188
188
  def historical_premium(
189
- reference_date: DateScalar,
189
+ date: DateScalar,
190
190
  maturity: DateScalar,
191
191
  ) -> float:
192
192
  """
193
193
  Calculate the premium of the LTN bond over the DI Future rate for a given date.
194
194
 
195
195
  Args:
196
- reference_date (DateScalar): The reference date to fetch the rates.
196
+ date (DateScalar): The reference date to fetch the rates.
197
197
  maturity (DateScalar): The maturity date of the LTN bond.
198
198
 
199
199
  Returns:
@@ -206,11 +206,11 @@ def historical_premium(
206
206
 
207
207
  """
208
208
  # Convert input dates to a consistent format
209
- reference_date = dc.convert_input_dates(reference_date)
209
+ date = dc.convert_input_dates(date)
210
210
  maturity = dc.convert_input_dates(maturity)
211
211
 
212
212
  # Retrieve LTN rates for the reference date
213
- df_anbima = rates(reference_date)
213
+ df_anbima = rates(date)
214
214
  if df_anbima.empty:
215
215
  return float("NaN")
216
216
 
@@ -221,7 +221,7 @@ def historical_premium(
221
221
  ltn_rate = float(ltn_rates.iloc[0])
222
222
 
223
223
  # Retrieve DI rate for the reference date and maturity
224
- dif = di.DIFutures(trade_date=reference_date)
224
+ dif = di.DIFutures(date=date)
225
225
  di_rate = dif.rate(expiration=maturity, interpolate=True, extrapolate=False)
226
226
  if pd.isnull(di_rate): # Check if the DI rate is NaN
227
227
  return float("NaN")
@@ -53,12 +53,12 @@ def _check_maturities(
53
53
  raise ValueError("NTN-B maturity must be 15/02, 15/05, 15/08 or 15/11.")
54
54
 
55
55
 
56
- def rates(reference_date: DateScalar) -> pd.DataFrame:
56
+ def rates(date: DateScalar) -> pd.DataFrame:
57
57
  """
58
58
  Fetch the bond indicative rates for the given reference date.
59
59
 
60
60
  Args:
61
- reference_date (DateScalar): The reference date for fetching the data.
61
+ date (DateScalar): The reference date for fetching the data.
62
62
 
63
63
  Returns:
64
64
  pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
@@ -86,18 +86,18 @@ def rates(reference_date: DateScalar) -> pd.DataFrame:
86
86
  13 2060-08-15 0.060179
87
87
 
88
88
  """
89
- ntnb_rates = tpf.anbima_tpf_rates(reference_date, "NTN-B")
89
+ ntnb_rates = tpf.anbima_tpf_rates(date, "NTN-B")
90
90
  if ntnb_rates.empty:
91
91
  return pd.DataFrame()
92
92
  return ntnb_rates[["MaturityDate", "IndicativeRate"]]
93
93
 
94
94
 
95
- def maturities(reference_date: DateScalar) -> pd.Series:
95
+ def maturities(date: DateScalar) -> pd.Series:
96
96
  """
97
97
  Get the bond maturities available for the given reference date.
98
98
 
99
99
  Args:
100
- reference_date (DateScalar): The reference date for fetching the data.
100
+ date (DateScalar): The reference date for fetching the data.
101
101
 
102
102
  Returns:
103
103
  pd.Series: Series containing the maturity dates for the NTN-B bonds.
@@ -122,7 +122,7 @@ def maturities(reference_date: DateScalar) -> pd.Series:
122
122
  dtype: datetime64[ns]
123
123
 
124
124
  """
125
- df_rates = rates(reference_date)
125
+ df_rates = rates(date)
126
126
  s_maturities = df_rates["MaturityDate"]
127
127
  s_maturities.name = None
128
128
  return s_maturities
@@ -3,7 +3,7 @@ from collections.abc import Callable
3
3
  import numpy as np
4
4
  import pandas as pd
5
5
 
6
- from pyield import bday, data_cache
6
+ from pyield import bday
7
7
  from pyield import date_converter as dc
8
8
  from pyield import interpolator as ip
9
9
  from pyield.anbima import tpf
@@ -24,23 +24,12 @@ COUPON_PMT = 48.80885
24
24
  FINAL_PMT = 1048.80885
25
25
 
26
26
 
27
- def reference_dates() -> pd.Series:
28
- """
29
- Fetch the NTN-F bond reference dates available in the Anbima database.
30
-
31
- Returns:
32
- pd.Series: A Series of NTN-F bond reference dates.
33
- """
34
- df = data_cache.get_anbima_dataset().query("BondType == 'NTN-F'")
35
- return df["ReferenceDate"].drop_duplicates().sort_values().reset_index(drop=True)
36
-
37
-
38
- def rates(reference_date: DateScalar) -> pd.DataFrame:
27
+ def rates(date: DateScalar) -> pd.DataFrame:
39
28
  """
40
29
  Fetch the bond indicative rates for the given reference date.
41
30
 
42
31
  Args:
43
- reference_date (DateScalar): The reference date for fetching the data.
32
+ date (DateScalar): The reference date for fetching the data.
44
33
 
45
34
  Returns:
46
35
  pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
@@ -55,18 +44,18 @@ def rates(reference_date: DateScalar) -> pd.DataFrame:
55
44
  4 2033-01-01 0.116307
56
45
  5 2035-01-01 0.116586
57
46
  """
58
- ntnf_rates = tpf.anbima_tpf_rates(reference_date, "NTN-F")
47
+ ntnf_rates = tpf.anbima_tpf_rates(date, "NTN-F")
59
48
  if ntnf_rates.empty:
60
49
  return pd.DataFrame()
61
50
  return ntnf_rates[["MaturityDate", "IndicativeRate"]]
62
51
 
63
52
 
64
- def maturities(reference_date: DateScalar) -> pd.Series:
53
+ def maturities(date: DateScalar) -> pd.Series:
65
54
  """
66
55
  Fetch the NTN-F bond maturities available for the given reference date.
67
56
 
68
57
  Args:
69
- reference_date (DateScalar): The reference date for fetching the data.
58
+ date (DateScalar): The reference date for fetching the data.
70
59
 
71
60
  Returns:
72
61
  pd.Series: A Series of NTN-F bond maturities available for the reference date.
@@ -82,7 +71,7 @@ def maturities(reference_date: DateScalar) -> pd.Series:
82
71
  dtype: datetime64[ns]
83
72
 
84
73
  """
85
- df_rates = rates(reference_date)
74
+ df_rates = rates(date)
86
75
  s_maturities = df_rates["MaturityDate"]
87
76
  s_maturities.name = None
88
77
  return s_maturities
@@ -341,7 +330,7 @@ def spot_rates( # noqa
341
330
  return df
342
331
 
343
332
 
344
- def di_spreads(reference_date: DateScalar) -> pd.DataFrame:
333
+ def di_spreads(date: DateScalar) -> pd.DataFrame:
345
334
  """
346
335
  Calculates the DI spread for the NTN-F based on ANBIMA's indicative rates.
347
336
 
@@ -349,7 +338,7 @@ def di_spreads(reference_date: DateScalar) -> pd.DataFrame:
349
338
  rates and calculates the spread between these rates in basis points.
350
339
 
351
340
  Parameters:
352
- reference_date (DateScalar): The reference date for the spread calculation.
341
+ date (DateScalar): The reference date for the spread calculation.
353
342
 
354
343
  Returns:
355
344
  pd.DataFrame: DataFrame with columns "MaturityDate", "DISpread".
@@ -366,7 +355,7 @@ def di_spreads(reference_date: DateScalar) -> pd.DataFrame:
366
355
 
367
356
  """
368
357
  # Fetch DI Spreads for the reference date
369
- df = tt.pre_spreads(reference_date)
358
+ df = tt.pre_spreads(date)
370
359
  df = (
371
360
  df.query("BondType == 'NTN-F'")
372
361
  .sort_values(["MaturityDate"])
@@ -587,13 +576,13 @@ def premium(
587
576
 
588
577
 
589
578
  def historical_premium(
590
- reference_date: DateScalar,
579
+ date: DateScalar,
591
580
  maturity: DateScalar,
592
581
  ) -> float:
593
- reference_date = dc.convert_input_dates(reference_date)
582
+ date = dc.convert_input_dates(date)
594
583
  maturity = dc.convert_input_dates(maturity)
595
584
 
596
- df_ntnf = rates(reference_date)
585
+ df_ntnf = rates(date)
597
586
  if df_ntnf.empty:
598
587
  return float("NaN")
599
588
 
@@ -602,14 +591,14 @@ def historical_premium(
602
591
  return float("NaN")
603
592
  ntnf_ytm = float(ntnf_ytms.iloc[0])
604
593
 
605
- df = cash_flows(reference_date, maturity, adj_payment_dates=True)
606
- df["BDToMat"] = bday.count(reference_date, df["PaymentDate"])
594
+ df = cash_flows(date, maturity, adj_payment_dates=True)
595
+ df["BDToMat"] = bday.count(date, df["PaymentDate"])
607
596
  df["BYears"] = df["BDToMat"] / 252
608
- df["ReferenceDate"] = reference_date
597
+ df["ReferenceDate"] = date
609
598
 
610
599
  dif = di.DIFutures() # Instantiate the DI Futures class
611
600
  df["DIRate"] = dif.interpolate_rates(
612
- trade_dates=df["ReferenceDate"],
601
+ dates=df["ReferenceDate"],
613
602
  expirations=df["PaymentDate"],
614
603
  extrapolate=False,
615
604
  )
@@ -58,7 +58,7 @@ def calculate_present_value(
58
58
  return (cash_flows / (1 + rates) ** periods).sum()
59
59
 
60
60
 
61
- def pre_spreads(reference_date: DateScalar) -> pd.DataFrame:
61
+ def pre_spreads(date: DateScalar) -> pd.DataFrame:
62
62
  """
63
63
  Calculates the DI spread for Brazilian treasury bonds (LTN and NTN-F) based on
64
64
  ANBIMA's indicative rates.
@@ -69,15 +69,15 @@ def pre_spreads(reference_date: DateScalar) -> pd.DataFrame:
69
69
  provided, the function uses the previous business day.
70
70
 
71
71
  Parameters:
72
- reference_date (DateScalar): The reference date for the spread calculation.
72
+ date (DateScalar): The reference date for the spread calculation.
73
73
 
74
74
  Returns:
75
75
  pd.DataFrame: DataFrame containing the bond type, maturity date and the
76
76
  calculated spread in basis points.
77
77
  """
78
78
  # Fetch DI rates for the reference date
79
- converted_date = dc.convert_input_dates(reference_date)
80
- di = DIFutures(trade_date=converted_date, month_start=True)
79
+ converted_date = dc.convert_input_dates(date)
80
+ di = DIFutures(date=converted_date, month_start=True)
81
81
  df_di = di.df
82
82
  if "SettlementRate" not in df_di.columns:
83
83
  raise ValueError("DI rates data is missing the 'SettlementRate' column.")
@@ -14,9 +14,8 @@ classifiers = [
14
14
  "Topic :: Office/Business :: Financial :: Investment",
15
15
  ]
16
16
  dependencies = [
17
- "pandas[html,parquet]>=2.0.0",
18
- "numpy>=2.0.0",
19
- "python-calamine>=0.2.0",
17
+ "pandas[html,parquet,excel]>=2.0.0",
18
+ "numpy>=2.0.0",
20
19
  "requests>=2.31.0",
21
20
  ]
22
21
  dynamic = ["version"]
@@ -1 +0,0 @@
1
- __version__ = "0.28.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