Skip to content

chirindaopensource/identification_of_the_onset_of_financial_rogue_waves

Repository files navigation

README.md

Real-Time Identification of the Onset of Financial Rogue Waves

License: MIT Python Version Source Year Discipline: FinEcon Discipline: TimeSeries Discipline: Physics Discipline: Quantum Discipline: StatPhys Method: FFT Method: Hilbert Method: Eigenvalue Method: Anderson Method: Omori Method: KDE Data: Cboe Data: STOXX Code style: black Pandas NumPy SciPy Matplotlib Open Source

Repository: https://github.com/chirindaopensource/identification_of_the_onset_of_financial_rogue_waves

Owner: 2026 Craig Chirinda (Open Source Projects)

Table of Contents

Introduction

This project is an independent, professional-grade implementation of the ideas, methodologies, and experimental protocols from the arXiv preprint titled "Real-time identification of the onset of financial rogue waves" by the authors:

  • Rosie Hayward
  • Orla Lennon
  • Fabio Biancalana

This repository provides a complete, end-to-end computational framework for replicating the paper's findings. It bridges the disciplines of nonlinear wave physics and financial econometrics, translating the dynamics of optical and hydrodynamical rogue waves into a deterministic, real-time early warning system for extreme financial volatility events.

By extracting the slowly-varying envelope of implied volatility indices (VIX, VXO, VSTOXX) and modeling it as a potential well within a linearised Schrödinger equation, this codebase identifies the onset of Anderson localisation. The resulting eigenvalue-gradient indicator constitutes a universal ex-ante regime-change signal, enabling economic agents to pre-emptively mitigate the adverse impacts of impending financial crises without relying on look-ahead bias or black-box machine learning models.

Theoretical Background

The implemented methods rely on a profound mathematical analogy between classical wave systems and financial markets.

1. The Nonlinear Schrödinger Equation (NLSE) Analogy: The slowly varying envelope of financial volatility is modeled analogously to an optical field propagating in a Kerr medium. The framework examines the instantaneous linear states of this system via the eigenvalue problem: $$ \lambda\psi = -\frac{1}{2}\frac{\partial^2\psi}{\partial t^2} + U\psi $$ where the dimensionless potential $U$ is defined by the squared envelope of the volatility index: $U = -|\psi|^2$.

2. Anderson Localisation & Eigenvalue Gradients: As volatility surges, the potential well deepens, causing the ground-state eigenvector to become spatially localized (Anderson localisation). The minimum eigenvalue $\lambda_{\min}$ tracks the basin of this potential. A rapid, sustained drop in $\lambda_{\min}$ generates a sharp spike in its numerical gradient $g_j = |\lambda_{\min}^{(j)} - \lambda_{\min}^{(j-1)}|$, serving as a highly reliable, noise-resistant precursor to an extreme event.

3. Statistical Physics of Extreme Events: The framework adopts oceanographic criteria to define financial rogue waves. The Significant Wave Height (SWH) is computed as the mean of the highest one-third of envelope peak prominences. Peaks exceeding $2.5 \times \text{SWH}$ are classified as major rogue waves. Furthermore, the system demonstrates that post-peak volatility exceedances follow an Omori-like power-law decay ($N(t) \sim t^{-p}$), confirming the complex-systems analogy.

Features

  • Strict No-Look-Ahead Simulation: The real-time pipeline recomputes the FFT/Hilbert envelope daily using only historical data, guaranteeing zero information leakage and ensuring the indicator is genuinely predictive.
  • Deterministic Signal Processing: Employs symmetric mirror-padding prior to frequency-domain filtering to mathematically eliminate Fourier boundary artifacts.
  • Robust Out-of-Sample Validation: Implements strict chronological partitioning for the VXO and VSTOXX indices. Thresholds are calibrated exclusively on in-sample slices (maximizing $TP - 0.5FP$) and evaluated blindly on out-of-sample data.
  • Automated Reproducibility Auditing: The master orchestrator automatically verifies computed metrics (e.g., detection rates, precision, cross-correlation lags) against the paper's published numerical bounds, generating a definitive pass/fail Markdown report.

