voly 0.0.161__tar.gz → 0.0.163__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 (26) hide show
  1. {voly-0.0.161/src/voly.egg-info → voly-0.0.163}/PKG-INFO +1 -1
  2. {voly-0.0.161 → voly-0.0.163}/pyproject.toml +2 -2
  3. {voly-0.0.161 → voly-0.0.163}/src/voly/formulas.py +28 -35
  4. {voly-0.0.161 → voly-0.0.163/src/voly.egg-info}/PKG-INFO +1 -1
  5. {voly-0.0.161 → voly-0.0.163}/LICENSE +0 -0
  6. {voly-0.0.161 → voly-0.0.163}/README.md +0 -0
  7. {voly-0.0.161 → voly-0.0.163}/setup.cfg +0 -0
  8. {voly-0.0.161 → voly-0.0.163}/setup.py +0 -0
  9. {voly-0.0.161 → voly-0.0.163}/src/voly/__init__.py +0 -0
  10. {voly-0.0.161 → voly-0.0.163}/src/voly/client.py +0 -0
  11. {voly-0.0.161 → voly-0.0.163}/src/voly/core/__init__.py +0 -0
  12. {voly-0.0.161 → voly-0.0.163}/src/voly/core/charts.py +0 -0
  13. {voly-0.0.161 → voly-0.0.163}/src/voly/core/data.py +0 -0
  14. {voly-0.0.161 → voly-0.0.163}/src/voly/core/fit.py +0 -0
  15. {voly-0.0.161 → voly-0.0.163}/src/voly/core/hd.py +0 -0
  16. {voly-0.0.161 → voly-0.0.163}/src/voly/core/interpolate.py +0 -0
  17. {voly-0.0.161 → voly-0.0.163}/src/voly/core/rnd.py +0 -0
  18. {voly-0.0.161 → voly-0.0.163}/src/voly/exceptions.py +0 -0
  19. {voly-0.0.161 → voly-0.0.163}/src/voly/models.py +0 -0
  20. {voly-0.0.161 → voly-0.0.163}/src/voly/utils/__init__.py +0 -0
  21. {voly-0.0.161 → voly-0.0.163}/src/voly/utils/density.py +0 -0
  22. {voly-0.0.161 → voly-0.0.163}/src/voly/utils/logger.py +0 -0
  23. {voly-0.0.161 → voly-0.0.163}/src/voly.egg-info/SOURCES.txt +0 -0
  24. {voly-0.0.161 → voly-0.0.163}/src/voly.egg-info/dependency_links.txt +0 -0
  25. {voly-0.0.161 → voly-0.0.163}/src/voly.egg-info/requires.txt +0 -0
  26. {voly-0.0.161 → voly-0.0.163}/src/voly.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voly
3
- Version: 0.0.161
3
+ Version: 0.0.163
4
4
  Summary: Options & volatility research package
5
5
  Author-email: Manu de Cara <manu.de.cara@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "voly"
7
- version = "0.0.161"
7
+ version = "0.0.163"
8
8
  description = "Options & volatility research package"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -60,7 +60,7 @@ line_length = 100
60
60
  multi_line_output = 3
61
61
 
62
62
  [tool.mypy]
63
- python_version = "0.0.161"
63
+ python_version = "0.0.163"
64
64
  warn_return_any = true
65
65
  warn_unused_configs = true
66
66
  disallow_untyped_defs = true
@@ -15,22 +15,43 @@ from typing import Tuple
15
15
  def vectorize_inputs(func):
16
16
  """
17
17
  Decorator to vectorize Black-Scholes functions to handle both scalar and array inputs.
18
+ For invalid inputs (K <= 0, o <= 0, or t <= 0), returns np.nan instead of trying to compute.
18
19
  """
20
+
19
21
  def wrapper(s, K, r, o, t, option_type='call'):
20
22
  # Check if inputs are scalar
21
23
  K_scalar = np.isscalar(K)
22
24
  o_scalar = np.isscalar(o)
23
-
24
- # If both inputs are scalar, use the original function directly
25
- if K_scalar and o_scalar:
25
+ t_scalar = np.isscalar(t)
26
+
27
+ # Convert pandas Series to numpy arrays if needed
28
+ if isinstance(K, pd.Series):
29
+ K = K.values
30
+ if isinstance(o, pd.Series):
31
+ o = o.values
32
+ if isinstance(t, pd.Series):
33
+ t = t.values
34
+
35
+ # If all inputs are scalar, use the original function directly
36
+ if K_scalar and o_scalar and t_scalar:
26
37
  return func(s, K, r, o, t, option_type)
27
38
 
28
- # Use NumPy's vectorize to handle array inputs
29
- vectorized_func = np.vectorize(lambda K_val, o_val:
30
- func(s, K_val, r, o_val, t, option_type))
39
+ # For arrays, we need to apply the function element-wise
40
+ # Instead of using np.vectorize directly, we'll create a custom vectorized function
41
+ # that handles the conditions properly
42
+ def safe_vectorized_func(K_val, o_val, t_val):
43
+ # Check for invalid strike price, volatility, or time values
44
+ if K_val <= 0 or o_val <= 0 or t_val <= 0:
45
+ return np.nan # Return NaN for invalid inputs
46
+ else:
47
+ # Only call the function if inputs are valid
48
+ return func(s, K_val, r, o_val, t_val, option_type)
49
+
50
+ # Now use numpy's vectorize on our safe function
51
+ vectorized_func = np.vectorize(safe_vectorized_func)
31
52
 
