voly 0.0.7__tar.gz → 0.0.9__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.
- {voly-0.0.7/src/voly.egg-info → voly-0.0.9}/PKG-INFO +1 -1
- {voly-0.0.7 → voly-0.0.9}/pyproject.toml +2 -6
- {voly-0.0.7 → voly-0.0.9}/src/voly/client.py +1 -1
- {voly-0.0.7 → voly-0.0.9/src/voly.egg-info}/PKG-INFO +1 -1
- voly-0.0.9/tests/test_client.py +91 -0
- voly-0.0.7/tests/test_client.py +0 -52
- {voly-0.0.7 → voly-0.0.9}/LICENSE +0 -0
- {voly-0.0.7 → voly-0.0.9}/README.md +0 -0
- {voly-0.0.7 → voly-0.0.9}/setup.cfg +0 -0
- {voly-0.0.7 → voly-0.0.9}/setup.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/__init__.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/core/__init__.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/core/charts.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/core/data.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/core/fit.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/core/interpolate.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/core/rnd.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/exceptions.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/formulas.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/models.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/utils/__init__.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly/utils/logger.py +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly.egg-info/SOURCES.txt +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly.egg-info/dependency_links.txt +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly.egg-info/requires.txt +0 -0
- {voly-0.0.7 → voly-0.0.9}/src/voly.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "voly"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.9"
|
|
8
8
|
description = "Options & volatility research package"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -61,12 +61,8 @@ line_length = 100
|
|
|
61
61
|
multi_line_output = 3
|
|
62
62
|
|
|
63
63
|
[tool.mypy]
|
|
64
|
-
python_version = "0.0.
|
|
64
|
+
python_version = "0.0.9"
|
|
65
65
|
warn_return_any = true
|
|
66
66
|
warn_unused_configs = true
|
|
67
67
|
disallow_untyped_defs = true
|
|
68
68
|
disallow_incomplete_defs = true
|
|
69
|
-
|
|
70
|
-
[tool.pytest.ini_options]
|
|
71
|
-
testpaths = ["tests"]
|
|
72
|
-
python_files = "test_*.py"
|
|
@@ -286,7 +286,7 @@ class VolyClient:
|
|
|
286
286
|
Returns:
|
|
287
287
|
- Implied volatility
|
|
288
288
|
"""
|
|
289
|
-
return iv(option_price, s, k, r,
|
|
289
|
+
return iv(option_price, s, k, r, t, option_type)
|
|
290
290
|
|
|
291
291
|
# -------------------------------------------------------------------------
|
|
292
292
|
# Model Fitting
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for the VolyClient class using Python's built-in unittest framework.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
import numpy as np
|
|
7
|
+
from voly import VolyClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestVolyClient(unittest.TestCase):
|
|
11
|
+
"""Test cases for the VolyClient class."""
|
|
12
|
+
|
|
13
|
+
def setUp(self):
|
|
14
|
+
"""Set up test fixtures."""
|
|
15
|
+
self.voly = VolyClient()
|
|
16
|
+
|
|
17
|
+
def test_voly_initialization(self):
|
|
18
|
+
"""Test that the voly initializes correctly."""
|
|
19
|
+
self.assertIsNotNone(self.voly)
|
|
20
|
+
|
|
21
|
+
def test_bs_pricing(self):
|
|
22
|
+
"""Test Black-Scholes pricing function."""
|
|
23
|
+
# Test call price
|
|
24
|
+
call_price = self.voly.bs(s=100, k=100, r=0.05, vol=0.2, t=1, option_type='call')
|
|
25
|
+
self.assertGreater(call_price, 0)
|
|
26
|
+
self.assertLess(call_price, 20) # Sanity check
|
|
27
|
+
|
|
28
|
+
# Test put price
|
|
29
|
+
put_price = self.voly.bs(s=100, k=100, r=0.05, vol=0.2, t=1, option_type='put')
|
|
30
|
+
self.assertGreater(put_price, 0)
|
|
31
|
+
self.assertLess(put_price, 20) # Sanity check
|
|
32
|
+
|
|
33
|
+
# Test put-call parity (approximately)
|
|
34
|
+
parity_diff = abs(call_price - put_price - 100 + 100 * np.exp(-0.05))
|
|
35
|
+
self.assertLess(parity_diff, 1e-10)
|
|
36
|
+
|
|
37
|
+
def test_greeks_calculation(self):
|
|
38
|
+
"""Test that all Greeks are calculated correctly."""
|
|
39
|
+
# Calculate all Greeks
|
|
40
|
+
greeks = self.voly.greeks(s=100, k=100, r=0.05, vol=0.2, t=1, option_type='call')
|
|
41
|
+
|
|
42
|
+
# Check that all expected Greeks are present
|
|
43
|
+
expected_keys = ['price', 'delta', 'gamma', 'vega', 'theta', 'rho', 'vanna', 'volga', 'charm']
|
|
44
|
+
for key in expected_keys:
|
|
45
|
+
self.assertIn(key, greeks)
|
|
46
|
+
self.assertIsInstance(greeks[key], float)
|
|
47
|
+
|
|
48
|
+
# Basic sanity checks
|
|
49
|
+
self.assertGreater(greeks['delta'], 0) # Call delta positive
|
|
50
|
+
self.assertLess(greeks['delta'], 1) # Call delta less than 1
|
|
51
|
+
self.assertGreater(greeks['gamma'], 0) # Gamma always positive
|
|
52
|
+
self.assertGreater(greeks['vega'], 0) # Vega always positive
|
|
53
|
+
self.assertLess(greeks['theta'], 0) # Call theta typically negative
|
|
54
|
+
|
|
55
|
+
def test_delta_values(self):
|
|
56
|
+
"""Test delta values for different moneyness levels."""
|
|
57
|
+
# Deep ITM call should have delta close to 1
|
|
58
|
+
itm_delta = self.voly.delta(s=100, k=50, r=0.05, vol=0.2, t=1, option_type='call')
|
|
59
|
+
self.assertGreater(itm_delta, 0.95)
|
|
60
|
+
|
|
61
|
+
# Deep OTM call should have delta close to 0
|
|
62
|
+
otm_delta = self.voly.delta(s=100, k=200, r=0.05, vol=0.2, t=1, option_type='call')
|
|
63
|
+
self.assertLess(otm_delta, 0.05)
|
|
64
|
+
|
|
65
|
+
# Deep ITM put should have delta close to -1
|
|
66
|
+
itm_put_delta = self.voly.delta(s=100, k=200, r=0.05, vol=0.2, t=1, option_type='put')
|
|
67
|
+
self.assertLess(itm_put_delta, -0.95)
|
|
68
|
+
|
|
69
|
+
# Deep OTM put should have delta close to 0
|
|
70
|
+
otm_put_delta = self.voly.delta(s=100, k=50, r=0.05, vol=0.2, t=1, option_type='put')
|
|
71
|
+
self.assertGreater(otm_put_delta, -0.05)
|
|
72
|
+
|
|
73
|
+
def test_implied_volatility(self):
|
|
74
|
+
"""Test implied volatility calculation."""
|
|
75
|
+
# Calculate option price with known volatility
|
|
76
|
+
vol = 0.2
|
|
77
|
+
s = 100
|
|
78
|
+
k = 100
|
|
79
|
+
r = 0.05
|
|
80
|
+
t = 1
|
|
81
|
+
option_price = self.voly.bs(s=s, k=k, r=r, vol=vol, t=t, option_type='call')
|
|
82
|
+
|
|
83
|
+
# Calculate implied volatility from the price
|
|
84
|
+
implied_vol = self.voly.iv(option_price=option_price, s=s, k=k, r=r, t=t, option_type='call')
|
|
85
|
+
|
|
86
|
+
# Verify that the implied volatility is close to the original volatility
|
|
87
|
+
self.assertAlmostEqual(vol, implied_vol, places=4)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
if __name__ == '__main__':
|
|
91
|
+
unittest.main()
|
voly-0.0.7/tests/test_client.py
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for the VolyClient class.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import pytest
|
|
6
|
-
import numpy as np
|
|
7
|
-
from voly import VolyClient
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def test_client_initialization():
|
|
11
|
-
"""Test that the client initializes correctly."""
|
|
12
|
-
client = VolyClient()
|
|
13
|
-
assert client is not None
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def test_bs_pricing():
|
|
17
|
-
"""Test Black-Scholes pricing function."""
|
|
18
|
-
client = VolyClient()
|
|
19
|
-
|
|
20
|
-
# Test call price
|
|
21
|
-
call_price = client.bs(s=100, k=100, r=0.05, vol=0.2, t=1, option_type='call')
|
|
22
|
-
assert call_price > 0
|
|
23
|
-
assert call_price < 20 # Sanity check
|
|
24
|
-
|
|
25
|
-
# Test put price
|
|
26
|
-
put_price = client.bs(s=100, k=100, r=0.05, vol=0.2, t=1, option_type='put')
|
|
27
|
-
assert put_price > 0
|
|
28
|
-
assert put_price < 20 # Sanity check
|
|
29
|
-
|
|
30
|
-
# Test put-call parity (approximately)
|
|
31
|
-
parity_diff = abs(call_price - put_price - 100 + 100 * np.exp(-0.05))
|
|
32
|
-
assert parity_diff < 1e-10
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def test_greeks_calculation():
|
|
36
|
-
"""Test that all Greeks are calculated correctly."""
|
|
37
|
-
client = VolyClient()
|
|
38
|
-
|
|
39
|
-
# Calculate all Greeks
|
|
40
|
-
greeks = client.greeks(s=100, k=100, r=0.05, vol=0.2, t=1, option_type='call')
|
|
41
|
-
|
|
42
|
-
# Check that all expected Greeks are present
|
|
43
|
-
expected_keys = ['price', 'delta', 'gamma', 'vega', 'theta', 'rho', 'vanna', 'volga', 'charm']
|
|
44
|
-
for key in expected_keys:
|
|
45
|
-
assert key in greeks
|
|
46
|
-
assert isinstance(greeks[key], float)
|
|
47
|
-
|
|
48
|
-
# Basic sanity checks
|
|
49
|
-
assert 0 < greeks['delta'] < 1 # Call delta between 0 and 1
|
|
50
|
-
assert greeks['gamma'] > 0 # Gamma always positive
|
|
51
|
-
assert greeks['vega'] > 0 # Vega always positive
|
|
52
|
-
assert greeks['theta'] < 0 # Call theta typically negative
|
|
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
|