Methodology Implemented

  1. Data Validation & Cleansing: Enforces strict pandas extension types (float64, datetime64[ns]), verifies monotonicity, and reindexes the time series to a uniform trading-day calendar to satisfy the $\Delta t = 1$ finite-difference assumption.
  2. Envelope Extraction: Executes a 92.5th (baseline) or 95th (real-time) percentile FFT amplitude filter, followed by an inverse FFT and a Hilbert transform to isolate the slowly-varying crisis structure $\psi(t)$.
  3. Ground-Truth Labeling: Retrospectively identifies local maxima on the full-series envelope, computes the SWH, and labels major and minor rogue waves.
  4. Real-Time Eigenvalue Simulation: Constructs an $L \times L$ ($L=80$) symmetric tridiagonal Hamiltonian matrix for the trailing 10 days, diagonalizes it to extract $\lambda_{\min}$, and computes the numerical gradient $g_j$.
  5. Indicator Generation & Clustering: Calculates the warning indicator $I_i = g_{\max} \times c$. Continuous warning spikes occurring within a 10-day trading window are clustered to flag the true ex-ante regime-change signal.
  6. Performance Evaluation: Matches signals to ground-truth peaks using strict temporal rules (240-day lookback, 80-day separation from the previous peak, 10-day late cutoff) to compute Precision and Detection Rates.

Below is a diagram which illustrates the Inputs, Processes and Outputs (IPOs) of the proposed research methodology:

Pipeline Architecture

Core Components (Notebook Structure)

Note: All orchestrator callables and their constituent helper functions are contained within a singular, comprehensive Jupyter Notebook (identification_of_the_onset_of_financial_rogue_waves_draft.ipynb).

The notebook is structured as a logical sequence of 7 distinct tasks:

  • Task 1: Input Validation and Data Cleansing
  • Task 2: Full-Series Envelope Extraction and Rogue-Wave Ground-Truth Labeling
  • Task 3: Real-Time Warning Indicator Simulation (VIX)
  • Task 4: In-Sample Performance Evaluation (VIX)
  • Task 5: Out-of-Sample Threshold Calibration and Testing (VXO, VSTOXX)
  • Task 6: Supplementary Analyses (Omori Law, Turbulence Analogy, Anderson Localisation)
  • Task 7: Final Orchestrator and Reproducibility Check

Key Callable: execute_end_to_end_research_pipeline

The project is designed around a single, top-level user-facing interface function:

  • execute_end_to_end_research_pipeline: This apex orchestrator function coordinates the entire research protocol. A single call to this function ingests the raw DataFrames, executes the data cleansing, runs the real-time eigenvalue simulations for all indices, performs out-of-sample calibration, executes the supplementary physics analyses, and packages the results into an exported directory of CSVs, PNGs, and Markdown reports.

Prerequisites

  • Python 3.10+
  • Core Python dependencies: numpy, pandas, scipy, matplotlib, pyyaml.

Installation

  1. Clone the repository:

    git clone https://github.com/chirindaopensource/identification_of_the_onset_of_financial_rogue_waves.git
    cd identification_of_the_onset_of_financial_rogue_waves
  2. Create and activate a virtual environment (recommended):

    python -m venv venv
    source venv/bin/activate  # On Windows, use `venv\Scripts\activate`
  3. Install Python dependencies:

    pip install numpy pandas scipy matplotlib pyyaml

Input Data Structure

The pipeline requires three primary raw data structures (pandas DataFrames) representing the VIX, VXO, and VSTOXX indices. They must adhere strictly to the following schema:

Column: Date

  • Data type: datetime64[ns]
  • Meaning: Calendar date of the trading day. Contains only trading days; weekends and exchange holidays are absent. Sorted ascending, no duplicates.

Column: Close

  • Data type: float64
  • Meaning: Official end-of-day value of the implied volatility index, quoted in percentage points.
  • Properties: Non-negative, heteroskedastic, volatile clusters, long memory; contains no missing values. This is the sole numeric input to the entire pipeline. No returns, options data, or macroeconomic variables are used.

Usage

Here is the granular, step-by-step guide to executing the end-to-end pipeline for "Real-time identification of the onset of financial rogue waves". This example demonstrates how to synthetically generate the required implied volatility index data, load the study configuration from a YAML file, and execute the full research pipeline using the execute_end_to_end_research_pipeline orchestrator.

Note: It is assumed that all the callables that have been defined in this conversation are present in a single Jupyter notebook environment, and that there is no external folder with .py functions. It is also assumed that the config.yaml file is saved in the current working directory.

Step 1: Synthetic Data Generation (raw_data_sets_dict)

