PYield 0.23.0__tar.gz → 0.23.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.
- {pyield-0.23.0 → pyield-0.23.2}/PKG-INFO +1 -1
- pyield-0.23.2/pyield/__about__.py +1 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/bday.py +0 -4
- {pyield-0.23.0 → pyield-0.23.2}/pyield/bonds/ltn.py +3 -4
- {pyield-0.23.0 → pyield-0.23.2}/pyield/bonds/ntnb.py +5 -5
- {pyield-0.23.0 → pyield-0.23.2}/pyield/bonds/ntnf.py +11 -13
- {pyield-0.23.0 → pyield-0.23.2}/pyield/di.py +50 -8
- {pyield-0.23.0 → pyield-0.23.2}/pyield/indicators.py +50 -50
- {pyield-0.23.0 → pyield-0.23.2}/pyield/interpolator.py +33 -32
- {pyield-0.23.0 → pyield-0.23.2}/pyproject.toml +2 -1
- pyield-0.23.0/pyield/__about__.py +0 -1
- {pyield-0.23.0 → pyield-0.23.2}/LICENSE +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/README.md +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/__init__.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/anbima.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/b3_futures/__init__.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/b3_futures/common.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/b3_futures/historical.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/b3_futures/intraday.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/b3_futures/xml.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/bonds/__init__.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/bonds/bond_tools.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/bonds/lft.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/conftest.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/data_cache.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/date_converter.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/holidays/__init__.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/holidays/br_holidays_old.txt +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/holidays/brholidays.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/projections.py +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/py.typed +0 -0
- {pyield-0.23.0 → pyield-0.23.2}/pyield/tools.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.23.2"
|
|
@@ -239,10 +239,6 @@ def count(
|
|
|
239
239
|
for counting.
|
|
240
240
|
end (ScalarDateTypes | ArrayDateTypes): The end date(s) for counting, which
|
|
241
241
|
is excluded from the count themselves.
|
|
242
|
-
holiday_option (Literal["old", "new", "infer"], optional):
|
|
243
|
-
Specifies which set of holidays to consider in the count. 'old' or 'new'
|
|
244
|
-
refer to predefined holiday lists, while 'infer' automatically selects the
|
|
245
|
-
list based on the most recent date in the input. Defaults to "infer".
|
|
246
242
|
|
|
247
243
|
Returns:
|
|
248
244
|
int | pd.Series: Returns an integer if `start` and `end` are single dates,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
-
from pyield import anbima, bday
|
|
3
|
+
from pyield import anbima, bday, di
|
|
4
4
|
from pyield import date_converter as dc
|
|
5
5
|
from pyield.bonds import bond_tools as bt
|
|
6
|
-
from pyield.di import DIFutures
|
|
7
6
|
|
|
8
7
|
FACE_VALUE = 1000
|
|
9
8
|
|
|
@@ -219,8 +218,8 @@ def historical_premium(
|
|
|
219
218
|
ltn_rate = float(ltn_rates.iloc[0])
|
|
220
219
|
|
|
221
220
|
# Retrieve DI rate for the reference date and maturity
|
|
222
|
-
|
|
223
|
-
di_rate =
|
|
221
|
+
dif = di.DIFutures(trade_date=reference_date)
|
|
222
|
+
di_rate = dif.rate(expiration=maturity)
|
|
224
223
|
if pd.isnull(di_rate): # Check if the DI rate is NaN
|
|
225
224
|
return float("NaN")
|
|
226
225
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import pandas as pd
|
|
3
3
|
|
|
4
|
+
import pyield.bonds.bond_tools as bt
|
|
5
|
+
import pyield.date_converter as dc
|
|
6
|
+
import pyield.interpolator as ip
|
|
4
7
|
from pyield import anbima, bday
|
|
5
|
-
from pyield import date_converter as dc
|
|
6
|
-
from pyield.bonds import bond_tools as bt
|
|
7
|
-
from pyield.interpolator import Interpolator
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
10
|
Constants calculated as per Anbima Rules and in base 100
|
|
@@ -397,7 +397,7 @@ def spot_rates(
|
|
|
397
397
|
_check_maturities(maturities)
|
|
398
398
|
|
|
399
399
|
# Create the interpolator object
|
|
400
|
-
ff_interpolator = Interpolator(
|
|
400
|
+
ff_interpolator = ip.Interpolator(
|
|
401
401
|
method="flat_forward",
|
|
402
402
|
known_bdays=bday.count(settlement, maturities),
|
|
403
403
|
known_rates=rates,
|
|
@@ -495,7 +495,7 @@ def bei_rates(
|
|
|
495
495
|
df["BDays"] = bday.count(settlement, df["MaturityDate"])
|
|
496
496
|
df = df.rename(columns={"SpotRate": "RIR"})
|
|
497
497
|
|
|
498
|
-
nir_interplator = Interpolator(
|
|
498
|
+
nir_interplator = ip.Interpolator(
|
|
499
499
|
method="flat_forward",
|
|
500
500
|
known_bdays=bday.count(settlement, nominal_maturities),
|
|
501
501
|
known_rates=nominal_rates,
|
|
@@ -3,11 +3,10 @@ from collections.abc import Callable
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pandas as pd
|
|
5
5
|
|
|
6
|
-
from pyield import anbima, bday
|
|
6
|
+
from pyield import anbima, bday, di
|
|
7
7
|
from pyield import date_converter as dc
|
|
8
|
+
from pyield import interpolator as ip
|
|
8
9
|
from pyield.bonds import bond_tools as bt
|
|
9
|
-
from pyield.di import DIFutures
|
|
10
|
-
from pyield.interpolator import Interpolator
|
|
11
10
|
|
|
12
11
|
"""
|
|
13
12
|
Constants calculated as per Anbima Rules
|
|
@@ -260,12 +259,12 @@ def spot_rates( # noqa
|
|
|
260
259
|
settlement = dc.convert_input_dates(settlement)
|
|
261
260
|
|
|
262
261
|
# Create flat forward interpolators for LTN and NTN-F rates
|
|
263
|
-
ltn_rate_interpolator = Interpolator(
|
|
262
|
+
ltn_rate_interpolator = ip.Interpolator(
|
|
264
263
|
method="flat_forward",
|
|
265
264
|
known_bdays=bday.count(settlement, ltn_maturities),
|
|
266
265
|
known_rates=ltn_rates,
|
|
267
266
|
)
|
|
268
|
-
ntnf_rate_interpolator = Interpolator(
|
|
267
|
+
ntnf_rate_interpolator = ip.Interpolator(
|
|
269
268
|
method="flat_forward",
|
|
270
269
|
known_bdays=bday.count(settlement, ntnf_maturities),
|
|
271
270
|
known_rates=ntnf_rates,
|
|
@@ -445,7 +444,7 @@ def di_net_spread( # noqa
|
|
|
445
444
|
settlement = dc.convert_input_dates(settlement)
|
|
446
445
|
ntnf_maturity = dc.convert_input_dates(ntnf_maturity)
|
|
447
446
|
|
|
448
|
-
ff_interpolator = Interpolator(
|
|
447
|
+
ff_interpolator = ip.Interpolator(
|
|
449
448
|
"flat_forward",
|
|
450
449
|
bday.count(settlement, di_expirations),
|
|
451
450
|
di_rates,
|
|
@@ -497,10 +496,9 @@ def premium(
|
|
|
497
496
|
ntnf_maturity (str | pd.Timestamp): The maturity date of the NTN-F bond in
|
|
498
497
|
'DD-MM-YYYY' format or a pandas Timestamp.
|
|
499
498
|
ntnf_rate (float): The yield to maturity (YTM) of the NTN-F bond.
|
|
500
|
-
di_expirations (pd.Series): Series containing the expiration dates for DI
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
expiration dates.
|
|
499
|
+
di_expirations (pd.Series): Series containing the expiration dates for DI rates.
|
|
500
|
+
di_rates (pd.Series): Series containing the DI rates corresponding to
|
|
501
|
+
the expiration dates.
|
|
504
502
|
|
|
505
503
|
Returns:
|
|
506
504
|
float: The premium of the NTN-F bond over the DI curve, expressed as a
|
|
@@ -531,7 +529,7 @@ def premium(
|
|
|
531
529
|
df["BDays"] = bday.count(settlement, df["PaymentDate"])
|
|
532
530
|
df["BYears"] = df["BDays"] / 252
|
|
533
531
|
|
|
534
|
-
ff_interpolator = Interpolator(
|
|
532
|
+
ff_interpolator = ip.Interpolator(
|
|
535
533
|
"flat_forward",
|
|
536
534
|
bday.count(settlement, di_expirations),
|
|
537
535
|
di_rates,
|
|
@@ -579,8 +577,8 @@ def historical_premium(
|
|
|
579
577
|
df = cash_flows(reference_date, maturity, adj_payment_dates=True)
|
|
580
578
|
df["BDays"] = bday.count(reference_date, df["PaymentDate"])
|
|
581
579
|
df["BYears"] = df["BDays"] / 252
|
|
582
|
-
|
|
583
|
-
df["DIRate"] = df["PaymentDate"].apply(
|
|
580
|
+
dif = di.DIFutures(reference_date)
|
|
581
|
+
df["DIRate"] = df["PaymentDate"].apply(dif.rate)
|
|
584
582
|
|
|
585
583
|
# Calculate the present value of the cash flows using the DI rate
|
|
586
584
|
bond_price = bt.calculate_present_value(
|
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
+
import pyield.b3_futures as b3
|
|
4
|
+
import pyield.date_converter as dc
|
|
5
|
+
import pyield.tools as tl
|
|
3
6
|
from pyield import bday, interpolator
|
|
4
|
-
from pyield import date_converter as dc
|
|
5
|
-
from pyield.b3_futures import futures
|
|
6
7
|
from pyield.data_cache import get_anbima_dataset, get_di_dataset
|
|
7
|
-
from pyield.tools import forward_rates
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class DIFutures:
|
|
11
|
+
"""
|
|
12
|
+
Class to retrieve and manipulate DI futures contract data.
|
|
13
|
+
|
|
14
|
+
This class provides access to DI futures data for a specified trade date, and
|
|
15
|
+
includes options to adjust expiration dates and apply filters based on LTN and
|
|
16
|
+
NTN-F bond maturities.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
To create a `DIFutures` instance and retrieve data:
|
|
20
|
+
|
|
21
|
+
>>> di = yd.DIFutures(trade_date="16-10-2024", adj_expirations=True)
|
|
22
|
+
>>> df = di.data # Retrieve DI contract dataframe for the specified date
|
|
23
|
+
>>> df.iloc[:5, :5] # Show the first five rows and columns
|
|
24
|
+
TickerSymbol ExpirationDate BDaysToExp OpenContracts TradeCount
|
|
25
|
+
0 DI1X24 2024-11-01 12 1744269 635
|
|
26
|
+
1 DI1Z24 2024-12-01 31 1429375 1012
|
|
27
|
+
2 DI1F25 2025-01-01 52 5423969 6812
|
|
28
|
+
3 DI1G25 2025-02-01 74 279491 97
|
|
29
|
+
4 DI1H25 2025-03-01 94 344056 221
|
|
30
|
+
|
|
31
|
+
You can also retrieve forward rates for the DI contracts:
|
|
32
|
+
|
|
33
|
+
>>> di.forwards.iloc[:5] # Show the first five rows
|
|
34
|
+
ExpirationDate SettlementRate ForwardRate
|
|
35
|
+
0 2024-11-01 0.10653 0.10653
|
|
36
|
+
1 2024-12-01 0.1091 0.110726
|
|
37
|
+
2 2025-01-01 0.11164 0.1154
|
|
38
|
+
3 2025-02-01 0.11362 0.118314
|
|
39
|
+
4 2025-03-01 0.1157 0.12343
|
|
40
|
+
"""
|
|
41
|
+
|
|
11
42
|
trade_dates = (
|
|
12
43
|
get_di_dataset()
|
|
13
44
|
.drop_duplicates(subset=["TradeDate"])["TradeDate"]
|
|
@@ -50,7 +81,7 @@ class DIFutures:
|
|
|
50
81
|
)
|
|
51
82
|
|
|
52
83
|
if df.empty:
|
|
53
|
-
df = futures(contract_code="DI1", trade_date=self._trade_date)
|
|
84
|
+
df = b3.futures(contract_code="DI1", trade_date=self._trade_date)
|
|
54
85
|
|
|
55
86
|
if df.empty:
|
|
56
87
|
return pd.DataFrame()
|
|
@@ -120,7 +151,7 @@ class DIFutures:
|
|
|
120
151
|
if df.empty:
|
|
121
152
|
return pd.DataFrame()
|
|
122
153
|
|
|
123
|
-
df["ForwardRate"] = forward_rates(
|
|
154
|
+
df["ForwardRate"] = tl.forward_rates(
|
|
124
155
|
business_days=bday.count(self._trade_date, df["ExpirationDate"]),
|
|
125
156
|
zero_rates=df["SettlementRate"],
|
|
126
157
|
)
|
|
@@ -174,11 +205,15 @@ class DIFutures:
|
|
|
174
205
|
@property
|
|
175
206
|
def trade_date(self) -> pd.Timestamp:
|
|
176
207
|
"""
|
|
177
|
-
|
|
208
|
+
The trade date to retrieve the DI contract data.
|
|
209
|
+
|
|
210
|
+
This property can be both read and set. When setting a value, it automatically
|
|
211
|
+
converts the input date format to a `pd.Timestamp`.
|
|
178
212
|
|
|
179
213
|
Returns:
|
|
180
214
|
pd.Timestamp: The trade date set for this instance.
|
|
181
215
|
"""
|
|
216
|
+
|
|
182
217
|
return self._trade_date
|
|
183
218
|
|
|
184
219
|
@trade_date.setter
|
|
@@ -188,7 +223,11 @@ class DIFutures:
|
|
|
188
223
|
@property
|
|
189
224
|
def adj_expirations(self) -> bool:
|
|
190
225
|
"""
|
|
191
|
-
|
|
226
|
+
Adjusts the expiration dates to the start of the month.
|
|
227
|
+
|
|
228
|
+
This property can be both read and set. When set to `True`, all expiration dates
|
|
229
|
+
are adjusted to the first day of the month. For example, an expiration date of
|
|
230
|
+
02/01/2025 will be adjusted to 01/01/2025.
|
|
192
231
|
|
|
193
232
|
Returns:
|
|
194
233
|
bool: Whether expiration dates are adjusted to the start of the month.
|
|
@@ -202,7 +241,10 @@ class DIFutures:
|
|
|
202
241
|
@property
|
|
203
242
|
def prefixed_filter(self) -> bool:
|
|
204
243
|
"""
|
|
205
|
-
|
|
244
|
+
Filters DI Futures to match prefixed TN bond maturities.
|
|
245
|
+
|
|
246
|
+
This property can be both read and set. When set to `True`, DI Futures will be
|
|
247
|
+
filtered to match the maturities of LTN and NTN-F bonds from the Anbima dataset.
|
|
206
248
|
|
|
207
249
|
Returns:
|
|
208
250
|
bool: Whether DI Futures are filtered to match prefixed Anbima bond
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import time
|
|
2
3
|
from typing import Literal
|
|
3
4
|
|
|
4
5
|
import pandas as pd
|
|
5
6
|
import requests
|
|
6
|
-
from requests.
|
|
7
|
-
from urllib3.util import Retry
|
|
7
|
+
from requests.exceptions import RequestException
|
|
8
8
|
|
|
9
9
|
from pyield import date_converter as dc
|
|
10
10
|
|
|
11
11
|
type IndicatorCode = Literal["IPCA_MR", "SELIC_TARGET", "SELIC_OVER", "DI", "VNA_LFT"]
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
TIMEOUT = (5, 20)
|
|
14
|
+
MAX_ATTEMPTS = 5
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def indicator(
|
|
@@ -91,7 +93,7 @@ def ipca_monthly_rate(reference_date: pd.Timestamp) -> float:
|
|
|
91
93
|
api_url = f"https://servicodados.ibge.gov.br/api/v3/agregados/6691/periodos/{ipca_date}/variaveis/63?localidades=N1[all]"
|
|
92
94
|
|
|
93
95
|
# Send a GET request to the API
|
|
94
|
-
response = requests.get(api_url, timeout=
|
|
96
|
+
response = requests.get(api_url, timeout=TIMEOUT)
|
|
95
97
|
|
|
96
98
|
# Raises HTTPError, if one occurred
|
|
97
99
|
response.raise_for_status()
|
|
@@ -123,31 +125,29 @@ def _selic_target(reference_date: pd.Timestamp) -> float:
|
|
|
123
125
|
selic_date = reference_date.strftime("%d/%m/%Y")
|
|
124
126
|
api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.432/dados?formato=json&dataInicial={selic_date}&dataFinal={selic_date}"
|
|
125
127
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
)
|
|
132
|
-
s.mount("https://", HTTPAdapter(max_retries=retries))
|
|
128
|
+
attempt = 0
|
|
129
|
+
while attempt < MAX_ATTEMPTS:
|
|
130
|
+
try:
|
|
131
|
+
response = requests.get(api_url, timeout=TIMEOUT)
|
|
132
|
+
response.raise_for_status() # Raise an error for bad HTTP response
|
|
133
133
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
response.raise_for_status() # Raise an error for bad HTTP response
|
|
134
|
+
# Try parsing JSON, raises an error if response is not valid JSON
|
|
135
|
+
data = response.json()
|
|
137
136
|
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
# Access the value directly, any issue will raise an exception
|
|
138
|
+
value = data[0]["valor"]
|
|
139
|
+
return round(float(value) / 100, 4)
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
except (RequestException, KeyError, IndexError, ValueError) as e:
|
|
142
|
+
msg = f"Error fetching SELIC Target rate (attempt {attempt + 1}): {e}"
|
|
143
|
+
logging.error(msg)
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
# Increment attempt count and add backoff delay
|
|
146
|
+
attempt += 1
|
|
147
|
+
time.sleep(1.5**attempt) # Exponential backoff: 1.5, 2.3, 3.9, 5.1, 7.6 seconds
|
|
147
148
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return float("nan")
|
|
149
|
+
# After all retries, return NaN
|
|
150
|
+
return float("nan")
|
|
151
151
|
|
|
152
152
|
|
|
153
153
|
def _selic_over(reference_date: pd.Timestamp) -> float:
|
|
@@ -169,37 +169,37 @@ def _selic_over(reference_date: pd.Timestamp) -> float:
|
|
|
169
169
|
# https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
|
|
170
170
|
api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.1178/dados?formato=json&dataInicial={formatted_date}&dataFinal={formatted_date}"
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return float(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
172
|
+
attempt = 0
|
|
173
|
+
|
|
174
|
+
while attempt < MAX_ATTEMPTS:
|
|
175
|
+
try:
|
|
176
|
+
response = requests.get(api_url, timeout=TIMEOUT)
|
|
177
|
+
response.raise_for_status() # Handle 4xx/5xx HTTP errors
|
|
178
|
+
|
|
179
|
+
# Try parsing JSON, raises an error if response is not valid JSON
|
|
180
|
+
data = response.json()
|
|
181
|
+
|
|
182
|
+
# Access the value directly, any issue will raise an exception
|
|
183
|
+
value = data[0]["valor"]
|
|
184
|
+
return round(float(value) / 100, 4)
|
|
185
|
+
|
|
186
|
+
except (RequestException, KeyError, IndexError, ValueError) as e:
|
|
187
|
+
msg = f"Error fetching SELIC Over rate (attempt {attempt + 1}): {e}"
|
|
188
|
+
logging.error(msg)
|
|
189
|
+
|
|
190
|
+
# Increment attempt count and add backoff delay
|
|
191
|
+
attempt += 1
|
|
192
|
+
time.sleep(1.5**attempt) # Exponential backoff: 1.5, 2.3, 3.9, 5.1, 7.6 seconds
|
|
193
|
+
|
|
194
|
+
# After all retries, return NaN
|
|
195
|
+
return float("nan")
|
|
196
196
|
|
|
197
197
|
|
|
198
198
|
def _di(reference_date: pd.Timestamp) -> float:
|
|
199
199
|
# https://api.bcb.gov.br/dados/serie/bcdata.sgs.11/dados?formato=json&dataInicial=12/04/2024&dataFinal=12/04/2024
|
|
200
200
|
di_date = reference_date.strftime("%d/%m/%Y")
|
|
201
201
|
api_url = f"https://api.bcb.gov.br/dados/serie/bcdata.sgs.11/dados?formato=json&dataInicial={di_date}&dataFinal={di_date}"
|
|
202
|
-
response = requests.get(api_url, timeout=
|
|
202
|
+
response = requests.get(api_url, timeout=TIMEOUT)
|
|
203
203
|
response.raise_for_status()
|
|
204
204
|
|
|
205
205
|
if di_date not in response.text:
|
|
@@ -216,7 +216,7 @@ def _vna_lft(reference_date: pd.Timestamp) -> float:
|
|
|
216
216
|
url_file = f"{reference_date.strftime('%Y%m%d')}APC238"
|
|
217
217
|
url_vna = url_base + url_file
|
|
218
218
|
|
|
219
|
-
response = requests.get(url_vna, timeout=
|
|
219
|
+
response = requests.get(url_vna, timeout=TIMEOUT)
|
|
220
220
|
response.raise_for_status()
|
|
221
221
|
file_text = response.text
|
|
222
222
|
|
|
@@ -6,45 +6,46 @@ import pandas as pd
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Interpolator:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
method: Literal["flat_forward", "linear"],
|
|
12
|
-
known_bdays: pd.Series | list,
|
|
13
|
-
known_rates: pd.Series | list,
|
|
14
|
-
extrapolate: bool = False,
|
|
15
|
-
):
|
|
16
|
-
"""
|
|
17
|
-
Initialize the Interpolator with given atributes.
|
|
9
|
+
"""
|
|
10
|
+
Interpolator class for interest rate interpolation.
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
Args:
|
|
13
|
+
method (Literal["flat_forward", "linear"]): The interpolation method to use.
|
|
14
|
+
known_bdays (pd.Series | pd.Index | list): Series of known business days.
|
|
15
|
+
known_rates (pd.Series | pd.Index | list): Series of known interest rates.
|
|
16
|
+
extrapolate (bool, optional): Whether to extrapolate beyond known business days.
|
|
24
17
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
Raises:
|
|
19
|
+
ValueError: If known_bdays and known_rates do not have the same length.
|
|
20
|
+
ValueError: If the interpolation method is not recognized
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
Returns:
|
|
23
|
+
Interpolator: An instance of the Interpolator
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Examples:
|
|
35
|
-
>>> from pyield import Interpolator
|
|
36
|
-
>>> known_bdays = [30, 60, 90]
|
|
37
|
-
>>> known_rates = [0.045, 0.05, 0.055]
|
|
25
|
+
Note:
|
|
26
|
+
This class uses a 252 business days per year convention.
|
|
38
27
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
Examples:
|
|
29
|
+
>>> from pyield import Interpolator
|
|
30
|
+
>>> known_bdays = [30, 60, 90]
|
|
31
|
+
>>> known_rates = [0.045, 0.05, 0.055]
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
>>> lin_interp = Interpolator("linear", known_bdays, known_rates)
|
|
34
|
+
>>> lin_interp(45)
|
|
35
|
+
0.0475
|
|
46
36
|
|
|
47
|
-
""
|
|
37
|
+
>>> ffo_interp = Interpolator("flat_forward", known_bdays, known_rates)
|
|
38
|
+
>>> ffo_interp(45)
|
|
39
|
+
0.04833068080970859
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
method: Literal["flat_forward", "linear"],
|
|
45
|
+
known_bdays: pd.Series | list,
|
|
46
|
+
known_rates: pd.Series | list,
|
|
47
|
+
extrapolate: bool = False,
|
|
48
|
+
):
|
|
48
49
|
self.method = method
|
|
49
50
|
self.known_bdays = known_bdays
|
|
50
51
|
self.known_rates = known_rates
|
|
@@ -32,7 +32,7 @@ dependencies = [
|
|
|
32
32
|
"types-requests",
|
|
33
33
|
]
|
|
34
34
|
dynamic = []
|
|
35
|
-
version = "0.23.
|
|
35
|
+
version = "0.23.2"
|
|
36
36
|
|
|
37
37
|
[project.license]
|
|
38
38
|
file = "LICENSE"
|
|
@@ -61,6 +61,7 @@ dev = [
|
|
|
61
61
|
"mkdocs",
|
|
62
62
|
"mkdocs-material",
|
|
63
63
|
"mkdocstrings[python]",
|
|
64
|
+
"mkdocs-autorefs",
|
|
64
65
|
]
|
|
65
66
|
|
|
66
67
|
[tool.ruff]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.23.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
|