voly 0.0.182__py3-none-any.whl → 0.0.184__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/core/fit.py +127 -128
- voly/models.py +2 -2
- {voly-0.0.182.dist-info → voly-0.0.184.dist-info}/METADATA +1 -1
- {voly-0.0.182.dist-info → voly-0.0.184.dist-info}/RECORD +7 -7
- {voly-0.0.182.dist-info → voly-0.0.184.dist-info}/WHEEL +0 -0
- {voly-0.0.182.dist-info → voly-0.0.184.dist-info}/licenses/LICENSE +0 -0
- {voly-0.0.182.dist-info → voly-0.0.184.dist-info}/top_level.txt +0 -0
    
        voly/core/fit.py
    CHANGED
    
    | @@ -215,8 +215,8 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame: | |
| 215 215 | 
             
                        w1 = SVIModel.svi(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
         | 
| 216 216 | 
             
                        w2 = SVIModel.svi(k_val, a2 * t2, b2 * t2, m2, rho2, sigma2)
         | 
| 217 217 | 
             
                        if w2 < w1 - 1e-6:
         | 
| 218 | 
            -
                            logger.warning(
         | 
| 219 | 
            -
             | 
| 218 | 
            +
                            logger.warning(f"Calendar arbitrage violation at t1={t1:.4f}, t2={t2:.4f}, k={k_val:.4f}: ")
         | 
| 219 | 
            +
                            logger.warning(f"w1={w1:.6f}, w2={w2:.6f}")
         | 
| 220 220 | 
             
                            calendar_arbitrage_free = False
         | 
| 221 221 | 
             
                            break
         | 
| 222 222 | 
             
                    if not calendar_arbitrage_free:
         | 
| @@ -232,134 +232,133 @@ def fit_model(option_chain: pd.DataFrame) -> pd.DataFrame: | |
| 232 232 | 
             
                        results_df.at[idx, 'calendar_arbitrage_free'] = calendar_arbitrage_free
         | 
| 233 233 |  | 
| 234 234 | 
             
                # Calendar arbitrage correction
         | 
| 235 | 
            -
                 | 
| 236 | 
            -
             | 
| 237 | 
            -
                     | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
                         | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
                         | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
             | 
| 260 | 
            -
             | 
| 261 | 
            -
             | 
| 262 | 
            -
             | 
| 263 | 
            -
             | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 269 | 
            -
             | 
| 270 | 
            -
             | 
| 271 | 
            -
             | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 274 | 
            -
             | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
             | 
| 278 | 
            -
             | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 281 | 
            -
             | 
| 282 | 
            -
             | 
| 283 | 
            -
             | 
| 284 | 
            -
             | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
                         | 
| 288 | 
            -
             | 
| 289 | 
            -
             | 
| 290 | 
            -
             | 
| 291 | 
            -
             | 
| 292 | 
            -
                             | 
| 293 | 
            -
             | 
| 294 | 
            -
             | 
| 295 | 
            -
             | 
| 296 | 
            -
             | 
| 297 | 
            -
             | 
| 298 | 
            -
                         | 
| 299 | 
            -
                             | 
| 300 | 
            -
                                idx = results_df.index[j]
         | 
| 301 | 
            -
                                break
         | 
| 302 | 
            -
             | 
| 303 | 
            -
                        if idx is not None:
         | 
| 304 | 
            -
                            results_df.at[idx, 'a'] = float(a_scaled)
         | 
| 305 | 
            -
                            results_df.at[idx, 'b'] = float(b_scaled)
         | 
| 306 | 
            -
                            results_df.at[idx, 'm'] = float(m)
         | 
| 307 | 
            -
                            results_df.at[idx, 'rho'] = float(rho)
         | 
| 308 | 
            -
                            results_df.at[idx, 'sigma'] = float(sigma)
         | 
| 309 | 
            -
                            results_df.at[idx, 'nu'] = float(nu)
         | 
| 310 | 
            -
                            results_df.at[idx, 'psi'] = float(psi)
         | 
| 311 | 
            -
                            results_df.at[idx, 'p'] = float(p)
         | 
| 312 | 
            -
                            results_df.at[idx, 'c'] = float(c)
         | 
| 313 | 
            -
                            results_df.at[idx, 'nu_tilde'] = float(nu_tilde)
         | 
| 314 | 
            -
                            results_df.at[idx, 'rmse'] = float(rmse)
         | 
| 315 | 
            -
                            results_df.at[idx, 'mae'] = float(mae)
         | 
| 316 | 
            -
                            results_df.at[idx, 'r2'] = float(r2)
         | 
| 317 | 
            -
                            results_df.at[idx, 'max_error'] = float(max_error)
         | 
| 318 | 
            -
                            results_df.at[idx, 'log_min_strike'] = float(log_min_strike)
         | 
| 319 | 
            -
                            results_df.at[idx, 'usd_min_strike'] = float(usd_min_strike)
         | 
| 320 | 
            -
                            results_df.at[idx, 'butterfly_arbitrage_free'] = butterfly_arbitrage_free
         | 
| 321 | 
            -
                            results_df.at[idx, 'fit_success'] = bool(not np.isnan(a))
         | 
| 322 | 
            -
             | 
| 323 | 
            -
                    # Calendar arbitrage check (post-correction)
         | 
| 324 | 
            -
                    logger.info("\nChecking calendar arbitrage (post-correction)...")
         | 
| 325 | 
            -
                    calendar_arbitrage_free = False # Should be True
         | 
| 326 | 
            -
                    for i in range(len(sorted_maturities) - 1):
         | 
| 327 | 
            -
                        mat1, mat2 = sorted_maturities[i], sorted_maturities[i + 1]
         | 
| 328 | 
            -
                        t1, params1 = params_dict[mat1]
         | 
| 329 | 
            -
                        t2, params2 = params_dict[mat2]
         | 
| 330 | 
            -
                        a1, b1, m1, rho1, sigma1 = params1
         | 
| 331 | 
            -
                        a2, b2, m2, rho2, sigma2 = params2
         | 
| 332 | 
            -
             | 
| 333 | 
            -
                        if np.isnan(a1) or np.isnan(a2):
         | 
| 334 | 
            -
                            continue
         | 
| 335 | 
            -
             | 
| 336 | 
            -
                        group = groups.get_group(mat2)
         | 
| 337 | 
            -
                        K = group['strikes'].values
         | 
| 338 | 
            -
                        s = group['index_price'].iloc[0]
         | 
| 339 | 
            -
                        k_market = np.log(K / s)
         | 
| 340 | 
            -
                        mask = ~np.isnan(k_market)
         | 
| 341 | 
            -
                        k_check = np.unique(np.concatenate(
         | 
| 342 | 
            -
                            [k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]), 200)]))
         | 