The first requirement is a high-fidelity synthetic representation of the VIX, VXO, and VSTOXX indices. These datasets must adhere strictly to the schema defined in the study: a Date column (strictly increasing trading days) and a Close column (non-negative float64 values).

Methodology:

  1. Date Generation: We generate a sequence of business days spanning the exact study periods for each index to simulate a trading calendar.
  2. Return Simulation: Implied volatility indices are strictly positive, mean-reverting, and exhibit volatility clustering. We simulate this using a discrete-time Ornstein-Uhlenbeck process (an AR(1) process on log-volatility): $\ln(V_t) = (1 - \phi)\mu + \phi \ln(V_{t-1}) + \sigma \epsilon_t$. Exponentiating the result guarantees non-negativity and realistic heteroskedasticity.
  3. Schema Enforcement: We explicitly cast columns to datetime64[ns] and float64 to match the strict validation requirements of Task 1.
# Import the pandas library for time-series and DataFrame manipulation
import pandas as pd
# Import the numpy library for vectorized mathematical operations and random sampling
import numpy as np
# Import the os module for file system path operations
import os
# Import the yaml module to parse the configuration file
import yaml
# Import typing constructs for strict static type hinting
from typing import Dict, Any

# Set a fixed random seed to ensure the synthetic data generation is perfectly reproducible
np.random.seed(42)

def generate_synthetic_volatility_index(
    start_date: str,
    end_date: str,
    long_term_mean: float = 20.0,
    persistence: float = 0.95,
    vol_of_vol: float = 0.10
) -> pd.DataFrame:
    """
    Generates a synthetic implied volatility index DataFrame for testing purposes.

    Purpose:
        To create a high-fidelity mock dataset that mimics the schema and statistical
        properties of indices like the VIX, VXO, and VSTOXX. The data is generated 
        using an AR(1) process on log-volatility to ensure mean-reversion, strict 
        positivity, and volatility clustering.

    Inputs:
        start_date (str): The start date of the simulation in 'YYYY-MM-DD' format.
        end_date (str): The end date of the simulation in 'YYYY-MM-DD' format.
        long_term_mean (float): The asymptotic mean of the volatility index (e.g., 20.0).
        persistence (float): The AR(1) autoregressive coefficient (phi), controlling memory.
        vol_of_vol (float): The standard deviation of the daily log-volatility shocks.

    Processes:
        1. Date Generation: Creates a sequence of business days (Monday-Friday).
        2. Log-Volatility Simulation: Generates an AR(1) process: 
           ln(V_t) = (1 - phi)*mu + phi*ln(V_{t-1}) + sigma*epsilon_t
        3. Transformation: Exponentiates the log-volatility to obtain the 'Close' level.
        4. Schema Enforcement: Casts columns to datetime64[ns] and float64.

    Outputs:
        pd.DataFrame: A DataFrame containing:
            - 'Date': datetime64[ns], strictly increasing trading days.
            - 'Close': float64, non-negative simulated volatility levels.

    Raises:
        ValueError: If start_date is not strictly before end_date, or if persistence >= 1.
    """
    # Validate that the start date chronologically precedes the end date
    if pd.Timestamp(start_date) >= pd.Timestamp(end_date):
        # Raise a ValueError to prevent invalid temporal generation
        raise ValueError(f"start_date ({start_date}) must be strictly before end_date ({end_date}).")
        
    # Validate that the persistence parameter ensures a stationary process
    if not (0.0 <= persistence < 1.0):
        # Raise a ValueError if the AR(1) process would be explosive or non-stationary
        raise ValueError(f"persistence must be in [0, 1), got {persistence}.")

    # Generate a sequence of business days ('B' frequency) to simulate a trading calendar
    dates: pd.DatetimeIndex = pd.date_range(start=start_date, end=end_date, freq='B')
    
    # Determine the total number of trading days to simulate
    n: int = len(dates)
    
    # Calculate the natural logarithm of the long-term mean to center the AR(1) process
    mu_log: float = float(np.log(long_term_mean))
    
    # Generate standard normal random shocks for the entire time series
    shocks: np.ndarray = np.random.normal(loc=0.0, scale=vol_of_vol, size=n)
    
    # Initialize an array to hold the simulated log-volatility values
    log_vol: np.ndarray = np.zeros(n, dtype=np.float64)
    
    # Set the initial log-volatility state to the long-term mean
    log_vol[0] = mu_log
    
    # Iterate sequentially through time to construct the AR(1) process
    for t in range(1, n):
        # Apply the AR(1) equation: ln(V_t) = (1-phi)*mu + phi*ln(V_{t-1}) + shock
        log_vol[t] = (1.0 - persistence) * mu_log + persistence * log_vol[t-1] + shocks[t]

    # Exponentiate the log-volatility array to transform it back to the linear scale
    close_prices: np.ndarray = np.exp(log_vol)

    # Construct the pandas DataFrame using the generated dates and prices
    df: pd.DataFrame = pd.DataFrame({
        "Date": dates,
        "Close": close_prices
    })

    # Explicitly cast the 'Date' column to datetime64[ns] to satisfy Task 1 validation
    df["Date"] = df["Date"].astype("datetime64[ns]")
    
    # Explicitly cast the 'Close' column to float64 to satisfy Task 1 validation
    df["Close"] = df["Close"].astype("float64")

    # Return the fully constructed and schema-compliant DataFrame
    return df

