PYield 0.30.2__tar.gz → 0.30.4__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.30.2 → pyield-0.30.4}/PKG-INFO +1 -1
- pyield-0.30.4/pyield/__about__.py +1 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/anbima/ettj.py +11 -9
- {pyield-0.30.2 → pyield-0.30.4}/pyield/anbima/ima.py +25 -23
- {pyield-0.30.2 → pyield-0.30.4}/pyield/anbima/imaq.py +13 -11
- {pyield-0.30.2 → pyield-0.30.4}/pyield/anbima/ipca.py +6 -6
- {pyield-0.30.2 → pyield-0.30.4}/pyield/anbima/tpf.py +3 -3
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/di.py +25 -18
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/di_over.py +6 -4
- {pyield-0.30.2 → pyield-0.30.4}/pyield/bc/__init__.py +7 -7
- {pyield-0.30.2 → pyield-0.30.4}/pyield/bc/bcdata.py +1 -1
- pyield-0.30.2/pyield/bc/sec.py → pyield-0.30.4/pyield/bc/trade.py +30 -10
- {pyield-0.30.2 → pyield-0.30.4}/pyield/tpf/ntnf.py +1 -2
- {pyield-0.30.2 → pyield-0.30.4}/pyield/tpf/tools.py +2 -2
- pyield-0.30.2/pyield/__about__.py +0 -1
- {pyield-0.30.2 → pyield-0.30.4}/.gitignore +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/LICENSE +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/README.md +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/__init__.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/anbima/__init__.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/__init__.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/futures/__init__.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/futures/common.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/futures/historical.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/futures/intraday.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/b3/futures/xml.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/bc/auction.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/bc/ptax.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/bc/repo.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/bc/vna.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/bday.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/conftest.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/data_cache.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/date_converter.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/forwards.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/holidays/__init__.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/holidays/br_holidays_old.txt +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/holidays/brholidays.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/ibge/__init__.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/ibge/ipca.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/interpolator.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/py.typed +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/retry.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/tpf/__init__.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/tpf/lft.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/tpf/ltn.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyield/tpf/ntnb.py +0 -0
- {pyield-0.30.2 → pyield-0.30.4}/pyproject.toml +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.30.4"
|
|
@@ -117,15 +117,17 @@ def last_ettj() -> pd.DataFrame:
|
|
|
117
117
|
calculated and included in the returned DataFrame.
|
|
118
118
|
|
|
119
119
|
Returns:
|
|
120
|
-
pd.DataFrame: A DataFrame containing the
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
120
|
+
pd.DataFrame: A DataFrame containing the latest ETTJ data.
|
|
121
|
+
|
|
122
|
+
DataFrame columns:
|
|
123
|
+
- date: Reference date of the yield curve
|
|
124
|
+
- vertex: Time point in business days
|
|
125
|
+
- nominal_rate: Zero-coupon nominal interest rate
|
|
126
|
+
- real_rate: Zero-coupon real interest rate (IPCA-indexed)
|
|
127
|
+
- implied_inflation: Implied inflation rate (break-even inflation)
|
|
128
|
+
- nominal_rate_fwd: Forward nominal interest rate
|
|
129
|
+
- real_rate_fwd: Forward real interest rate
|
|
130
|
+
- implied_inflation_fwd: Forward implied inflation rate
|
|
129
131
|
|
|
130
132
|
Note:
|
|
131
133
|
All rates are expressed in decimal format (e.g., 0.12 for 12%).
|
|
@@ -128,29 +128,31 @@ def last_ima(ima_type: ima_types | None = None) -> pd.DataFrame:
|
|
|
128
128
|
IMA indexes are returned. Defaults to None.
|
|
129
129
|
|
|
130
130
|
Returns:
|
|
131
|
-
pd.DataFrame: A DataFrame containing the IMA data
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
131
|
+
pd.DataFrame: A DataFrame containing the IMA data.
|
|
132
|
+
|
|
133
|
+
DataFrame columns:
|
|
134
|
+
- Date: reference date of the data.
|
|
135
|
+
- IMAType: type of IMA index.
|
|
136
|
+
- BondType: type of bond.
|
|
137
|
+
- Maturity: bond maturity date.
|
|
138
|
+
- SelicCode: bond code in the SELIC system.
|
|
139
|
+
- ISIN: international Securities Identification Number.
|
|
140
|
+
- BDToMat: business days to maturity.
|
|
141
|
+
- Duration: duration of the bond in business years (252 days/year).
|
|
142
|
+
- IndicativeRate: indicative rate.
|
|
143
|
+
- Price: bond price.
|
|
144
|
+
- InterestPrice: interest price.
|
|
145
|
+
- DV01: DV01 in R$.
|
|
146
|
+
- PMR: average repurchase term.
|
|
147
|
+
- Weight: weight of the bond in the index.
|
|
148
|
+
- Convexity: convexity of the bond.
|
|
149
|
+
- TheoreticalQuantity: theoretical quantity.
|
|
150
|
+
- NumberOfOperations: number of operations.
|
|
151
|
+
- NegotiatedQuantity: negotiated quantity.
|
|
152
|
+
- NegotiatedValue: negotiated value.
|
|
153
|
+
- MarketQuantity: market quantity.
|
|
154
|
+
- MarketDV01: market DV01 in R$.
|
|
155
|
+
- MarketValue: market value in R$.
|
|
154
156
|
|
|
155
157
|
Raises:
|
|
156
158
|
Exception: Logs error and returns an empty DataFrame if any error occurs during
|
|
@@ -117,17 +117,19 @@ def imaq(date: DateScalar) -> pd.DataFrame:
|
|
|
117
117
|
the data.
|
|
118
118
|
|
|
119
119
|
Returns:
|
|
120
|
-
pd.DataFrame: A DataFrame containing the IMA data
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
120
|
+
pd.DataFrame: A DataFrame containing the IMA data.
|
|
121
|
+
|
|
122
|
+
DataFrame columns:
|
|
123
|
+
- Date: Reference date of the data.
|
|
124
|
+
- BondType: Type of bond.
|
|
125
|
+
- Maturity: Bond maturity date.
|
|
126
|
+
- SelicCode: Code representing the SELIC rate.
|
|
127
|
+
- ISIN: International Securities Identification Number.
|
|
128
|
+
- Price: Bond price.
|
|
129
|
+
- MarketQuantity: Market quantity (in units of 1000 bonds).
|
|
130
|
+
- MarketValue: Market value (in units of 1000 reais).
|
|
131
|
+
- QuantityVariation: Variation in quantity (in units of 1000 bonds).
|
|
132
|
+
- BondStatus: Status of the bond.
|
|
131
133
|
|
|
132
134
|
Raises:
|
|
133
135
|
Exception: Logs error and returns an empty DataFrame if any error occurs during
|
|
@@ -25,12 +25,12 @@ def ipca_projection() -> IndicatorProjection:
|
|
|
25
25
|
containing economic indicators, and specifically processes the IPCA projection data.
|
|
26
26
|
|
|
27
27
|
Process:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
1. Accesses the ANBIMA indicators webpage
|
|
29
|
+
2. Extracts the third table that contains the IPCA projection
|
|
30
|
+
3. Locates the row labeled as "IPCA1"
|
|
31
|
+
4. Extracts the projection value and converts it to decimal format
|
|
32
|
+
5. Extracts and formats the reference month of the projection
|
|
33
|
+
6. Extracts the date and time of the last update
|
|
34
34
|
|
|
35
35
|
Returns:
|
|
36
36
|
IndicatorProjection: An object containing:
|
|
@@ -78,7 +78,7 @@ def _process_raw_df(df_raw: pd.DataFrame) -> pd.DataFrame:
|
|
|
78
78
|
return df.sort_values(["BondType", "MaturityDate"], ignore_index=True)
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
def tpf_data(date: DateScalar, bond_type:
|
|
81
|
+
def tpf_data(date: DateScalar, bond_type: BOND_TYPES | None = None) -> pd.DataFrame:
|
|
82
82
|
"""Fetch and process TPF secondary market data from ANBIMA.
|
|
83
83
|
|
|
84
84
|
This function retrieves bond market data from the ANBIMA website for a
|
|
@@ -109,8 +109,8 @@ def tpf_data(date: DateScalar, bond_type: str | None = None) -> pd.DataFrame:
|
|
|
109
109
|
return df
|
|
110
110
|
df = _process_raw_df(df)
|
|
111
111
|
if bond_type:
|
|
112
|
-
|
|
113
|
-
df = df.query("BondType == @
|
|
112
|
+
norm_bond_type = _bond_type_mapping(bond_type) # noqa
|
|
113
|
+
df = df.query("BondType == @norm_bond_type").reset_index(drop=True)
|
|
114
114
|
return df.sort_values(["BondType", "MaturityDate"]).reset_index(drop=True)
|
|
115
115
|
except HTTPError as e:
|
|
116
116
|
if e.code == 404: # noqa
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
1
3
|
import pandas as pd
|
|
2
4
|
|
|
3
5
|
import pyield.date_converter as dc
|
|
@@ -6,6 +8,8 @@ from pyield import b3, bday, interpolator
|
|
|
6
8
|
from pyield.data_cache import get_anbima_dataset, get_di_dataset
|
|
7
9
|
from pyield.date_converter import DateArray, DateScalar
|
|
8
10
|
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
class DIFutures:
|
|
11
15
|
"""
|
|
@@ -61,7 +65,7 @@ class DIFutures:
|
|
|
61
65
|
|
|
62
66
|
def __init__(
|
|
63
67
|
self,
|
|
64
|
-
date: DateScalar
|
|
68
|
+
date: DateScalar,
|
|
65
69
|
month_start: bool = False,
|
|
66
70
|
pre_filter: bool = False,
|
|
67
71
|
all_columns: bool = True,
|
|
@@ -100,19 +104,22 @@ class DIFutures:
|
|
|
100
104
|
|
|
101
105
|
def _update_df(self) -> pd.DataFrame:
|
|
102
106
|
"""Retrieve DI contract DataFrame for the initialized trade date."""
|
|
103
|
-
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
)
|
|
107
|
+
# Return an empty DataFrame if the trade date is a holiday
|
|
108
|
+
if not bday.is_business_day(self._date):
|
|
109
|
+
logger.warning("Specified date is not a business day.")
|
|
110
|
+
logger.warning("Returning empty DataFrame.")
|
|
111
|
+
return pd.DataFrame()
|
|
112
|
+
|
|
113
|
+
# Get historical data
|
|
114
|
+
df = get_di_dataset().query("TradeDate == @self._date").reset_index(drop=True)
|
|
115
|
+
|
|
116
|
+
if df.empty:
|
|
117
|
+
logger.info("No historical data found. Trying real-time data.")
|
|
118
|
+
df = b3.futures(contract_code="DI1", date=self._date)
|
|
114
119
|
|
|
115
120
|
if df.empty:
|
|
121
|
+
logger.warning("No DI Futures data found for the specified date.")
|
|
122
|
+
logger.warning("Returning empty DataFrame.")
|
|
116
123
|
return pd.DataFrame()
|
|
117
124
|
|
|
118
125
|
if "DaysToExpiration" in df.columns:
|
|
@@ -349,12 +356,12 @@ class DIFutures:
|
|
|
349
356
|
return self._date
|
|
350
357
|
|
|
351
358
|
@date.setter
|
|
352
|
-
def date(self, value: DateScalar
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
359
|
+
def date(self, value: DateScalar):
|
|
360
|
+
self._date = dc.convert_input_dates(value)
|
|
361
|
+
bz_today = pd.Timestamp.today(tz="America/Sao_Paulo")
|
|
362
|
+
bz_today = bz_today.normalize().tz_localize(None)
|
|
363
|
+
if self._date > bz_today:
|
|
364
|
+
raise ValueError("Trade date cannot be in the future.")
|
|
358
365
|
self._dirty = True
|
|
359
366
|
|
|
360
367
|
@property
|
|
@@ -5,6 +5,9 @@ from pyield.date_converter import DateScalar, convert_input_dates
|
|
|
5
5
|
|
|
6
6
|
logger = logging.getLogger(__name__)
|
|
7
7
|
|
|
8
|
+
# 4 decimal places in rate = 2 decimal places in percentage
|
|
9
|
+
DI_OVER_DECIMAL_PLACES = 4
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
def di_over(date: DateScalar) -> float:
|
|
10
13
|
"""
|
|
@@ -14,7 +17,7 @@ def di_over(date: DateScalar) -> float:
|
|
|
14
17
|
date (str): Date in DD/MM/YYYY format
|
|
15
18
|
|
|
16
19
|
Returns:
|
|
17
|
-
float: DI rate for the specified date
|
|
20
|
+
float: DI rate for the specified date or NaN (Not a Number) if no data is found.
|
|
18
21
|
|
|
19
22
|
Raises:
|
|
20
23
|
ValueError: If date is not in the correct format
|
|
@@ -47,7 +50,7 @@ def di_over(date: DateScalar) -> float:
|
|
|
47
50
|
if lines:
|
|
48
51
|
raw_rate = lines[0].strip()
|
|
49
52
|
rate = int(raw_rate) / 10000
|
|
50
|
-
return round(rate,
|
|
53
|
+
return round(rate, DI_OVER_DECIMAL_PLACES)
|
|
51
54
|
else:
|
|
52
55
|
logger.error(f"No data found for date {date}")
|
|
53
56
|
return float("nan")
|
|
@@ -62,8 +65,7 @@ def di_over(date: DateScalar) -> float:
|
|
|
62
65
|
logger.exception("Unexpected error")
|
|
63
66
|
raise
|
|
64
67
|
finally:
|
|
65
|
-
# Ensure FTP connection is closed
|
|
66
|
-
if ftp:
|
|
68
|
+
if ftp and ftp.sock: # Ensure FTP connection is closed AND socket exists
|
|
67
69
|
try:
|
|
68
70
|
ftp.quit()
|
|
69
71
|
except: # noqa
|
|
@@ -9,19 +9,19 @@ from pyield.bc.bcdata import (
|
|
|
9
9
|
)
|
|
10
10
|
from pyield.bc.ptax import ptax_series
|
|
11
11
|
from pyield.bc.repo import repos
|
|
12
|
-
from pyield.bc.
|
|
12
|
+
from pyield.bc.trade import sec
|
|
13
13
|
from pyield.bc.vna import vna_lft
|
|
14
14
|
|
|
15
15
|
__all__ = [
|
|
16
16
|
"auctions",
|
|
17
|
-
"
|
|
18
|
-
"ptax_series",
|
|
19
|
-
"vna_lft",
|
|
20
|
-
"selic_over_series",
|
|
21
|
-
"selic_target_series",
|
|
17
|
+
"di_over",
|
|
22
18
|
"di_over_series",
|
|
19
|
+
"ptax_series",
|
|
20
|
+
"repos",
|
|
23
21
|
"sec",
|
|
24
|
-
"di_over",
|
|
25
22
|
"selic_over",
|
|
23
|
+
"selic_over_series",
|
|
26
24
|
"selic_target",
|
|
25
|
+
"selic_target_series",
|
|
26
|
+
"vna_lft",
|
|
27
27
|
]
|
|
@@ -146,7 +146,7 @@ def selic_over_series(
|
|
|
146
146
|
Date Value
|
|
147
147
|
0 2024-05-31 0.104
|
|
148
148
|
|
|
149
|
-
# No data on 26-01-2025 (sunday). Rate changed due to Copom meeting.
|
|
149
|
+
>>> # No data on 26-01-2025 (sunday). Rate changed due to Copom meeting.
|
|
150
150
|
>>> bc.selic_over_series("26-01-2025") # Returns all data since 26-01-2025
|
|
151
151
|
Date Value
|
|
152
152
|
0 2025-01-27 0.1215
|
|
@@ -62,22 +62,42 @@ def _fetch_data_from_url(file_url: str) -> pd.DataFrame:
|
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
def sec(target_date: DateScalar) -> pd.DataFrame:
|
|
65
|
-
"""Fetches
|
|
65
|
+
"""Fetches secondary market trading data for all Federal Public Securities (TPF)
|
|
66
|
+
registered on SELIC for the *month* of the specified date.
|
|
66
67
|
|
|
67
|
-
Downloads the
|
|
68
|
-
website for the
|
|
69
|
-
extracted, and
|
|
70
|
-
|
|
68
|
+
Downloads the monthly bond trading data from the Brazilian Central Bank (BCB)
|
|
69
|
+
website for the month corresponding to the provided date. The data is downloaded as
|
|
70
|
+
a ZIP file, extracted, and loaded into a Pandas DataFrame.
|
|
71
|
+
The data contains all trades executed during the month, separated by settlement day
|
|
72
|
+
('SettlementDate').
|
|
71
73
|
|
|
72
74
|
Args:
|
|
73
|
-
target_date (DateScalar): The date for which to fetch the bond
|
|
74
|
-
|
|
75
|
-
`pyield.date_converter.convert_input_dates`.
|
|
75
|
+
target_date (DateScalar): The date for which to fetch the bond trading data.
|
|
76
|
+
This can be any date-like object understood by
|
|
77
|
+
`pyield.date_converter.convert_input_dates`. Only the year and month
|
|
78
|
+
of this date will be used to download the corresponding monthly file.
|
|
76
79
|
|
|
77
80
|
Returns:
|
|
78
81
|
pd.DataFrame: A DataFrame containing the bond trading data for the
|
|
79
|
-
specified
|
|
80
|
-
|
|
82
|
+
specified month.
|
|
83
|
+
|
|
84
|
+
DataFrame columns:
|
|
85
|
+
- SettlementDate: Date when the trade settled
|
|
86
|
+
- BondType: Security type abbreviation
|
|
87
|
+
- SelicCode: Unique code in the SELIC system
|
|
88
|
+
- ISIN: International Securities Identification Number
|
|
89
|
+
- IssueDate: Date when the security was issued
|
|
90
|
+
- Maturity: Security's maturity date
|
|
91
|
+
- TradeCount: Number of trades executed
|
|
92
|
+
- TradeQuantity: Quantity traded
|
|
93
|
+
- TradeValue: Total value traded
|
|
94
|
+
- AvgPrice: Average price
|
|
95
|
+
- AvgRate: Average rate
|
|
96
|
+
And additional trading metrics like min/max prices and rates.
|
|
97
|
+
|
|
98
|
+
Examples:
|
|
99
|
+
>>> from pyield import bc
|
|
100
|
+
>>> df = bc.sec("07-01-2025") # Returns all trades for January 2025
|
|
81
101
|
"""
|
|
82
102
|
url = _build_download_url(target_date)
|
|
83
103
|
df = _fetch_data_from_url(url)
|
|
@@ -258,7 +258,6 @@ def spot_rates( # noqa
|
|
|
258
258
|
"BDToMat" is the business days from the settlement date to the maturities.
|
|
259
259
|
|
|
260
260
|
Examples:
|
|
261
|
-
|
|
262
261
|
>>> df_ltn = yd.ltn.rates("03-09-2024")
|
|
263
262
|
>>> df_ntnf = yd.ntnf.rates("03-09-2024")
|
|
264
263
|
>>> yd.ntnf.spot_rates(
|
|
@@ -522,7 +521,7 @@ def premium(
|
|
|
522
521
|
factor.
|
|
523
522
|
|
|
524
523
|
Examples:
|
|
525
|
-
# Obs: only some of the DI rates will be used in the example.
|
|
524
|
+
>>> # Obs: only some of the DI rates will be used in the example.
|
|
526
525
|
>>> exp_dates = pd.to_datetime(["2025-01-01", "2030-01-01", "2035-01-01"])
|
|
527
526
|
>>> di_rates = pd.Series([0.10823, 0.11594, 0.11531])
|
|
528
527
|
>>> premium(
|
|
@@ -79,8 +79,8 @@ def pre_spreads(date: DateScalar) -> pd.DataFrame:
|
|
|
79
79
|
converted_date = dc.convert_input_dates(date)
|
|
80
80
|
di = DIFutures(date=converted_date, month_start=True)
|
|
81
81
|
df_di = di.df
|
|
82
|
-
if "SettlementRate" not in df_di.columns:
|
|
83
|
-
raise ValueError("DI
|
|
82
|
+
if "SettlementRate" not in df_di.columns or df_di.empty:
|
|
83
|
+
raise ValueError("DI data is missing the 'SettlementRate' column or is empty.")
|
|
84
84
|
|
|
85
85
|
df_di = df_di[["ExpirationDate", "SettlementRate"]].copy()
|
|
86
86
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.30.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
|
|
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
|