Mandelbrot Ch. 2: Fractals & Multi-Scale Market Geometry

阅读中文版

Self-similarity across timeframes, the Koch curve and coastline paradox applied to price charts, and constructing multifractal price generators.

🔊 Listen to Article (Chinese Audio)

Mandelbrot Fractal Ch. 2: Fractals & Multi-Scale Market Geometry

"Show any expert a stock chart with the time axis erased — a one-minute chart, a daily chart, a yearly chart — and no one can tell which timeframe it is from shape alone. That is not coincidence; it is the mathematical signature of fractal structure." — Benoit Mandelbrot

From the Coastline Paradox to Market Geometry

Mandelbrot's fractal geometry begins with: "How long is the coast of Britain?" The answer depends on ruler length — shorter rulers capture more jagged detail and yield longer measured coastlines. This scale-dependence is the hallmark of a fractal: self-similarity across magnifications.

Applied to markets, erasing the time axis of a price chart reveals statistically similar "texture" whether the chart spans minutes, hours, days, or months.

The Mathematics of Fractal Dimension

$$D = \frac{\log(N)}{\log(1/r)}$$

For the Koch curve, each segment splits into 4 self-similar copies at scale $r = 1/3$:

$$D_{Koch} = \frac{\log 4}{\log 3} \approx 1.2619$$

Fractal Dimension of Price Paths

Using box-counting:

$$D = \lim_{\epsilon \to 0} \frac{\log N(\epsilon)}{\log(1/\epsilon)}$$

Market Regime Fractal Dimension Path Character
Strong trend $D \approx 1.2$–$1.35$ Smooth, few reversals
Random walk / chop $D \approx 1.5$ Resembles Brownian motion
Panic / high volatility $D \approx 1.6$–$1.8$ Highly jagged, near plane-filling

Multifractal Price Generators

Unlike Geometric Brownian Motion (single fractal everywhere), Mandelbrot's multifractal model allows local fractal dimension to vary by regime — calm periods vs. panics.

import numpy as np

def midpoint_displacement_fractal(n_iterations=10, roughness=0.5, seed=42):
    np.random.seed(seed)
    n_points = 2 ** n_iterations + 1
    path = np.zeros(n_points)
    path[-1] = np.random.normal(0, 10)
    step, scale = n_points - 1, 10.0
    while step > 1:
        half = step // 2
        for start in range(0, n_points - 1, step):
            mid = start + half
            path[mid] = (path[start] + path[start + step]) / 2 + np.random.normal(0, scale)
        scale *= (0.5 ** roughness)
        step = half
    return path

Practical Execution Rules

  1. Do not draw conclusions from a single timeframe's chart pattern — self-similarity means head-and-shoulders on a daily chart is equally common (and equally non-predictive) on a 1-minute chart.
  2. Quantify regime with fractal dimension, not just moving averages — rising $D$ above 1.6 signals a shift to jagged, panic-like structure; reduce trend-following exposure.
  3. Reject the illusion that longer timeframes are inherently "more real." Fractal geometry shows no privileged natural timescale for price.