| 343 | 
            -
             | 
| 344 | 
            -
                        for k_val in k_check:
         | 
| 345 | 
            -
                            w1 = SVIModel.svi(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
         | 
| 346 | 
            -
                            w2 = SVIModel.svi(k_val, a2 * t2, b2 * t2, m2, rho2, sigma2)
         | 
| 347 | 
            -
                            if w2 < w1 - 1e-6:
         | 
| 348 | 
            -
                                logger.warning(
         | 
| 349 | 
            -
                                    f"Calendar arbitrage violation at t1={t1:.4f}, t2={t2:.4f}, k={k_val:.4f}: w1={w1:.6f}, w2={w2:.6f}")
         | 
| 350 | 
            -
                                calendar_arbitrage_free = False
         | 
| 351 | 
            -
                                break
         | 
| 352 | 
            -
                        if not calendar_arbitrage_free:
         | 
| 235 | 
            +
                logger.info("\nPerforming calendar arbitrage correction...")
         | 
| 236 | 
            +
                for i in range(1, len(sorted_maturities)):
         | 
| 237 | 
            +
                    mat2 = sorted_maturities[i]
         | 
| 238 | 
            +
                    mat1 = sorted_maturities[i - 1]
         | 
| 239 | 
            +
                    t2, params2 = params_dict[mat2]
         | 
| 240 | 
            +
                    t1, params1 = params_dict[mat1]
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                    if np.any(np.isnan(params2)) or np.any(np.isnan(params1)):
         | 
| 243 | 
            +
                        continue
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                    group = groups.get_group(mat2)
         | 
| 246 | 
            +
                    s = group['index_price'].iloc[0]
         | 
| 247 | 
            +
                    K = group['strikes'].values
         | 
| 248 | 
            +
                    iv = group['mark_iv'].values
         | 
| 249 | 
            +
                    vega = group['vega'].values if 'vega' in group.columns else np.ones_like(iv)
         | 
| 250 | 
            +
                    k = np.log(K / s)
         | 
| 251 | 
            +
                    w = (iv ** 2) * t2
         | 
| 252 | 
            +
                    mask = ~np.isnan(w) & ~np.isnan(vega) & ~np.isnan(k) & (iv >= 0)
         | 
| 253 | 
            +
                    k, w, vega, iv = k[mask], w[mask], vega[mask], iv[mask]
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                    new_params = SVIModel.correct_calendar_arbitrage(
         | 
| 256 | 
            +
                        params=params2, t=t2, tiv=w, vega=vega, k=k,
         | 
| 257 | 
            +
                        prev_params=params1, prev_t=t1, k_grid=k_grid
         | 
| 258 | 
            +
                    )
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                    params_dict[mat2] = (t2, new_params)
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                    a, b, m, rho, sigma = new_params
         | 
| 263 | 
            +
                    a_scaled, b_scaled = a * t2, b * t2
         | 
| 264 | 
            +
                    nu, psi, p, c, nu_tilde = SVIModel.raw_to_jw_params(a_scaled, b_scaled, m, rho, sigma, t2)
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                    # Recompute fit statistics
         | 
| 267 | 
            +
                    w_model = np.array([SVIModel.svi(x, a_scaled, b_scaled, m, rho, sigma) for x in k])
         | 
| 268 | 
            +
                    iv_model = np.sqrt(w_model / t2)
         | 
| 269 | 
            +
                    iv_market = iv
         | 
| 270 | 
            +
                    rmse = np.sqrt(mean_squared_error(iv_market, iv_model))
         | 
| 271 | 
            +
                    mae = mean_absolute_error(iv_market, iv_model)
         | 
| 272 | 
            +
                    r2 = r2_score(iv_market, iv_model)
         | 
| 273 | 
            +
                    max_error = np.max(np.abs(iv_market - iv_model))
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                    # Recompute min strike
         | 
| 276 | 
            +
                    log_min_strike = SVIModel.svi_min_strike(sigma, rho, m)
         | 
| 277 | 
            +
                    usd_min_strike = np.exp(log_min_strike) * s
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    # Update butterfly arbitrage check
         | 
| 280 | 
            +
                    butterfly_arbitrage_free = True
         | 
| 281 | 
            +
                    k_range = np.linspace(min(k), max(k), 200)
         | 
| 282 | 
            +
                    w_k = lambda k: SVIModel.svi(k, a_scaled, b_scaled, m, rho, sigma)
         | 
| 283 | 
            +
                    w_prime = lambda k: b_scaled * (rho + (k - m) / np.sqrt((k - m) ** 2 + sigma ** 2))
         | 
| 284 | 
            +
                    w_double_prime = lambda k: b_scaled * sigma ** 2 / ((k - m) ** 2 + sigma ** 2) ** (3 / 2)
         | 
| 285 | 
            +
             | 
| 286 | 
            +
                    for k_val in k_range:
         | 
| 287 | 
            +
                        wk = w_k(k_val)
         | 
| 288 | 
            +
                        wp = w_prime(k_val)
         | 
| 289 | 
            +
                        wpp = w_double_prime(k_val)
         | 
| 290 | 
            +
                        g = (1 - (k_val * wp) / (2 * wk)) ** 2 - (wp ** 2) / 4 * (1 / wk + 1 / 4) + wpp / 2
         | 
| 291 | 
            +
                        if g < 0:
         | 
| 292 | 
            +
                            butterfly_arbitrage_free = False
         | 
| 293 | 
            +
                            break
         | 
| 294 | 
            +
             | 
| 295 | 
            +
                    # Find the correct index to update
         | 
| 296 | 
            +
                    idx = None
         | 
| 297 | 
            +
                    for j, maturity_name in enumerate(maturity_names):
         | 
| 298 | 
            +
                        if results_df.iloc[j]['maturity_date'] == mat2:
         | 
| 299 | 
            +
                            idx = results_df.index[j]
         | 
| 353 300 | 
             
                            break
         | 
| 354 301 |  | 
| 355 | 
            -
                     | 
| 356 | 
            -
                        idx =  | 
| 357 | 
            -
                         | 
| 358 | 
            -
             | 
| 359 | 
            -
             | 
| 360 | 
            -
             | 
| 361 | 
            -
                         | 
| 362 | 
            -
             | 
| 302 | 
            +
                    if idx is not None:
         | 
| 303 | 
            +
                        results_df.at[idx, 'a'] = float(a_scaled)
         | 
| 304 | 
            +
                        results_df.at[idx, 'b'] = float(b_scaled)
         | 
| 305 | 
            +
                        results_df.at[idx, 'm'] = float(m)
         | 
| 306 | 
            +
                        results_df.at[idx, 'rho'] = float(rho)
         | 
| 307 | 
            +
                        results_df.at[idx, 'sigma'] = float(sigma)
         | 
| 308 | 
            +
                        results_df.at[idx, 'nu'] = float(nu)
         | 
| 309 | 
            +
                        results_df.at[idx, 'psi'] = float(psi)
         | 
| 310 | 
            +
                        results_df.at[idx, 'p'] = float(p)
         | 
| 311 | 
            +
                        results_df.at[idx, 'c'] = float(c)
         | 
| 312 | 
            +
                        results_df.at[idx, 'nu_tilde'] = float(nu_tilde)
         | 
| 313 | 
            +
                        results_df.at[idx, 'rmse'] = float(rmse)
         | 
| 314 | 
            +
                        results_df.at[idx, 'mae'] = float(mae)
         | 
| 315 | 
            +
                        results_df.at[idx, 'r2'] = float(r2)
         | 
| 316 | 
            +
                        results_df.at[idx, 'max_error'] = float(max_error)
         | 
| 317 | 
            +
                        results_df.at[idx, 'log_min_strike'] = float(log_min_strike)
         | 
| 318 | 
            +
                        results_df.at[idx, 'usd_min_strike'] = float(usd_min_strike)
         | 
| 319 | 
            +
                        results_df.at[idx, 'butterfly_arbitrage_free'] = butterfly_arbitrage_free
         | 
| 320 | 
            +
                        results_df.at[idx, 'fit_success'] = bool(not np.isnan(a))
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                # Calendar arbitrage check (post-correction)
         | 
| 323 | 
            +
                logger.info("\nChecking calendar arbitrage (post-correction)...")
         | 
| 324 | 
            +
                calendar_arbitrage_free = True
         | 
| 325 | 
            +
                for i in range(len(sorted_maturities) - 1):
         | 
| 326 | 
            +
                    mat1, mat2 = sorted_maturities[i], sorted_maturities[i + 1]
         | 
| 327 | 
            +
                    t1, params1 = params_dict[mat1]
         | 
| 328 | 
            +
                    t2, params2 = params_dict[mat2]
         | 
| 329 | 
            +
                    a1, b1, m1, rho1, sigma1 = params1
         | 
| 330 | 
            +
                    a2, b2, m2, rho2, sigma2 = params2
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                    if np.isnan(a1) or np.isnan(a2):
         | 
| 333 | 
            +
                        continue
         | 
| 334 | 
            +
             | 
| 335 | 
            +
                    group = groups.get_group(mat2)
         | 
| 336 | 
            +
                    K = group['strikes'].values
         | 
| 337 | 
            +
                    s = group['index_price'].iloc[0]
         | 
| 338 | 
            +
                    k_market = np.log(K / s)
         | 
| 339 | 
            +
                    mask = ~np.isnan(k_market)
         | 
| 340 | 
            +
                    k_check = np.unique(np.concatenate(
         | 
| 341 | 
            +
                        [k_market[mask], np.linspace(min(k_market[mask]), max(k_market[mask]), 200)]))
         | 
| 342 | 
            +
             | 
| 343 | 
            +
                    for k_val in k_check:
         | 
| 344 | 
            +
                        w1 = SVIModel.svi(k_val, a1 * t1, b1 * t1, m1, rho1, sigma1)
         | 
| 345 | 
            +
                        w2 = SVIModel.svi(k_val, a2 * t2, b2 * t2, m2, rho2, sigma2)
         | 
| 346 | 
            +
                        if w2 < w1 - 1e-6:
         | 
| 347 | 
            +
                            logger.warning(
         | 
| 348 | 
            +
                                f"Calendar arbitrage violation at t1={t1:.4f}, t2={t2:.4f}, k={k_val:.4f}: w1={w1:.6f}, w2={w2:.6f}")
         | 
| 349 | 
            +
                            calendar_arbitrage_free = False
         | 
| 350 | 
            +
                            break
         | 
| 351 | 
            +
                    if not calendar_arbitrage_free:
         | 
| 352 | 
            +
                        break
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                for mat in sorted_maturities:
         | 
| 355 | 
            +
                    idx = None
         | 
| 356 | 
            +
                    for j, maturity_name in enumerate(maturity_names):
         | 
| 357 | 
            +
                        if results_df.iloc[j]['maturity_date'] == mat:
         | 
| 358 | 
            +
                            idx = results_df.index[j]
         | 
| 359 | 
            +
                            break
         | 
| 360 | 
            +
                    if idx is not None:
         | 
| 361 | 
            +
                        results_df.at[idx, 'calendar_arbitrage_free'] = calendar_arbitrage_free
         | 
| 363 362 |  | 
| 364 363 | 
             
                logger.info("Model fitting complete.")
         | 
| 365 364 | 
             
                return results_df
         | 
    
        voly/models.py
    CHANGED
    
    | @@ -165,10 +165,10 @@ class SVIModel: | |
| 165 165 | 
             
                        w_current = cls.svi(k_constraint, new_params[0] * t, new_params[1] * t, *new_params[2:])
         | 
| 166 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 | 
            +
                        logger.info(f"Calendar arbitrage correction {'successful' if violation >= -1e-6 else 'failed'} for t={t:.4f}, "
         | 
| 169 169 | 
             
                              f"min margin={violation:.6f}")
         | 
| 170 170 | 
             
                        return new_params
         | 
| 171 | 
            -
                     | 
| 171 | 
            +
                    logger.warning(f"Calendar arbitrage correction failed for t={t:.4f}")
         | 
| 172 172 | 
             
                    return params
         | 
| 173 173 |  | 
| 174 174 |  | 
| @@ -2,19 +2,19 @@ voly/__init__.py,sha256=8xyDk7rFCn_MOD5hxuv5cxxKZvBVRiSIM7TgaMPpwpw,211 | |
| 2 2 | 
             
            voly/client.py,sha256=dPyRRmZ_Gvo1zCZMo9eFOx2oaYocmkOt71fzdmOXFyM,14387
         | 
| 3 3 | 
             
            voly/exceptions.py,sha256=PBsbn1vNMvKcCJwwJ4lBO6glD85jo1h2qiEmD7ArAjs,92
         | 
| 4 4 | 
             
            voly/formulas.py,sha256=JnEs6G0wlfRNH6X_YEJMe2RtLH-ryhzufjsim73Bj3c,11176
         | 
| 5 | 
            -
            voly/models.py,sha256= | 
| 5 | 
            +
            voly/models.py,sha256=A7zIUnIoH2rwb2_kp96xfFuOQ8CkGQ-XCx1cOGJSlco,7009
         | 
| 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= | 
| 9 | 
            +
            voly/core/fit.py,sha256=CIayT6HKd-8pc8P76bc2vNivNmF_Uu4fHRNRqNup2R8,17210
         | 
| 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. | 
| 17 | 
            -
            voly-0.0. | 
| 18 | 
            -
            voly-0.0. | 
| 19 | 
            -
            voly-0.0. | 
| 20 | 
            -
            voly-0.0. | 
| 16 | 
            +
            voly-0.0.184.dist-info/licenses/LICENSE,sha256=wcHIVbE12jfcBOai_wqBKY6xvNQU5E909xL1zZNq_2Q,1065
         | 
| 17 | 
            +
            voly-0.0.184.dist-info/METADATA,sha256=RoKiGHZQ4w4M5KsFMq6hCDmCe8KkTAKCKhcnEDc9C98,4115
         | 
| 18 | 
            +
            voly-0.0.184.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
         | 
| 19 | 
            +
            voly-0.0.184.dist-info/top_level.txt,sha256=ZfLw2sSxF-LrKAkgGjOmeTcw6_gD-30zvtdEY5W4B7c,5
         | 
| 20 | 
            +
            voly-0.0.184.dist-info/RECORD,,
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |