PYield 0.7.5__tar.gz → 0.7.7__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.5 → pyield-0.7.7}/PKG-INFO +1 -1
- pyield-0.7.7/pyield/__about__.py +1 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/data_access.py +1 -1
- {pyield-0.7.5 → pyield-0.7.7}/pyield/futures/common.py +82 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/futures/ddi.py +26 -66
- {pyield-0.7.5 → pyield-0.7.7}/pyield/futures/di.py +33 -84
- {pyield-0.7.5 → pyield-0.7.7}/pyield/futures/frc.py +8 -45
- {pyield-0.7.5 → pyield-0.7.7}/pyield/projections.py +7 -4
- {pyield-0.7.5 → pyield-0.7.7}/pyproject.toml +1 -1
- pyield-0.7.5/pyield/__about__.py +0 -1
- {pyield-0.7.5 → pyield-0.7.7}/LICENSE +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/README.md +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/__init__.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/bday.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/data_analysis.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/futures/__init__.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/futures/di_xml.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/holidays/__init__.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/holidays/br_holidays_old.txt +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/holidays/core.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/indicators.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/py.typed +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/treasuries.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/pyield/utils.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/tests/__init__.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/tests/test_bday.py +0 -0
- {pyield-0.7.5 → pyield-0.7.7}/tests/test_futures.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.7.7"
|
|
@@ -111,7 +111,7 @@ def fetch_indicator(
|
|
|
111
111
|
raise ValueError("Indicator type not supported.")
|
|
112
112
|
|
|
113
113
|
|
|
114
|
-
def fetch_projection(projection_code: str) ->
|
|
114
|
+
def fetch_projection(projection_code: str) -> pr.IndicatorProjection:
|
|
115
115
|
"""
|
|
116
116
|
Fetches a financial projection for a specified code and reference date.
|
|
117
117
|
|
|
@@ -5,6 +5,28 @@ import requests
|
|
|
5
5
|
|
|
6
6
|
from .. import bday
|
|
7
7
|
|
|
8
|
+
COLUMNS_MAPPING = {
|
|
9
|
+
"VENCTO": "ExpirationCode",
|
|
10
|
+
"CONTR. ABERT.(1)": "OpenContracts", # At the start of the day
|
|
11
|
+
"CONTR. FECH.(2)": "OpenContractsEndSession", # At the end of the day
|
|
12
|
+
"NÚM. NEGOC.": "TradeCount",
|
|
13
|
+
"CONTR. NEGOC.": "TradeVolume",
|
|
14
|
+
"VOL.": "FinancialVolume",
|
|
15
|
+
"AJUSTE": "SettlementPrice",
|
|
16
|
+
"AJUSTE ANTER. (3)": "PrevSettlementRate",
|
|
17
|
+
"AJUSTE CORRIG. (4)": "AdjSettlementRate",
|
|
18
|
+
"AJUSTE DE REF.": "SettlementRate", # FRC
|
|
19
|
+
"PREÇO MÍN.": "MinRate",
|
|
20
|
+
"PREÇO MÉD.": "AvgRate",
|
|
21
|
+
"PREÇO MÁX.": "MaxRate",
|
|
22
|
+
"PREÇO ABERTU.": "FirstRate",
|
|
23
|
+
"ÚLT. PREÇO": "CloseRate",
|
|
24
|
+
"VAR. PTOS.": "PointsVariation",
|
|
25
|
+
# Attention: bid/ask rates are inverted
|
|
26
|
+
"ÚLT.OF. COMPRA": "CloseAskRate",
|
|
27
|
+
"ÚLT.OF. VENDA": "CloseBidRate",
|
|
28
|
+
}
|
|
29
|
+
|
|
8
30
|
|
|
9
31
|
def get_expiration_date(expiration_code: str) -> pd.Timestamp:
|
|
10
32
|
"""
|
|
@@ -228,3 +250,63 @@ def fetch_last_raw_df(future_code: str) -> pd.DataFrame:
|
|
|
228
250
|
df = df.convert_dtypes(dtype_backend="numpy_nullable")
|
|
229
251
|
|
|
230
252
|
return df
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def rename_columns(df: pd.DataFrame):
|
|
256
|
+
all_columns = {
|
|
257
|
+
"VENCTO": "ExpirationCode",
|
|
258
|
+
"CONTR. ABERT.(1)": "OpenContracts", # At the start of the day
|
|
259
|
+
"CONTR. FECH.(2)": "OpenContractsEndSession", # At the end of the day
|
|
260
|
+
"NÚM. NEGOC.": "TradeCount",
|
|
261
|
+
"CONTR. NEGOC.": "TradeVolume",
|
|
262
|
+
"VOL.": "FinancialVolume",
|
|
263
|
+
"AJUSTE": "SettlementPrice",
|
|
264
|
+
"AJUSTE ANTER. (3)": "PrevSettlementRate",
|
|
265
|
+
"AJUSTE CORRIG. (4)": "AdjSettlementRate",
|
|
266
|
+
"AJUSTE DE REF.": "SettlementRate", # FRC
|
|
267
|
+
"PREÇO MÍN.": "MinRate",
|
|
268
|
+
"PREÇO MÉD.": "AvgRate",
|
|
269
|
+
"PREÇO MÁX.": "MaxRate",
|
|
270
|
+
"PREÇO ABERTU.": "FirstRate",
|
|
271
|
+
"ÚLT. PREÇO": "CloseRate",
|
|
272
|
+
"VAR. PTOS.": "PointsVariation",
|
|
273
|
+
# Attention: bid/ask rates are inverted
|
|
274
|
+
"ÚLT.OF. COMPRA": "CloseAskRate",
|
|
275
|
+
"ÚLT.OF. VENDA": "CloseBidRate",
|
|
276
|
+
}
|
|
277
|
+
rename_dict = {}
|
|
278
|
+
for col in all_columns:
|
|
279
|
+
if col in df.columns:
|
|
280
|
+
rename_dict[col] = all_columns[col]
|
|
281
|
+
return df.rename(columns=rename_dict)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def reorder_columns(df: pd.DataFrame):
|
|
285
|
+
all_columns = [
|
|
286
|
+
"TradeDate",
|
|
287
|
+
"TickerSymbol",
|
|
288
|
+
# "ExpirationCode",
|
|
289
|
+
"ExpirationDate",
|
|
290
|
+
"BDaysToExp",
|
|
291
|
+
"DaysToExp",
|
|
292
|
+
"OpenContracts",
|
|
293
|
+
# "OpenContractsEndSession" since there is no OpenContracts at the end of the
|
|
294
|
+
# day in XML data, it will be removed to avoid confusion with XML data
|
|
295
|
+
"TradeCount",
|
|
296
|
+
"TradeVolume",
|
|
297
|
+
"FinancialVolume",
|
|
298
|
+
"SettlementPrice",
|
|
299
|
+
"SettlementRate",
|
|
300
|
+
"FirstRate",
|
|
301
|
+
"MinRate",
|
|
302
|
+
"AvgRate",
|
|
303
|
+
"MaxRate",
|
|
304
|
+
"CloseAskRate",
|
|
305
|
+
"CloseBidRate",
|
|
306
|
+
"CloseRate",
|
|
307
|
+
]
|
|
308
|
+
reordered_columns = []
|
|
309
|
+
for col in all_columns:
|
|
310
|
+
if col in df.columns:
|
|
311
|
+
reordered_columns.append(col)
|
|
312
|
+
return df[reordered_columns]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
-
from . import common
|
|
3
|
+
from . import common as cm
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def _convert_prices_to_rates(prices: pd.Series, n_days: pd.Series) -> pd.Series:
|
|
@@ -15,9 +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
|
|
18
|
+
# Round to 5 (3 in %) dec. places (contract's current max. precision)
|
|
19
|
+
return rates.round(5)
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
def _process_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
@@ -31,32 +30,7 @@ def _process_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
|
31
30
|
Returns:
|
|
32
31
|
pd.DataFrame: Processed and transformed data as a Pandas pd.DataFrame.
|
|
33
32
|
"""
|
|
34
|
-
|
|
35
|
-
if df.empty:
|
|
36
|
-
return df
|
|
37
|
-
|
|
38
|
-
rename_dict = {
|
|
39
|
-
"VENCTO": "ExpirationCode",
|
|
40
|
-
"CONTR. ABERT.(1)": "OpenContracts", # At the start of the day
|
|
41
|
-
"CONTR. FECH.(2)": "OpenContractsEndSession", # At the end of the day
|
|
42
|
-
"NÚM. NEGOC.": "TradeCount",
|
|
43
|
-
"CONTR. NEGOC.": "TradeVolume",
|
|
44
|
-
"VOL.": "FinancialVolume",
|
|
45
|
-
"AJUSTE": "SettlementPrice",
|
|
46
|
-
"AJUSTE ANTER. (3)": "PrevSettlementRate",
|
|
47
|
-
"AJUSTE CORRIG. (4)": "AdjSettlementRate",
|
|
48
|
-
"PREÇO MÍN.": "MinRate",
|
|
49
|
-
"PREÇO MÉD.": "AvgRate",
|
|
50
|
-
"PREÇO MÁX.": "MaxRate",
|
|
51
|
-
"PREÇO ABERTU.": "FirstRate",
|
|
52
|
-
"ÚLT. PREÇO": "LastRate",
|
|
53
|
-
"VAR. PTOS.": "PointsVariation",
|
|
54
|
-
# Attention: bid/ask rates are inverted
|
|
55
|
-
"ÚLT.OF. COMPRA": "LastAskRate",
|
|
56
|
-
"ÚLT.OF. VENDA": "LastBidRate",
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
df = df.rename(columns=rename_dict)
|
|
33
|
+
df = cm.rename_columns(df)
|
|
60
34
|
|
|
61
35
|
df["TradeDate"] = trade_date
|
|
62
36
|
# Convert to datetime64[ns] since it is pandas default type for timestamps
|
|
@@ -65,51 +39,37 @@ def _process_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
|
65
39
|
# Contract code format was changed in 22/05/2006
|
|
66
40
|
if trade_date < pd.Timestamp("2006-05-22"):
|
|
67
41
|
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
68
|
-
|
|
42
|
+
cm.get_old_expiration_date, args=(trade_date,)
|
|
69
43
|
)
|
|
70
44
|
else:
|
|
71
|
-
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
45
|
+
df["ExpirationDate"] = df["ExpirationCode"].apply(cm.get_expiration_date)
|
|
72
46
|
|
|
73
|
-
df["
|
|
47
|
+
df["DaysToExp"] = (df["ExpirationDate"] - trade_date).dt.days
|
|
74
48
|
# Convert to nullable integer, since other columns use this data type
|
|
75
|
-
df["
|
|
76
|
-
# Remove expired contracts
|
|
77
|
-
df.query("DaysToExpiration > 0", inplace=True)
|
|
49
|
+
df["DaysToExp"] = df["DaysToExp"].astype(pd.Int64Dtype())
|
|
78
50
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
)
|
|
51
|
+
# Remove expired contracts
|
|
52
|
+
df.query("DaysToExp > 0", inplace=True)
|
|
82
53
|
|
|
54
|
+
# Columns where 0 means NaN
|
|
83
55
|
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
84
56
|
cols_with_nan = rate_cols + ["SettlementPrice"]
|
|
85
|
-
#
|
|
57
|
+
# Replace 0 with NaN in these columns
|
|
86
58
|
df[cols_with_nan] = df[cols_with_nan].replace(0, pd.NA)
|
|
87
|
-
|
|
59
|
+
|
|
88
60
|
df[rate_cols] = df[rate_cols].div(100).round(5)
|
|
89
61
|
|
|
62
|
+
# Calculate SettlementRate
|
|
63
|
+
df["SettlementRate"] = _convert_prices_to_rates(
|
|
64
|
+
df["SettlementPrice"], df["DaysToExp"]
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
df["TickerSymbol"] = "DI1" + df["ExpirationCode"]
|
|
68
|
+
|
|
90
69
|
# Filter and order columns
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"ExpirationDate",
|
|
95
|
-
"DaysToExpiration",
|
|
96
|
-
"OpenContracts",
|
|
97
|
-
# "OpenContractsEndSession" since there is no OpenContracts at the end of the
|
|
98
|
-
# day in XML data, it will be removed to avoid confusion with XML data
|
|
99
|
-
"TradeCount",
|
|
100
|
-
"TradeVolume",
|
|
101
|
-
"FinancialVolume",
|
|
102
|
-
"SettlementPrice",
|
|
103
|
-
"MinRate",
|
|
104
|
-
"AvgRate",
|
|
105
|
-
"MaxRate",
|
|
106
|
-
"FirstRate",
|
|
107
|
-
"LastRate",
|
|
108
|
-
"LastAskRate",
|
|
109
|
-
"LastBidRate",
|
|
110
|
-
"SettlementRate",
|
|
111
|
-
]
|
|
112
|
-
return df[ordered_cols]
|
|
70
|
+
df = cm.reorder_columns(df)
|
|
71
|
+
|
|
72
|
+
return df
|
|
113
73
|
|
|
114
74
|
|
|
115
75
|
def fetch_past_ddi(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.DataFrame:
|
|
@@ -132,10 +92,10 @@ def fetch_past_ddi(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.Dat
|
|
|
132
92
|
>>> di.fetch_ddi(pd.Timestamp("2021-01-04"))
|
|
133
93
|
|
|
134
94
|
Notes:
|
|
135
|
-
-
|
|
95
|
+
- DaysToExp: number of business days to ExpirationDate.
|
|
136
96
|
- OpenContracts: number of open contracts at the start of the trading day.
|
|
137
97
|
"""
|
|
138
|
-
df_raw =
|
|
139
|
-
if return_raw:
|
|
98
|
+
df_raw = cm.fetch_past_raw_df(asset_code="DDI", trade_date=trade_date)
|
|
99
|
+
if return_raw or df_raw.empty:
|
|
140
100
|
return df_raw
|
|
141
101
|
return _process_raw_df(df_raw, 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
|
|
22
|
-
|
|
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:
|
|
20
|
+
# Round to 5 (3 in %) dec. places (contract's current max. precision)
|
|
21
|
+
return rates.round(5)
|
|
22
|
+
|
|
23
|
+
|
|
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,28 +42,7 @@ 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
|
-
|
|
56
|
-
"VENCTO": "ExpirationCode",
|
|
57
|
-
"CONTR. ABERT.(1)": "OpenContracts", # At the start of the day
|
|
58
|
-
"CONTR. FECH.(2)": "OpenContractsEndSession", # At the end of the day
|
|
59
|
-
"NÚM. NEGOC.": "TradeCount",
|
|
60
|
-
"CONTR. NEGOC.": "TradeVolume",
|
|
61
|
-
"VOL.": "FinancialVolume",
|
|
62
|
-
"AJUSTE": "SettlementPrice",
|
|
63
|
-
"AJUSTE ANTER. (3)": "PrevSettlementRate",
|
|
64
|
-
"AJUSTE CORRIG. (4)": "AdjSettlementRate",
|
|
65
|
-
"PREÇO MÍN.": "MinRate",
|
|
66
|
-
"PREÇO MÉD.": "AvgRate",
|
|
67
|
-
"PREÇO MÁX.": "MaxRate",
|
|
68
|
-
"PREÇO ABERTU.": "FirstRate",
|
|
69
|
-
"ÚLT. PREÇO": "CloseRate",
|
|
70
|
-
"VAR. PTOS.": "PointsVariation",
|
|
71
|
-
# Attention: bid/ask rates are inverted
|
|
72
|
-
"ÚLT.OF. COMPRA": "CloseAskRate",
|
|
73
|
-
"ÚLT.OF. VENDA": "CloseBidRate",
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
df = df.rename(columns=rename_dict)
|
|
45
|
+
df = cm.rename_columns(df)
|
|
77
46
|
|
|
78
47
|
df["TradeDate"] = trade_date
|
|
79
48
|
# Convert to datetime64[ns] since it is pandas default type for timestamps
|
|
@@ -82,56 +51,39 @@ def _process_past_raw_df(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataF
|
|
|
82
51
|
# Contract code format was changed in 22/05/2006
|
|
83
52
|
if trade_date < pd.Timestamp("2006-05-22"):
|
|
84
53
|
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
85
|
-
|
|
54
|
+
cm.get_old_expiration_date, args=(trade_date,)
|
|
86
55
|
)
|
|
87
56
|
else:
|
|
88
|
-
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
57
|
+
df["ExpirationDate"] = df["ExpirationCode"].apply(cm.get_expiration_date)
|
|
58
|
+
|
|
59
|
+
df["BDaysToExp"] = bd.count_bdays(trade_date, df["ExpirationDate"])
|
|
89
60
|
|
|
90
|
-
df["BDaysToExp"] = bday.count_bdays(trade_date, df["ExpirationDate"])
|
|
91
61
|
# Remove expired contracts
|
|
92
62
|
df.query("BDaysToExp > 0", inplace=True)
|
|
93
63
|
|
|
94
|
-
#
|
|
95
|
-
|
|
96
|
-
|
|
64
|
+
# Columns where 0 means NaN
|
|
65
|
+
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
66
|
+
cols_with_nan = rate_cols + ["SettlementPrice"]
|
|
67
|
+
# Replace 0 with NaN in these columns
|
|
68
|
+
df[cols_with_nan] = df[cols_with_nan].replace(0, pd.NA)
|
|
69
|
+
|
|
70
|
+
# Prior to 17/01/2002 (inclusive), prices were not converted to rates
|
|
71
|
+
if trade_date > pd.Timestamp("2002-01-17"):
|
|
72
|
+
# Remove % and round to 5 (3 in %) dec. places in rate columns
|
|
73
|
+
df[rate_cols] = df[rate_cols].div(100).round(5)
|
|
74
|
+
else:
|
|
75
|
+
df = _adjust_older_contracts_rates(df, rate_cols)
|
|
97
76
|
|
|
77
|
+
# Calculate SettlementRate
|
|
98
78
|
df["SettlementRate"] = _convert_prices_to_rates(
|
|
99
79
|
df["SettlementPrice"], df["BDaysToExp"]
|
|
100
80
|
)
|
|
101
81
|
|
|
102
|
-
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
103
|
-
cols_with_nan = rate_cols + ["SettlementPrice"]
|
|
104
|
-
# Columns where 0 means NaN
|
|
105
|
-
df[cols_with_nan] = df[cols_with_nan].replace(0, pd.NA)
|
|
106
|
-
# Remove % and round to 5 dec. places (3 in %) since it is the contract's precision
|
|
107
|
-
df[rate_cols] = df[rate_cols].div(100).round(5)
|
|
108
|
-
|
|
109
82
|
df["TickerSymbol"] = "DI1" + df["ExpirationCode"]
|
|
110
83
|
|
|
111
84
|
# Filter and order columns
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"TickerSymbol",
|
|
115
|
-
# "ExpirationCode",
|
|
116
|
-
"ExpirationDate",
|
|
117
|
-
"BDaysToExp",
|
|
118
|
-
"OpenContracts",
|
|
119
|
-
# "OpenContractsEndSession" since there is no OpenContracts at the end of the
|
|
120
|
-
# day in XML data, it will be removed to avoid confusion with XML data
|
|
121
|
-
"TradeCount",
|
|
122
|
-
"TradeVolume",
|
|
123
|
-
"FinancialVolume",
|
|
124
|
-
"SettlementPrice",
|
|
125
|
-
"SettlementRate",
|
|
126
|
-
"FirstRate",
|
|
127
|
-
"MinRate",
|
|
128
|
-
"AvgRate",
|
|
129
|
-
"MaxRate",
|
|
130
|
-
"CloseAskRate",
|
|
131
|
-
"CloseBidRate",
|
|
132
|
-
"CloseRate",
|
|
133
|
-
]
|
|
134
|
-
return df[ordered_cols]
|
|
85
|
+
df = cm.reorder_columns(df)
|
|
86
|
+
return df
|
|
135
87
|
|
|
136
88
|
|
|
137
89
|
def _process_last_raw_di_df(raw_df: pd.DataFrame) -> pd.DataFrame:
|
|
@@ -161,7 +113,7 @@ def _process_last_raw_di_df(raw_df: pd.DataFrame) -> pd.DataFrame:
|
|
|
161
113
|
# Rename columns
|
|
162
114
|
df = df.rename(columns=rename_columns)
|
|
163
115
|
|
|
164
|
-
df["BDaysToExp"] =
|
|
116
|
+
df["BDaysToExp"] = bd.count_bdays(df["TradeTimestamp"], df["ExpirationDate"])
|
|
165
117
|
|
|
166
118
|
# Remove percentage in all rate columns
|
|
167
119
|
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
@@ -178,7 +130,7 @@ def fetch_last_di() -> pd.DataFrame:
|
|
|
178
130
|
Returns:
|
|
179
131
|
pd.DataFrame: A Pandas pd.DataFrame containing the latest DI futures data.
|
|
180
132
|
"""
|
|
181
|
-
raw_df =
|
|
133
|
+
raw_df = cm.fetch_last_raw_df(future_code="DI1")
|
|
182
134
|
return _process_last_raw_di_df(raw_df)
|
|
183
135
|
|
|
184
136
|
|
|
@@ -202,10 +154,7 @@ def fetch_past_di(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.Data
|
|
|
202
154
|
- BDaysToExp: number of business days to ExpirationDate.
|
|
203
155
|
- OpenContracts: number of open contracts at the start of the trading day.
|
|
204
156
|
"""
|
|
205
|
-
df_raw =
|
|
206
|
-
if return_raw:
|
|
157
|
+
df_raw = cm.fetch_past_raw_df(asset_code="DI1", trade_date=trade_date)
|
|
158
|
+
if return_raw or df_raw.empty:
|
|
207
159
|
return df_raw
|
|
208
|
-
|
|
209
|
-
return pd.DataFrame()
|
|
210
|
-
else:
|
|
211
|
-
return _process_past_raw_df(df_raw, trade_date)
|
|
160
|
+
return _process_past_raw_df(df_raw, trade_date)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
|
|
3
|
-
from . import common
|
|
3
|
+
from . import common as cm
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def _process_past_data(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFrame:
|
|
@@ -14,28 +14,7 @@ def _process_past_data(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFra
|
|
|
14
14
|
Returns:
|
|
15
15
|
pd.DataFrame: Processed and transformed data as a Pandas pd.DataFrame.
|
|
16
16
|
"""
|
|
17
|
-
|
|
18
|
-
if df.empty:
|
|
19
|
-
return df
|
|
20
|
-
|
|
21
|
-
rename_dict = {
|
|
22
|
-
"VENCTO": "ExpirationCode",
|
|
23
|
-
"NÚM. NEGOC.": "TradeCount",
|
|
24
|
-
"CONTR. NEGOC.": "TradeVolume",
|
|
25
|
-
"VOL.": "FinancialVolume",
|
|
26
|
-
"AJUSTE DE REF.": "SettlementRate",
|
|
27
|
-
"PREÇO ABERTU.": "FirstRate",
|
|
28
|
-
"PREÇO MÍN.": "MinRate",
|
|
29
|
-
"PREÇO MÉD.": "AvgRate",
|
|
30
|
-
"PREÇO MÁX.": "MaxRate",
|
|
31
|
-
"ÚLT. PREÇO": "CloseRate",
|
|
32
|
-
"VAR. PTOS.": "PointsVariation",
|
|
33
|
-
# Attention: bid/ask rates are inverted
|
|
34
|
-
"ÚLT.OF. COMPRA": "CloseAskRate",
|
|
35
|
-
"ÚLT.OF. VENDA": "CloseBidRate",
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
df = df.rename(columns=rename_dict)
|
|
17
|
+
df = cm.rename_columns(df)
|
|
39
18
|
|
|
40
19
|
df["TradeDate"] = trade_date
|
|
41
20
|
# Convert to datetime64[ns] since it is pandas default type for timestamps
|
|
@@ -44,10 +23,10 @@ def _process_past_data(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFra
|
|
|
44
23
|
# Contract code format was changed in 22/05/2006
|
|
45
24
|
if trade_date < pd.Timestamp("2006-05-22"):
|
|
46
25
|
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
47
|
-
|
|
26
|
+
cm.get_old_expiration_date, args=(trade_date,)
|
|
48
27
|
)
|
|
49
28
|
else:
|
|
50
|
-
df["ExpirationDate"] = df["ExpirationCode"].apply(
|
|
29
|
+
df["ExpirationDate"] = df["ExpirationCode"].apply(cm.get_expiration_date)
|
|
51
30
|
|
|
52
31
|
# Replace 0 values in rate columns with pd.NA and remove percentage
|
|
53
32
|
rate_cols = [col for col in df.columns if "Rate" in col]
|
|
@@ -57,24 +36,8 @@ def _process_past_data(df: pd.DataFrame, trade_date: pd.Timestamp) -> pd.DataFra
|
|
|
57
36
|
df["TickerSymbol"] = "FRC" + df["ExpirationCode"]
|
|
58
37
|
|
|
59
38
|
# Filter and order columns
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"TickerSymbol",
|
|
63
|
-
# "ExpirationCode",
|
|
64
|
-
"ExpirationDate",
|
|
65
|
-
"TradeCount",
|
|
66
|
-
"TradeVolume",
|
|
67
|
-
"FinancialVolume",
|
|
68
|
-
"SettlementRate",
|
|
69
|
-
"FirstRate",
|
|
70
|
-
"MinRate",
|
|
71
|
-
"AvgRate",
|
|
72
|
-
"MaxRate",
|
|
73
|
-
"CloseAskRate",
|
|
74
|
-
"CloseBidRate",
|
|
75
|
-
"CloseRate",
|
|
76
|
-
]
|
|
77
|
-
return df[ordered_cols]
|
|
39
|
+
df = cm.reorder_columns(df)
|
|
40
|
+
return df
|
|
78
41
|
|
|
79
42
|
|
|
80
43
|
def fetch_past_frc(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.DataFrame:
|
|
@@ -92,7 +55,7 @@ def fetch_past_frc(trade_date: pd.Timestamp, return_raw: bool = False) -> pd.Dat
|
|
|
92
55
|
Returns:
|
|
93
56
|
pd.DataFrame: A Pandas pd.DataFrame containing processed DI futures data.
|
|
94
57
|
"""
|
|
95
|
-
df_raw =
|
|
96
|
-
if return_raw:
|
|
58
|
+
df_raw = cm.fetch_past_raw_df(asset_code="FRC", trade_date=trade_date)
|
|
59
|
+
if return_raw or df_raw.empty:
|
|
97
60
|
return df_raw
|
|
98
61
|
return _process_past_data(df_raw, trade_date)
|
|
@@ -63,19 +63,22 @@ def fetch_current_month_ipca_projection() -> IndicatorProjection:
|
|
|
63
63
|
data = workbook.get_sheet_by_name(first_sheet).to_python(skip_empty_area=True)
|
|
64
64
|
|
|
65
65
|
# Extract projection update date and time from the first row
|
|
66
|
-
|
|
66
|
+
update_str = str(data[0][0])
|
|
67
|
+
last_update_str = update_str.split("Atualização:")[-1].strip()
|
|
67
68
|
last_updated = pd.to_datetime(last_update_str, format="%d/%m/%Y - %H:%M h")
|
|
68
69
|
|
|
69
70
|
# Find the row containing the IPCA projection and extract its data
|
|
70
71
|
ipca_data = next(line for line in data if "IPCA1" in line)
|
|
72
|
+
ipca_text = str(ipca_data[-1])
|
|
71
73
|
|
|
72
74
|
# Convert the last element of the IPCA data row to float for the projection value
|
|
73
|
-
ipca_value = round(float(
|
|
75
|
+
ipca_value = round(float(ipca_text) / 100, 4)
|
|
74
76
|
|
|
75
77
|
# Extract and format the reference month
|
|
76
|
-
|
|
78
|
+
projection_text = str(ipca_data[1])
|
|
79
|
+
month_str = projection_text.split("(")[-1].split(")")[0]
|
|
77
80
|
locale.setlocale(locale.LC_TIME, "pt_BR.UTF-8")
|
|
78
|
-
ipca_month_ts = pd.to_datetime(
|
|
81
|
+
ipca_month_ts = pd.to_datetime(month_str, format="%b/%y")
|
|
79
82
|
ipca_month_br = ipca_month_ts.strftime("%b/%Y").upper()
|
|
80
83
|
locale.setlocale(locale.LC_TIME, "") # Reset locale to default
|
|
81
84
|
|
pyield-0.7.5/pyield/__about__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.7.5"
|
|
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
|