Skip to main content

A Python library for quantitative analysis of volatility patterns and regime dynamics.

Project description

SixEyes

A Python library for volatility estimation, regime analysis, and hidden state modeling in financial time series.

SixEyes is designed for quantitative teams and research groups that require transparent, modular, and production-aligned volatility forecasting infrastructure.


Modules

Module Status Description
Volatility Available Rolling, EWMA, range-based, asymmetric, and vol-of-vol estimators
RegimeModel In development Regime-switching models for structural break detection

Installation

pip install sixeyes

Setup & Testing

All examples below use S&P 500 daily OHLC data pulled from Yahoo Finance.

import yfinance as yf
import numpy as np

df = yf.download("^GSPC", start="2020-01-01", end="2024-12-31")
returns = np.log(df["Close"] / df["Close"].shift(1)).dropna()

Volatility

Rolling Standard Deviation

Close-to-close log return vol over a fixed 21-day window.

from sixeyes.Volatility import RollingSTD

model = RollingSTD(window_size=21, days_per_annum=252, annualize=True)
vol = model.compute(returns=returns)
forecast = model.predict(horizon=5, returns=returns)

EWMA

Same as rolling std but decays older observations — a spike in March weights less by April. RiskMetrics standard is alpha=0.94 for daily data.

from sixeyes.Volatility import EWMA

model = EWMA(alpha=0.94, span=20, days_per_annum=252, annualize=True)
vol = model.compute(returns=returns.values)
forecast = model.predict(horizon=5, returns=returns.values)

Parkinson

Replaces close-to-close returns with the daily high-low range — more efficient for FX or futures where overnight gaps are small.

from sixeyes.Volatility import Parkinson

model = Parkinson(window=21, annualize=True)
vol = model.compute(high=df["High"].values, low=df["Low"].values)
forecast = model.predict(horizon=5, high=df["High"].values, low=df["Low"].values)

Garman-Klass

Uses all four OHLC prices — the most efficient classical daily estimator for equities where the open-close drift matters.

from sixeyes.Volatility import GarmanKlass

model = GarmanKlass(window=21, annualize=True)
vol = model.compute(
    open_=df["Open"].values,
    high=df["High"].values,
    low=df["Low"].values,
    close=df["Close"].values,
)
forecast = model.predict(
    horizon=5,
    open_=df["Open"].values,
    high=df["High"].values,
    low=df["Low"].values,
    close=df["Close"].values,
)

Downside Volatility

Computes vol using only negative return days — separates loss dispersion from gain dispersion, which rolling std conflates.

from sixeyes.Volatility import DownSideVolatility

model = DownSideVolatility(window=21, annualize=True)
downside_vol = model.compute(returns.values)
forecast = model.predict(horizon=5, returns=returns.values)

# Sortino ratio
ann_return = returns.mean() * 252
sortino = (ann_return - 0.05) / downside_vol[-1]

Vol of Vol

Rolling standard deviation of a vol series — measures how much volatility is itself moving day to day.

from sixeyes.Volatility import VolOfVol, EWMA

ewma_vol = EWMA(alpha=0.94, span=20, days_per_annum=252).compute(returns.values)
ewma_forecast = EWMA(alpha=0.94, span=20, days_per_annum=252).predict(horizon=5, returns=returns.values)

model = VolOfVol(window=21)
vov = model.compute(ewma_vol)
vov_forecast = model.predict(horizon=5, vol_series=ewma_vol)

Forecasting and Evaluation

Each estimator's predict(horizon) shifts the vol series forward to produce a persistence forecast. evaluate() scores it against future realized vol using RMSE — useful for choosing the right estimator per instrument.

from sixeyes.Volatility import Parkinson, GarmanKlass, EWMA
from sixeyes.Volatility.evaluation import evaluate

high, low = df["High"].values, df["Low"].values
r = returns.values

results = {
    "Parkinson":   evaluate(Parkinson(21, annualize=False), r, {"high": high, "low": low}, horizon=5),
    "GarmanKlass": evaluate(GarmanKlass(21, annualize=False), r, {"open_": df["Open"].values, "high": high, "low": low, "close": df["Close"].values}, horizon=5),
    "EWMA":        evaluate(EWMA(0.94, 252, 20, annualize=False), r, {"returns": r}, horizon=5),
}

for name, rmse in results.items():
    print(f"{name:12s}  RMSE: {rmse:.6f}")

Putting It Together

import pandas as pd
import numpy as np
import yfinance as yf
from sixeyes.Volatility import RollingSTD, EWMA, GarmanKlass, DownSideVolatility, VolOfVol

df = yf.download("^GSPC", start="2020-01-01", end="2024-12-31")
returns = np.log(df["Close"] / df["Close"].shift(1)).dropna()
r = returns.values
ev = EWMA(alpha=0.94, span=20, days_per_annum=252).compute(r)

summary = pd.DataFrame({
    "rolling":    RollingSTD(21, 252).compute(returns=returns),
    "ewma":       ev,
    "gk":         GarmanKlass(21).compute(df.Open.values, df.High.values, df.Low.values, df.Close.values),
    "downside":   DownSideVolatility(21, annualize=True).compute(r),
    "vol_of_vol": VolOfVol(21).compute(ev),
}, index=returns.index)

print(summary.tail(3))

RegimeModel (coming soon)

The RegimeModel module will provide regime-switching models for identifying structural breaks and latent market states. Planned:

  • Hidden Markov Model state estimation
  • Regime-conditional vol and return statistics
  • Transition probability matrices
  • State sequence visualization

License

MIT License © Umer Farooq

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sixeyes-0.2.0.tar.gz (7.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sixeyes-0.2.0-py3-none-any.whl (7.4 kB view details)

Uploaded Python 3

File details

Details for the file sixeyes-0.2.0.tar.gz.

File metadata

  • Download URL: sixeyes-0.2.0.tar.gz
  • Upload date:
  • Size: 7.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.10

File hashes

Hashes for sixeyes-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8daffaeda21fe70c016c5e8eb6adcd49c847038d9e55d3ebe51576a8d7f7a34a
MD5 31ae04c17946567d1d513cc5cc5075ee
BLAKE2b-256 946455ccb604ace33af7b6dd1fc559b380e104e61e333be520e6903000267d6f

See more details on using hashes here.

File details

Details for the file sixeyes-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: sixeyes-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 7.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.10

File hashes

Hashes for sixeyes-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2e40f6048d6b3133e079b85d6185567966870b9d550a959b48bf9a5829fc5a3e
MD5 8d9b38e7a91981d704efd9ad3d5070ef
BLAKE2b-256 86fb27834a2bd92ccd8d6fc531a45c2ea7279443e12dc554eab8a80ceb778174

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page