# Generate the synthetic VIX dataset spanning 1990 to 2025
vix_df: pd.DataFrame = generate_synthetic_volatility_index("1990-01-02", "2025-04-07")

# Generate the synthetic VXO dataset spanning 1987 to 2020
vxo_df: pd.DataFrame = generate_synthetic_volatility_index("1987-01-02", "2020-12-31")

# Generate the synthetic VSTOXX dataset spanning 1999 to 2025
vstoxx_df: pd.DataFrame = generate_synthetic_volatility_index("1999-01-04", "2025-04-09")

# Aggregate the generated DataFrames into the master dictionary required by the orchestrator
raw_data_sets_dict: Dict[str, pd.DataFrame] = {
    "VIX": vix_df,
    "VXO": vxo_df,
    "VSTOXX": vstoxx_df
}

# Print a diagnostic message confirming successful data generation
print("Synthetic Volatility Data Generated Successfully.")

Step 2: Loading the Configuration (config.yaml)

The study relies on a deterministic configuration file (config.yaml) that defines all hyperparameters, data splits, and evaluation metrics. We assume this file exists in the working directory.

Methodology:

  1. File I/O: Open config.yaml in read mode.
  2. Parsing: Use yaml.safe_load to convert the YAML structure into a nested Python dictionary.
  3. Verification: Validate the output type to ensure the file was parsed into a dictionary correctly.
import yaml

def load_study_configuration(filepath: str = "config.yaml") -> Dict[str, Any]:
    """
    Loads the study configuration parameters from a YAML file into a Python dictionary.

    Purpose:
        To ingest the deterministic hyperparameters, data split definitions, and
        evaluation metrics defined in the external configuration file. This ensures
        reproducibility by separating code from configuration.

    Inputs:
        filepath (str): The relative or absolute path to the YAML configuration file.
                        Default is "config.yaml".

    Processes:
        1. File Access: Attempts to open the specified file in read mode.
        2. Parsing: Uses PyYAML's safe_load to parse the YAML structure securely.
        3. Validation: Catches and handles FileNotFoundError and YAMLError.

    Outputs:
        Dict[str, Any]: A nested dictionary containing the study configuration.

    Raises:
        TypeError: If filepath is not a string.
        FileNotFoundError: If the configuration file does not exist.
        yaml.YAMLError: If the file contains invalid YAML syntax.
    """
    # Validate that the provided filepath is a string
    if not isinstance(filepath, str):
        # Raise a TypeError if the filepath is invalid
        raise TypeError(f"filepath must be a string, got {type(filepath).__name__}.")

    # Attempt to execute the file reading and parsing block
    try:
        # Open the YAML file in read-only mode using a context manager
        with open(filepath, "r", encoding="utf-8") as file:
            # Parse the YAML content safely into a Python dictionary
            config: Dict[str, Any] = yaml.safe_load(file)

        # Log a success message to the standard output
        print(f"Successfully loaded configuration from {filepath}")

        # Return the parsed configuration dictionary
        return config

    # Catch the specific exception where the file is missing from the directory
    except FileNotFoundError:
        # Print a critical warning indicating the file is missing
        print(f"Error: {filepath} not found. Please ensure the file exists in the working directory.")
        # Re-raise the exception as the pipeline cannot proceed without configuration
        raise
        
    # Catch any exceptions related to malformed YAML syntax
    except yaml.YAMLError as e:
        # Print an error message detailing the parsing failure
        print(f"Error parsing YAML file {filepath}: {e}")
        # Re-raise the exception to halt execution
        raise

