PYield 0.7.4__tar.gz → 0.7.6__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.7.4 → pyield-0.7.6}/PKG-INFO +52 -26
- {pyield-0.7.4 → pyield-0.7.6}/README.md +51 -25
- pyield-0.7.6/pyield/__about__.py +1 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/futures/common.py +3 -2
- {pyield-0.7.4 → pyield-0.7.6}/pyield/futures/ddi.py +16 -49
- {pyield-0.7.4 → pyield-0.7.6}/pyield/futures/di.py +32 -51
- {pyield-0.7.4 → pyield-0.7.6}/pyield/futures/frc.py +9 -5
- {pyield-0.7.4 → pyield-0.7.6}/pyproject.toml +1 -1
- {pyield-0.7.4 → pyield-0.7.6}/tests/test_futures.py +3 -3
- pyield-0.7.4/pyield/__about__.py +0 -1
- {pyield-0.7.4 → pyield-0.7.6}/LICENSE +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/__init__.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/bday.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/data_access.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/data_analysis.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/futures/__init__.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/futures/di_xml.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/holidays/__init__.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/holidays/br_holidays_old.txt +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/holidays/core.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/indicators.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/projections.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/py.typed +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/treasuries.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/pyield/utils.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/tests/__init__.py +0 -0
- {pyield-0.7.4 → pyield-0.7.6}/tests/test_bday.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PYield
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.6
|
|
4
4
|
Summary: A Python library for analysis of fixed income instruments in Brazil
|
|
5
5
|
Keywords: fixed-income, brazil, finance, analysis, bonds
|
|
6
6
|
Author-Email: Carlos Carvalho <cr.cj@outlook.com>
|
|
@@ -45,7 +45,7 @@ Description-Content-Type: text/markdown
|
|
|
45
45
|
[](https://python.org "Go to Python homepage")
|
|
46
46
|
[](#license)
|
|
47
47
|
|
|
48
|
-
# PYield: Fixed Income
|
|
48
|
+
# PYield: Brazilian Fixed Income Toolkit
|
|
49
49
|
|
|
50
50
|
## Introduction
|
|
51
51
|
|
|
@@ -99,17 +99,27 @@ dtype: datetime64[ns]
|
|
|
99
99
|
|
|
100
100
|
### Futures Data
|
|
101
101
|
```python
|
|
102
|
-
# Fetch
|
|
102
|
+
# Fetch current DI Futures data from B3 (15 minutes delay)
|
|
103
|
+
>>> yd.fetch_asset(asset_code="DI1")
|
|
104
|
+
TradeTimestamp TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
|
|
105
|
+
2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
|
|
106
|
+
2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
|
|
107
|
+
2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
|
|
108
|
+
... ... ... ... ... ... ... ... ...
|
|
109
|
+
2024-04-21 13:37:39 DI1F37 2037-01-02 3183 ... <NA> <NA> 0.11600 <NA>
|
|
110
|
+
2024-04-21 13:37:39 DI1F38 2038-01-04 3432 ... <NA> <NA> 0.11600 <NA>
|
|
111
|
+
2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
|
|
112
|
+
|
|
113
|
+
# Fetch historical DI Futures data from B3
|
|
103
114
|
>>> yd.fetch_asset(asset_code="DI1", reference_date='2024-03-08')
|
|
104
|
-
|
|
105
115
|
TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastBidRate SettlementRate
|
|
106
|
-
2024-03-08
|
|
107
|
-
2024-03-08
|
|
108
|
-
2024-03-08
|
|
109
|
-
...
|
|
110
|
-
2024-03-08
|
|
111
|
-
2024-03-08
|
|
112
|
-
2024-03-08
|
|
116
|
+
2024-03-08 DI1J24 2024-04-01 15 ... 10.952 10.952 10.956 10.956
|
|
117
|
+
2024-03-08 DI1K24 2024-05-02 37 ... 10.776 10.774 10.780 10.777
|
|
118
|
+
2024-03-08 DI1M24 2024-06-03 58 ... 10.604 10.602 10.604 10.608
|
|
119
|
+
... ... ... ... ... ... ... ... ...
|
|
120
|
+
2024-03-08 DI1F37 2037-01-02 3213 ... <NA> <NA> <NA> 10.859
|
|
121
|
+
2024-03-08 DI1F38 2038-01-04 3462 ... <NA> <NA> <NA> 10.859
|
|
122
|
+
2024-03-08 DI1F39 2039-01-03 3713 ... <NA> <NA> <NA> 10.85
|
|
113
123
|
```
|
|
114
124
|
|
|
115
125
|
### Treasury Bonds Data
|
|
@@ -119,14 +129,14 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
|
|
|
119
129
|
# Obs: Anbima members have access to the full history
|
|
120
130
|
>>> yd.fetch_asset(asset_code="NTN-B", reference_date='2024-04-12')
|
|
121
131
|
|
|
122
|
-
BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate
|
|
123
|
-
NTN-B 2024-04-12
|
|
124
|
-
NTN-B 2024-04-12
|
|
125
|
-
NTN-B 2024-04-12
|
|
126
|
-
...
|
|
127
|
-
NTN-B 2024-04-12
|
|
128
|
-
NTN-B 2024-04-12
|
|
129
|
-
NTN-B 2024-04-12
|
|
132
|
+
BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate Price
|
|
133
|
+
NTN-B 2024-04-12 2024-08-15 0.07540 0.07504 0.07523 4,271.43565
|
|
134
|
+
NTN-B 2024-04-12 2025-05-15 0.05945 0.05913 0.05930 4,361.34391
|
|
135
|
+
NTN-B 2024-04-12 2026-08-15 0.05927 0.05897 0.05910 4,301.40082
|
|
136
|
+
... ... ... ... ... ... ...
|
|
137
|
+
NTN-B 2024-04-12 2050-08-15 0.06039 0.06006 0.06023 4,299.28233
|
|
138
|
+
NTN-B 2024-04-12 2055-05-15 0.06035 0.05998 0.06017 4,367.13360
|
|
139
|
+
NTN-B 2024-04-12 2060-08-15 0.06057 0.06016 0.06036 4,292.26323
|
|
130
140
|
```
|
|
131
141
|
|
|
132
142
|
### Spreads Calculation
|
|
@@ -135,13 +145,13 @@ NTN-B 2024-04-12 2060-08-15 0.06057 0.06016 0.06036 4,292.26323
|
|
|
135
145
|
>>> yd.calculate_spreads(spread_type="di_vs_pre", reference_date="2024-4-11")
|
|
136
146
|
|
|
137
147
|
BondType ReferenceDate MaturityDate DISpread
|
|
138
|
-
LTN
|
|
139
|
-
LTN
|
|
140
|
-
LTN
|
|
141
|
-
... ... ... ...
|
|
142
|
-
NTN-F 2024-04-11
|
|
143
|
-
NTN-F 2024-04-11
|
|
144
|
-
NTN-F 2024-04-11
|
|
148
|
+
LTN 2024-04-11 2024-07-01 -20.28
|
|
149
|
+
LTN 2024-04-11 2024-10-01 -10.19
|
|
150
|
+
LTN 2024-04-11 2025-01-01 -15.05
|
|
151
|
+
... ... ... ...
|
|
152
|
+
NTN-F 2024-04-11 2031-01-01 -0.66
|
|
153
|
+
NTN-F 2024-04-11 2033-01-01 -5.69
|
|
154
|
+
NTN-F 2024-04-11 2035-01-01 -1.27
|
|
145
155
|
```
|
|
146
156
|
|
|
147
157
|
### Indicators Data
|
|
@@ -158,3 +168,19 @@ NTN-F 2024-04-11 2035-01-01 -1.27000
|
|
|
158
168
|
>>> yd.fetch_indicator(indicator_code="IPCA", reference_date='2024-04-10')
|
|
159
169
|
None
|
|
160
170
|
```
|
|
171
|
+
|
|
172
|
+
### Projections Data
|
|
173
|
+
```python
|
|
174
|
+
# Fetch current month projection for IPCA from IBGE API
|
|
175
|
+
>>> ipca = yd.fetch_projection(projection_code="IPCA_CM")
|
|
176
|
+
>>> print(ipca)
|
|
177
|
+
IndicatorProjection(
|
|
178
|
+
last_updated=Timestamp('2024-04-19 18:55:00'),
|
|
179
|
+
reference_month_ts=Timestamp('2024-04-01 00:00:00'),
|
|
180
|
+
reference_month_br='ABR/2024',
|
|
181
|
+
projected_value=0.0035
|
|
182
|
+
)
|
|
183
|
+
>>> ipca.projected_value
|
|
184
|
+
0.0035
|
|
185
|
+
```
|
|
186
|
+
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://python.org "Go to Python homepage")
|
|
3
3
|
[](#license)
|
|
4
4
|
|
|
5
|
-
# PYield: Fixed Income
|
|
5
|
+
# PYield: Brazilian Fixed Income Toolkit
|
|
6
6
|
|
|
7
7
|
## Introduction
|
|
8
8
|
|
|
@@ -56,17 +56,27 @@ dtype: datetime64[ns]
|
|
|
56
56
|
|
|
57
57
|
### Futures Data
|
|
58
58
|
```python
|
|
59
|
-
# Fetch
|
|
59
|
+
# Fetch current DI Futures data from B3 (15 minutes delay)
|
|
60
|
+
>>> yd.fetch_asset(asset_code="DI1")
|
|
61
|
+
TradeTimestamp TickerSymbol ExpirationDate BDaysToExp ... MaxRate LastAskRate LastBidRate LastRate
|
|
62
|
+
2024-04-21 13:37:39 DI1K24 2024-05-02 7 ... 0.10660 0.10652 0.10660 0.10660
|
|
63
|
+
2024-04-21 13:37:39 DI1M24 2024-06-03 28 ... 0.10518 0.10510 0.10516 0.10518
|
|
64
|
+
2024-04-21 13:37:39 DI1N24 2024-07-01 48 ... 0.10480 0.10456 0.10462 0.10460
|
|
65
|
+
... ... ... ... ... ... ... ... ...
|
|
66
|
+
2024-04-21 13:37:39 DI1F37 2037-01-02 3183 ... <NA> <NA> 0.11600 <NA>
|
|
67
|
+
2024-04-21 13:37:39 DI1F38 2038-01-04 3432 ... <NA> <NA> 0.11600 <NA>
|
|
68
|
+
2024-04-21 13:37:39 DI1F39 2039-01-03 3683 ... <NA> <NA> <NA> <NA>
|
|
69
|
+
|
|
70
|
+
# Fetch historical DI Futures data from B3
|
|
60
71
|
>>> yd.fetch_asset(asset_code="DI1", reference_date='2024-03-08')
|
|
61
|
-
|
|
62
72
|
TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastBidRate SettlementRate
|
|
63
|
-
2024-03-08
|
|
64
|
-
2024-03-08
|
|
65
|
-
2024-03-08
|
|
66
|
-
...
|
|
67
|
-
2024-03-08
|
|
68
|
-
2024-03-08
|
|
69
|
-
2024-03-08
|
|
73
|
+
2024-03-08 DI1J24 2024-04-01 15 ... 10.952 10.952 10.956 10.956
|
|
74
|
+
2024-03-08 DI1K24 2024-05-02 37 ... 10.776 10.774 10.780 10.777
|
|
75
|
+
2024-03-08 DI1M24 2024-06-03 58 ... 10.604 10.602 10.604 10.608
|
|
76
|
+
... ... ... ... ... ... ... ... ...
|
|
77
|
+
2024-03-08 DI1F37 2037-01-02 3213 ... <NA> <NA> <NA> 10.859
|
|
78
|
+
2024-03-08 DI1F38 2038-01-04 3462 ... <NA> <NA> <NA> 10.859
|
|
79
|
+
2024-03-08 DI1F39 2039-01-03 3713 ... <NA> <NA> <NA> 10.85
|
|
70
80
|
```
|
|
71
81
|
|
|
72
82
|
### Treasury Bonds Data
|
|
@@ -76,14 +86,14 @@ TradeDate TickerSymbol ExpirationDate BDaysToExp ... LastRate LastAskRate LastB
|
|
|
76
86
|
# Obs: Anbima members have access to the full history
|
|
77
87
|
>>> yd.fetch_asset(asset_code="NTN-B", reference_date='2024-04-12')
|
|
78
88
|
|
|
79
|
-
BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate
|
|
80
|
-
NTN-B 2024-04-12
|
|
81
|
-
NTN-B 2024-04-12
|
|
82
|
-
NTN-B 2024-04-12
|
|
83
|
-
...
|
|
84
|
-
NTN-B 2024-04-12
|
|
85
|
-
NTN-B 2024-04-12
|
|
86
|
-
NTN-B 2024-04-12
|
|
89
|
+
BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate Price
|
|
90
|
+
NTN-B 2024-04-12 2024-08-15 0.07540 0.07504 0.07523 4,271.43565
|
|
91
|
+
NTN-B 2024-04-12 2025-05-15 0.05945 0.05913 0.05930 4,361.34391
|
|
92
|
+
NTN-B 2024-04-12 2026-08-15 0.05927 0.05897 0.05910 4,301.40082
|
|
93
|
+
... ... ... ... ... ... ...
|
|
94
|
+
NTN-B 2024-04-12 2050-08-15 0.06039 0.06006 0.06023 4,299.28233
|
|
95
|
+
NTN-B 2024-04-12 2055-05-15 0.06035 0.05998 0.06017 4,367.13360
|
|
96
|
+
NTN-B 2024-04-12 2060-08-15 0.06057 0.06016 0.06036 4,292.26323
|
|
87
97
|
```
|
|
88
98
|
|
|
89
99
|
### Spreads Calculation
|
|
@@ -92,13 +102,13 @@ NTN-B 2024-04-12 2060-08-15 0.06057 0.06016 0.06036 4,292.26323
|
|
|
92
102
|
>>> yd.calculate_spreads(spread_type="di_vs_pre", reference_date="2024-4-11")
|
|
93
103
|
|
|
94
104
|
BondType ReferenceDate MaturityDate DISpread
|
|
95
|
-
LTN
|
|
96
|
-
LTN
|
|
97
|
-
LTN
|
|
98
|
-
... ... ... ...
|
|
99
|
-
NTN-F 2024-04-11
|
|
100
|
-
NTN-F 2024-04-11
|
|
101
|
-
NTN-F 2024-04-11
|
|
105
|
+
LTN 2024-04-11 2024-07-01 -20.28
|
|
106
|
+
LTN 2024-04-11 2024-10-01 -10.19
|
|
107
|
+
LTN 2024-04-11 2025-01-01 -15.05
|
|
108
|
+
... ... ... ...
|
|
109
|
+
NTN-F 2024-04-11 2031-01-01 -0.66
|
|
110
|
+
NTN-F 2024-04-11 2033-01-01 -5.69
|
|
111
|
+
NTN-F 2024-04-11 2035-01-01 -1.27
|
|
102
112
|
```
|
|
103
113
|
|
|
104
114
|
### Indicators Data
|
|
@@ -115,3 +125,19 @@ NTN-F 2024-04-11 2035-01-01 -1.27000
|
|
|
115
125
|
>>> yd.fetch_indicator(indicator_code="IPCA", reference_date='2024-04-10')
|
|
116
126
|
None
|
|
117
127
|
```
|
|
128
|
+
|
|
129
|
+
### Projections Data
|
|
130
|
+
```python
|
|
131
|
+
# Fetch current month projection for IPCA from IBGE API
|
|
132
|
+
>>> ipca = yd.fetch_projection(projection_code="IPCA_CM")
|
|
133
|
+
>>> print(ipca)
|
|
134
|
+
IndicatorProjection(
|
|
135
|
+
last_updated=Timestamp('2024-04-19 18:55:00'),
|
|
136
|
+
reference_month_ts=Timestamp('2024-04-01 00:00:00'),
|
|
137
|
+
reference_month_br='ABR/2024',
|
|
138
|
+
projected_value=0.0035
|
|
139
|
+
)
|
|
140
|
+
>>> ipca.projected_value
|
|
141
|
+
0.0035
|
|
142
|
+
```
|
|
143
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.7.6"
|
|
@@ -133,7 +133,8 @@ def get_old_expiration_date(
|
|
|
133
133
|
|
|
134
134
|
def fetch_past_raw_df(asset_code: str, trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
135
135
|
"""
|
|
136
|
-
Fetch the historical futures data from B3 for a specific trade date.
|
|
136
|
+
Fetch the historical futures data from B3 for a specific trade date. If the data is
|
|
137
|
+
not available, an empty DataFrame is returned.
|
|
137
138
|
|
|
138
139
|
Args:
|
|
139
140
|
trade_date (pd.Timestamp): The trade date for which the data should be fetched.
|
|
@@ -148,7 +149,7 @@ def fetch_past_raw_df(asset_code: str, trade_date: pd.Timestamp) -> pd.DataFrame
|
|
|
148
149
|
|
|
149
150
|
text = r.text
|
|
150
151
|
if "AJUSTE" not in text:
|
|
151
|
-
|
|
152
|
+
return pd.DataFrame()
|
|
152
153
|
|
|
153
154
|
df = pd.read_html(
|
|
154
155
|
io.StringIO(text),
|
|
@@ -15,29 +15,8 @@ def _convert_prices_to_rates(prices: pd.Series, n_days: pd.Series) -> pd.Series:
|
|
|
15
15
|
pd.Series: A pd.Series containing DDI futures rates.
|
|
16
16
|
"""
|
|
17
17
|
rates = (100_000 / prices - 1) * (360 / n_days)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return 100 * rates
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _convert_prices_in_older_contracts(df: pd.DataFrame) -> pd.DataFrame:
|
|
24
|
-
# Prior to 01/01/2002, prices were not converted to rates
|
|
25
|
-
convert_cols = [
|
|
26
|
-
"FirstRate",
|
|
27
|
-
"MinRate",
|
|
28
|
-
"MaxRate",
|
|
29
|
-
"AvgRate",
|
|
30
|
-
"LastRate",
|
|
31
|
-
"LastBidRate",
|
|
32
|
-
"LastAskRate",
|
|
33
|
-
]
|
|
34
|
-
for col in convert_cols:
|
|
35
|
-
df[col] = _convert_prices_to_rates(df[col], df["DaysToExpiration"])
|
|
36
|
-
|
|
37
|
-
# Invert low and high prices
|
|
38
|
-
df["MinRate"], df["MaxRate"] = df["MaxRate"], df["MinRate"]
|
|
39
|
-
|
|
40
|
-
return df
|
|
18
|
+
# Round to 5 (3 in %) dec. places (contract's current max. precision)
|
|
19
|
+
return rates.round(5)
|
|
41
20
|
|
|
42
21
|
|
|
43
22
|
def _process_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
@@ -90,46 +69,34 @@ def _process_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
|
90
69
|
else:
|
|
91
70
|
df["ExpirationDate"] = df["ExpirationCode"].apply(common.get_expiration_date)
|
|
92
71
|
|
|
93
|
-
df["
|
|
72
|
+
df["DaysToExp"] = (df["ExpirationDate"] - trade_date).dt.days
|
|
94
73
|
# Convert to nullable integer, since other columns use this data type
|
|
95
|
-
df["
|
|
74
|
+
df["DaysToExp"] = df["DaysToExp"].astype(pd.Int64Dtype())
|
|
75
|
+
|
|
96
76
|
# Remove expired contracts
|
|
97
|
-
df.query("
|
|
77
|
+
df.query("DaysToExp > 0", inplace=True)
|
|
98
78
|
|
|
99
79
|
# Columns where 0 means NaN
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
"MaxRate",
|
|
105
|
-
"AvgRate",
|
|
106
|
-
"LastRate",
|
|
107
|
-
"LastBidRate",
|
|
108
|
-
"LastAskRate",
|
|
109
|
-
]
|
|
110
|
-
for col in cols_with_nan:
|
|
111
|
-
df[col] = df[col].replace(0, pd.NA)
|
|
80
|
+
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
81
|
+
cols_with_nan = rate_cols + ["SettlementPrice"]
|
|
82
|
+
# Replace 0 with NaN in these columns
|
|
83
|
+
df[cols_with_nan] = df[cols_with_nan].replace(0, pd.NA)
|
|
112
84
|
|
|
113
|
-
|
|
114
|
-
if trade_date <= pd.Timestamp("2002-01-17"):
|
|
115
|
-
df = _convert_prices_in_older_contracts(df)
|
|
85
|
+
df[rate_cols] = df[rate_cols].div(100).round(5)
|
|
116
86
|
|
|
87
|
+
# Calculate SettlementRate
|
|
117
88
|
df["SettlementRate"] = _convert_prices_to_rates(
|
|
118
|
-
df["SettlementPrice"], df["
|
|
89
|
+
df["SettlementPrice"], df["DaysToExp"]
|
|
119
90
|
)
|
|
120
91
|
|
|
121
|
-
|
|
122
|
-
# precision used by B3. Obs: 5 decimal places = 3 decimal places in percentage
|
|
123
|
-
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
124
|
-
for col in rate_cols:
|
|
125
|
-
df[col] = (df[col] / 100).round(5)
|
|
92
|
+
df["TickerSymbol"] = "DI1" + df["ExpirationCode"]
|
|
126
93
|
|
|
127
94
|
# Filter and order columns
|
|
128
95
|
ordered_cols = [
|
|
129
96
|
"TradeDate",
|
|
130
97
|
"ExpirationCode",
|
|
131
98
|
"ExpirationDate",
|
|
132
|
-
"
|
|
99
|
+
"DaysToExp",
|
|
133
100
|
"OpenContracts",
|
|
134
101
|
# "OpenContractsEndSession" since there is no OpenContracts at the end of the
|
|
135
102
|
# day in XML data, it will be removed to avoid confusion with XML data
|
|
@@ -169,7 +136,7 @@ def fetch_past_ddi(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.Dat
|
|
|
169
136
|
>>> di.fetch_ddi(pd.Timestamp("2021-01-04"))
|
|
170
137
|
|
|
171
138
|
Notes:
|
|
172
|
-
-
|
|
139
|
+
- DaysToExp: number of business days to ExpirationDate.
|
|
173
140
|
- OpenContracts: number of open contracts at the start of the trading day.
|
|
174
141
|
"""
|
|
175
142
|
df_raw = common.fetch_past_raw_df(asset_code="DDI", trade_date=trade_date)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
-
from .. import bday
|
|
4
|
-
from . import common
|
|
3
|
+
from .. import bday as bd
|
|
4
|
+
from . import common as cm
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def _convert_prices_to_rates(prices: pd.Series, bd: pd.Series) -> pd.Series:
|
|
@@ -17,22 +17,12 @@ def _convert_prices_to_rates(prices: pd.Series, bd: pd.Series) -> pd.Series:
|
|
|
17
17
|
"""
|
|
18
18
|
rates = (100_000 / prices) ** (252 / bd) - 1
|
|
19
19
|
|
|
20
|
-
#
|
|
21
|
-
return
|
|
20
|
+
# Round to 5 (3 in %) dec. places (contract's current max. precision)
|
|
21
|
+
return rates.round(5)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
convert_cols = [
|
|
27
|
-
"FirstRate",
|
|
28
|
-
"MinRate",
|
|
29
|
-
"MaxRate",
|
|
30
|
-
"AvgRate",
|
|
31
|
-
"CloseRate",
|
|
32
|
-
"CloseBidRate",
|
|
33
|
-
"CloseAskRate",
|
|
34
|
-
]
|
|
35
|
-
for col in convert_cols:
|
|
24
|
+
def _adjust_older_contracts_rates(df: pd.DataFrame, rate_cols: list) -> pd.DataFrame:
|
|
25
|
+
for col in rate_cols:
|
|
36
26
|
df[col] = _convert_prices_to_rates(df[col], df["BDaysToExp"])
|
|
37
27
|
|
|
38
28
|
# Invert low and high prices
|
|
@@ -52,10 +42,6 @@ def _process_past_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataF
|
|
|
52
42
|
Returns:
|
|
53
43
|
pd.DataFrame: Processed and transformed data as a Pandas pd.DataFrame.
|
|
54
44
|
"""
|
|
55
|
-
# Check if the pd.DataFrame is empty
|
|
56
|
-
if df.empty:
|
|
57
|
-
return df
|
|
58
|
-
|
|
59
45
|
rename_dict = {
|
|
60
46
|
"VENCTO": "ExpirationCode",
|
|
61
47
|
"CONTR. ABERT.(1)": "OpenContracts", # At the start of the day
|
|
@@ -86,43 +72,34 @@ def _process_past_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataF
|
|
|
86
72
|
# Contract code format was changed in 22/05/2006
|
|
87
73
|
if trade_date < pd.Timestamp("2006-05-22"):
|
|
88
74
|
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
89
|
-
|
|
75
|
+
cm.get_old_expiration_date, args=(trade_date,)
|
|
90
76
|
)
|
|
91
77
|
else:
|
|
92
|
-
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
78
|
+
df["ExpirationDate"] = df["ExpirationCode"].apply(cm.get_expiration_date)
|
|
79
|
+
|
|
80
|
+
df["BDaysToExp"] = bd.count_bdays(trade_date, df["ExpirationDate"])
|
|
93
81
|
|
|
94
|
-
df["BDaysToExp"] = bday.count_bdays(trade_date, df["ExpirationDate"])
|
|
95
82
|
# Remove expired contracts
|
|
96
83
|
df.query("BDaysToExp > 0", inplace=True)
|
|
97
84
|
|
|
98
85
|
# Columns where 0 means NaN
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
df[col] = df[col].replace(0, pd.NA)
|
|
111
|
-
|
|
112
|
-
# Prior to 17/01/2002 (incluive), prices were not converted to rates
|
|
113
|
-
if trade_date <= pd.Timestamp("2002-01-17"):
|
|
114
|
-
df = _convert_prices_in_older_contracts(df)
|
|
86
|
+
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
87
|
+
cols_with_nan = rate_cols + ["SettlementPrice"]
|
|
88
|
+
# Replace 0 with NaN in these columns
|
|
89
|
+
df[cols_with_nan] = df[cols_with_nan].replace(0, pd.NA)
|
|
90
|
+
|
|
91
|
+
# Prior to 17/01/2002 (inclusive), prices were not converted to rates
|
|
92
|
+
if trade_date > pd.Timestamp("2002-01-17"):
|
|
93
|
+
# Remove % and round to 5 (3 in %) dec. places in rate columns
|
|
94
|
+
df[rate_cols] = df[rate_cols].div(100).round(5)
|
|
95
|
+
else:
|
|
96
|
+
df = _adjust_older_contracts_rates(df, rate_cols)
|
|
115
97
|
|
|
98
|
+
# Calculate SettlementRate
|
|
116
99
|
df["SettlementRate"] = _convert_prices_to_rates(
|
|
117
100
|
df["SettlementPrice"], df["BDaysToExp"]
|
|
118
101
|
)
|
|
119
102
|
|
|
120
|
-
# Remove percentage in all rate columns and round to 5 decimal places since it's the
|
|
121
|
-
# precision used by B3. Obs: 5 decimal places = 3 decimal places in percentage
|
|
122
|
-
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
123
|
-
for col in rate_cols:
|
|
124
|
-
df[col] = (df[col] / 100).round(5)
|
|
125
|
-
|
|
126
103
|
df["TickerSymbol"] = "DI1" + df["ExpirationCode"]
|
|
127
104
|
|
|
128
105
|
# Filter and order columns
|
|
@@ -178,7 +155,7 @@ def _process_last_raw_di_df(raw_df: pd.DataFrame) -> pd.DataFrame:
|
|
|
178
155
|
# Rename columns
|
|
179
156
|
df = df.rename(columns=rename_columns)
|
|
180
157
|
|
|
181
|
-
df["BDaysToExp"] =
|
|
158
|
+
df["BDaysToExp"] = bd.count_bdays(df["TradeTimestamp"], df["ExpirationDate"])
|
|
182
159
|
|
|
183
160
|
# Remove percentage in all rate columns
|
|
184
161
|
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
@@ -195,7 +172,7 @@ def fetch_last_di() -> pd.DataFrame:
|
|
|
195
172
|
Returns:
|
|
196
173
|
pd.DataFrame: A Pandas pd.DataFrame containing the latest DI futures data.
|
|
197
174
|
"""
|
|
198
|
-
raw_df =
|
|
175
|
+
raw_df = cm.fetch_last_raw_df(future_code="DI1")
|
|
199
176
|
return _process_last_raw_di_df(raw_df)
|
|
200
177
|
|
|
201
178
|
|
|
@@ -204,11 +181,12 @@ def fetch_past_di(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.Data
|
|
|
204
181
|
Fetchs the DI futures data for a given date from B3.
|
|
205
182
|
|
|
206
183
|
This function fetches and processes the DI futures data from B3 for a specific
|
|
207
|
-
trade date. It's the primary external interface for accessing DI data.
|
|
184
|
+
trade date. It's the primary external interface for accessing DI data. If the data
|
|
185
|
+
is not available, an empty DataFrame is returned.
|
|
208
186
|
|
|
209
187
|
Args:
|
|
210
188
|
trade_date (pd.Timestamp): The trade date to fetch the DI futures data.
|
|
211
|
-
|
|
189
|
+
return_raw (bool): If True, returns the raw data as a Pandas pd.DataFrame.
|
|
212
190
|
Defaults to False.
|
|
213
191
|
|
|
214
192
|
Returns:
|
|
@@ -218,7 +196,10 @@ def fetch_past_di(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.Data
|
|
|
218
196
|
- BDaysToExp: number of business days to ExpirationDate.
|
|
219
197
|
- OpenContracts: number of open contracts at the start of the trading day.
|
|
220
198
|
"""
|
|
221
|
-
df_raw =
|
|
199
|
+
df_raw = cm.fetch_past_raw_df(asset_code="DI1", trade_date=trade_date)
|
|
222
200
|
if return_raw:
|
|
223
201
|
return df_raw
|
|
224
|
-
|
|
202
|
+
if df_raw.empty:
|
|
203
|
+
return pd.DataFrame()
|
|
204
|
+
else:
|
|
205
|
+
return _process_past_raw_df(df_raw, trade_date)
|
|
@@ -41,14 +41,18 @@ def _process_past_data(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFra
|
|
|
41
41
|
# Convert to datetime64[ns] since it is pandas default type for timestamps
|
|
42
42
|
df["TradeDate"] = df["TradeDate"].astype("datetime64[ns]")
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
# Contract code format was changed in 22/05/2006
|
|
45
|
+
if trade_date < pd.Timestamp("2006-05-22"):
|
|
46
|
+
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
47
|
+
common.get_old_expiration_date, args=(trade_date,)
|
|
48
|
+
)
|
|
49
|
+
else:
|
|
50
|
+
df["ExpirationDate"] = df["ExpirationCode"].apply(common.get_expiration_date)
|
|
45
51
|
|
|
46
52
|
# Replace 0 values in rate columns with pd.NA and remove percentage
|
|
47
53
|
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
# Round to 5 decimal places (3 in %) since it is the contract's precision
|
|
51
|
-
df[col] = (df[col] / 100).round(5)
|
|
54
|
+
# Round to 5 decimal places (3 in %) since it is the contract's precision
|
|
55
|
+
df[rate_cols] = df[rate_cols].replace(0, pd.NA).div(100).round(5)
|
|
52
56
|
|
|
53
57
|
df["TickerSymbol"] = "FRC" + df["ExpirationCode"]
|
|
54
58
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
|
-
import pytest
|
|
3
2
|
|
|
4
3
|
from pyield import futures as ft
|
|
5
4
|
|
|
@@ -76,5 +75,6 @@ def test_settlement_rates_with_current_holiday_list():
|
|
|
76
75
|
|
|
77
76
|
def test_non_business_day():
|
|
78
77
|
non_business_day = pd.Timestamp("2023-12-24")
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
# Test if it an empty DataFrame is returned
|
|
79
|
+
df = ft.fetch_past_di(trade_date=non_business_day)
|
|
80
|
+
assert df.empty
|
pyield-0.7.4/pyield/__about__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.7.4"
|
|
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
|