PYield 0.32.3__tar.gz → 0.32.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {pyield-0.32.3 → pyield-0.32.4}/PKG-INFO +1 -1
  2. pyield-0.32.4/pyield/__about__.py +1 -0
  3. {pyield-0.32.3 → pyield-0.32.4}/pyield/conftest.py +2 -0
  4. pyield-0.32.4/pyield/fwd.py +164 -0
  5. pyield-0.32.3/pyield/__about__.py +0 -1
  6. pyield-0.32.3/pyield/fwd.py +0 -120
  7. {pyield-0.32.3 → pyield-0.32.4}/.gitignore +0 -0
  8. {pyield-0.32.3 → pyield-0.32.4}/LICENSE +0 -0
  9. {pyield-0.32.3 → pyield-0.32.4}/README.md +0 -0
  10. {pyield-0.32.3 → pyield-0.32.4}/pyield/__init__.py +0 -0
  11. {pyield-0.32.3 → pyield-0.32.4}/pyield/anbima/__init__.py +0 -0
  12. {pyield-0.32.3 → pyield-0.32.4}/pyield/anbima/ettj.py +0 -0
  13. {pyield-0.32.3 → pyield-0.32.4}/pyield/anbima/ima.py +0 -0
  14. {pyield-0.32.3 → pyield-0.32.4}/pyield/anbima/imaq.py +0 -0
  15. {pyield-0.32.3 → pyield-0.32.4}/pyield/anbima/ipca.py +0 -0
  16. {pyield-0.32.3 → pyield-0.32.4}/pyield/anbima/tpf.py +0 -0
  17. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/__init__.py +0 -0
  18. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/di.py +0 -0
  19. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/di_over.py +0 -0
  20. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/futures/__init__.py +0 -0
  21. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/futures/common.py +0 -0
  22. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/futures/historical.py +0 -0
  23. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/futures/intraday.py +0 -0
  24. {pyield-0.32.3 → pyield-0.32.4}/pyield/b3/futures/xml.py +0 -0
  25. {pyield-0.32.3 → pyield-0.32.4}/pyield/bc/__init__.py +0 -0
  26. {pyield-0.32.3 → pyield-0.32.4}/pyield/bc/auction.py +0 -0
  27. {pyield-0.32.3 → pyield-0.32.4}/pyield/bc/bcdata.py +0 -0
  28. {pyield-0.32.3 → pyield-0.32.4}/pyield/bc/ptax.py +0 -0
  29. {pyield-0.32.3 → pyield-0.32.4}/pyield/bc/repo.py +0 -0
  30. {pyield-0.32.3 → pyield-0.32.4}/pyield/bc/trade.py +0 -0
  31. {pyield-0.32.3 → pyield-0.32.4}/pyield/bc/vna.py +0 -0
  32. {pyield-0.32.3 → pyield-0.32.4}/pyield/bday.py +0 -0
  33. {pyield-0.32.3 → pyield-0.32.4}/pyield/data_cache.py +0 -0
  34. {pyield-0.32.3 → pyield-0.32.4}/pyield/date_converter.py +0 -0
  35. {pyield-0.32.3 → pyield-0.32.4}/pyield/holidays/__init__.py +0 -0
  36. {pyield-0.32.3 → pyield-0.32.4}/pyield/holidays/br_holidays_new.txt +0 -0
  37. {pyield-0.32.3 → pyield-0.32.4}/pyield/holidays/br_holidays_old.txt +0 -0
  38. {pyield-0.32.3 → pyield-0.32.4}/pyield/holidays/brholidays.py +0 -0
  39. {pyield-0.32.3 → pyield-0.32.4}/pyield/ibge/__init__.py +0 -0
  40. {pyield-0.32.3 → pyield-0.32.4}/pyield/ibge/ipca.py +0 -0
  41. {pyield-0.32.3 → pyield-0.32.4}/pyield/interpolator.py +0 -0
  42. {pyield-0.32.3 → pyield-0.32.4}/pyield/py.typed +0 -0
  43. {pyield-0.32.3 → pyield-0.32.4}/pyield/retry.py +0 -0
  44. {pyield-0.32.3 → pyield-0.32.4}/pyield/tpf/__init__.py +0 -0
  45. {pyield-0.32.3 → pyield-0.32.4}/pyield/tpf/lft.py +0 -0
  46. {pyield-0.32.3 → pyield-0.32.4}/pyield/tpf/ltn.py +0 -0
  47. {pyield-0.32.3 → pyield-0.32.4}/pyield/tpf/ntnb.py +0 -0
  48. {pyield-0.32.3 → pyield-0.32.4}/pyield/tpf/ntnc.py +0 -0
  49. {pyield-0.32.3 → pyield-0.32.4}/pyield/tpf/ntnf.py +0 -0
  50. {pyield-0.32.3 → pyield-0.32.4}/pyield/tpf/tools.py +0 -0
  51. {pyield-0.32.3 → pyield-0.32.4}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PYield
3
- Version: 0.32.3
3
+ Version: 0.32.4
4
4
  Summary: A Python library for analysis of fixed income instruments in Brazil
5
5
  Project-URL: Source, https://github.com/crdcj/PYield
6
6
  Author-email: Carlos Carvalho <cr.cj@outlook.com>
@@ -0,0 +1 @@
1
+ __version__ = "0.32.4"
@@ -1,3 +1,4 @@
1
+ import pandas
1
2
  import pytest
2
3
 
3
4
  import pyield
@@ -6,6 +7,7 @@ import pyield
6
7
  @pytest.fixture(autouse=True)
7
8
  def add_np(doctest_namespace):
8
9
  doctest_namespace["yd"] = pyield
10
+ doctest_namespace["pd"] = pandas
9
11
 
10
12
 
11
13
  def pytest_configure(config):
@@ -0,0 +1,164 @@
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
+ Calcula taxas a termo (forward rates) a partir de taxas zero (spot rates).
11
+
12
+ Utiliza a fórmula:
13
+ f₁→₂ = ((1 + r₂)^(du₂/252) / (1 + r₁)^(du₁/252))^(252/(du₂ - du₁)) - 1
14
+
15
+ Como du/252 = t (tempo em anos úteis), a fórmula pode ser simplificada para:
16
+ f₁→₂ = ((1 + r₂)^t₂ / (1 + r₁)^t₁)^(1/(t₂ - t₁)) - 1
17
+
18
+ Onde:
19
+ - r₁ é a taxa zero para o vértice anterior.
20
+ - r₂ é a taxa zero para o vértice atual.
21
+ - t₁ é o prazo em anos para o vértice anterior (calculado como du₁/252).
22
+ - t₂ é o prazo em anos para o vértice atual (calculado como du₂/252).
23
+ - A constante 252 representa o número de dias úteis no ano.
24
+
25
+ A primeira taxa a termo de cada sequência (ou grupo) é definida como a
26
+ taxa zero desse primeiro vértice (f₁→₂ = r₂), dado que não existe um vértice
27
+ anterior (r₁) para se calcular a taxa a termo do primeiro ponto.
28
+
29
+ A função lida internamente com o alinhamento dos índices das Séries de
30
+ entrada através de `reset_index`. Os cálculos são realizados após ordenar
31
+ os dados pelos prazos (`bdays`) dentro de cada grupo definido por
32
+ `groupby_dates` (ou como um único grupo se `groupby_dates` não for
33
+ fornecido), garantindo a ordem cronológica correta para a fórmula.
34
+
35
+ Valores NaN nas taxas ou prazos de entrada resultarão em NaN na saída,
36
+ exceto para o primeiro ponto de cada grupo, que é tratado separadamente.
37
+
38
+ Args:
39
+ bdays (pd.Series): Número de dias úteis para cada taxa zero.
40
+ rates (pd.Series): Taxas zero correspondentes aos dias úteis.
41
+ groupby_dates (pd.Series | None, optional): Critério de agrupamento
42
+ opcional para segmentar os cálculos (ex: por data de referência).
43
+ Se None, todos os dados são tratados como um único grupo.
44
+ Default None.
45
+
46
+ Returns:
47
+ pd.Series: Série contendo as taxas a termo calculadas (tipo Float64).
48
+ A primeira taxa de cada grupo corresponde à taxa zero inicial.
49
+
50
+ Example:
51
+ >>> bdays = pd.Series([10, 20, 30])
52
+ >>> rates = pd.Series([0.05, 0.06, 0.07])
53
+ >>> yd.forwards(bdays, rates)
54
+ 0 0.05
55
+ 1 0.070095
56
+ 2 0.090284
57
+ dtype: Float64
58
+ """
59
+ # Reset Series indexes to avoid misalignment issues during calculations
60
+ bdays = bdays.reset_index(drop=True).astype("Int64")
61
+ rates = rates.reset_index(drop=True).astype("Float64")
62
+ if groupby_dates is not None:
63
+ groupby_dates = groupby_dates.reset_index(drop=True)
64
+
65
+ # Create a DataFrame to work with the given series
66
+ df = pd.DataFrame({"du2": bdays, "r2": rates})
67
+ df["t2"] = df["du2"] / 252
68
+
69
+ # If no groupby_dates is provided, create a dummy column to group the DataFrame
70
+ if groupby_dates is not None:
71
+ df["groupby_date"] = groupby_dates
72
+ else:
73
+ df["groupby_date"] = 0 # Dummy value to group the DataFrame
74
+
75
+ # Sort by the groupby_dates and t2 columns to ensure proper chronological order
76
+ df.sort_values(by=["groupby_date", "t2"], inplace=True)
77
+
78
+ # Calculate the next zero rate and business day for each group
79
+ df["r1"] = df.groupby("groupby_date")["r2"].shift(1)
80
+ df["t1"] = df.groupby("groupby_date")["t2"].shift(1)
81
+
82
+ # Calculate the formula components
83
+ factor_r2 = (1 + df["r2"]) ** df["t2"] # (1 + r₂)^t₂
84
+ factor_r1 = (1 + df["r1"]) ** df["t1"] # (1 + r₁)^t₁
85
+ time_exp = 1 / (df["t2"] - df["t1"]) # 1/(t₂ - t₁)
86
+
87
+ # f₁→₂ = ((1 + r₂)^t₂ / (1 + r₁)^t₁)^(1/(t₂ - t₁)) - 1
88
+ df["f1_2"] = (factor_r2 / factor_r1) ** time_exp - 1
89
+
90
+ # Identifify the first index of each group of dates
91
+ first_indices = df.groupby("groupby_date").head(1).index
92
+ # Set the first forward rate of each group to the zero rate
93
+ df.loc[first_indices, "f1_2"] = df.loc[first_indices, "r2"]
94
+
95
+ # Return the forward rates as a Series
96
+ f1_2 = df["f1_2"]
97
+ f1_2.name = None
98
+ return f1_2
99
+
100
+
101
+ def forward(
102
+ bday1: int,
103
+ bday2: int,
104
+ rate1: float,
105
+ rate2: float,
106
+ ) -> float:
107
+ """
108
+ Calcula a taxa a termo (forward rate) entre dois prazos (dias úteis).
109
+
110
+ Utiliza a fórmula:
111
+ f₁→₂ = ((1 + r₂)^(du₂/252) / (1 + r₁)^(du₁/252))^(252/(du₂ - du₁)) - 1
112
+
113
+ Onde:
114
+ - r₁ é a taxa zero para o primeiro prazo (du₁).
115
+ - r₂ é a taxa zero para o segundo prazo (du₂).
116
+ - du₁ é o número de dias úteis até a primeira data.
117
+ - du₂ é o número de dias úteis até a segunda data.
118
+ - A constante 252 representa o número de dias úteis no ano.
119
+
120
+ Como du/252 = t (tempo em anos úteis), a fórmula pode ser simplificada para:
121
+ f₁→₂ = ((1 + r₂)^t₂ / (1 + r₁)^t₁)^(1/(t₂ - t₁)) - 1
122
+
123
+ Args:
124
+ bday1 (int): Número de dias úteis do primeiro ponto (prazo menor).
125
+ bday2 (int): Número de dias úteis do segundo ponto (prazo maior).
126
+ rate1 (float): Taxa zero (spot rate) para o prazo `bday1`.
127
+ rate2 (float): Taxa zero (spot rate) para o prazo `bday2`.
128
+
129
+ Returns:
130
+ float: A taxa a termo calculada entre `bday1` e `bday2`. Retorna
131
+ `float('nan')` se `bday2 <= bday1` ou se qualquer um dos
132
+ argumentos de entrada for NaN.
133
+
134
+ Example:
135
+ >>> # Exemplo correto: bday2 > bday1
136
+ >>> yd.forward(10, 20, 0.05, 0.06)
137
+ 0.0700952380952371
138
+ >>> # Exemplo inválido: bday2 <= bday1
139
+ >>> yd.forward(20, 10, 0.06, 0.05)
140
+ nan
141
+ >>> yd.forward(10, 10, 0.05, 0.05)
142
+ nan
143
+ >>> # Exemplo com NaN na entrada
144
+ >>> yd.forward(10, 20, 0.05, pd.NA)
145
+ nan
146
+
147
+ Note:
148
+ É fundamental que `bday2` seja estritamente maior que `bday1` para que
149
+ o cálculo da taxa a termo seja matematicamente válido.
150
+ """
151
+ if pd.isna(rate1) or pd.isna(rate2) or pd.isna(bday1) or pd.isna(bday2):
152
+ # If any of the inputs are NaN, return NaN
153
+ return float("nan")
154
+
155
+ # Handle the case where the two dates are the same
156
+ if bday2 <= bday1:
157
+ return float("nan")
158
+
159
+ # Convert business days to business years
160
+ t1 = bday1 / 252
161
+ t2 = bday2 / 252
162
+
163
+ # f₁→₂ = ((1 + r₂)^t₂ / (1 + r₁)^t₁)^(1/(t₂ - t₁)) - 1
164
+ return ((1 + rate2) ** t2 / (1 + rate1) ** t1) ** (1 / (t2 - t1)) - 1
@@ -1 +0,0 @@
1
- __version__ = "0.32.3"
@@ -1,120 +0,0 @@
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
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