voly 0.0.178__py3-none-any.whl → 0.0.179__py3-none-any.whl

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/client.py CHANGED
@@ -91,9 +91,9 @@ class VolyClient:
91
91
  # -------------------------------------------------------------------------
92
92
 
93
93
  @staticmethod
94
- def svi_raw(k: float, a: float, b: float, m: float, rho: float, sigma: float) -> float:
94
+ def svi(k: float, a: float, b: float, m: float, rho: float, sigma: float) -> float:
95
95
  """Calculate SVI total implied variance using raw parameterization."""
96
- return SVIModel.svi_raw(k, a, b, m, rho, sigma)
96
+ return SVIModel.svi(k, a, b, m, rho, sigma)
97
97
 
98
98
  @staticmethod
99
99
  def d1(s: float, K: float, r: float, o: float, t: float,
voly/core/fit.py CHANGED
@@ -96,8 +96,6 @@ def fit_model(option_chain: pd.DataFrame,
96
96
  mask = ~np.isnan(w) & ~np.isnan(vega) & ~np.isnan(k) & (iv >= 0)
97
97
  k, w, vega, iv = k[mask], w[mask], vega[mask], iv[mask]
98
98
 
99
- logger.info(f"Points after filtering: {len(k)}")
100
-
101
99
  params = [np.nan] * 5
102
100
  loss = np.inf
103
101
  nu = psi = p = c = nu_tilde = np.nan
@@ -119,7 +117,7 @@ def fit_model(option_chain: pd.DataFrame,
119
117
  nu, psi, p, c, nu_tilde = SVIModel.raw_to_jw_params(a_scaled, b_scaled, m, rho, sigma, t)
120
118
 
121
119
  # Compute fit statistics
122
- w_model = np.array([SVIModel.svi_raw(x, a_scaled, b_scaled, m, rho, sigma) for x in k])
120
+ w_model = np.array([SVIModel.svi(x, a_scaled, b_scaled, m, rho, sigma) for x in k])
123
121
  iv_model = np.sqrt(w_model / t)
124
122
  iv_market = iv
125
123
  rmse = np.sqrt(mean_squared_error(iv_market, iv_model))
@@ -133,7 +131,7 @@ def fit_model(option_chain: pd.DataFrame,
133
131
 
134
132
  # Butterfly arbitrage check
135
133
  k_range = np.linspace(min(k), max(k), domain_params[2])
136
- w_k = lambda k: SVIModel.svi_raw(k, a_scaled, b_scaled, m, rho, sigma)
134
+ w_k = lambda k: SVIModel.svi(k, a_scaled, b_scaled, m, rho, sigma)
137
135
  w_prime = lambda k: b_scaled * (rho + (k - m) / np.sqrt((k - m) ** 2 + sigma ** 2))
138
136
  w_double_prime = lambda k: b_scaled * sigma ** 2 / ((k - m) ** 2 + sigma ** 2) ** (3 / 2)
139
137
 
@@ -149,9 +147,6 @@ def fit_model(option_chain: pd.DataFrame,
149
147
  # Log result
150
148
  status = f'{GREEN}SUCCESS{RESET}' if not np.isnan(params[0]) else f'{RED}FAILED{RESET}'
151
149
  logger.info(f'Optimization for {maturity_name}: {status}')
152
- if not np.isnan(params[0]):
153
- logger.info(
154
- f"Maturity {maturity_name}: a={a_scaled:.4f}, b={b_scaled:.4f}, m={m:.4f}, rho={rho:.4f}, sigma={sigma:.4f}")
155
150
  logger.info("=================================================================")
156
151
 
157
152
  results_data['s'].append(float(s))
@@ -219,8 +214,8 @@ def fit_model(option_chain: pd.DataFrame,
219
214
  np.concatenate([k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]), domain_params[2])]))
220
215
 
221
216
  for k_val in k_check:
222
- w1 = SVIModel.svi_raw(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
223
- w2 = SVIModel.svi_raw(k_val, a2 * t2, b2 * t2, m2, rho2, sigma2)
217
+ w1 = SVIModel.svi(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
218
+ w2 = SVIModel.svi(k_val, a2 * t2, b2 * t2, m2, rho2, sigma2)
224
219
  if w2 < w1 - 1e-6:
225
220
  logger.warning(
226
221
  f"Calendar arbitrage violation at t1={t1:.4f}, t2={t2:.4f}, k={k_val:.4f}: w1={w1:.6f}, w2={w2:.6f}")
@@ -272,7 +267,7 @@ def fit_model(option_chain: pd.DataFrame,
272
267
  nu, psi, p, c, nu_tilde = SVIModel.raw_to_jw_params(a_scaled, b_scaled, m, rho, sigma, t2)
273
268
 
274
269
  # Recompute fit statistics
275
- w_model = np.array([SVIModel.svi_raw(x, a_scaled, b_scaled, m, rho, sigma) for x in k])
270
+ w_model = np.array([SVIModel.svi(x, a_scaled, b_scaled, m, rho, sigma) for x in k])
276
271
  iv_model = np.sqrt(w_model / t2)
277
272
  iv_market = iv
278
273
  rmse = np.sqrt(mean_squared_error(iv_market, iv_model))
@@ -287,7 +282,7 @@ def fit_model(option_chain: pd.DataFrame,
287
282
  # Update butterfly arbitrage check
288
283
  butterfly_arbitrage_free = True
289
284
  k_range = np.linspace(min(k), max(k), domain_params[2])
290
- w_k = lambda k: SVIModel.svi_raw(k, a_scaled, b_scaled, m, rho, sigma)
285
+ w_k = lambda k: SVIModel.svi(k, a_scaled, b_scaled, m, rho, sigma)
291
286
  w_prime = lambda k: b_scaled * (rho + (k - m) / np.sqrt((k - m) ** 2 + sigma ** 2))
292
287
  w_double_prime = lambda k: b_scaled * sigma ** 2 / ((k - m) ** 2 + sigma ** 2) ** (3 / 2)
293
288
 
@@ -349,8 +344,8 @@ def fit_model(option_chain: pd.DataFrame,
349
344
  [k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]), domain_params[2])]))
350
345
 
351
346
  for k_val in k_check:
352
- w1 = SVIModel.svi_raw(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
353
- w2 = SVIModel.svi_raw(k_val, a2 * t2, b2 * t2, m2, rho2, sigma2)
347
+ w1 = SVIModel.svi(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
348
+ w2 = SVIModel.svi(k_val, a2 * t2, b2 * t2, m2, rho2, sigma2)
354
349
  if w2 < w1 - 1e-6:
355
350
  logger.warning(
356
351
  f"Calendar arbitrage violation at t1={t1:.4f}, t2={t2:.4f}, k={k_val:.4f}: w1={w1:.6f}, w2={w2:.6f}")
@@ -418,7 +413,7 @@ def get_iv_surface(model_results: pd.DataFrame,
418
413
  t = model_results.loc[i, 't']
419
414
 
420
415
  # Calculate implied volatility
421
- w = np.array([SVIModel.svi_raw(x, *params) for x in LM])
416
+ w = np.array([SVIModel.svi(x, *params) for x in LM])
422
417
  o = np.sqrt(w / t)
423
418
  iv_surface[i] = o
424
419
 
voly/models.py CHANGED
@@ -31,7 +31,7 @@ class SVIModel:
31
31
  }
32
32
 
33
33
  @staticmethod
34
- def svi_raw(k, a, b, m, rho, sigma):
34
+ def svi(k, a, b, m, rho, sigma):
35
35
  assert b >= 0 and abs(rho) <= 1 and sigma >= 0 and a + b * sigma * np.sqrt(1 - rho ** 2) >= 0
36
36
  return a + b * (rho * (k - m) + np.sqrt((k - m) ** 2 + sigma ** 2))
37
37
 
@@ -128,7 +128,7 @@ class SVIModel:
128
128
 
129
129
  def objective(x):
130
130
  a, b, m, rho, sigma = x
131
- w_model = cls.svi_raw(k, a * t, b * t, m, rho, sigma)
131
+ w_model = cls.svi(k, a * t, b * t, m, rho, sigma)
132
132
  from sklearn.metrics import mean_squared_error
133
133
  fit_loss = mean_squared_error(tiv, w_model, sample_weight=vega)
134
134
  param_deviation = sum(((x[i] - x_init) / max(abs(x_init), 1e-6)) ** 2
@@ -137,8 +137,8 @@ class SVIModel:
137
137
 
138
138
  def calendar_constraint(x):
139
139
  a, b, m, rho, sigma = x
140
- w_current = cls.svi_raw(k_constraint, a * t, b * t, m, rho, sigma)
141
- w_prev = cls.svi_raw(k_constraint, a_prev * prev_t, b_prev * prev_t, m_prev, rho_prev, sigma_prev)
140
+ w_current = cls.svi(k_constraint, a * t, b * t, m, rho, sigma)
141
+ w_prev = cls.svi(k_constraint, a_prev * prev_t, b_prev * prev_t, m_prev, rho_prev, sigma_prev)
142
142
  return w_current - w_prev
143
143
 
144
144
  bounds = [
@@ -162,8 +162,8 @@ class SVIModel:
162
162
 
163
163
  if result.success:
164
164
  new_params = result.x
165
- w_current = cls.svi_raw(k_constraint, new_params[0] * t, new_params[1] * t, *new_params[2:])
166
- w_prev = cls.svi_raw(k_constraint, a_prev * prev_t, b_prev * prev_t, m_prev, rho_prev, sigma_prev)
165
+ w_current = cls.svi(k_constraint, new_params[0] * t, new_params[1] * t, *new_params[2:])
166
+ w_prev = cls.svi(k_constraint, a_prev * prev_t, b_prev * prev_t, m_prev, rho_prev, sigma_prev)
167
167
  violation = np.min(w_current - w_prev)
168
168
  print(f"Calendar arbitrage correction {'successful' if violation >= -1e-6 else 'failed'} for t={t:.4f}, "
169
169
  f"min margin={violation:.6f}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: voly
3
- Version: 0.0.178
3
+ Version: 0.0.179
4
4
  Summary: Options & volatility research package
5
5
  Author-email: Manu de Cara <manu.de.cara@gmail.com>
6
6
  License: MIT
@@ -1,20 +1,20 @@
1
1
  voly/__init__.py,sha256=8xyDk7rFCn_MOD5hxuv5cxxKZvBVRiSIM7TgaMPpwpw,211
2
- voly/client.py,sha256=Ge0-aBvKd32aHqMCaA1xgxOS_Z-bi4neYYAGil89A6I,14595
2
+ voly/client.py,sha256=M_-d3ibPp2Uc8ucEkWfhKbqKOQ7xSuUO6dGHTIqmG3E,14587
3
3
  voly/exceptions.py,sha256=PBsbn1vNMvKcCJwwJ4lBO6glD85jo1h2qiEmD7ArAjs,92
4
4
  voly/formulas.py,sha256=JnEs6G0wlfRNH6X_YEJMe2RtLH-ryhzufjsim73Bj3c,11176
5
- voly/models.py,sha256=ydfhdCELDsoFJF9VKq8bnRiO2lRsmC3iQGo9Jx_jjVc,7018
5
+ voly/models.py,sha256=wxqf9T4D2ORO7g3KcwxUL0E78fG69W29xqer3ccoUXo,6994
6
6
  voly/core/__init__.py,sha256=bu6fS2I1Pj9fPPnl-zY3L7NqrZSY5Zy6NY2uMUvdhKs,183
7
7
  voly/core/charts.py,sha256=2S-BfCo30aj1_xlNLqF-za5rQWxF_mWKIdtdOe5bgbw,12735
8
8
  voly/core/data.py,sha256=9v9iuE2XdIIlzoRAB7q1ol7YghBzBsPGAiwZ11oDuis,13650
9
- voly/core/fit.py,sha256=eYTXkoSZIdHYgjW1GQ-qD4Qe3DsZVfuMzmv1Gj_yJfY,18218
9
+ voly/core/fit.py,sha256=RUFawNWRZR9RGLGNtYuJgQmaLmCEkrfVaAimUJruOGY,17937
10
10
  voly/core/hd.py,sha256=UFAyLncNUHivpPAcko6IK1bC55mudVtdlRFfXp63HXE,14771
11
11
  voly/core/interpolate.py,sha256=JkK172-FXyhesW3hY4pEeuJWG3Bugq7QZXbeKoRpLuo,5305
12
12
  voly/core/rnd.py,sha256=GoC3m1Q46Wnk5tV_mstr-3_aktHeue6BBLh4DQTciW0,13307
13
13
  voly/utils/__init__.py,sha256=E05mWatyC-PDOsCxQV1p5Xi1IgpOomxrNURyCx_gB-w,200
14
14
  voly/utils/density.py,sha256=q0fX4im9TGwMCZ32Hzdv8CNh56KnJo8bmG5w0gVWZH8,5879
15
15
  voly/utils/logger.py,sha256=4-_2bVJmq17Q0d7Rd2mPg1AeR8gxv6EPvcmBDMFWcSM,1744
16
- voly-0.0.178.dist-info/licenses/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
17
- voly-0.0.178.dist-info/METADATA,sha256=_NfVcF39Ez-Ytgo5sP1fxpujPIUzhASwcRjmrNCY9S4,4115
18
- voly-0.0.178.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
19
- voly-0.0.178.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
20
- voly-0.0.178.dist-info/RECORD,,
16
+ voly-0.0.179.dist-info/licenses/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
17
+ voly-0.0.179.dist-info/METADATA,sha256=r0MQ4zUUjTh4a6FvIMoO3XsAsen_cAXQJToJ2VQMlT0,4115
18
+ voly-0.0.179.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
19
+ voly-0.0.179.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
20
+ voly-0.0.179.dist-info/RECORD,,
File without changes