# Load the configuration dictionary into memory from the working directory
# Note: Ensure 'config.yaml' is in your working directory.
try:
    study_config: Dict[str, Any] = load_study_configuration("config.yaml")
except FileNotFoundError:
    print("Configuration file missing. Please ensure config.yaml is present.")

Step 3: Executing the Pipeline (execute_end_to_end_research_pipeline)

With the data (raw_data_sets_dict) and configuration (study_config) in memory, we invoke the top-level orchestrator. This function manages the entire lifecycle: data cleansing, envelope extraction, real-time eigenvalue simulation, out-of-sample threshold calibration, supplementary physics analyses, and artifact export.

Methodology:

  1. Function Call: Pass the dictionary of DataFrames and the configuration dictionary to execute_end_to_end_research_pipeline.
  2. Output Handling: The function returns a master payload dictionary containing:
    • status: The execution completion state.
    • cleaned_data: The gap-filled, temporally aligned DataFrames.
    • study_results: The nested metrics, Matplotlib figures, and pandas tables.
    • export_path: The directory where the CSVs and PNGs were saved.
# ==============================================================================
# Execution of the End-to-End Study Pipeline
# ==============================================================================

# Ensure the execution block only runs if this script is the main entry point
if __name__ == "__main__":
    
    # Verify that the raw data dictionary is populated and the config is loaded
    if raw_data_sets_dict and study_config:
        
        # Print an initialization message to the console
        print("\nInitiating Financial Rogue Wave Detection Pipeline...")
        
        # Define the output directory for the generated artifacts
        output_directory: str = "./rogue_wave_artifacts"
        
        # Execute the top-level orchestrator, passing the data, config, and export path
        pipeline_payload: Dict[str, Any] = execute_end_to_end_research_pipeline(
            raw_data_sets_dict=raw_data_sets_dict,
            CONFIG=study_config,
            output_dir=output_directory,
            run_supplementary=True
        )
        
        # ==============================================================================
        # Inspecting the Outputs
        # ==============================================================================
        
        # Print a visual separator to indicate completion
        print("\n" + "="*80)
        # Print the final execution status retrieved from the payload
        print(f"STUDY EXECUTION COMPLETE - STATUS: {pipeline_payload['status'].upper()}")
        # Print a visual separator
        print("="*80)
        
        # Check if the pipeline completed successfully before attempting to access results
        if pipeline_payload["status"] in ["success", "completed_with_export_errors"]:
            
            # Extract the nested study results dictionary from the payload
            study_artifacts: Dict[str, Any] = pipeline_payload["study_results"]
            
            # --- 1. Accessing VIX Baseline Results ---
            # Verify that the VIX results exist in the artifacts
            if "VIX" in study_artifacts and "metrics" in study_artifacts["VIX"]:
                # Extract the VIX performance metrics
                vix_metrics: Dict[str, float] = study_artifacts["VIX"]["metrics"]
                # Print the VIX header
                print("\n[Baseline Results for VIX]")
                # Print the VIX metrics formatted as a pandas DataFrame for readability
                print(pd.DataFrame([vix_metrics]))
                
            # --- 2. Accessing VXO Out-of-Sample Results ---
            # Verify that the VXO results exist in the artifacts
            if "VXO" in study_artifacts and "full_performance" in study_artifacts["VXO"]:
                # Extract the VXO out-of-sample performance metrics
                vxo_metrics: Dict[str, float] = study_artifacts["VXO"]["full_performance"]
                # Extract the calibrated threshold for the VXO
                vxo_threshold: float = study_artifacts["VXO"]["chosen_threshold"]
                # Print the VXO header including the calibrated threshold
                print(f"\n[Out-of-Sample Results for VXO | Calibrated Threshold: {vxo_threshold}]")
                # Print the VXO metrics formatted as a pandas DataFrame
                print(pd.DataFrame([vxo_metrics]))

            # --- 3. Accessing Export Information ---
            # Extract the export path from the payload
            export_path: str = pipeline_payload.get("export_path", "Unknown")
            # Print a visual separator for the export summary
            print("\n" + "="*80)
            # Print the directory where the CSVs, PNGs, and Markdown reports were saved
            print(f"ARTIFACTS EXPORTED TO: {export_path}")
            # Print a visual separator
            print("="*80)
            
        else:
            # If the pipeline failed, print the accumulated error messages
            print("\nPipeline failed. Review the errors below:")
            # Iterate through and print each error in the payload's error list
            for err in pipeline_payload.get("errors", []):
                print(f"- {err}")
                
    else:
        # Print an error if the prerequisites (data or config) are missing
        print("Error: Missing raw data or configuration. Cannot proceed.")

