PYield 0.25.0__tar.gz → 0.25.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 (34) hide show
  1. {pyield-0.25.0 → pyield-0.25.2}/PKG-INFO +2 -2
  2. {pyield-0.25.0 → pyield-0.25.2}/README.md +1 -1
  3. pyield-0.25.2/pyield/__about__.py +1 -0
  4. {pyield-0.25.0 → pyield-0.25.2}/pyield/b3_futures/historical.py +13 -5
  5. {pyield-0.25.0 → pyield-0.25.2}/pyield/b3_futures/intraday.py +30 -15
  6. {pyield-0.25.0 → pyield-0.25.2}/pyield/di.py +5 -1
  7. pyield-0.25.0/pyield/__about__.py +0 -1
  8. {pyield-0.25.0 → pyield-0.25.2}/.gitignore +0 -0
  9. {pyield-0.25.0 → pyield-0.25.2}/LICENSE +0 -0
  10. {pyield-0.25.0 → pyield-0.25.2}/pyield/__init__.py +0 -0
  11. {pyield-0.25.0 → pyield-0.25.2}/pyield/anbima.py +0 -0
  12. {pyield-0.25.0 → pyield-0.25.2}/pyield/b3_futures/__init__.py +0 -0
  13. {pyield-0.25.0 → pyield-0.25.2}/pyield/b3_futures/common.py +0 -0
  14. {pyield-0.25.0 → pyield-0.25.2}/pyield/b3_futures/xml.py +0 -0
  15. {pyield-0.25.0 → pyield-0.25.2}/pyield/bday.py +0 -0
  16. {pyield-0.25.0 → pyield-0.25.2}/pyield/bonds/__init__.py +0 -0
  17. {pyield-0.25.0 → pyield-0.25.2}/pyield/bonds/bond_tools.py +0 -0
  18. {pyield-0.25.0 → pyield-0.25.2}/pyield/bonds/lft.py +0 -0
  19. {pyield-0.25.0 → pyield-0.25.2}/pyield/bonds/ltn.py +0 -0
  20. {pyield-0.25.0 → pyield-0.25.2}/pyield/bonds/ntnb.py +0 -0
  21. {pyield-0.25.0 → pyield-0.25.2}/pyield/bonds/ntnf.py +0 -0
  22. {pyield-0.25.0 → pyield-0.25.2}/pyield/conftest.py +0 -0
  23. {pyield-0.25.0 → pyield-0.25.2}/pyield/data_cache.py +0 -0
  24. {pyield-0.25.0 → pyield-0.25.2}/pyield/date_converter.py +0 -0
  25. {pyield-0.25.0 → pyield-0.25.2}/pyield/holidays/__init__.py +0 -0
  26. {pyield-0.25.0 → pyield-0.25.2}/pyield/holidays/br_holidays_new.txt +0 -0
  27. {pyield-0.25.0 → pyield-0.25.2}/pyield/holidays/br_holidays_old.txt +0 -0
  28. {pyield-0.25.0 → pyield-0.25.2}/pyield/holidays/brholidays.py +0 -0
  29. {pyield-0.25.0 → pyield-0.25.2}/pyield/indicators.py +0 -0
  30. {pyield-0.25.0 → pyield-0.25.2}/pyield/interpolator.py +0 -0
  31. {pyield-0.25.0 → pyield-0.25.2}/pyield/projections.py +0 -0
  32. {pyield-0.25.0 → pyield-0.25.2}/pyield/py.typed +0 -0
  33. {pyield-0.25.0 → pyield-0.25.2}/pyield/tools.py +0 -0
  34. {pyield-0.25.0 → pyield-0.25.2}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: PYield
3
- Version: 0.25.0
3
+ Version: 0.25.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>
@@ -169,7 +169,7 @@ dtype: datetime64[ns]
169
169
  >>> import pyield as yd
170
170
  # Fetch current DI Futures data from B3 (15 minutes delay)
171
171
  >>> yd.futures(contract_code="DI1")
172
- TradeTime TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate CurrentRate
172
+ TradeTime TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
173
173
  2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
174
174
  2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
175
175
  2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
@@ -129,7 +129,7 @@ dtype: datetime64[ns]
129
129
  >>> import pyield as yd
130
130
  # Fetch current DI Futures data from B3 (15 minutes delay)
131
131
  >>> yd.futures(contract_code="DI1")
132
- TradeTime TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate CurrentRate
132
+ TradeTime TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
133
133
  2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
134
134
  2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
135
135
  2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
