voly 0.0.9__py3-none-any.whl → 0.0.11__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 +4 -4
- voly/core/data.py +0 -25
- voly/utils/logger.py +0 -4
- {voly-0.0.9.dist-info → voly-0.0.11.dist-info}/METADATA +1 -2
- {voly-0.0.9.dist-info → voly-0.0.11.dist-info}/RECORD +8 -8
- {voly-0.0.9.dist-info → voly-0.0.11.dist-info}/LICENSE +0 -0
- {voly-0.0.9.dist-info → voly-0.0.11.dist-info}/WHEEL +0 -0
- {voly-0.0.9.dist-info → voly-0.0.11.dist-info}/top_level.txt +0 -0
voly/client.py
CHANGED
|
@@ -294,7 +294,7 @@ class VolyClient:
|
|
|
294
294
|
|
|
295
295
|
@staticmethod
|
|
296
296
|
def fit_model(market_data: pd.DataFrame,
|
|
297
|
-
|
|
297
|
+
model_name: str = 'svi',
|
|
298
298
|
moneyness_range: Tuple[float, float] = (-2, 2),
|
|
299
299
|
num_points: int = 500,
|
|
300
300
|
plot: bool = False) -> Dict[str, Any]:
|
|
@@ -303,7 +303,7 @@ class VolyClient:
|
|
|
303
303
|
|
|
304
304
|
Parameters:
|
|
305
305
|
- market_data: DataFrame with market data
|
|
306
|
-
-
|
|
306
|
+
- model_name: Name of model to fit (default: 'svi')
|
|
307
307
|
- moneyness_range: (min, max) range for moneyness grid
|
|
308
308
|
- num_points: Number of points for moneyness grid
|
|
309
309
|
- plot: Whether to generate and return plots
|
|
@@ -311,12 +311,12 @@ class VolyClient:
|
|
|
311
311
|
Returns:
|
|
312
312
|
- Dictionary with fitting results and optional plots
|
|
313
313
|
"""
|
|
314
|
-
logger.info(f"Fitting {
|
|
314
|
+
logger.info(f"Fitting {model_name.upper()} model to market data")
|
|
315
315
|
|
|
316
316
|
# Fit the model
|
|
317
317
|
fit_results = fit_model(
|
|
318
318
|
market_data=market_data,
|
|
319
|
-
|
|
319
|
+
model_name=model_name,
|
|
320
320
|
moneyness_range=moneyness_range,
|
|
321
321
|
num_points=num_points
|
|
322
322
|
)
|
voly/core/data.py
CHANGED
|
@@ -45,8 +45,6 @@ async def unsubscribe_channels(ws, channels):
|
|
|
45
45
|
@catch_exception
|
|
46
46
|
async def process_batch(ws, batch: List[str], batch_num: int, total_batches: int) -> List[Dict[str, Any]]:
|
|
47
47
|
"""Process a batch of instruments and return their data"""
|
|
48
|
-
batch_start = time.time()
|
|
49
|
-
|
|
50
48
|
# Create channel subscriptions
|
|
51
49
|
ticker_channels = [f"ticker.{instr}.100ms" for instr in batch]
|
|
52
50
|
book_channels = [f"book.{instr}.100ms" for instr in batch]
|
|
@@ -123,10 +121,6 @@ async def process_batch(ws, batch: List[str], batch_num: int, total_batches: int
|
|
|
123
121
|
|
|
124
122
|
batch_results.append(row)
|
|
125
123
|
|
|
126
|
-
batch_time = time.time() - batch_start
|
|
127
|
-
logger.info(
|
|
128
|
-
f"Batch {batch_num}/{total_batches} completed in {batch_time:.2f}s - {len(batch_results)} instruments processed")
|
|
129
|
-
|
|
130
124
|
return batch_results
|
|
131
125
|
|
|
132
126
|
|
|
@@ -227,7 +221,6 @@ def process_option_chain(df: pd.DataFrame, currency: str, min_dte: float = 2.0)
|
|
|
227
221
|
return None
|
|
228
222
|
|
|
229
223
|
# Apply extraction to create new columns
|
|
230
|
-
logger.info(f"Extracting option details from instrument names...")
|
|
231
224
|
df['details'] = df['instrument_name'].apply(lambda x: extract_details(x))
|
|
232
225
|
df['strike'] = df['details'].apply(lambda x: x['strike'] if x else None)
|
|
233
226
|
df['option_type'] = df['details'].apply(lambda x: x['option_type'] if x else None)
|
|
@@ -240,7 +233,6 @@ def process_option_chain(df: pd.DataFrame, currency: str, min_dte: float = 2.0)
|
|
|
240
233
|
|
|
241
234
|
# Get reference time from timestamp
|
|
242
235
|
reference_time = datetime.datetime.fromtimestamp(df['timestamp'].iloc[0] / 1000)
|
|
243
|
-
logger.info(f"Reference time: {reference_time}")
|
|
244
236
|
|
|
245
237
|
# Calculate days to expiry (DTE)
|
|
246
238
|
df['dte'] = (df['expiry_date'] - reference_time).dt.total_seconds() / (24 * 60 * 60)
|
|
@@ -261,23 +253,6 @@ def process_option_chain(df: pd.DataFrame, currency: str, min_dte: float = 2.0)
|
|
|
261
253
|
df = df.dropna(subset=['mark_iv', 'log_moneyness', 'yte'])
|
|
262
254
|
logger.info(f"Removed {original_rows - len(df)} rows with missing data")
|
|
263
255
|
|
|
264
|
-
# Filter options with DTE > min_dte
|
|
265
|
-
if min_dte > 0:
|
|
266
|
-
original_count = len(df)
|
|
267
|
-
df = df[df['dte'] > min_dte]
|
|
268
|
-
logger.info(f"Filtered out {original_count - len(df)} options with DTE < {min_dte}")
|
|
269
|
-
|
|
270
|
-
# Group by time to expiry and ensure we have enough data points for each expiry
|
|
271
|
-
expiry_counts = df.groupby('yte').size()
|
|
272
|
-
valid_expiries = expiry_counts[expiry_counts >= 5].index
|
|
273
|
-
df = df[df['yte'].isin(valid_expiries)]
|
|
274
|
-
logger.info(f"Filtered to {len(df)} options with at least 5 strikes per expiry")
|
|
275
|
-
|
|
276
|
-
# Report on the maturities we're working with
|
|
277
|
-
maturities = df.groupby(['maturity_name', 'yte']).size().reset_index()
|
|
278
|
-
for _, row in maturities.iterrows():
|
|
279
|
-
logger.info(f"Maturity: {row['maturity_name']}, YTE: {row['yte']:.4f}, Strikes: {row[0]}")
|
|
280
|
-
|
|
281
256
|
return df
|
|
282
257
|
|
|
283
258
|
|
voly/utils/logger.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: voly
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.11
|
|
4
4
|
Summary: Options & volatility research package
|
|
5
5
|
Author-email: Manu de Cara <manu.de.cara@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -27,7 +27,6 @@ Requires-Dist: websockets>=10.0
|
|
|
27
27
|
Requires-Dist: requests>=2.26.0
|
|
28
28
|
Requires-Dist: loguru>=0.5.3
|
|
29
29
|
Provides-Extra: dev
|
|
30
|
-
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
30
|
Requires-Dist: black>=22.1.0; extra == "dev"
|
|
32
31
|
Requires-Dist: isort>=5.10.1; extra == "dev"
|
|
33
32
|
Requires-Dist: mypy>=0.931; extra == "dev"
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
voly/__init__.py,sha256=8xyDk7rFCn_MOD5hxuv5cxxKZvBVRiSIM7TgaMPpwpw,211
|
|
2
|
-
voly/client.py,sha256=
|
|
2
|
+
voly/client.py,sha256=i7wPy02L1y21giYUVAQTWkCuNAwykCUAWlJ-D1pA4YM,17493
|
|
3
3
|
voly/exceptions.py,sha256=PBsbn1vNMvKcCJwwJ4lBO6glD85jo1h2qiEmD7ArAjs,92
|
|
4
4
|
voly/formulas.py,sha256=aG_HSq_a4j7TcuKiINlHSpmNdmfZa_fzYbAk8EGt954,7427
|
|
5
5
|
voly/models.py,sha256=YJ12aamLz_-aOni4Qm0_XV9u4bjKK3vfJz0J2gc1h0o,3565
|
|
6
6
|
voly/core/__init__.py,sha256=GU6l7hpxJfitPx9jnmBtcb_QIeqOO8liZsSbLXXSbq8,384
|
|
7
7
|
voly/core/charts.py,sha256=GF55IS-aZfcc_0yoSPRPIPBPcJhFD1El18wNCo_mI_A,29918
|
|
8
|
-
voly/core/data.py,sha256=
|
|
8
|
+
voly/core/data.py,sha256=RCvL9ZZWHgO2cfNbLSby2zNsoJmF2VCkJ0yRb1HtjHs,10171
|
|
9
9
|
voly/core/fit.py,sha256=JSQuEkdriVdilcIPAJaieZUofYdCfSGJ5wVB1wRBfVs,11280
|
|
10
10
|
voly/core/interpolate.py,sha256=ztVIePJZOh-CIbn69wkh1JW2rKywNe2FEewRN0zcSAo,8185
|
|
11
11
|
voly/core/rnd.py,sha256=-xBVzvM9sMIBtfOfWyBJKtiVcBShSGTNNp2PZFOD5j0,12155
|
|
12
12
|
voly/utils/__init__.py,sha256=E05mWatyC-PDOsCxQV1p5Xi1IgpOomxrNURyCx_gB-w,200
|
|
13
|
-
voly/utils/logger.py,sha256=
|
|
14
|
-
voly-0.0.
|
|
15
|
-
voly-0.0.
|
|
16
|
-
voly-0.0.
|
|
17
|
-
voly-0.0.
|
|
18
|
-
voly-0.0.
|
|
13
|
+
voly/utils/logger.py,sha256=4-_2bVJmq17Q0d7Rd2mPg1AeR8gxv6EPvcmBDMFWcSM,1744
|
|
14
|
+
voly-0.0.11.dist-info/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
|
|
15
|
+
voly-0.0.11.dist-info/METADATA,sha256=ggw_f34HW4h4RTN5_37TpH7bW_sVJ-_AdCpVeG_Fz9Y,4092
|
|
16
|
+
voly-0.0.11.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
17
|
+
voly-0.0.11.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
|
|
18
|
+
voly-0.0.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|