Summary of the Execution Flow

  1. Data Ingestion: The synthetic raw_data_sets_dict (containing VIX, VXO, and VSTOXX DataFrames) and the parsed study_config YAML dictionary are passed to the top-level orchestrator.
  2. Validation & Cleansing (Task 1): The pipeline validates the schema (Date, Close), enforces strict type contracts, and reindexes the data to a uniform trading-day calendar, forward-filling any gaps to ensure the $\Delta t = 1$ assumption holds for the finite-difference approximation.
  3. Envelope Extraction (Task 2): For each index, the pipeline mirrors the series, applies a high-percentile FFT filter (92.5% or 95%), and uses a Hilbert transform to extract the slowly-varying volatility envelope $\psi(t)$.
  4. Ground-Truth Labeling (Task 2): The pipeline identifies peaks on the full-series envelope, computes the Significant Wave Height (SWH), and retrospectively labels major ($&gt;2.5\times\text{SWH}$) and minor ($&gt;2.0\times\text{SWH}$) rogue waves.
  5. Real-Time Simulation (Task 3): The pipeline simulates daily data arrival. It constructs an $L \times L$ Hamiltonian matrix $H$ using the potential $U = -|\psi|^2$, diagonalizes it to find the minimum eigenvalue $\lambda_{\min}$, and computes the numerical gradient $g_j$ to generate the warning indicator $I_i$.
  6. Out-of-Sample Calibration & Testing (Task 5): For VXO and VSTOXX, the pipeline splits the data chronologically. It optimizes the warning threshold on the in-sample slice (maximizing $TP - 0.5FP$) and evaluates precision and detection rates strictly on the out-of-sample partition.
  7. Supplementary Analyses (Task 6): The pipeline computes the Omori-law aftershock decay exponent $p$, generates Kernel Density Estimates (KDE) for the turbulence analogy, and calculates Anderson localisation metrics (eigenvector width, skewness, kurtosis).
  8. Export & Audit (Task 7): The pipeline verifies the computed metrics against the paper's published targets, generates a Markdown reproducibility report, and exports all tables (CSVs) and diagnostic figures (PNGs) to the local file system.

Output Structure

The pipeline returns a comprehensive, timestamped directory (reproducibility_output_YYYYMMDD_HHMMSS) containing the following key artifacts:

  • Table1.csv: In-sample performance metrics for the VIX index.
  • Table2.csv: Out-of-sample performance metrics and calibrated threshold for the VXO index.
  • Table3.csv: Out-of-sample performance metrics and calibrated threshold for the VSTOXX index.
  • S1.csv, S2.csv, S3.csv: Chronological event logs detailing every first-signal and ground-truth peak, including classification flags (TP, False, Late, Low) and days-to-peak metrics.
  • fig4.png: Diagnostic plot displaying the raw VIX, maximum eigenvalue gradient, envelope wave, and classified warning signals.
  • fig5.png: Pearson cross-correlation plot confirming the leading indicator property of the eigenvalue gradient.
  • figS1.png: Log-log plot of cumulative exceedances demonstrating Omori-law aftershock decay.
  • figS2a.png, figS2b.png: Kernel Density Estimates (KDE) of raw and normalized envelope differences, illustrating the turbulence analogy.
  • figS3.png: Four-panel KDE plot of Anderson localisation metrics (eigenvector width, skewness, kurtosis, distance) binned by proximity to the next rogue peak.
  • reproducibility_report.md: An automated validation audit verifying the computed metrics against the paper's published numerical bounds.
  • README.txt: A brief summary of the directory contents.

Project Structure