32
53
  # Call the vectorized function with the inputs
33
- return vectorized_func(K, o)
54
+ return vectorized_func(K, o, t)
34
55
 
35
56
  return wrapper
36
57
 
@@ -39,8 +60,6 @@ def vectorize_inputs(func):
39
60
  @vectorize_inputs
40
61
  def d1(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
41
62
  # option_type is ignored in this function but included for compatibility
42
- if o <= 0 or t <= 0:
43
- return np.nan
44
63
  return (np.log(s / K) + (r + o ** 2 / 2) * t) / (o * np.sqrt(t))
45
64
 
46
65
 
@@ -48,8 +67,6 @@ def d1(s: float, K: float, r: float, o: float, t: float, option_type: str = 'cal
48
67
  @vectorize_inputs
49
68
  def d2(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
50
69
  # option_type is ignored in this function but included for compatibility
51
- if o <= 0 or t <= 0:
52
- return np.nan
53
70
  return d1(s, K, r, o, t, option_type) - o * np.sqrt(t)
54
71
 
55
72
 
@@ -93,9 +110,6 @@ def delta(s: float, K: float, r: float, o: float, t: float, option_type: str = '
93
110
  @catch_exception
94
111
  @vectorize_inputs
95
112
  def gamma(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
96
- if o <= 0 or t <= 0:
97
- return 0.0
98
-
99
113
  d1_val = d1(s, K, r, o, t, option_type)
100
114
  return norm.pdf(d1_val) / (s * o * np.sqrt(t))
101
115
 
@@ -103,9 +117,6 @@ def gamma(s: float, K: float, r: float, o: float, t: float, option_type: str = '
103
117
  @catch_exception
104
118
  @vectorize_inputs
105
119
  def vega(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
106
- if o <= 0 or t <= 0:
107
- return 0.0
108
-
109
120
  d1_val = d1(s, K, r, o, t, option_type)
110
121
  return s * norm.pdf(d1_val) * np.sqrt(t) / 100 # Divided by 100 for 1% change
111
122
 
@@ -113,9 +124,6 @@ def vega(s: float, K: float, r: float, o: float, t: float, option_type: str = 'c
113
124
  @catch_exception
114
125
  @vectorize_inputs
115
126
  def theta(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
116
- if o <= 0 or t <= 0:
117
- return 0.0
118
-
119
127
  d1_val = d1(s, K, r, o, t, option_type)
120
128
  d2_val = d2(s, K, r, o, t, option_type)
121
129
 
@@ -135,9 +143,6 @@ def theta(s: float, K: float, r: float, o: float, t: float, option_type: str = '
135
143
  @catch_exception
136
144
  @vectorize_inputs
137
145
  def rho(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
138
- if o <= 0 or t <= 0:
139
- return 0.0
140
-
141
146
  d2_val = d2(s, K, r, o, t, option_type)
142
147
 
143
148
  if option_type.lower() in ["call", "c"]:
@@ -149,9 +154,6 @@ def rho(s: float, K: float, r: float, o: float, t: float, option_type: str = 'ca
149
154
  @catch_exception
150
155
  @vectorize_inputs
151
156
  def vanna(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
152
- if o <= 0 or t <= 0:
153
- return 0.0
154
-
155
157
  d1_val = d1(s, K, r, o, t, option_type)
156
158
  d2_val = d2(s, K, r, o, t, option_type)
157
159
 
@@ -161,9 +163,6 @@ def vanna(s: float, K: float, r: float, o: float, t: float, option_type: str = '
161
163
  @catch_exception
162
164
  @vectorize_inputs
163
165
  def volga(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
164
- if o <= 0 or t <= 0:
165
- return 0.0
166
-
167
166
  d1_val = d1(s, K, r, o, t, option_type)
168
167
  d2_val = d2(s, K, r, o, t, option_type)
169
168
 
@@ -173,9 +172,6 @@ def volga(s: float, K: float, r: float, o: float, t: float, option_type: str = '
173
172
  @catch_exception
174
173
  @vectorize_inputs
175
174
  def charm(s: float, K: float, r: float, o: float, t: float, option_type: str = 'call') -> float:
176
- if o <= 0 or t <= 0:
177
- return 0.0
178
-
179
175
  d1_val = d1(s, K, r, o, t, option_type)
180
176
  d2_val = d2(s, K, r, o, t, option_type)
181
177
 
@@ -227,9 +223,6 @@ def iv(option_price: float, s: float, K: float, r: float, t: float,
227
223
  Returns:
228
224
  - Implied volatility
229
225
  """
230
- if t <= 0:
231
- return np.nan
232
-
233
226
  # Check if option price is within theoretical bounds
234
227
  if option_type.lower() in ["call", "c"]:
235
228
  intrinsic = max(0, s - K * np.exp(-r * t))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voly
3
- Version: 0.0.161
3
+ Version: 0.0.163
4
4
  Summary: Options & volatility research package
5
5
  Author-email: Manu de Cara <manu.de.cara@gmail.com>
6
6
  License: MIT
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