Mandelbrot Ch. 4: Volatility Clustering & Multi-Fractal Trading Time

阅读中文版

Why large moves cluster together, the distinction between clock time and trading time, and building a multifractal time-deformation model.

🔊 Listen to Article (Chinese Audio)

Mandelbrot Fractal Ch. 4: Volatility Clustering & Multi-Fractal Trading Time

"Market time is not the uniform time of a clock — it is elastic, compressed by panic and stretched by calm. Understanding this distinction between trading time and clock time is the key to volatility clustering." — Benoit Mandelbrot

"Large Changes Follow Large Changes, Small Follow Small"

Mandelbrot's cotton-price research revealed volatility clustering: violent moves cluster together, calm periods cluster together, and the clustering pattern itself is fractal — self-similar across timeframes. This directly contradicts Geometric Brownian Motion's assumption of constant volatility.

Clock Time vs. Trading Time

Mandelbrot distinguished clock time (uniform physical seconds) from trading time — the market's internal rhythm of information flow and activity, which is not synchronized with the clock.

$$\theta(t) = \int_0^t \phi(s)\,ds$$

where $\theta(t)$ is cumulative trading time and $\phi(s)$ is an activity-density proxy (volume or realized volatility). Under trading time $\theta$, prices behave closer to standard Brownian motion; under clock time $t$, they show clustered fat tails.

GARCH vs. Multifractal Cascades

$$\sigma_t^2 = \omega + \alpha\epsilon_{t-1}^2 + \beta\sigma_{t-1}^2$$

GARCH captures short-run mean-reverting volatility clustering with a single autoregressive timescale. Mandelbrot's multifractal cascade model instead allocates volatility weight recursively across multiple timescales, naturally reproducing cross-scale clustering.

Model Time-Scale Treatment Clustering Fidelity
GBM Single constant volatility None
GARCH(1,1) Single autoregressive scale Partial, short-run only
Multifractal cascade Multi-level cascade Cross-scale self-similar clustering
import numpy as np

def multifractal_cascade_volatility(n_steps=1024, levels=10, m0=0.6, seed=7):
    np.random.seed(seed)
    weights = np.ones(1)
    for _ in range(levels):
        m1 = np.random.choice([m0, 2 - m0], size=len(weights))
        m2 = 2 - m1
        weights = np.column_stack([weights * m1, weights * m2]).flatten()
    weights = weights[:n_steps] / np.mean(weights[:n_steps])
    return np.random.normal(0, 1, n_steps) * np.sqrt(np.abs(weights))

Practical Execution Rules

  1. Cut leverage proactively during panic regimes rather than waiting for lagging volatility confirmation — clustering means high volatility tends to persist for subsequent sessions.
  2. Model options around information-flow density, not calendar days — earnings, FOMC, and holidays deform trading time relative to clock time.
  3. Monitor multiple realized-volatility windows (5/20/60-day) rather than a single GARCH parameter, since clustering has genuine cross-scale structure.