PYield 0.32.2__tar.gz → 0.32.3__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.32.2 → pyield-0.32.3}/PKG-INFO +1 -1
- pyield-0.32.3/pyield/__about__.py +1 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/__init__.py +2 -1
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/di.py +4 -5
- pyield-0.32.3/pyield/fwd.py +120 -0
- pyield-0.32.2/pyield/__about__.py +0 -1
- pyield-0.32.2/pyield/forward.py +0 -56
- {pyield-0.32.2 → pyield-0.32.3}/.gitignore +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/LICENSE +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/README.md +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/anbima/__init__.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/anbima/ettj.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/anbima/ima.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/anbima/imaq.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/anbima/ipca.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/anbima/tpf.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/__init__.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/di_over.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/futures/__init__.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/futures/common.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/futures/historical.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/futures/intraday.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/b3/futures/xml.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bc/__init__.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bc/auction.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bc/bcdata.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bc/ptax.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bc/repo.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bc/trade.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bc/vna.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/bday.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/conftest.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/data_cache.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/date_converter.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/holidays/__init__.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/holidays/br_holidays_new.txt +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/holidays/br_holidays_old.txt +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/holidays/brholidays.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/ibge/__init__.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/ibge/ipca.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/interpolator.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/py.typed +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/retry.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/tpf/__init__.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/tpf/lft.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/tpf/ltn.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/tpf/ntnb.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/tpf/ntnc.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/tpf/ntnf.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyield/tpf/tools.py +0 -0
- {pyield-0.32.2 → pyield-0.32.3}/pyproject.toml +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.32.3"
|
|
@@ -4,7 +4,7 @@ from pyield import anbima, b3, bc, bday, ibge
|
|
|
4
4
|
from pyield.__about__ import __version__
|
|
5
5
|
from pyield.b3 import futures
|
|
6
6
|
from pyield.b3.di import DIFutures
|
|
7
|
-
from pyield.
|
|
7
|
+
from pyield.fwd import forward, forwards
|
|
8
8
|
from pyield.interpolator import Interpolator
|
|
9
9
|
from pyield.tpf import lft, ltn, ntnb, ntnc, ntnf
|
|
10
10
|
|
|
@@ -14,6 +14,7 @@ __all__ = [
|
|
|
14
14
|
"bday",
|
|
15
15
|
"DIFutures",
|
|
16
16
|
"forwards",
|
|
17
|
+
"forward",
|
|
17
18
|
"futures",
|
|
18
19
|
"ibge",
|
|
19
20
|
"Interpolator",
|
|
@@ -5,8 +5,7 @@ from zoneinfo import ZoneInfo
|
|
|
5
5
|
import pandas as pd
|
|
6
6
|
|
|
7
7
|
import pyield.date_converter as dc
|
|
8
|
-
|
|
9
|
-
from pyield import b3, bday, interpolator
|
|
8
|
+
from pyield import b3, bday, fwd, interpolator
|
|
10
9
|
from pyield.data_cache import get_cached_dataset
|
|
11
10
|
from pyield.date_converter import DateArray, DateScalar
|
|
12
11
|
|
|
@@ -206,9 +205,9 @@ class DIFutures:
|
|
|
206
205
|
if df.empty:
|
|
207
206
|
return pd.DataFrame()
|
|
208
207
|
|
|
209
|
-
df["ForwardRate"] =
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
df["ForwardRate"] = fwd.forwards(
|
|
209
|
+
bdays=bday.count(df["TradeDate"], df["ExpirationDate"]),
|
|
210
|
+
rates=df["SettlementRate"],
|
|
212
211
|
groupby_dates=df["TradeDate"],
|
|
213
212
|
)
|
|
214
213
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def forwards(
|
|
5
|
+
bdays: pd.Series,
|
|
6
|
+
rates: pd.Series,
|
|
7
|
+
groupby_dates: pd.Series | None = None,
|
|
8
|
+
) -> pd.Series:
|
|
9
|
+
"""
|
|
10
|
+
Calculates forward rates from zero rates using the formula:
|
|
11
|
+
f₁→₂ = ((1 + r₂)^(du₂/252) / (1 + r₁)^(du₁/252))^(252/(du₂ - du₁)) - 1
|
|
12
|
+
|
|
13
|
+
Since du/252 = t, the formula can be simplified to:
|
|
14
|
+
f₁→₂ = ((1 + r₂)^t₂ / (1 + r₁)^t₁)^(1/(t₂ - t₁)) - 1
|
|
15
|
+
|
|
16
|
+
where:
|
|
17
|
+
- r₁ is the zero rate for the previous period
|
|
18
|
+
- r₂ is the zero rate for the current period
|
|
19
|
+
- t₁ is the time in years for the previous period
|
|
20
|
+
- t₂ is the time in years for the current period
|
|
21
|
+
|
|
22
|
+
The first forward rate is set to the corresponding zero rate.
|
|
23
|
+
This function can also handle grouping of the input data based on the
|
|
24
|
+
`groupby_dates` parameter. If provided, the calculations will be performed
|
|
25
|
+
separately for each group, allowing for different forward rate calculations
|
|
26
|
+
based on the grouping criteria.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
bdays (pd.Series): Number of business days for each zero rate.
|
|
30
|
+
rates (pd.Series): Zero rates corresponding to the business days.
|
|
31
|
+
groupby_dates (pd.Series | None, optional): Optional grouping criteria to
|
|
32
|
+
segment calculations. If not provided, calculations will not be grouped.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
pd.Series: Series of calculated forward rates with the first rate set to the
|
|
36
|
+
corresponding zero rate.
|
|
37
|
+
"""
|
|
38
|
+
# Reset Series indexes to avoid misalignment issues during calculations
|
|
39
|
+
bdays = bdays.reset_index(drop=True)
|
|
40
|
+
rates = rates.reset_index(drop=True)
|
|
41
|
+
if groupby_dates is not None:
|
|
42
|
+
groupby_dates = groupby_dates.reset_index(drop=True)
|
|
43
|
+
|
|
44
|
+
# Create a DataFrame to work with the given series
|
|
45
|
+
df = pd.DataFrame({"du2": bdays, "r2": rates})
|
|
46
|
+
df["t2"] = df["du2"] / 252
|
|
47
|
+
|
|
48
|
+
# If no groupby_dates is provided, create a dummy column to group the DataFrame
|
|
49
|
+
if groupby_dates is not None:
|
|
50
|
+
df["groupby_date"] = groupby_dates
|
|
51
|
+
else:
|
|
52
|
+
df["groupby_date"] = 0 # Dummy value to group the DataFrame
|
|
53
|
+
|
|
54
|
+
# Sort by the groupby_dates and bd columns to ensure proper chronological order
|
|
55
|
+
df.sort_values(by=["groupby_date", "t2"], inplace=True)
|
|
56
|
+
|
|
57
|
+
# GetCalculate the next zero rate and business day for each group
|
|
58
|
+
df["r1"] = df.groupby("groupby_date")["r2"].shift(1)
|
|
59
|
+
df["t1"] = df.groupby("groupby_date")["t2"].shift(1)
|
|
60
|
+
|
|
61
|
+
# Calculate the formula components
|
|
62
|
+
factor_r2 = (1 + df["r2"]) ** df["t2"] # (1 + r₂)^t₂
|
|
63
|
+
factor_r1 = (1 + df["r1"]) ** df["t1"] # (1 + r₁)^t₁
|
|
64
|
+
time_exp = 1 / (df["t2"] - df["t1"]) # 1/(t₂ - t₁)
|
|
65
|
+
|
|
66
|
+
# f₁→₂ = ((1 + r₂)^t₂ / (1 + r₁)^t₁)^(1/(t₂ - t₁)) - 1
|
|
67
|
+
df["f1_2"] = (factor_r2 / factor_r1) ** time_exp - 1
|
|
68
|
+
|
|
69
|
+
# Identifify the first index of each group of dates
|
|
70
|
+
first_indices = df.groupby("groupby_date").head(1).index
|
|
71
|
+
# Set the first forward rate of each group to the zero rate
|
|
72
|
+
df.loc[first_indices, "f1_2"] = df.loc[first_indices, "r2"]
|
|
73
|
+
|
|
74
|
+
# Return the forward rates as a Series converting to Float64 to handle NaN values
|
|
75
|
+
return df["f1_2"].astype("Float64")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def forward(
|
|
79
|
+
bday1: int,
|
|
80
|
+
bday2: int,
|
|
81
|
+
rate1: float,
|
|
82
|
+
rate2: float,
|
|
83
|
+
) -> float:
|
|
84
|
+
"""
|
|
85
|
+
Calculates the forward rate between two business days using the formula:
|
|
86
|
+
f₁→₂ = ((1 + r₂)^(du₂/252) / (1 + r₁)^(du₁/252))^(252/(du₂ - du₁)) - 1
|
|
87
|
+
|
|
88
|
+
where:
|
|
89
|
+
- r₁ is the zero rate for the previous period
|
|
90
|
+
- r₂ is the zero rate for the current period
|
|
91
|
+
- du₁ is the number of business days until the first date
|
|
92
|
+
- du₂ is the number of business days until the second date
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
bday1 (int): Number of business days until the first date.
|
|
96
|
+
bday2 (int): Number of business days until the second date.
|
|
97
|
+
rate1 (float): Zero rate for the first date.
|
|
98
|
+
rate2 (float): Zero rate for the second date.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
float: The calculated forward rate.
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
>>> forward(10, 20, 0.05, 0.06)
|
|
105
|
+
0.0700952380952371
|
|
106
|
+
"""
|
|
107
|
+
if pd.isna(rate1) or pd.isna(rate2) or pd.isna(bday1) or pd.isna(bday2):
|
|
108
|
+
# If any of the inputs are NaN, return NaN
|
|
109
|
+
return float("nan")
|
|
110
|
+
|
|
111
|
+
# Handle the case where the two dates are the same
|
|
112
|
+
if bday1 == bday2:
|
|
113
|
+
return float("nan")
|
|
114
|
+
|
|
115
|
+
# Convert business days to business years
|
|
116
|
+
t1 = bday1 / 252
|
|
117
|
+
t2 = bday2 / 252
|
|
118
|
+
|
|
119
|
+
# f₁→₂ = ((1 + r₂)^t₂ / (1 + r₁)^t₁)^(1/(t₂ - t₁)) - 1
|
|
120
|
+
return ((1 + rate2) ** t2 / (1 + rate1) ** t1) ** (1 / (t2 - t1)) - 1
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.32.2"
|
pyield-0.32.2/pyield/forward.py
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import pandas as pd
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def forwards(
|
|
5
|
-
business_days: pd.Series,
|
|
6
|
-
zero_rates: pd.Series,
|
|
7
|
-
groupby_dates: pd.Series | None = None,
|
|
8
|
-
) -> pd.Series:
|
|
9
|
-
"""Calculates forward rates from zero rates.
|
|
10
|
-
|
|
11
|
-
Args:
|
|
12
|
-
business_days (pd.Series): Number of business days for each zero rate.
|
|
13
|
-
zero_rates (pd.Series): Zero rates corresponding to the business days.
|
|
14
|
-
groupby_dates (pd.Series | None, optional): Optional grouping criteria to
|
|
15
|
-
segment calculations. If not provided, calculations will not be grouped.
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
pd.Series: Series of calculated forward rates with the first rate set to the
|
|
19
|
-
corresponding zero rate.
|
|
20
|
-
"""
|
|
21
|
-
# Reset Series indexes to avoid misalignment issues during calculations
|
|
22
|
-
business_days = business_days.reset_index(drop=True)
|
|
23
|
-
zero_rates = zero_rates.reset_index(drop=True)
|
|
24
|
-
if groupby_dates is not None:
|
|
25
|
-
groupby_dates = groupby_dates.reset_index(drop=True)
|
|
26
|
-
|
|
27
|
-
# Create a DataFrame to work with the given series
|
|
28
|
-
df = pd.DataFrame({"bd": business_days, "zero_rate": zero_rates})
|
|
29
|
-
|
|
30
|
-
# If no groupby_dates is provided, create a dummy column to group the DataFrame
|
|
31
|
-
if groupby_dates is not None:
|
|
32
|
-
df["groupby_date"] = groupby_dates
|
|
33
|
-
else:
|
|
34
|
-
df["groupby_date"] = 0 # Dummy value to group the DataFrame
|
|
35
|
-
|
|
36
|
-
# Sort by the groupby_dates and bd columns to ensure proper chronological order
|
|
37
|
-
df.sort_values(by=["groupby_date", "bd"], inplace=True)
|
|
38
|
-
|
|
39
|
-
# Calculate the next zero rate and business day for each group
|
|
40
|
-
df["next_rate"] = df.groupby("groupby_date")["zero_rate"].shift(1)
|
|
41
|
-
df["next_bday"] = df.groupby("groupby_date")["bd"].shift(1)
|
|
42
|
-
|
|
43
|
-
# Calculate the forward rates using the formula
|
|
44
|
-
factor1 = (1 + df["next_rate"]) ** (df["next_bday"] / 252)
|
|
45
|
-
factor2 = (1 + df["zero_rate"]) ** (df["bd"] / 252)
|
|
46
|
-
factor3 = 252 / (df["next_bday"] - df["bd"])
|
|
47
|
-
df["fwd_rate"] = (factor1 / factor2) ** factor3 - 1
|
|
48
|
-
|
|
49
|
-
# Identifify the first index of each group of dates
|
|
50
|
-
first_indices = df.groupby("groupby_date").head(1).index
|
|
51
|
-
# Set the first forward rate of each group to the zero rate
|
|
52
|
-
df.loc[first_indices, "fwd_rate"] = df.loc[first_indices, "zero_rate"]
|
|
53
|
-
|
|
54
|
-
df["fwd_rate"] = df["fwd_rate"].astype("Float64")
|
|
55
|
-
|
|
56
|
-
return df["fwd_rate"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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
|