voly 0.0.87__tar.gz → 0.0.90__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: voly
3
- Version: 0.0.87
3
+ Version: 0.0.90
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.87"
7
+ version = "0.0.90"
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.87"
63
+ python_version = "0.0.90"
64
64
  warn_return_any = true
65
65
  warn_unused_configs = true
66
66
  disallow_untyped_defs = true
@@ -19,12 +19,11 @@ from voly.formulas import (
19
19
  )
20
20
  from voly.core.data import fetch_option_chain, process_option_chain
21
21
  from voly.core.fit import fit_model, get_iv_surface
22
- from voly.core.rnd import get_rnd_surface, calculate_pdf, calculate_cdf, calculate_strike_probability
22
+ from voly.core.rnd import get_rnd_surface
23
23
  from voly.core.interpolate import interpolate_model
24
24
  from voly.core.charts import (
25
25
  plot_all_smiles, plot_raw_parameters, plot_jw_parameters, plot_fit_performance, plot_3d_surface,
26
- plot_fit_performance, plot_rnd, plot_pdf, plot_cdf, plot_rnd_all_expiries,
27
- plot_rnd_3d, plot_rnd_statistics, plot_interpolated_surface
26
+ plot_fit_performance
28
27
  )
29
28
 
30
29
 
@@ -11,7 +11,7 @@ from typing import List, Tuple, Dict, Optional, Union, Any
11
11
  from scipy.optimize import least_squares
12
12
  from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
13
13
  from voly.utils.logger import logger, catch_exception
14
- from voly.formulas import get_x_domain
14
+ from voly.formulas import get_domain
15
15
  from voly.exceptions import VolyError
16
16
  from voly.models import SVIModel
17
17
  import warnings
@@ -9,7 +9,7 @@ from typing import Dict, List, Tuple, Optional, Union, Any
9
9
  from voly.utils.logger import logger, catch_exception
10
10
  from voly.exceptions import VolyError
11
11
  from voly.models import SVIModel
12
- from voly.formulas import get_all_domains
12
+ from voly.formulas import get_domain
13
13
 
14
14
 
15
15
  # Breeden-Litzenberger Method
@@ -5,10 +5,6 @@ Volatility models for the Voly package.
5
5
  import numpy as np
6
6
  from typing import Tuple, Dict, List, Optional, Union
7
7
 
8
- # Configuration settings
9
- DEFAULT_MONEYNESS_RANGE = (-2, 2)
10
- DEFAULT_MONEYNESS_POINTS = 500
11
-
12
8
  class SVIModel:
13
9
  """
14
10
  Stochastic Volatility Inspired (SVI) model.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: voly
3
- Version: 0.0.87
3
+ Version: 0.0.90
4
4
  Summary: Options & volatility research package
5
5
  Author-email: Manu de Cara <manu.de.cara@gmail.com>
6
6
  License: MIT
@@ -19,5 +19,4 @@ src/voly/core/fit.py
19
19
  src/voly/core/interpolate.py
20
20
  src/voly/core/rnd.py
21
21
  src/voly/utils/__init__.py
22
- src/voly/utils/logger.py
23
- tests/test_client.py
22
+ src/voly/utils/logger.py
@@ -1,244 +0,0 @@
1
- """
2
- Comprehensive tests for the VolyClient class with detailed output.
3
- This file demonstrates expected values and provides informative output.
4
- """
5
-
6
- import unittest
7
- import numpy as np
8
- from voly import VolyClient
9
- import sys
10
-
11
-
12
- class VolyClientTestCase(unittest.TestCase):
13
- """
14
- Test cases for the VolyClient class with expected values and detailed output.
15
- """
16
-
17
- def setUp(self):
18
- """Set up test fixtures."""
19
- self.voly = VolyClient()
20
- # Add a divider line before each test for clearer output
21
- print("\n" + "=" * 80)
22
-
23
- def test_bs_pricing_with_expected_values(self):
24
- """Test Black-Scholes pricing with expected values."""
25
- print("\nTEST: Black-Scholes Pricing")
26
-
27
- # Test parameters
28
- s = 100.0
29
- k = 100.0
30
- r = 0.05
31
- vol = 0.2
32
- t = 1.0
33
-
34
- # Expected values (pre-calculated)
35
- expected_call = 10.45
36
- expected_put = 5.57
37
-
38
- # Calculate actual values
39
- actual_call = self.voly.bs(s=s, k=k, r=r, vol=vol, t=t, option_type='call')
40
- actual_put = self.voly.bs(s=s, k=k, r=r, vol=vol, t=t, option_type='put')
41
-
42
- # Print actual vs expected
43
- print(f"Parameters: S={s}, K={k}, r={r}, vol={vol}, t={t}")
44
- print(
45
- f"Call Price: Actual={actual_call:.4f}, Expected={expected_call:.4f}, Diff={abs(actual_call - expected_call):.6f}")
46
- print(
47
- f"Put Price: Actual={actual_put:.4f}, Expected={expected_put:.4f}, Diff={abs(actual_put - expected_put):.6f}")
48
-
49
- # Check put-call parity
50
- pcp_diff = actual_call - actual_put - s + k * np.exp(-r * t)
51
- print(f"Put-Call Parity Check: {pcp_diff:.8f} (should be close to 0)")
52
-
53
- # Assertions with tolerance
54
- self.assertAlmostEqual(actual_call, expected_call, delta=0.01,
55
- msg=f"Call price {actual_call:.4f} doesn't match expected {expected_call:.4f}")
56
- self.assertAlmostEqual(actual_put, expected_put, delta=0.01,
57
- msg=f"Put price {actual_put:.4f} doesn't match expected {expected_put:.4f}")
58
- self.assertAlmostEqual(pcp_diff, 0, delta=1e-10,
59
- msg="Put-call parity violated")
60
-
61
- def test_delta_values_across_moneyness(self):
62
- """Test delta values across different moneyness levels."""
63
- print("\nTEST: Delta Values Across Moneyness")
64
-
65
- # Test parameters
66
- s = 100.0
67
- r = 0.05
68
- vol = 0.2
69
- t = 1.0
70
-
71
- # Define test cases: strike, expected call delta, expected put delta
72
- test_cases = [
73
- (50.0, 0.9999, -0.0001), # Deep ITM call / Deep OTM put
74
- (75.0, 0.9631, -0.0369), # ITM call / OTM put
75
- (100.0, 0.6368, -0.3632), # ATM
76
- (125.0, 0.2219, -0.7781), # OTM call / ITM put
77
- (150.0, 0.0467, -0.9533) # Deep OTM call / Deep ITM put
78
- ]
79
-
80
- print(f"Parameters: S={s}, r={r}, vol={vol}, t={t}")
81
- print("\nDelta Values:")
82
- print(f"{'Strike':<10} {'Call Delta':<15} {'Expected':<15} {'Put Delta':<15} {'Expected':<15}")
83
- print("-" * 70)
84
-
85
- for strike, exp_call_delta, exp_put_delta in test_cases:
86
- call_delta = self.voly.delta(s=s, k=strike, r=r, vol=vol, t=t, option_type='call')
87
- put_delta = self.voly.delta(s=s, k=strike, r=r, vol=vol, t=t, option_type='put')
88
-
89
- print(f"{strike:<10.1f} {call_delta:<15.4f} {exp_call_delta:<15.4f} "
90
- f"{put_delta:<15.4f} {exp_put_delta:<15.4f}")
91
-
92
- # Check deltas are within expected range
93
- self.assertAlmostEqual(call_delta, exp_call_delta, delta=0.01,
94
- msg=f"Call delta for K={strike} incorrect")
95
- self.assertAlmostEqual(put_delta, exp_put_delta, delta=0.01,
96
- msg=f"Put delta for K={strike} incorrect")
97
-
98
- # Check put-call delta relationship: call_delta - put_delta = 1
99
- self.assertAlmostEqual(call_delta - put_delta, 1.0, delta=1e-10,
100
- msg="Delta relationship violated")
101
-
102
- def test_all_greeks_values(self):
103
- """Test all Greeks calculation with expected values."""
104
- print("\nTEST: All Greeks Values")
105
-
106
- # Test parameters
107
- s = 100.0
108
- k = 100.0
109
- r = 0.05
110
- vol = 0.2
111
- t = 1.0
112
-
113
- # Calculate all Greeks for a call
114
- call_greeks = self.voly.greeks(s=s, k=k, r=r, vol=vol, t=t, option_type='call')
115
-
116
- # Expected values (calculated using standard Black-Scholes formulas)
117
- expected_greeks = {
118
- 'price': 10.45,
119
- 'delta': 0.637,
120
- 'gamma': 0.019,
121
- 'vega': 0.375,
122
- 'theta': -0.018,
123
- 'rho': 0.52,
124
- }
125
-
126
- print(f"Parameters: S={s}, K={k}, r={r}, vol={vol}, t={t}")
127
- print("\nCall Option Greeks:")
128
- print(f"{'Greek':<10} {'Actual':<15} {'Expected':<15} {'Diff':<15}")
129
- print("-" * 55)
130
-
131
- for greek, expected in expected_greeks.items():
132
- actual = call_greeks[greek]
133
- print(f"{greek.capitalize():<10} {actual:<15.6f} {expected:<15.6f} {abs(actual - expected):<15.6f}")
134
-
135
- # Assert with appropriate tolerance
136
- self.assertAlmostEqual(actual, expected, delta=max(0.01, expected * 0.05),
137
- msg=f"{greek.capitalize()} value incorrect")
138
-
139
- # Additional checks for other Greeks
140
- print("\nAdditional Greeks:")
141
- for greek in ['vanna', 'volga', 'charm']:
142
- if greek in call_greeks:
143
- print(f"{greek.capitalize():<10} {call_greeks[greek]:<15.6f}")
144
-
145
- # Check basic relationships
146
- # Gamma should be positive for both calls and puts
147
- self.assertGreater(call_greeks['gamma'], 0, "Gamma should be positive")
148
-
149
- # Vega should be positive for both calls and puts
150
- self.assertGreater(call_greeks['vega'], 0, "Vega should be positive")
151
-
152
- # Theta is typically negative for calls and puts (time decay)
153
- self.assertLess(call_greeks['theta'], 0, "Theta should be negative for calls")
154
-
155
- def test_implied_volatility_calculation(self):
156
- """Test implied volatility calculation with known prices."""
157
- print("\nTEST: Implied Volatility Calculation")
158
-
159
- # Define test cases
160
- test_cases = [
161
- # S, K, r, vol, t
162
- (100.0, 100.0, 0.05, 0.2, 1.0), # ATM
163
- (100.0, 90.0, 0.05, 0.25, 0.5), # ITM
164
- (100.0, 110.0, 0.05, 0.3, 0.25) # OTM
165
- ]
166
-
167
- print(f"{'S':<8} {'K':<8} {'r':<8} {'t':<8} {'Input Vol':<12} {'Option Price':<15} "
168
- f"{'Implied Vol':<15} {'Diff':<10}")
169
- print("-" * 90)
170
-
171
- for s, k, r, vol, t in test_cases:
172
- # Calculate option price with known volatility
173
- call_price = self.voly.bs(s=s, k=k, r=r, vol=vol, t=t, option_type='call')
174
-
175
- # Calculate implied volatility from the price
176
- try:
177
- implied_vol = self.voly.iv(option_price=call_price, s=s, k=k, r=r, t=t, option_type='call')
178
- vol_diff = abs(vol - implied_vol)
179
- print(f"{s:<8.1f} {k:<8.1f} {r:<8.3f} {t:<8.2f} {vol:<12.4f} {call_price:<15.6f} "
180
- f"{implied_vol:<15.6f} {vol_diff:<10.6f}")
181
-
182
- # Assert implied vol matches input vol
183
- self.assertAlmostEqual(vol, implied_vol, delta=0.0001,
184
- msg=f"Implied volatility {implied_vol:.6f} doesn't match input {vol:.6f}")
185
- except Exception as e:
186
- print(f"{s:<8.1f} {k:<8.1f} {r:<8.3f} {t:<8.2f} {vol:<12.4f} {call_price:<15.6f} "
187
- f"ERROR: {str(e)}")
188
- self.fail(f"Implied volatility calculation failed: {str(e)}")
189
-
190
- def test_bs_pricing_extreme_cases(self):
191
- """Test Black-Scholes pricing under extreme conditions."""
192
- print("\nTEST: Black-Scholes Pricing - Extreme Cases")
193
-
194
- # Test zero volatility
195
- zero_vol_call = self.voly.bs(s=100, k=90, r=0.05, vol=0, t=1, option_type='call')
196
- zero_vol_put = self.voly.bs(s=100, k=110, r=0.05, vol=0, t=1, option_type='put')
197
-
198
- print("Zero Volatility:")
199
- print(f"Call (S=100, K=90): {zero_vol_call:.4f} (should equal intrinsic value 10)")
200
- print(f"Put (S=100, K=110): {zero_vol_put:.4f} (should equal intrinsic value 10)")
201
-
202
- self.assertAlmostEqual(zero_vol_call, 10.0, delta=0.01,
203
- msg="Zero vol ITM call should equal intrinsic value")
204
- self.assertAlmostEqual(zero_vol_put, 10.0, delta=0.01,
205
- msg="Zero vol ITM put should equal intrinsic value")
206
-
207
- # Test zero time to expiry
208
- zero_time_call = self.voly.bs(s=100, k=90, r=0.05, vol=0.2, t=0, option_type='call')
209
- zero_time_put = self.voly.bs(s=100, k=110, r=0.05, vol=0.2, t=0, option_type='put')
210
-
211
- print("\nZero Time to Expiry:")
212
- print(f"Call (S=100, K=90): {zero_time_call:.4f} (should equal intrinsic value 10)")
213
- print(f"Put (S=100, K=110): {zero_time_put:.4f} (should equal intrinsic value 10)")
214
-
215
- self.assertAlmostEqual(zero_time_call, 10.0, delta=0.01,
216
- msg="Zero time ITM call should equal intrinsic value")
217
- self.assertAlmostEqual(zero_time_put, 10.0, delta=0.01,
218
- msg="Zero time ITM put should equal intrinsic value")
219
-
220
- # Test deep ITM and OTM
221
- deep_itm_call = self.voly.bs(s=100, k=50, r=0.05, vol=0.2, t=1, option_type='call')
222
- deep_otm_call = self.voly.bs(s=100, k=200, r=0.05, vol=0.2, t=1, option_type='call')
223
-
224
- print("\nDeep ITM/OTM:")
225
- print(f"Deep ITM Call (S=100, K=50): {deep_itm_call:.4f}")
226
- print(f"Deep OTM Call (S=100, K=200): {deep_otm_call:.4f}")
227
-
228
- self.assertGreater(deep_itm_call, 50.0,
229
- msg="Deep ITM call should be greater than intrinsic value")
230
- self.assertGreater(deep_otm_call, 0.0,
231
- msg="Deep OTM call should have positive value")
232
- self.assertLess(deep_otm_call, 5.0,
233
- msg="Deep OTM call should have small value")
234
-
235
-
236
- if __name__ == '__main__':
237
- # More detailed output
238
- print("\nVOLY CLIENT DETAILED TEST SUITE")
239
- print("=" * 80)
240
- print(f"Testing against expected values for options pricing and Greeks")
241
- print("-" * 80)
242
-
243
- # Run tests with more verbose output
244
- unittest.main(verbosity=2)
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