What is the Ulcer Index?
The Ulcer Index (UI) is a risk measure developed by Peter Martin in 1987. Unlike traditional volatility measures like standard deviation, the Ulcer Index focuses specifically on downside volatility and the depth and duration of drawdowns. It quantifies the "pain" an investor experiences from price declines. A higher Ulcer Index indicates greater and longer-lasting drawdowns, implying higher risk or discomfort. A lower Ulcer Index suggests more stable performance with less significant or persistent declines.
The Ulcer Index is particularly valuable in portfolio management and for assessing risk-adjusted returns, as it provides a clearer picture of the downside risk faced by a trader or investor. It helps identify assets that might offer good returns but at the cost of severe or prolonged drawdowns.
Components and Calculation
The calculation of the Ulcer Index involves a few steps:
- Percentage Drawdown (PD): For each period, calculate the percentage that the current price is below the highest price reached in the lookback period (the "peak").
`PD = ((Current Close - Highest Close in 'length' period) / Highest Close in 'length' period) * 100`
Note: PD is always negative or zero. - Squared Percentage Drawdown: Square the PD values. This emphasizes larger drawdowns.
`Squared PD = PD * PD` - Average of Squared PD: Calculate the average of these squared PD values over the specified `length` (e.g., 14 periods).
`Avg_Squared_PD = SMA(Squared PD, length)` - Ulcer Index Formula: Take the square root of the `Avg_Squared_PD`.
`Ulcer Index = math.sqrt(Avg_Squared_PD)`
A common `length` for the Ulcer Index is 14 periods, but it can be adjusted to suit different analysis timeframes.
Basic Ulcer Index (UI) Implementation in Pine Script
Pine Script v5 provides a convenient built-in function `ta.ui()` for calculating the Ulcer Index.
//@version=5
indicator("My Ulcer Index", overlay=false) // overlay=false to plot in a separate pane
// Input for Ulcer Index length
length = input.int(14, title="UI Length", minval=1)
// Calculate Ulcer Index using the built-in function
// ta.ui implicitly uses 'close' as source and the provided length
ulcerIndexValue = ta.ui(length)
// Plot the Ulcer Index line
plot(ulcerIndexValue, title="Ulcer Index", color=color.orange, linewidth=2)
// Optional: Add reference levels for visual clarity
// These levels are subjective and depend on asset/risk tolerance.
// Lower values are generally better (less "ulcer-inducing" risk).
hline(2.0, "High Risk Ref", color=color.red, linestyle=hline.style_dashed)
hline(0.5, "Low Risk Ref", color=color.green, linestyle=hline.style_dashed)
Practical Ulcer Index Trading Strategies
1. Portfolio Risk Assessment and Asset Comparison
The primary use of the Ulcer Index is for comparing the drawdown risk of different assets or strategies, and for assessing the overall risk of a portfolio.
- Comparing Assets: An asset with a consistently lower Ulcer Index (for the same period) is considered to have less downside risk, even if its standard deviation is similar to another asset. This helps in choosing assets that align with your risk tolerance.
- Strategy Evaluation: When backtesting trading strategies, incorporate the Ulcer Index (or "Sortino Ratio" which uses UI) to evaluate not just returns, but returns adjusted for downside risk. A strategy with lower UI for similar returns might be preferable.
//@version=5
indicator("Ulcer Index for Risk Comparison", overlay=false)
length = input.int(14, title="UI Length", minval=1)
ulcerIndexValue = ta.ui(length)
plot(ulcerIndexValue, "Ulcer Index", color=color.orange, linewidth=2)
// Example: Display current Ulcer Index on chart
if barstate.islast
label.new(bar_index, ulcerIndexValue, "UI: " + str.tostring(ulcerIndexValue, "#.##"),
style=label.style_label_down, color=color.blue, textcolor=color.white)
// You'd typically use this for comparative analysis across different symbols or strategy runs
// rather than direct buy/sell signals on a single chart.
// Consider combining this with a custom screener or a script that plots multiple UIs.
2. Risk-Adjusted Entry/Exit Signals (Contextual)
While not a direct buy/sell signal generator, the Ulcer Index can provide context for trading decisions. For example, some traders might prefer to enter trades when the Ulcer Index is relatively low, suggesting less recent downside risk.
- Low UI for Entries: Consider entering a long position when the Ulcer Index for the asset is at historically low levels, suggesting a period of calm and minimal recent drawdowns. This could indicate a consolidation phase before an uptrend or a stable recovery.
- High UI for Exits/Caution: When the Ulcer Index rises significantly, indicating increasing drawdown risk, it might be a signal to reduce position size, tighten stops, or consider exiting profitable trades to avoid deeper pullbacks.
//@version=5
strategy("Ulcer Index Risk-Adjusted Strategy", overlay=true)
length = input.int(14, title="UI Length", minval=1)
ulcerIndexValue = ta.ui(length)
plot(ulcerIndexValue, "Ulcer Index", color=color.orange, display=display.pane_only)
hline(0.5, "Low UI Threshold", color=color.green, linestyle=hline.style_dashed, display=display.pane_only)
hline(1.5, "High UI Threshold", color=color.red, linestyle=hline.style_dashed, display=display.pane_only)
// Simple trend filter for entries
emaFast = ta.ema(close, 10)
emaSlow = ta.ema(close, 20)
isUptrend = emaFast > emaSlow and emaFast[1] <= emaSlow[1] // Bullish crossover
// Long Entry Condition: Bullish crossover AND UI is relatively low
longCondition = isUptrend and ulcerIndexValue < 0.7 // Example threshold
// Short Exit Condition: UI rises above a certain point, indicating increased drawdown
shortExitCondition = ulcerIndexValue > 1.0 and strategy.position_size > 0 // Exit if UI is high and we are long
if (longCondition)
strategy.entry("Long (Low UI)", strategy.long)
if (shortExitCondition)
strategy.close("Long (Low UI)", comment="High UI Exit")
// You would add more sophisticated exit rules (e.g., trend reversal, stop loss)
// and consider short entries when appropriate (e.g., downtrend + high UI)
3. Ulcer Index Divergence (Less Common)
While not its primary function, divergence between price and the Ulcer Index can sometimes offer insights, though interpretation requires care.
- Bullish Divergence: Price makes a lower low, but Ulcer Index makes a lower high (or remains relatively stable). This might suggest that despite price declining, the *severity* of drawdowns is not increasing, potentially indicating an exhaustion of selling pressure.
- Bearish Divergence: Price makes a higher high, but Ulcer Index makes a higher low (or continues to rise). This could mean that even as price rises, the underlying volatility and drawdown risk are increasing, signaling potential instability.
//@version=5
indicator("Ulcer Index Divergence", overlay=true)
length = input.int(14, title="UI Length", minval=1)
ulcerIndexValue = ta.ui(length)
plot(ulcerIndexValue, "Ulcer Index", color=color.orange)
hline(0.5, "Low UI Ref", color=color.green, linestyle=hline.style_dashed)
hline(1.5, "High UI Ref", color=color.red, linestyle=hline.style_dashed)
// Simple divergence detection (conceptual, robust detection requires advanced pivot logic)
// This is a simplified example focusing on price vs UI divergence.
// Bullish Divergence (Price lower low, UI lower high / stable)
// Price makes lower low, UI shows less "pain"
bullishDivergence = close < close[1] and close[1] < close[2] and ulcerIndexValue > ulcerIndexValue[1] and ulcerIndexValue[1] > ulcerIndexValue[2]
// Bearish Divergence (Price higher high, UI higher low / increasing "pain")
// Price makes higher high, UI shows more "pain"
bearishDivergence = close > close[1] and close[1] > close[2] and ulcerIndexValue < ulcerIndexValue[1] and ulcerIndexValue[1] < ulcerIndexValue[2]
plotshape(bullishDivergence, title="Bullish UI Divergence", location=location.belowbar, color=color.blue, style=shape.diamond, size=size.small)
plotshape(bearishDivergence, title="Bearish UI Divergence", location=location.abovebar, color=color.fuchsia, style=shape.diamond, size=size.small)
alertcondition(bullishDivergence, "Bullish UI Divergence", "Ulcer Index indicating potential bullish sentiment shift.")
alertcondition(bearishDivergence, "Bearish UI Divergence", "Ulcer Index indicating potential bearish sentiment shift.")
Optimizing Ulcer Index Performance
To get the most from the Ulcer Index in Pine Script:
- Parameter Tuning: The `length` parameter defines the lookback period for calculating drawdowns. A shorter length (e.g., 7 periods) will make UI more sensitive to recent, short-lived drawdowns. A longer length (e.g., 20 or 25 periods) will smooth out the index and reflect more significant, persistent drawdowns.
- Contextual Interpretation: The absolute value of the Ulcer Index is not as important as its relative value for a given asset over time, or its comparison across different assets. Determine what constitutes "high" or "low" UI for the specific asset you are analyzing through historical observation.
- Combine with Directional Indicators: The Ulcer Index is a risk indicator, not a directional one. It tells you *about* the risk, not *where* price is going. Always combine it with trend-following or momentum indicators to confirm entry/exit signals.
- Risk-Adjusted Ratios: The Ulcer Index is often used in performance metrics like the Sortino Ratio (`(Return - Risk-Free Rate) / Ulcer Index`) to evaluate risk-adjusted returns, providing a more robust measure than Sharpe Ratio for downside risk.
- Multi-Timeframe Analysis: Analyze UI on higher timeframes to understand the broader downside risk profile of an asset before looking for entry/exit signals on lower timeframes.
Common Ulcer Index Pitfalls
- Not a Directional Signal: The most common mistake is attempting to use Ulcer Index directly for buy/sell signals without considering price action or trend. It primarily measures risk, not momentum or direction.
- Lagging Indicator: As it's based on historical data and calculations, the Ulcer Index is a lagging indicator. It reflects past drawdowns, not immediate future price movements.
- Subjective Thresholds: There are no universal "overbought" or "oversold" levels for the Ulcer Index. What constitutes "high" or "low" risk depends on the asset, timeframe, and your personal risk tolerance, requiring careful calibration.
- Missed Opportunities: Waiting for an extremely low Ulcer Index to enter might mean missing out on significant early trend moves.
- Not a Standalone Indicator: The Ulcer Index provides crucial risk context but should always be part of a comprehensive trading system, never used in isolation.
Conclusion
The Ulcer Index is a valuable and distinct technical indicator available in Pine Script for TradingView, offering a unique perspective on market risk by quantifying the depth and duration of price drawdowns. Unlike traditional volatility measures, it directly addresses the "pain" associated with investment declines, making it particularly useful for portfolio management and assessing risk tolerance. While not a directional signal generator, its ability to highlight periods of significant downside risk or stability provides crucial context for trading decisions. By understanding its calculation, thoughtfully tuning its parameters, and integrating it strategically with directional indicators and robust risk management practices, you can leverage the Ulcer Index to make more informed and risk-aware trading decisions.
Enhance Your Trading
Get a high-performance Pine Script analysis tool for actionable market insights, designed for traders on the move.
This strategy runs in live mode on TradingView, helping you identify potential opportunities.
Subscribe now @ $99/month