@@ -0,0 +1 @@
1
+ __version__ = "0.25.2"
@@ -94,9 +94,9 @@ def _convert_prices_to_rates(
94
94
  Returns:
95
95
  pd.Series: A pd.Series containing the futures rates.
96
96
  """
97
- if count_convention == 252:
97
+ if count_convention == 252: # noqa
98
98
  rates = (100_000 / prices) ** (252 / days_to_expiration) - 1
99
- elif count_convention == 360:
99
+ elif count_convention == 360: # noqa
100
100
  rates = (100_000 / prices - 1) * (360 / days_to_expiration)
101
101
  else:
102
102
  raise ValueError("Invalid count_convention. Must be 252 or 360.")
@@ -210,7 +210,7 @@ def process_df(
210
210
 
211
211
  df["DaysToExp"] = (df["ExpirationDate"] - trade_date).dt.days
212
212
  # Convert to nullable integer, since it is the default type in the library
213
- df["DaysToExp"] = df["DaysToExp"].astype(pd.Int64Dtype())
213
+ df["DaysToExp"] = df["DaysToExp"].astype("Int64")
214
214
 
215
215
  df["BDaysToExp"] = bday.count(trade_date, df["ExpirationDate"])
216
216
 
@@ -232,19 +232,26 @@ def process_df(
232
232
  # Remove % and round to 5 (3 in %) dec. places in rate columns
233
233
  df[rate_cols] = df[rate_cols].div(100).round(5)
234
234
 
235
- if COUNT_CONVENTIONS[asset_code] == 252:
235
+ if COUNT_CONVENTIONS[asset_code] == 252: # noqa
236
236
  df["SettlementRate"] = _convert_prices_to_rates(
237
237
  prices=df["SettlementPrice"],
238
238
  days_to_expiration=df["BDaysToExp"],
239
239
  count_convention=252,
240
240
  )
241
- elif COUNT_CONVENTIONS[asset_code] == 360:
241
+ elif COUNT_CONVENTIONS[asset_code] == 360: # noqa
242
242
  df["SettlementRate"] = _convert_prices_to_rates(
243
243
  prices=df["SettlementPrice"],
244
244
  days_to_expiration=df["DaysToExp"],
245
245
  count_convention=360,
246
246
  )
247
247
 
248
+ # Calculate DV01 for DI1 contracts
249
+ if asset_code == "DI1":
250
+ duration = df["BDaysToExp"] / 252
251
+ modified_duration = duration / (1 + df["SettlementRate"])
252
+ df["DV01"] = 0.0001 * modified_duration * df["SettlementPrice"]
253
+ df["DV01"] = df["DV01"].astype("Float64")
254
+
248
255
  return df
249
256
 
250
257
 
@@ -262,6 +269,7 @@ def _select_and_reorder_columns(df: pd.DataFrame):
262
269
  "TradeCount",
263
270
  "TradeVolume",
264
271
  "FinancialVolume",
272
+ "DV01",
265
273
  "SettlementPrice",
266
274
  "SettlementRate",
267
275
  "OpenRate",
@@ -9,14 +9,14 @@ def _fetch_b3_df(future_code: str) -> pd.DataFrame:
9
9
  Fetch the latest data for a given future code from B3 derivatives quotation API.
10
10
 
11
11
  Args:
12
- future_code (str): The future code to fetch data for.
12
+ future_code (str): The future code to fetch data for.
13
13
 
14
14
  Returns:
15
- pd.DataFrame: DataFrame containing the normalized and cleaned data from the API.
16
- If no data is available, an empty DataFrame is returned.
15
+ pd.DataFrame: DataFrame containing the normalized and cleaned data from the API.
16
+ If no data is available, an empty DataFrame is returned.
17
17
 
18
18
  Raises:
19
- Exception: An exception is raised if the data fetch operation fails.
19
+ Exception: An exception is raised if the data fetch operation fails.
20
20
  """
21
21
 
22
22
  url = f"https://cotacao.b3.com.br/mds/api/v1/DerivativeQuotation/{future_code}"
@@ -46,10 +46,10 @@ def _rename_columns(df: pd.DataFrame) -> pd.DataFrame:
46
46
  Rename the columns of a DataFrame containing the futures data.
47
47
 
48
48
  Args:
49
- df (pd.DataFrame): A DataFrame containing futures data.
49
+ df (pd.DataFrame): A DataFrame containing futures data.
50
50
 
51
51
  Returns:
52
- pd.DataFrame: DataFrame with the columns renamed.
52
+ pd.DataFrame: DataFrame with the columns renamed.
53
53
  """
54
54
  all_columns = {
55
55
  "symb": "TickerSymbol",
@@ -60,14 +60,14 @@ def _rename_columns(df: pd.DataFrame) -> pd.DataFrame:
60
60
  "minPric": "MinRate",
61
61
  "maxPric": "MaxRate",
62
62
  "avrgPric": "AvgRate",
63
- "curPrc": "CurrentRate",
63
+ "curPrc": "LastRate",
64
64
  "grssAmt": "FinancialVolume",
65
65
  "mtrtyCode": "ExpirationDate",
66
66
  "opnCtrcts": "OpenContracts",
67
67
  "tradQty": "TradeCount",
68
68
  "traddCtrctsQty": "TradeVolume",
69
- "buyOffer.price": "CurrentAskRate",
70
- "sellOffer.price": "CurrentBidRate",
69
+ "buyOffer.price": "LastAskRate",
70
+ "sellOffer.price": "LastBidRate",
71
71
  }
72
72
  # Check which columns are present in the DataFrame before renaming
73
73
  rename_dict = {c: all_columns[c] for c in all_columns if c in df.columns}
@@ -108,12 +108,25 @@ def _process_df(raw_df: pd.DataFrame) -> pd.DataFrame:
108
108
 
109
109
  df["DaysToExp"] = (df["ExpirationDate"] - df["TradeDate"]).dt.days
110
110
  # Convert to nullable integer, since it is the default type in the library
111
- df["DaysToExp"] = df["DaysToExp"].astype(pd.Int64Dtype())
111
+ df["DaysToExp"] = df["DaysToExp"].astype("Int64")
112
112
 
113
113
  # Remove percentage in all rate columns
114
114
  rate_cols = [col for col in df.columns if "Rate" in col]
115
115
  df[rate_cols] = df[rate_cols].div(100).round(5)
116
116
 
117
+ # Adjust DI1 futures contracts
118
+ contract_type = df["TickerSymbol"].iloc[0][:3]
119
+ if contract_type in {"DI1", "DAP"}:
120
+ byears = df["BDaysToExp"] / 252
121
+ df["LastPrice"] = 100_000 / ((1 + df["LastRate"]) ** (byears))
122
+ df["LastPrice"] = df["LastPrice"].round(2).astype("Float64")
123
+
124
+ if contract_type == "DI1":
125
+ duration = df["BDaysToExp"] / 252
126
+ modified_duration = duration / (1 + df["LastRate"])
127
+ df["DV01"] = 0.0001 * modified_duration * df["LastPrice"]
128
+ df["DV01"] = df["DV01"].astype("Float64")
129
+
117
130
  return df
118
131
 
119
132
 
@@ -122,10 +135,10 @@ def _select_and_reorder_columns(df: pd.DataFrame) -> pd.DataFrame:
122
135
  Select and reorder columns in the DataFrame.
123
136
 
124
137
  Args:
125
- df (pd.DataFrame): A DataFrame containing futures data.
138
+ df (pd.DataFrame): A DataFrame containing futures data.
126
139
 
127
140
  Returns:
128
- pd.DataFrame: DataFrame with the columns selected and reordered.
141
+ pd.DataFrame: DataFrame with the columns selected and reordered.
129
142
  """
130
143
  all_columns = [
131
144
  "TradeDate",
@@ -138,6 +151,7 @@ def _select_and_reorder_columns(df: pd.DataFrame) -> pd.DataFrame:
138
151
  "TradeCount",
139
152
  "TradeVolume",
140
153
  "FinancialVolume",
154
+ "DV01",
141
155
  "PrevSettlementRate",
142
156
  "MinLimitRate",
143
157
  "MaxLimitRate",
@@ -145,9 +159,10 @@ def _select_and_reorder_columns(df: pd.DataFrame) -> pd.DataFrame:
145
159
  "MinRate",
146
160
  "AvgRate",
147
161
  "MaxRate",
148
- "CurrentAskRate",
149
- "CurrentBidRate",
150
- "CurrentRate",
162
+ "LastAskRate",
163
+ "LastBidRate",
164
+ "LastRate",
165
+ "LastPrice",
151
166
  ]
152
167
  reordered_columns = [col for col in all_columns if col in df.columns]
153
168
  return df[reordered_columns].copy()
@@ -150,14 +150,18 @@ class DIFutures:
150
150
  "TickerSymbol",
151
151
  "OpenContracts",
152
152
  "TradeVolume",
153
+ "DV01",
153
154
  "OpenRate",
154
155
  "MinRate",
155
156
  "MaxRate",
156
157
  "CloseRate",
157
158
  "SettlementRate",
159
+ "LastRate",
158
160
  "SettlementPrice",
161
+ "LastPrice",
159
162
  ]
160
- df = df[cols].copy()
163
+ selected_cols = [col for col in cols if col in df.columns]
164
+ df = df[selected_cols].copy()
161
165
 
162
166
  return df.sort_values(by=["TradeDate", "ExpirationDate"]).reset_index(drop=True)
163
167
 
@@ -1 +0,0 @@
1
- __version__ = "0.25.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