PYield 0.5.0__tar.gz → 0.6.0__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.5.0 → pyield-0.6.0}/PKG-INFO +63 -39
- pyield-0.6.0/README.md +102 -0
- pyield-0.6.0/pyield/__about__.py +1 -0
- pyield-0.6.0/pyield/__init__.py +14 -0
- pyield-0.6.0/pyield/bday.py +342 -0
- pyield-0.6.0/pyield/data_access.py +51 -0
- pyield-0.6.0/pyield/data_analysis.py +31 -0
- pyield-0.6.0/pyield/di/__init__.py +6 -0
- pyield-0.6.0/pyield/di/core.py +180 -0
- {pyield-0.5.0 → pyield-0.6.0}/pyield/di/web.py +46 -48
- {pyield-0.5.0 → pyield-0.6.0}/pyield/di/xml.py +5 -5
- {pyield-0.5.0 → pyield-0.6.0}/pyield/holidays/core.py +4 -5
- pyield-0.5.0/pyield/anbima.py → pyield-0.6.0/pyield/treasuries.py +57 -62
- pyield-0.6.0/pyield/utils.py +26 -0
- {pyield-0.5.0 → pyield-0.6.0}/pyproject.toml +11 -1
- {pyield-0.5.0 → pyield-0.6.0}/tests/test_br_calendar.py +7 -7
- {pyield-0.5.0 → pyield-0.6.0}/tests/test_di.py +7 -7
- pyield-0.5.0/README.md +0 -78
- pyield-0.5.0/pyield/__about__.py +0 -1
- pyield-0.5.0/pyield/__init__.py +0 -16
- pyield-0.5.0/pyield/calendar.py +0 -326
- pyield-0.5.0/pyield/di/__init__.py +0 -6
- pyield-0.5.0/pyield/di/core.py +0 -165
- {pyield-0.5.0 → pyield-0.6.0}/LICENSE +0 -0
- {pyield-0.5.0 → pyield-0.6.0}/pyield/holidays/__init__.py +0 -0
- {pyield-0.5.0 → pyield-0.6.0}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.5.0 → pyield-0.6.0}/pyield/holidays/br_holidays_old.txt +0 -0
- {pyield-0.5.0 → pyield-0.6.0}/pyield/py.typed +0 -0
- {pyield-0.5.0 → pyield-0.6.0}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PYield
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
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>
|
|
@@ -44,17 +44,18 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
[](https://python.org "Go to Python homepage")
|
|
45
45
|
[](#license)
|
|
46
46
|
|
|
47
|
-
# PYield:
|
|
47
|
+
# PYield: Fixed Income Toolbox for Brazilian Markets
|
|
48
48
|
|
|
49
49
|
## Introduction
|
|
50
50
|
|
|
51
|
-
Welcome to PYield, a Python library designed for the analysis of fixed income instruments in Brazil. This library is tailored for financial analysts, researchers, and enthusiasts interested in the Brazilian fixed income market. Leveraging the power of popular Python libraries like Pandas and Requests, PYield simplifies the process of obtaining and processing data from key sources such as
|
|
51
|
+
Welcome to PYield, a Python library designed for the analysis of fixed income instruments in Brazil. This library is tailored for financial analysts, researchers, and enthusiasts interested in the Brazilian fixed income market. Leveraging the power of popular Python libraries like Pandas and Requests, PYield simplifies the process of obtaining and processing data from key sources such as ANBIMA and B3.
|
|
52
|
+
|
|
52
53
|
## Features
|
|
53
54
|
|
|
54
|
-
- **Data Collection**: Automated fetching of data from
|
|
55
|
+
- **Data Collection**: Automated fetching of data from ANBIMA and B3.
|
|
55
56
|
- **Data Processing**: Efficient processing and normalization of fixed income data.
|
|
56
57
|
- **Analysis Tools**: Built-in functions for common analysis tasks in fixed income markets.
|
|
57
|
-
- **Easy Integration**: Seamless integration with
|
|
58
|
+
- **Easy Integration**: Seamless integration with pandas data analysis workflows.
|
|
58
59
|
- **Type Hints**: Full support for static type checking, enhancing development experience and code quality.
|
|
59
60
|
|
|
60
61
|
## Installation
|
|
@@ -63,30 +64,64 @@ You can install PYield using pip:
|
|
|
63
64
|
```sh
|
|
64
65
|
pip install pyield
|
|
65
66
|
```
|
|
67
|
+
|
|
66
68
|
## How to use PYield
|
|
67
|
-
|
|
69
|
+
|
|
70
|
+
### Futures Data
|
|
68
71
|
```python
|
|
69
72
|
import pyield as yd
|
|
70
73
|
|
|
71
|
-
# Get a
|
|
72
|
-
>>> yd.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
2024-03-08
|
|
76
|
-
2024-03-08
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
2024-03-08
|
|
80
|
-
2024-03-08
|
|
74
|
+
# Get a DataFrame with the DI Futures data from B3
|
|
75
|
+
>>> yd.get_data(asset_code="DI1", reference_date='2024-03-08')
|
|
76
|
+
|
|
77
|
+
TradeDate ExpirationCode ExpirationDate BDToExpiration ... LastRate LastAskRate LastBidRate SettlementRate
|
|
78
|
+
2024-03-08 J24 2024-04-01 15 ... 10.952 10.952 10.956 10.956
|
|
79
|
+
2024-03-08 K24 2024-05-02 37 ... 10.776 10.774 10.780 10.777
|
|
80
|
+
2024-03-08 M24 2024-06-03 58 ... 10.604 10.602 10.604 10.608
|
|
81
|
+
... ... ... ... ... ... ... ... ...
|
|
82
|
+
2024-03-08 F37 2037-01-02 3213 ... <NA> <NA> <NA> 10.859
|
|
83
|
+
2024-03-08 F38 2038-01-04 3462 ... <NA> <NA> <NA> 10.859
|
|
84
|
+
2024-03-08 F39 2039-01-03 3713 ... <NA> <NA> <NA> 10.85
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Treasury Bonds Data
|
|
88
|
+
```python
|
|
89
|
+
# Get a DataFrame with the NTN-B data from ANBIMA
|
|
90
|
+
# Anbima data is available for the last 5 working days
|
|
91
|
+
# Obs: Anbima members have access to the full history
|
|
92
|
+
>>> yd.get_data(asset_code="NTN-B", reference_date='2024-04-12')
|
|
93
|
+
|
|
94
|
+
BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate Price
|
|
95
|
+
NTN-B 2024-04-12 2024-08-15 0.07540 0.07504 0.07523 4,271.43565
|
|
96
|
+
NTN-B 2024-04-12 2025-05-15 0.05945 0.05913 0.05930 4,361.34391
|
|
97
|
+
NTN-B 2024-04-12 2026-08-15 0.05927 0.05897 0.05910 4,301.40082
|
|
98
|
+
... ... ... ... ... ... ...
|
|
99
|
+
NTN-B 2024-04-12 2050-08-15 0.06039 0.06006 0.06023 4,299.28233
|
|
100
|
+
NTN-B 2024-04-12 2055-05-15 0.06035 0.05998 0.06017 4,367.13360
|
|
101
|
+
NTN-B 2024-04-12 2060-08-15 0.06057 0.06016 0.06036 4,292.26323
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Spreads Calculation
|
|
105
|
+
```python
|
|
106
|
+
# Calculate the spread between two DI Futures contracts and the pre-fix bonds
|
|
107
|
+
>>> yd.calculate_spreads(spread_type="di_vs_pre", reference_date="2024-4-11")
|
|
108
|
+
|
|
109
|
+
BondType ReferenceDate MaturityDate DISpread
|
|
110
|
+
LTN 2024-04-11 2024-07-01 -20.28000
|
|
111
|
+
LTN 2024-04-11 2024-10-01 -10.19000
|
|
112
|
+
LTN 2024-04-11 2025-01-01 -15.05000
|
|
113
|
+
... ... ... ...
|
|
114
|
+
NTN-F 2024-04-11 2031-01-01 -0.66000
|
|
115
|
+
NTN-F 2024-04-11 2033-01-01 -5.69000
|
|
116
|
+
NTN-F 2024-04-11 2035-01-01 -1.27000
|
|
81
117
|
```
|
|
118
|
+
|
|
82
119
|
### Business Days Tools (Brazilian holidays are automatically considered)
|
|
83
120
|
```python
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
1
|
|
88
|
-
2 2024-01-03
|
|
89
|
-
dtype: datetime64[ns]
|
|
121
|
+
# Count the number of business days between two dates
|
|
122
|
+
# Start date is included, end date is excluded
|
|
123
|
+
>>> yd.count_bdays(start='2023-12-29', end='2024-01-02')
|
|
124
|
+
1
|
|
90
125
|
|
|
91
126
|
# Get the next business day after a given date (offset=1)
|
|
92
127
|
>>> yd.offset_bdays(dates="2023-12-29", offset=1)
|
|
@@ -100,21 +135,10 @@ Timestamp('2024-01-02 00:00:00')
|
|
|
100
135
|
>>> yd.offset_bdays(dates="2023-12-29", offset=0)
|
|
101
136
|
Timestamp('2023-12-29 00:00:00')
|
|
102
137
|
|
|
103
|
-
#
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
1
|
|
138
|
+
# Generate a pandas series with the business days between two dates
|
|
139
|
+
>>> yd.generate_bdays(start='2023-12-29', end='2024-01-03')
|
|
140
|
+
0 2023-12-29
|
|
141
|
+
1 2024-01-02
|
|
142
|
+
2 2024-01-03
|
|
143
|
+
dtype: datetime64[ns]
|
|
107
144
|
```
|
|
108
|
-
|
|
109
|
-
## Documentation
|
|
110
|
-
|
|
111
|
-
For detailed documentation on all features and functionalities, please visit PYield Documentation.
|
|
112
|
-
Contributing
|
|
113
|
-
|
|
114
|
-
Contributions to PYield are welcome! Please read our Contributing Guidelines for details on how to submit pull requests, report issues, or suggest enhancements.
|
|
115
|
-
License
|
|
116
|
-
|
|
117
|
-
PYield is licensed under the MIT License.
|
|
118
|
-
Acknowledgments
|
|
119
|
-
|
|
120
|
-
PYield was developed with the support of the Python community and financial analysts in Brazil. Special thanks to the maintainers of Pandas and Requests for their invaluable libraries.
|
pyield-0.6.0/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
[](https://pypi.python.org/pypi/pyield)
|
|
2
|
+
[](https://python.org "Go to Python homepage")
|
|
3
|
+
[](#license)
|
|
4
|
+
|
|
5
|
+
# PYield: Fixed Income Toolbox for Brazilian Markets
|
|
6
|
+
|
|
7
|
+
## Introduction
|
|
8
|
+
|
|
9
|
+
Welcome to PYield, a Python library designed for the analysis of fixed income instruments in Brazil. This library is tailored for financial analysts, researchers, and enthusiasts interested in the Brazilian fixed income market. Leveraging the power of popular Python libraries like Pandas and Requests, PYield simplifies the process of obtaining and processing data from key sources such as ANBIMA and B3.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Data Collection**: Automated fetching of data from ANBIMA and B3.
|
|
14
|
+
- **Data Processing**: Efficient processing and normalization of fixed income data.
|
|
15
|
+
- **Analysis Tools**: Built-in functions for common analysis tasks in fixed income markets.
|
|
16
|
+
- **Easy Integration**: Seamless integration with pandas data analysis workflows.
|
|
17
|
+
- **Type Hints**: Full support for static type checking, enhancing development experience and code quality.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
You can install PYield using pip:
|
|
22
|
+
```sh
|
|
23
|
+
pip install pyield
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## How to use PYield
|
|
27
|
+
|
|
28
|
+
### Futures Data
|
|
29
|
+
```python
|
|
30
|
+
import pyield as yd
|
|
31
|
+
|
|
32
|
+
# Get a DataFrame with the DI Futures data from B3
|
|
33
|
+
>>> yd.get_data(asset_code="DI1", reference_date='2024-03-08')
|
|
34
|
+
|
|
35
|
+
TradeDate ExpirationCode ExpirationDate BDToExpiration ... LastRate LastAskRate LastBidRate SettlementRate
|
|
36
|
+
2024-03-08 J24 2024-04-01 15 ... 10.952 10.952 10.956 10.956
|
|
37
|
+
2024-03-08 K24 2024-05-02 37 ... 10.776 10.774 10.780 10.777
|
|
38
|
+
2024-03-08 M24 2024-06-03 58 ... 10.604 10.602 10.604 10.608
|
|
39
|
+
... ... ... ... ... ... ... ... ...
|
|
40
|
+
2024-03-08 F37 2037-01-02 3213 ... <NA> <NA> <NA> 10.859
|
|
41
|
+
2024-03-08 F38 2038-01-04 3462 ... <NA> <NA> <NA> 10.859
|
|
42
|
+
2024-03-08 F39 2039-01-03 3713 ... <NA> <NA> <NA> 10.85
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Treasury Bonds Data
|
|
46
|
+
```python
|
|
47
|
+
# Get a DataFrame with the NTN-B data from ANBIMA
|
|
48
|
+
# Anbima data is available for the last 5 working days
|
|
49
|
+
# Obs: Anbima members have access to the full history
|
|
50
|
+
>>> yd.get_data(asset_code="NTN-B", reference_date='2024-04-12')
|
|
51
|
+
|
|
52
|
+
BondType ReferenceDate MaturityDate BidRate AskRate IndicativeRate Price
|
|
53
|
+
NTN-B 2024-04-12 2024-08-15 0.07540 0.07504 0.07523 4,271.43565
|
|
54
|
+
NTN-B 2024-04-12 2025-05-15 0.05945 0.05913 0.05930 4,361.34391
|
|
55
|
+
NTN-B 2024-04-12 2026-08-15 0.05927 0.05897 0.05910 4,301.40082
|
|
56
|
+
... ... ... ... ... ... ...
|
|
57
|
+
NTN-B 2024-04-12 2050-08-15 0.06039 0.06006 0.06023 4,299.28233
|
|
58
|
+
NTN-B 2024-04-12 2055-05-15 0.06035 0.05998 0.06017 4,367.13360
|
|
59
|
+
NTN-B 2024-04-12 2060-08-15 0.06057 0.06016 0.06036 4,292.26323
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Spreads Calculation
|
|
63
|
+
```python
|
|
64
|
+
# Calculate the spread between two DI Futures contracts and the pre-fix bonds
|
|
65
|
+
>>> yd.calculate_spreads(spread_type="di_vs_pre", reference_date="2024-4-11")
|
|
66
|
+
|
|
67
|
+
BondType ReferenceDate MaturityDate DISpread
|
|
68
|
+
LTN 2024-04-11 2024-07-01 -20.28000
|
|
69
|
+
LTN 2024-04-11 2024-10-01 -10.19000
|
|
70
|
+
LTN 2024-04-11 2025-01-01 -15.05000
|
|
71
|
+
... ... ... ...
|
|
72
|
+
NTN-F 2024-04-11 2031-01-01 -0.66000
|
|
73
|
+
NTN-F 2024-04-11 2033-01-01 -5.69000
|
|
74
|
+
NTN-F 2024-04-11 2035-01-01 -1.27000
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Business Days Tools (Brazilian holidays are automatically considered)
|
|
78
|
+
```python
|
|
79
|
+
# Count the number of business days between two dates
|
|
80
|
+
# Start date is included, end date is excluded
|
|
81
|
+
>>> yd.count_bdays(start='2023-12-29', end='2024-01-02')
|
|
82
|
+
1
|
|
83
|
+
|
|
84
|
+
# Get the next business day after a given date (offset=1)
|
|
85
|
+
>>> yd.offset_bdays(dates="2023-12-29", offset=1)
|
|
86
|
+
Timestamp('2024-01-02 00:00:00')
|
|
87
|
+
|
|
88
|
+
# Get the next business day if it is not a business day (offset=0)
|
|
89
|
+
>>> yd.offset_bdays(dates="2023-12-30", offset=0)
|
|
90
|
+
Timestamp('2024-01-02 00:00:00')
|
|
91
|
+
|
|
92
|
+
# Since 2023-12-29 is a business day, it returns the same date (offset=0)
|
|
93
|
+
>>> yd.offset_bdays(dates="2023-12-29", offset=0)
|
|
94
|
+
Timestamp('2023-12-29 00:00:00')
|
|
95
|
+
|
|
96
|
+
# Generate a pandas series with the business days between two dates
|
|
97
|
+
>>> yd.generate_bdays(start='2023-12-29', end='2024-01-03')
|
|
98
|
+
0 2023-12-29
|
|
99
|
+
1 2024-01-02
|
|
100
|
+
2 2024-01-03
|
|
101
|
+
dtype: datetime64[ns]
|
|
102
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.0"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from .__about__ import __version__
|
|
2
|
+
from .bday import count_bdays, generate_bdays, is_bday, offset_bdays
|
|
3
|
+
from .data_access import get_data
|
|
4
|
+
from .data_analysis import calculate_spreads
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"__version__",
|
|
8
|
+
"is_bday",
|
|
9
|
+
"generate_bdays",
|
|
10
|
+
"offset_bdays",
|
|
11
|
+
"count_bdays",
|
|
12
|
+
"get_data",
|
|
13
|
+
"calculate_spreads",
|
|
14
|
+
]
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Literal, overload
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from .holidays import BrHolidays
|
|
8
|
+
|
|
9
|
+
SingleDateTypes = str | np.datetime64 | pd.Timestamp | datetime
|
|
10
|
+
SeriesDateTypes = list | tuple | np.ndarray | pd.Series | pd.Index | pd.DatetimeIndex
|
|
11
|
+
|
|
12
|
+
TO_TIMESTAMP_TYPES = (str, np.datetime64, datetime)
|
|
13
|
+
TO_SERIES_TYPES = (list, tuple, np.ndarray, pd.Series, pd.Index, pd.DatetimeIndex)
|
|
14
|
+
|
|
15
|
+
# Initialize the BrHolidays class
|
|
16
|
+
br_holidays = BrHolidays()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@overload
|
|
20
|
+
def _normalize_input_dates(
|
|
21
|
+
dates: SingleDateTypes | None,
|
|
22
|
+
) -> pd.Timestamp: ...
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@overload
|
|
26
|
+
def _normalize_input_dates(
|
|
27
|
+
dates: SeriesDateTypes,
|
|
28
|
+
) -> pd.Series: ...
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _normalize_input_dates(
|
|
32
|
+
dates: SingleDateTypes | SeriesDateTypes | None = None,
|
|
33
|
+
) -> pd.Timestamp | pd.Series:
|
|
34
|
+
if dates is None:
|
|
35
|
+
return pd.Timestamp.today().normalize()
|
|
36
|
+
elif isinstance(dates, pd.Timestamp):
|
|
37
|
+
return dates.normalize()
|
|
38
|
+
elif isinstance(dates, TO_TIMESTAMP_TYPES):
|
|
39
|
+
return pd.Timestamp(dates).normalize()
|
|
40
|
+
elif isinstance(dates, TO_SERIES_TYPES):
|
|
41
|
+
result = pd.to_datetime(dates)
|
|
42
|
+
return pd.Series(result).dt.normalize()
|
|
43
|
+
else:
|
|
44
|
+
raise ValueError("Invalid date format.")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def is_bday(date: SingleDateTypes | None = None) -> bool:
|
|
48
|
+
"""
|
|
49
|
+
Checks if the input date is a business day.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
date (str | np.datetime64 | pd.Timestamp | datetime, optional): The date to
|
|
53
|
+
check. If None, the current date is used.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
bool: True if the input date is a business day, False otherwise.
|
|
57
|
+
|
|
58
|
+
Examples:
|
|
59
|
+
>>> yd.is_bday('2023-12-25') # Christmas
|
|
60
|
+
False
|
|
61
|
+
>>> yd.is_bday() # Check if today is a business day
|
|
62
|
+
True
|
|
63
|
+
"""
|
|
64
|
+
normalized_date = _normalize_input_dates(date)
|
|
65
|
+
# Shift the date if it is not a business day
|
|
66
|
+
adjusted_date = offset_bdays(normalized_date, 0)
|
|
67
|
+
return normalized_date == adjusted_date
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _convert_to_numpy_date(
|
|
71
|
+
dates: pd.Timestamp | pd.Series,
|
|
72
|
+
) -> np.datetime64 | np.ndarray:
|
|
73
|
+
"""
|
|
74
|
+
Converts the input dates to a numpy datetime64[D] format.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
dates (Timestamp | Series): A single date or a Series of dates.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
np.datetime64 | np.ndarray: The input dates in a numpy datetime64[D] format.
|
|
81
|
+
"""
|
|
82
|
+
if isinstance(dates, pd.Timestamp):
|
|
83
|
+
return np.datetime64(dates, "D")
|
|
84
|
+
else:
|
|
85
|
+
return dates.to_numpy().astype("datetime64[D]")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@overload
|
|
89
|
+
def offset_bdays(
|
|
90
|
+
dates: SingleDateTypes | None = None,
|
|
91
|
+
offset: int = 0,
|
|
92
|
+
roll: Literal["forward", "backward"] = "forward",
|
|
93
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
94
|
+
) -> pd.Timestamp: ...
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@overload
|
|
98
|
+
def offset_bdays(
|
|
99
|
+
dates: SeriesDateTypes,
|
|
100
|
+
offset: int = 0,
|
|
101
|
+
roll: Literal["forward", "backward"] = "forward",
|
|
102
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
103
|
+
) -> pd.Series: ...
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def offset_bdays(
|
|
107
|
+
dates: SingleDateTypes | SeriesDateTypes | None = None,
|
|
108
|
+
offset: int = 0,
|
|
109
|
+
roll: Literal["forward", "backward"] = "forward",
|
|
110
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
111
|
+
) -> pd.Timestamp | pd.Series:
|
|
112
|
+
"""
|
|
113
|
+
Offsets the dates to the next or previous business day, considering brazilian
|
|
114
|
+
holidays. This function supports both single dates and collections of dates,
|
|
115
|
+
handling them intelligently to return either a single offset date or a series of
|
|
116
|
+
offset dates. It is a wrapper for `numpy.busday_offset` adapted for Pandas data
|
|
117
|
+
types and holiday adjustments.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
dates (str | np.datetime64 | pd.Timestamp | datetime | list | tuple | np.ndarray
|
|
121
|
+
| pd.Series | pd.Index | pd.DatetimeIndex, optional):
|
|
122
|
+
The date(s) to offset. Can be a single date in various formats (string,
|
|
123
|
+
`datetime`, `Timestamp`, etc.) or a collection of dates (list, tuple,
|
|
124
|
+
`Series`, etc.). If None, the current date is used.
|
|
125
|
+
offset (int): The number of business days to offset the dates. Positive for
|
|
126
|
+
future dates, negative for past dates. Zero will return the same date if
|
|
127
|
+
it's a business day, or the next business day otherwise.
|
|
128
|
+
roll (Literal["forward", "backward"], optional): Direction to roll the date if
|
|
129
|
+
it falls on a holiday or weekend. 'forward' to the next business day,
|
|
130
|
+
'backward' to the previous. Defaults to 'forward'.
|
|
131
|
+
holiday_list (Literal["old", "new", "infer"], optional):
|
|
132
|
+
The list of holidays to consider. 'old' or 'new' use predefined lists, while
|
|
133
|
+
'infer' determines the most appropriate list based on the input dates.
|
|
134
|
+
Defaults to "infer".
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
pd.Timestamp | pd.Series: If a single date is provided, returns a single
|
|
138
|
+
`Timestamp` of the offset date. If a series of dates is provided, returns a
|
|
139
|
+
`Series` of offset dates.
|
|
140
|
+
|
|
141
|
+
Examples:
|
|
142
|
+
>>> date = '2023-12-23' # Saturday before Christmas
|
|
143
|
+
>>> yd.offset_bdays(date, 0)
|
|
144
|
+
Timestamp('2023-12-26')
|
|
145
|
+
|
|
146
|
+
>>> date = '2023-12-22' # Friday before Christmas
|
|
147
|
+
>>> yd.offset_bdays(date, 0)
|
|
148
|
+
Timestamp('2023-12-22') # No offset because it's a business day
|
|
149
|
+
|
|
150
|
+
>>> yd.offset_bdays(date, 1)
|
|
151
|
+
Timestamp('2023-12-26') # Offset to the next business day
|
|
152
|
+
|
|
153
|
+
>>> yd.offset_bdays(date, -1)
|
|
154
|
+
Timestamp('2023-12-21') # Offset to the previous business day
|
|
155
|
+
|
|
156
|
+
Note:
|
|
157
|
+
This function uses `numpy.busday_offset` under the hood, which means it follows
|
|
158
|
+
the same conventions and limitations for business day calculations. For detailed
|
|
159
|
+
information on error handling and behavior, refer to the `numpy.busday_offset`
|
|
160
|
+
documentation: https://numpy.org/doc/stable/reference/generated/numpy.busday_offset.html
|
|
161
|
+
"""
|
|
162
|
+
normalized_dates = _normalize_input_dates(dates)
|
|
163
|
+
|
|
164
|
+
selected_holidays = br_holidays.get_applicable_holidays(
|
|
165
|
+
normalized_dates, holiday_list
|
|
166
|
+
)
|
|
167
|
+
selected_holidays_np = _convert_to_numpy_date(selected_holidays)
|
|
168
|
+
|
|
169
|
+
dates_np = _convert_to_numpy_date(normalized_dates)
|
|
170
|
+
offsetted_dates_np = np.busday_offset(
|
|
171
|
+
dates_np, offsets=offset, roll=roll, holidays=selected_holidays_np
|
|
172
|
+
)
|
|
173
|
+
if isinstance(offsetted_dates_np, np.datetime64):
|
|
174
|
+
return pd.Timestamp(offsetted_dates_np, unit="ns")
|
|
175
|
+
else:
|
|
176
|
+
result = pd.to_datetime(offsetted_dates_np, unit="ns")
|
|
177
|
+
return pd.Series(result)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@overload
|
|
181
|
+
def count_bdays(
|
|
182
|
+
start: SingleDateTypes | None = None,
|
|
183
|
+
end: SingleDateTypes | None = None,
|
|
184
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
185
|
+
) -> int: ...
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@overload
|
|
189
|
+
def count_bdays(
|
|
190
|
+
start: SeriesDateTypes,
|
|
191
|
+
end: SingleDateTypes | None,
|
|
192
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
193
|
+
) -> pd.Series: ...
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@overload
|
|
197
|
+
def count_bdays(
|
|
198
|
+
start: SingleDateTypes | None,
|
|
199
|
+
end: SeriesDateTypes,
|
|
200
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
201
|
+
) -> pd.Series: ...
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@overload
|
|
205
|
+
def count_bdays(
|
|
206
|
+
start: SeriesDateTypes,
|
|
207
|
+
end: SeriesDateTypes,
|
|
208
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
209
|
+
) -> pd.Series: ...
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def count_bdays(
|
|
213
|
+
start: SingleDateTypes | SeriesDateTypes | None = None,
|
|
214
|
+
end: SingleDateTypes | SeriesDateTypes | None = None,
|
|
215
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
216
|
+
) -> int | pd.Series:
|
|
217
|
+
"""
|
|
218
|
+
Counts the number of business days between a `start` and `end` date(s), inclusively
|
|
219
|
+
for the start date and exclusively for the end date. The function can handle single
|
|
220
|
+
dates, arrays of dates, and mixed inputs, returning either a single integer or a
|
|
221
|
+
Series depending on the inputs. It accounts for specified holidays, effectively
|
|
222
|
+
excluding them from the business day count.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
start (str | np.datetime64 | pd.Timestamp | datetime | list | tuple |
|
|
226
|
+
np.ndarray | pd.Series | pd.Index | pd.DatetimeIndex, optional):
|
|
227
|
+
The start date(s) for counting. Defaults to the current date if None.
|
|
228
|
+
end (str | np.datetime64 | pd.Timestamp | datetime | list | tuple |
|
|
229
|
+
np.ndarray | pd.Series | pd.Index | pd.DatetimeIndex, optional):
|
|
230
|
+
The end date(s) for counting, which are excluded from the count themselves.
|
|
231
|
+
Defaults to the current date if None.
|
|
232
|
+
holiday_list (Literal["old", "new", "infer"], optional):
|
|
233
|
+
Specifies which set of holidays to consider in the count. 'old' or 'new'
|
|
234
|
+
refer to predefined holiday lists, while 'infer' automatically selects the
|
|
235
|
+
list based on the most recent date in the input. Defaults to "infer".
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
int | pd.Series: Returns an integer if `start` and `end` are single dates,
|
|
239
|
+
or a Series if either or both are arrays of dates. The value(s) represent
|
|
240
|
+
the count of business days between `start` and `end`.
|
|
241
|
+
|
|
242
|
+
Notes:
|
|
243
|
+
- This function is a wrapper around `numpy.busday_count`, adapted to work
|
|
244
|
+
directly with various Pandas and Numpy date formats.
|
|
245
|
+
- It supports flexible date inputs, including single dates, lists, Series, and
|
|
246
|
+
more, for both `start` and `end` parameters.
|
|
247
|
+
- The return type depends on the input types: single dates return an int, while
|
|
248
|
+
arrays of dates return a pd.Series with the count for each date range.
|
|
249
|
+
- See `numpy.busday_count` documentation for more details on how holidays are
|
|
250
|
+
handled and how business day counts are calculated:
|
|
251
|
+
https://numpy.org/doc/stable/reference/generated/numpy.busday_count.html.
|
|
252
|
+
|
|
253
|
+
Examples:
|
|
254
|
+
>>> yd.count_bdays('2023-12-15', '2024-01-01')
|
|
255
|
+
10
|
|
256
|
+
|
|
257
|
+
>>> start = '2023-01-01'
|
|
258
|
+
>>> end = pd.to_datetime(['2023-01-31', '2023-03-01'])
|
|
259
|
+
>>> yd.count_bdays(start, end)
|
|
260
|
+
pd.Series([22, 40], dtype='int64')
|
|
261
|
+
"""
|
|
262
|
+
normalized_start = _normalize_input_dates(start)
|
|
263
|
+
normalized_end = _normalize_input_dates(end)
|
|
264
|
+
|
|
265
|
+
# Determine which list of holidays to use
|
|
266
|
+
selected_holidays = br_holidays.get_applicable_holidays(
|
|
267
|
+
normalized_start, holiday_list
|
|
268
|
+
)
|
|
269
|
+
selected_holidays_np = _convert_to_numpy_date(selected_holidays)
|
|
270
|
+
|
|
271
|
+
# Convert inputs to numpy datetime64[D] before calling numpy.busday_count
|
|
272
|
+
start_np = _convert_to_numpy_date(normalized_start)
|
|
273
|
+
end_np = _convert_to_numpy_date(normalized_end)
|
|
274
|
+
|
|
275
|
+
result_np = np.busday_count(start_np, end_np, holidays=selected_holidays_np)
|
|
276
|
+
if isinstance(result_np, np.int64):
|
|
277
|
+
return int(result_np)
|
|
278
|
+
else:
|
|
279
|
+
return pd.Series(result_np, dtype="Int64")
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def generate_bdays(
|
|
283
|
+
start: SingleDateTypes | None = None,
|
|
284
|
+
end: SingleDateTypes | None = None,
|
|
285
|
+
inclusive: Literal["both", "neither", "left", "right"] = "both",
|
|
286
|
+
holiday_list: Literal["old", "new", "infer"] = "infer",
|
|
287
|
+
**kwargs,
|
|
288
|
+
) -> pd.Series:
|
|
289
|
+
"""
|
|
290
|
+
Generates a Series of business days between a `start` and `end` date, considering
|
|
291
|
+
the list of Brazilian holidays. It supports customization of holiday lists and
|
|
292
|
+
inclusion options for start and end dates. It wraps `pandas.bdate_range`.
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
start (str | np.datetime64 | pd.Timestamp | datetime, optional):
|
|
296
|
+
The start date for generating business days. Defaults to None, using the
|
|
297
|
+
current date.
|
|
298
|
+
end (str | np.datetime64 | pd.Timestamp | datetime, optional):
|
|
299
|
+
The end date for generating business days. Defaults to None, using the
|
|
300
|
+
current date.
|
|
301
|
+
inclusive (Literal["both", "neither", "left", "right"], optional):
|
|
302
|
+
Determines which of the start and end dates are included in the result.
|
|
303
|
+
Valid options are 'both', 'neither', 'left', 'right'. Defaults to 'both'.
|
|
304
|
+
holiday_list (Literal["old", "new", "infer"], optional):
|
|
305
|
+
Specifies the list of holidays to consider. 'old' or 'new' refer to
|
|
306
|
+
predefined lists, 'infer' selects the list based on the most recent date in
|
|
307
|
+
the range. Defaults to "infer".
|
|
308
|
+
**kwargs:
|
|
309
|
+
Additional keyword arguments passed to `pandas.bdate_range` for
|
|
310
|
+
customization.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
pd.Series: A Series representing a range of business days between the specified
|
|
314
|
+
start and end dates, considering the specified holidays.
|
|
315
|
+
|
|
316
|
+
Examples:
|
|
317
|
+
>>> yd.generate_bdays(start='2023-12-22', end='2024-01-02')
|
|
318
|
+
pd.Series(['2023-12-22', '2023-12-26', '2023-12-27', '2023-12-28', '2023-12-29',
|
|
319
|
+
'2024-01-02'], dtype='datetime64[ns]')
|
|
320
|
+
|
|
321
|
+
Note:
|
|
322
|
+
For detailed information on parameters and error handling, refer to
|
|
323
|
+
`pandas.bdate_range` documentation:
|
|
324
|
+
https://pandas.pydata.org/docs/reference/api/pandas.bdate_range.html.
|
|
325
|
+
"""
|
|
326
|
+
normalized_start = _normalize_input_dates(start)
|
|
327
|
+
normalized_end = _normalize_input_dates(end)
|
|
328
|
+
|
|
329
|
+
selected_holidays = br_holidays.get_applicable_holidays(
|
|
330
|
+
normalized_start, holiday_list
|
|
331
|
+
)
|
|
332
|
+
selected_holidays_list = selected_holidays.to_list()
|
|
333
|
+
|
|
334
|
+
result = pd.bdate_range(
|
|
335
|
+
normalized_start,
|
|
336
|
+
normalized_end,
|
|
337
|
+
freq="C",
|
|
338
|
+
inclusive=inclusive,
|
|
339
|
+
holidays=selected_holidays_list,
|
|
340
|
+
**kwargs,
|
|
341
|
+
)
|
|
342
|
+
return pd.Series(result)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
3
|
+
from . import di
|
|
4
|
+
from . import treasuries as tr
|
|
5
|
+
from .utils import _normalize_date
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_data(
|
|
9
|
+
asset_code: str,
|
|
10
|
+
reference_date: str | pd.Timestamp | None = None,
|
|
11
|
+
**kwargs,
|
|
12
|
+
) -> pd.DataFrame:
|
|
13
|
+
"""
|
|
14
|
+
Fetches data for a specified asset type and reference date.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
asset (str): The asset type. Available options are:
|
|
18
|
+
- "TRB": Fetches indicative rates for Brazilian treasury bonds from ANBIMA.
|
|
19
|
+
- "LTN": Fetches indicative rates for Brazilian LTN bonds from ANBIMA.
|
|
20
|
+
- "LFT": Fetches indicative rates for Brazilian LFT bonds from ANBIMA.
|
|
21
|
+
- "NTN-F": Fetches indicative rates for Brazilian NTN-F bonds from ANBIMA.
|
|
22
|
+
- "NTN-B": Fetches indicative rates for Brazilian NTN-B bonds from ANBIMA.
|
|
23
|
+
- "DI1": Fetches DI Futures rates from B3.
|
|
24
|
+
reference_date (str): Reference date for the data in YYYY-MM-DD format.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
pd.DataFrame: A DataFrame containing the fetched data.
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
ValueError: If the specified source or asset type is not supported.
|
|
31
|
+
"""
|
|
32
|
+
# Extract the internal use parameter with default value
|
|
33
|
+
return_raw = kwargs.get("return_raw", False)
|
|
34
|
+
|
|
35
|
+
# Validate the date, defaulting to the previous business day if not provided
|
|
36
|
+
normalized_date = _normalize_date(reference_date)
|
|
37
|
+
|
|
38
|
+
if asset_code.lower() == "trb":
|
|
39
|
+
# Fetch all indicative treasury rates from ANBIMA
|
|
40
|
+
return tr.fetch_data(reference_date=normalized_date, return_raw=return_raw)
|
|
41
|
+
elif asset_code.lower() in ["ltn", "lft", "ntn-f", "ntn-b"]:
|
|
42
|
+
# Fetch indicative rates for a specific type of Brazilian treasury bond
|
|
43
|
+
df = tr.fetch_data(reference_date=normalized_date)
|
|
44
|
+
return df.query(f"BondType == '{asset_code.upper()}'")
|
|
45
|
+
|
|
46
|
+
elif asset_code.lower() == "di1":
|
|
47
|
+
return di.fetch_data(
|
|
48
|
+
trade_date=normalized_date, source_type="bmf", return_raw=return_raw
|
|
49
|
+
)
|
|
50
|
+
else:
|
|
51
|
+
raise ValueError("Asset type not supported.")
|