identification_of_the_onset_of_financial_rogue_waves/
│
├── identification_of_the_onset_of_financial_rogue_waves_draft.ipynb  # Main implementation notebook containing all callables
├── config.yaml                                                       # Master configuration file (Hyperparameters, Thresholds, Rules)
│
├── rogue_wave_artifacts/                                             # Auto-generated archival directory
│   └── reproducibility_output_20260630_120000/
│       ├── Table1.csv
│       ├── Table2.csv
│       ├── Table3.csv
│       ├── S1.csv
│       ├── S2.csv
│       ├── S3.csv
│       ├── fig4.png
│       ├── fig5.png
│       ├── figS1.png
│       ├── figS2a.png
│       ├── figS2b.png
│       ├── figS3.png
│       ├── reproducibility_report.md
│       └── README.txt
│
├── LICENSE                                                           # MIT Project License File
└── README.md                                                         # This file

Customization

The pipeline is highly customizable via the config.yaml file. Researchers and quantitative engineers can modify study parameters such as:

  • Signal Processing Settings: Adjust the fft_percentile_fullseries (e.g., 92.5) and fft_percentile_realtime (e.g., 95.0) to tune the sensitivity of the envelope extraction.
  • Hamiltonian Parameters: Modify the window_length_L (default 80) to experiment with different memory horizons for the eigenvalue decomposition.
  • Indicator Logic: Tune the indicator_lookback_days (default 10) or the gradient_floor (default 50) to alter the responsiveness of the warning indicator.
  • Rogue Wave Definitions: Change the rogue_wave_factor_major (default 2.5) and rogue_wave_factor_minor (default 2.0) to redefine what constitutes an extreme event based on the Significant Wave Height (SWH).
  • Evaluation Rules: Adjust the detection_lookback_windows (default 3) or late_signal_cutoff_days (default 10) to tighten or loosen the criteria for a True Positive detection.

Contributing

Contributions are welcome. Please fork the repository, create a feature branch, and submit a pull request with a clear description of your changes.

Strict Engineering Standards: Adherence to PEP-8, strict static type hinting (typing module), and the draconian requirement for line-by-line in-text comments that explain the mathematical or logical purpose of every single line of code is strictly required for all pull requests to maintain the implementation-grade standard of this repository.

Recommended Extensions

Future extensions, building upon this foundational framework, could include:

  • Intraday Data Integration: Adapting the finite-difference approximation to handle high-frequency (e.g., 5-minute or tick-level) data to capture "flash" events like the February 2018 VIX spike that evade daily granularity.
  • Automated Threshold Optimization: Replacing the manual in-sample grid search with a dynamic, expanding-window optimization algorithm to continuously recalibrate the warning threshold in production environments.
  • Multi-Asset Application: Extending the methodology beyond equity volatility to commodity volatility indices (e.g., OVX for crude oil) or credit spread indices to test the universality of the regime-change signal.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Citation

If you use this code or the methodology in your research, please cite the original arXiv preprint:

@misc{hayward2026roguewaves,
  title={Real-time identification of the onset of financial rogue waves},
  author={Hayward, Rosie and Lennon, Orla and Biancalana, Fabio},
  howpublished={arXiv preprint arXiv:2606.31475v1 [q-fin.ST]},
  year={2026},
  url={https://arxiv.org/abs/2606.31475}
}

For the implementation itself, you may cite this repository:

@misc{chirinda2026roguewavesimpl,
  author = {Chirinda, Craig S.},
  title = {Real-Time Identification of the Onset of Financial Rogue Waves: A Python Implementation},
  year = {2026},
  publisher = {GitHub},
  howpublished = {\url{https://github.com/chirindaopensource/identification_of_the_onset_of_financial_rogue_waves}}
}

Acknowledgments

  • Credit to Rosie Hayward, Orla Lennon, and Fabio Biancalana for the foundational theoretical framework, the rigorous epistemic design, and the synthesis of nonlinear wave physics with financial econometrics.
  • This project is built upon the exceptional tools provided by the open-source community. Sincere thanks to the developers of the scientific Python ecosystem, particularly the NumPy, Pandas, SciPy, and Matplotlib contributors.

--

This README was generated based on the structure and content of the identification_of_the_onset_of_financial_rogue_waves_draft.ipynb notebook and follows best practices for research software documentation.

About

End-to-End Python implementation of Hayward et. al's (2026) method for modeling financial volatility as a nonlinear wave system. Extracts VIX/VXO/VSTOXX envelopes via FFT and Hilbert transforms, builds a Schrödinger-type Hamiltonian, and tracks eigenvalue-gradient shifts signaling Anderson localisation ahead of volatility events. 

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages