PYield 0.22.2__tar.gz → 0.23.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyield-0.22.2 → pyield-0.23.0}/PKG-INFO +1 -1
- pyield-0.23.0/pyield/__about__.py +1 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/bonds/bond_tools.py +1 -1
- {pyield-0.22.2 → pyield-0.23.0}/pyield/bonds/ntnb.py +76 -3
- {pyield-0.22.2 → pyield-0.23.0}/pyield/di.py +36 -19
- {pyield-0.22.2 → pyield-0.23.0}/pyield/indicators.py +71 -37
- {pyield-0.22.2 → pyield-0.23.0}/pyproject.toml +1 -1
- pyield-0.22.2/pyield/__about__.py +0 -1
- {pyield-0.22.2 → pyield-0.23.0}/LICENSE +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/README.md +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/__init__.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/anbima.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/b3_futures/__init__.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/b3_futures/common.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/b3_futures/historical.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/b3_futures/intraday.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/b3_futures/xml.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/bday.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/bonds/__init__.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/bonds/lft.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/bonds/ltn.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/bonds/ntnf.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/conftest.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/data_cache.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/date_converter.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/holidays/__init__.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/holidays/br_holidays_old.txt +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/holidays/brholidays.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/interpolator.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/projections.py +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/py.typed +0 -0
- {pyield-0.22.2 → pyield-0.23.0}/pyield/tools.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.23.0"
|
|
@@ -79,7 +79,7 @@ def di_spreads(reference_date: str | pd.Timestamp) -> pd.DataFrame:
|
|
|
79
79
|
# Fetch DI rates for the reference date
|
|
80
80
|
reference_date = dc.convert_input_dates(reference_date)
|
|
81
81
|
di = DIFutures(reference_date, adj_expirations=True)
|
|
82
|
-
df_di = di.data
|
|
82
|
+
df_di = di.data
|
|
83
83
|
if "SettlementRate" not in df_di.columns:
|
|
84
84
|
raise ValueError("DI rates data is missing the 'SettlementRate' column.")
|
|
85
85
|
|
|
@@ -60,6 +60,29 @@ def rates(reference_date: str | pd.Timestamp) -> pd.DataFrame:
|
|
|
60
60
|
|
|
61
61
|
Returns:
|
|
62
62
|
pd.DataFrame: DataFrame with columns "MaturityDate" and "IndicativeRate".
|
|
63
|
+
|
|
64
|
+
Returned columns:
|
|
65
|
+
- MaturityDate: The maturity date of the bond.
|
|
66
|
+
- IndicativeRate: The indicative rate for the bond.
|
|
67
|
+
|
|
68
|
+
Examples:
|
|
69
|
+
>>> yd.ntnb.rates("16-08-2024")
|
|
70
|
+
MaturityDate IndicativeRate
|
|
71
|
+
0 2025-05-15 0.063893
|
|
72
|
+
1 2026-08-15 0.066095
|
|
73
|
+
2 2027-05-15 0.064164
|
|
74
|
+
3 2028-08-15 0.063199
|
|
75
|
+
4 2029-05-15 0.061753
|
|
76
|
+
5 2030-08-15 0.059997
|
|
77
|
+
6 2032-08-15 0.060025
|
|
78
|
+
7 2033-05-15 0.059876
|
|
79
|
+
8 2035-05-15 0.059557
|
|
80
|
+
9 2040-08-15 0.058873
|
|
81
|
+
10 2045-05-15 0.060013
|
|
82
|
+
11 2050-08-15 0.060247
|
|
83
|
+
12 2055-05-15 0.059926
|
|
84
|
+
13 2060-08-15 0.060179
|
|
85
|
+
|
|
63
86
|
"""
|
|
64
87
|
ntnb_rates = anbima.rates(reference_date, "NTN-B")
|
|
65
88
|
if ntnb_rates.empty:
|
|
@@ -76,9 +99,31 @@ def maturities(reference_date: str | pd.Timestamp) -> pd.Series:
|
|
|
76
99
|
|
|
77
100
|
Returns:
|
|
78
101
|
pd.Series: Series containing the maturity dates for the NTN-B bonds.
|
|
102
|
+
|
|
103
|
+
Examples:
|
|
104
|
+
|
|
105
|
+
>>> yd.ntnb.maturities("16-08-2024")
|
|
106
|
+
0 2025-05-15
|
|
107
|
+
1 2026-08-15
|
|
108
|
+
2 2027-05-15
|
|
109
|
+
3 2028-08-15
|
|
110
|
+
4 2029-05-15
|
|
111
|
+
5 2030-08-15
|
|
112
|
+
6 2032-08-15
|
|
113
|
+
7 2033-05-15
|
|
114
|
+
8 2035-05-15
|
|
115
|
+
9 2040-08-15
|
|
116
|
+
10 2045-05-15
|
|
117
|
+
11 2050-08-15
|
|
118
|
+
12 2055-05-15
|
|
119
|
+
13 2060-08-15
|
|
120
|
+
dtype: datetime64[ns]
|
|
121
|
+
|
|
79
122
|
"""
|
|
80
123
|
df_rates = rates(reference_date)
|
|
81
|
-
|
|
124
|
+
s_maturities = df_rates["MaturityDate"]
|
|
125
|
+
s_maturities.name = None
|
|
126
|
+
return s_maturities
|
|
82
127
|
|
|
83
128
|
|
|
84
129
|
def _generate_coupon_dates_map(
|
|
@@ -236,6 +281,8 @@ def quotation(
|
|
|
236
281
|
99.3651
|
|
237
282
|
>>> yd.ntnb.quotation("31-05-2024", "15-08-2060", 0.061878)
|
|
238
283
|
99.5341
|
|
284
|
+
>>> yd.ntnb.quotation("15-08-2024", "15-08-2032", 0.05929)
|
|
285
|
+
100.6409
|
|
239
286
|
"""
|
|
240
287
|
# Validate and normalize dates
|
|
241
288
|
settlement = dc.convert_input_dates(settlement)
|
|
@@ -281,6 +328,8 @@ def price(
|
|
|
281
328
|
Examples:
|
|
282
329
|
>>> yd.ntnb.price(4299.160173, 99.3651)
|
|
283
330
|
4271.864805
|
|
331
|
+
>>> yd.ntnb.price(4315.498383, 100.6409)
|
|
332
|
+
4343.156412
|
|
284
333
|
"""
|
|
285
334
|
return bt.truncate(vna * quotation / 100, 6)
|
|
286
335
|
|
|
@@ -298,7 +347,6 @@ def spot_rates(
|
|
|
298
347
|
the spot rates that discount each bond's cash flows to its current
|
|
299
348
|
price.
|
|
300
349
|
|
|
301
|
-
|
|
302
350
|
Args:
|
|
303
351
|
settlement (str | pd.Timestamp): The reference date for settlement.
|
|
304
352
|
maturities (pd.Series): Series of maturity dates for the bonds.
|
|
@@ -307,6 +355,32 @@ def spot_rates(
|
|
|
307
355
|
Returns:
|
|
308
356
|
pd.DataFrame: DataFrame with columns "MaturityDate", "SpotRate".
|
|
309
357
|
|
|
358
|
+
Examples:
|
|
359
|
+
# Get the NTN-B rates for a specific reference date
|
|
360
|
+
>>> df_rates = yd.ntnb.rates("16-08-2024")
|
|
361
|
+
|
|
362
|
+
# Calculate the spot rates considering the settlement at the reference date
|
|
363
|
+
>>> yd.ntnb.spot_rates(
|
|
364
|
+
... settlement="16-08-2024",
|
|
365
|
+
... maturities=df_rates["MaturityDate"],
|
|
366
|
+
... rates=df_rates["IndicativeRate"],
|
|
367
|
+
... )
|
|
368
|
+
MaturityDate SpotRate
|
|
369
|
+
0 2025-05-15 0.063894
|
|
370
|
+
1 2026-08-15 0.066141
|
|
371
|
+
2 2027-05-15 0.064087
|
|
372
|
+
3 2028-08-15 0.063057
|
|
373
|
+
4 2029-05-15 0.061458
|
|
374
|
+
5 2030-08-15 0.059491
|
|
375
|
+
6 2032-08-15 0.059652
|
|
376
|
+
7 2033-05-15 0.059497
|
|
377
|
+
8 2035-05-15 0.059151
|
|
378
|
+
9 2040-08-15 0.058326
|
|
379
|
+
10 2045-05-15 0.060371
|
|
380
|
+
11 2050-08-15 0.060772
|
|
381
|
+
12 2055-05-15 0.059909
|
|
382
|
+
13 2060-08-15 0.060652
|
|
383
|
+
|
|
310
384
|
Notes:
|
|
311
385
|
The calculation of the spot rates for NTN-B bonds considers the following steps:
|
|
312
386
|
- Map all all possible payment dates up to the longest maturity date.
|
|
@@ -315,7 +389,6 @@ def spot_rates(
|
|
|
315
389
|
- Calculate the real spot rates for each maturity date.
|
|
316
390
|
- Columns in the returned DataFrame:
|
|
317
391
|
- MaturityDate: The maturity date of the bond.
|
|
318
|
-
- YTM: The yield to maturity rate for the bond.
|
|
319
392
|
- SpotRate: The real spot rate for the bond.
|
|
320
393
|
"""
|
|
321
394
|
# Process and validate the input data
|
|
@@ -30,19 +30,19 @@ class DIFutures:
|
|
|
30
30
|
Initialize the DIFutures instance with a specific trade date.
|
|
31
31
|
|
|
32
32
|
Args:
|
|
33
|
-
trade_date (str | pd.Timestamp): The
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
contracts to match LTN and NTN-F bond maturities.
|
|
33
|
+
trade_date (str | pd.Timestamp): The date to retrieve the contract data.
|
|
34
|
+
adj_expirations (bool): If True, adjusts the expiration dates to the start
|
|
35
|
+
of the month.
|
|
36
|
+
prefixed_filter (bool): If True, filters the DI contracts to match LTN and
|
|
37
|
+
NTN-F bond maturities.
|
|
39
38
|
"""
|
|
40
39
|
self._trade_date = dc.convert_input_dates(trade_date)
|
|
41
|
-
self.
|
|
42
|
-
self.
|
|
40
|
+
self._adj_expirations = adj_expirations
|
|
41
|
+
self._prefixed_filter = prefixed_filter
|
|
43
42
|
|
|
43
|
+
@property
|
|
44
44
|
def data(self) -> pd.DataFrame:
|
|
45
|
-
"""Retrieve DI contract
|
|
45
|
+
"""Retrieve DI contract DataFrame for the initialized trade date."""
|
|
46
46
|
df = (
|
|
47
47
|
get_di_dataset()
|
|
48
48
|
.query("TradeDate == @self.trade_date")
|
|
@@ -51,6 +51,7 @@ class DIFutures:
|
|
|
51
51
|
|
|
52
52
|
if df.empty:
|
|
53
53
|
df = futures(contract_code="DI1", trade_date=self._trade_date)
|
|
54
|
+
|
|
54
55
|
if df.empty:
|
|
55
56
|
return pd.DataFrame()
|
|
56
57
|
|
|
@@ -58,10 +59,18 @@ class DIFutures:
|
|
|
58
59
|
if "DaysToExpiration" in df.columns:
|
|
59
60
|
df.drop(columns=["DaysToExpiration"], inplace=True)
|
|
60
61
|
|
|
61
|
-
if self.
|
|
62
|
+
if self._prefixed_filter:
|
|
63
|
+
df_anbima = get_anbima_dataset()
|
|
64
|
+
|
|
65
|
+
# Find the closest Anbima reference date to the trade date
|
|
66
|
+
anbima_dates = (
|
|
67
|
+
df_anbima["ReferenceDate"].drop_duplicates().reset_index(drop=True)
|
|
68
|
+
)
|
|
69
|
+
dates_diff = (anbima_dates - self._trade_date).abs()
|
|
70
|
+
closest_date = anbima_dates[dates_diff.idxmin()] # noqa
|
|
71
|
+
|
|
62
72
|
df_pre = (
|
|
63
|
-
|
|
64
|
-
.query("ReferenceDate == @self.trade_date")
|
|
73
|
+
df_anbima.query("ReferenceDate == @closest_date")
|
|
65
74
|
.query("BondType in ['LTN', 'NTN-F']")
|
|
66
75
|
.drop_duplicates(ignore_index=True)
|
|
67
76
|
)
|
|
@@ -69,7 +78,7 @@ class DIFutures:
|
|
|
69
78
|
adj_pre_maturities = bday.offset(pre_maturities, 0) # noqa
|
|
70
79
|
df.query("ExpirationDate in @adj_pre_maturities", inplace=True)
|
|
71
80
|
|
|
72
|
-
if self.
|
|
81
|
+
if self._adj_expirations:
|
|
73
82
|
df["ExpirationDate"] = (
|
|
74
83
|
df["ExpirationDate"].dt.to_period("M").dt.to_timestamp()
|
|
75
84
|
)
|
|
@@ -87,7 +96,7 @@ class DIFutures:
|
|
|
87
96
|
Returns:
|
|
88
97
|
pd.Series: A Series of unique expiration dates for DI contracts.
|
|
89
98
|
"""
|
|
90
|
-
df = self.data
|
|
99
|
+
df = self.data.drop_duplicates(subset=["ExpirationDate"])
|
|
91
100
|
return df["ExpirationDate"].sort_values(ignore_index=True)
|
|
92
101
|
|
|
93
102
|
@property
|
|
@@ -107,7 +116,7 @@ class DIFutures:
|
|
|
107
116
|
- ForwardRate: The forward rate calculated between successive expiration
|
|
108
117
|
dates.
|
|
109
118
|
"""
|
|
110
|
-
df = self.data
|
|
119
|
+
df = self.data
|
|
111
120
|
if df.empty:
|
|
112
121
|
return pd.DataFrame()
|
|
113
122
|
|
|
@@ -125,21 +134,30 @@ class DIFutures:
|
|
|
125
134
|
extrapolate: bool = False,
|
|
126
135
|
) -> float:
|
|
127
136
|
"""Retrieve the DI rate for a specified expiration date."""
|
|
128
|
-
expiration =
|
|
137
|
+
expiration = dc.convert_input_dates(expiration)
|
|
138
|
+
|
|
139
|
+
if self._adj_expirations:
|
|
140
|
+
# Force the expiration date to be the start of the month
|
|
141
|
+
expiration = expiration.to_period("M").to_timestamp()
|
|
142
|
+
else:
|
|
143
|
+
# Force the expiration date to be a business day
|
|
144
|
+
expiration = bday.offset(expiration, 0)
|
|
129
145
|
|
|
130
146
|
if not interpolate and extrapolate:
|
|
131
147
|
raise ValueError("Extrapolation is not allowed without interpolation.")
|
|
132
148
|
|
|
133
|
-
df = self.data
|
|
149
|
+
df = self.data
|
|
150
|
+
|
|
134
151
|
if df.empty:
|
|
135
152
|
return float("NaN")
|
|
136
153
|
|
|
137
154
|
df_exp = df.query("ExpirationDate == @expiration")
|
|
155
|
+
|
|
138
156
|
if df_exp.empty and not interpolate:
|
|
139
157
|
return float("NaN")
|
|
140
158
|
|
|
141
159
|
if expiration in df_exp["ExpirationDate"].values:
|
|
142
|
-
return float(df_exp["SettlementRate"].
|
|
160
|
+
return float(df_exp["SettlementRate"].iat[0])
|
|
143
161
|
|
|
144
162
|
if not interpolate:
|
|
145
163
|
return float("NaN")
|
|
@@ -166,7 +184,6 @@ class DIFutures:
|
|
|
166
184
|
@trade_date.setter
|
|
167
185
|
def trade_date(self, value: str | pd.Timestamp):
|
|
168
186
|
self._trade_date = dc.convert_input_dates(value)
|
|
169
|
-
return self._trade_date
|
|
170
187
|
|
|
171
188
|
@property
|
|
172
189
|
def adj_expirations(self) -> bool:
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import logging
|
|
2
2
|
from typing import Literal
|
|
3
3
|
|
|
4
4
|
import pandas as pd
|
|
5
5
|
import requests
|
|
6
|
+
from requests.adapters import HTTPAdapter
|
|
7
|
+
from urllib3.util import Retry
|
|
6
8
|
|
|
7
9
|
from pyield import date_converter as dc
|
|
8
10
|
|
|
@@ -105,60 +107,92 @@ def ipca_monthly_rate(reference_date: pd.Timestamp) -> float:
|
|
|
105
107
|
|
|
106
108
|
|
|
107
109
|
def _selic_target(reference_date: pd.Timestamp) -> float:
|
|
110
|
+
"""
|
|
111
|
+
Fetches the SELIC Target rate for a specific reference date.
|
|
112
|
+
|
|
113
|
+
The SELIC Target rate is the official rate set by the Central Bank of Brazil.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
reference_date (pd.Timestamp): The date for which to fetch the SELIC Target.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
float: The SELIC Target rate as a float rounded to 4 decimal places or NaN if
|
|
120
|
+
the rate is not available.
|
|
121
|
+
"""
|
|
108
122
|
# https://api.bcb.gov.br/dados/serie/bcdata.sgs.432/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
|
|
109
123
|
selic_date = reference_date.strftime("%d/%m/%Y")
|
|
110
124
|
api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.432/dados?formato=json&dataInicial={selic_date}&dataFinal={selic_date}"
|
|
111
|
-
response = requests.get(api_url, timeout=10)
|
|
112
|
-
response.raise_for_status()
|
|
113
125
|
|
|
114
|
-
|
|
126
|
+
s = requests.Session()
|
|
127
|
+
retries = Retry(
|
|
128
|
+
total=5, # Retry 5 times
|
|
129
|
+
backoff_factor=1, # Exponential backoff: 1, 2, 4, 8, 16 seconds
|
|
130
|
+
status_forcelist=[500, 502, 503, 504], # Retry on these HTTP status codes
|
|
131
|
+
)
|
|
132
|
+
s.mount("https://", HTTPAdapter(max_retries=retries))
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
response = s.get(api_url, timeout=(5, 20))
|
|
136
|
+
response.raise_for_status() # Raise an error for bad HTTP response
|
|
137
|
+
|
|
138
|
+
if selic_date not in response.text:
|
|
139
|
+
return float("nan")
|
|
140
|
+
|
|
141
|
+
data = response.json()
|
|
142
|
+
if not data or "valor" not in data[0]:
|
|
143
|
+
return float("nan")
|
|
144
|
+
|
|
145
|
+
value = data[0]["valor"]
|
|
146
|
+
return round(float(value) / 100, 4)
|
|
147
|
+
|
|
148
|
+
except requests.exceptions.RequestException as e:
|
|
149
|
+
logging.error(f"Error fetching SELIC Target rate: {e}")
|
|
115
150
|
return float("nan")
|
|
116
|
-
data = response.json()
|
|
117
|
-
return round(float(data[0]["valor"]) / 100, 4)
|
|
118
151
|
|
|
119
152
|
|
|
120
153
|
def _selic_over(reference_date: pd.Timestamp) -> float:
|
|
121
154
|
"""
|
|
122
|
-
|
|
123
|
-
banks in the interbank market, using public securities as collateral. This rate may
|
|
124
|
-
vary daily depending on the supply and demand for resources between financial
|
|
125
|
-
institutions.
|
|
126
|
-
"""
|
|
127
|
-
formatted_date = reference_date.strftime("%d/%m/%Y")
|
|
128
|
-
# https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
|
|
129
|
-
api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=json&dataInicial={formatted_date}&dataFinal={formatted_date}"
|
|
155
|
+
Fetches the SELIC Over rate for a specific reference date.
|
|
130
156
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
timeout = 10
|
|
134
|
-
backoff_factor = 2
|
|
157
|
+
The SELIC Over rate is the daily average interest rate effectively practiced
|
|
158
|
+
between banks in the interbank market, using public securities as collateral.
|
|
135
159
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
response = requests.get(api_url, timeout=timeout)
|
|
139
|
-
response.raise_for_status() # Check for HTTP errors
|
|
160
|
+
Args:
|
|
161
|
+
reference_date (pd.Timestamp): The date for which to fetch the SELIC Over rate.
|
|
140
162
|
|
|
141
|
-
|
|
142
|
-
|
|
163
|
+
Returns:
|
|
164
|
+
float: The SELIC Over rate as a float rounded to 4 decimal places or NaN if
|
|
165
|
+
the rate is not available.
|
|
166
|
+
"""
|
|
143
167
|
|
|
144
|
-
|
|
168
|
+
formatted_date = reference_date.strftime("%d/%m/%Y")
|
|
169
|
+
# https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
|
|
170
|
+
api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=json&dataInicial={formatted_date}&dataFinal={formatted_date}"
|
|
145
171
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
172
|
+
s = requests.Session()
|
|
173
|
+
retries = Retry(
|
|
174
|
+
total=5,
|
|
175
|
+
backoff_factor=1,
|
|
176
|
+
status_forcelist=[500, 502, 503, 504],
|
|
177
|
+
)
|
|
178
|
+
s.mount("https://", HTTPAdapter(max_retries=retries))
|
|
179
|
+
try:
|
|
180
|
+
response = s.get(api_url, timeout=(5, 20))
|
|
181
|
+
response.raise_for_status() # Raise an error for bad HTTP response
|
|
182
|
+
|
|
183
|
+
if formatted_date not in response.text:
|
|
184
|
+
return float("nan")
|
|
150
185
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
except requests.exceptions.ConnectionError as e:
|
|
154
|
-
print(f"Connection error on attempt {attempt + 1}: {e}. Retrying...")
|
|
155
|
-
except requests.exceptions.RequestException as e:
|
|
156
|
-
print(f"An error occurred: {e}")
|
|
186
|
+
data = response.json()
|
|
187
|
+
if not data or "valor" not in data[0]:
|
|
157
188
|
return float("nan")
|
|
158
189
|
|
|
159
|
-
|
|
190
|
+
value = data[0]["valor"]
|
|
191
|
+
return round(float(value) / 100, 4)
|
|
160
192
|
|
|
161
|
-
|
|
193
|
+
except requests.exceptions.RequestException as e:
|
|
194
|
+
logging.error(f"Error fetching SELIC Over rate: {e}")
|
|
195
|
+
return float("nan")
|
|
162
196
|
|
|
163
197
|
|
|
164
198
|
def _di(reference_date: pd.Timestamp) -> float:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.22.2"
|
|
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
|