Skip to the content.

← All indicators

zeonta.ulcer_index() — Drawdown-based risk measure — the expected percentage decline, not price swing size.

What it measures

Unlike atr or bbands, which measure movement in either direction, the Ulcer Index (Peter Martin, 1987) only measures how far price has fallen from its own recent high — squaring the drawdown before averaging means a single deep decline dominates the reading far more than several small ones of the same total size, mirroring how a real drawdown actually feels to hold through.

Formula

PercentDrawdown = (Close - HighestClose(n)) / HighestClose(n) x 100; UI = sqrt(mean(PercentDrawdown^2, n))

Parameters

Required inputs: close

Parameter Default
length 14

Returns

Column
UI_14

Usage

Examples run against the 300-bar OHLCV fixture in tests/data/ohlcv.csv, loaded as df. The output shown is the real output.

import pandas as pd
import zeonta

df = pd.read_csv('tests/data/ohlcv.csv', parse_dates=['date']).set_index('date')
zeonta.ulcer_index(df['close']).tail(3)
date
2024-10-25    1.909861
2024-10-26    2.083540
2024-10-27    2.327038
Name: UI_14, dtype: float64

Accessor form: df.zta.ulcer_index(...)

How to read it

Higher readings mean deeper, more sustained drawdowns — a security a risk-averse holder would find harder to sit through, even if its raw price swings (as measured by atr) are not especially large. Comparing the Ulcer Index across candidate investments is a way to rank them by how much drawdown pain they have historically caused, independent of their average return.

Pitfalls

Originally designed with mutual funds in mind and focused purely on downside risk — it says nothing about upside potential, so it should complement a return measure, not replace one.

Reference

Formula source: https://chartschool.stockcharts.com/table-of-contents/technical-indicators-and-overlays/technical-indicators/ulcer-index