Help with Formula for Ulcer Index

The Ulcer Index is an analytical tool that I would like to use in evaluating trading strategies. I have tried to make a formula file to calculate it and use Exploration output to compare results with the Ulcer Index metric that Amibroker provides with its standard backtest report.

The basic formula from the original developer is:
SumSq = 0
MaxValue = 0
for T = 1 to NumOfPeriods do
if
Value[T] > MaxValue then MaxValue = Value[T]
else
SumSq = SumSq + sqr(100 * ((Value[T] / MaxValue) - 1))
UI = sqrt(SumSq / NumOfPeriods)

Or in common language:
Percent Drawdown = ((Close - NumPeriods Max Close) / Max Close) X 100
Squared Average = (NumPeriods Sum of Percent Drawdown Squared / NumPeriods
Ulcer Index = Square Root of Squared Average

My formula attempt to make the UI calculation is:

GraphLabelDecimals = 2;
SetChartOptions( 0, chartShowDates | chartWrapTitle );
uiPer = Param( "UI Periods", 55, 34, 233 );
//---------------------------------------------------------
//                   Detect Watchlist
//---------------------------------------------------------
wlnumber = GetOption( "FilterIncludeWatchlist" );
watchlist = GetCategorySymbols( categoryWatchlist, wlnumber );
wlist = CategoryGetName( categoryWatchlist, wlnumber );
//---------------------------------------------------------
//                     Calculate UI
//---------------------------------------------------------
xPeak = HHV( Close, uiPer );
maxEq = IIf( Close > Ref( xPeak, -1 ), Close, xPeak );
cDD = ( HHV( C, uiPer ) - C ) / HHV( C, uiPer ) * 100;		//current drawdown
maxDD = HHV( cDD, uiPer );
sqrDD = cDD ^ 2;
sumDD = Sum( sqrDD, uiPer );
UI = sqrt( sumDD / uiPer );
Plot( UI, "", colorYellow );
//---------------------------------------------------------
//                   Title Information
//---------------------------------------------------------
Title = Name() + "  (" + _SECTION_NAME() + ")" +
        EncodeColor( colorDarkYellow ) + "   UI Lookback " + UIper +
        EncodeColor( colorPaleBlue ) + " - " + Prec( UI, 5 );
//---------------------------------------------------------
//             Specify Columns for Exploration
//---------------------------------------------------------
Filter = 1;
SetSortColumns( 2 );
SetOption( "NoDefaultColumns", True );
AddTextColumn( Name(), "  " + UIper + " Day", 1.0, -1, -1, 55 );
AddColumn( DateTime(), "Lookback  ",
           formatDateTime, colorDefault, colorDefault, 110 );
AddColumn( UI, "UI", 1.2, colorCustom1, colorDefault, 50 );type or paste code here

The Exploration output of this formula does not match the Amibroker calculation, but strangely, when the formula is plotted on a chart, the UI value matches.

There is an error in my formula, but after hours of trying, I have not been able to determine what the problem is. I welcome any suggestions from more experienced programmers that would identify necessary corrections so the formula will properly calculate the UI.

Russell

1 Like

Hi Russman, wow that's a big effort but why do reinvent the wheel? :wink:
Ulcer Index and Ulcer Performance Index are already part of the standard metrics reported using the default backtester.

Please refer to THIS part of the manual for the metrics already available.

Thanks 2DD for the reply and the link.

I would like to use the Ulcer Index as a volatility input, along with other factors, in the determination of PositionScore. I can't use the backtest report output for this purpose, thus the need for a custom formula.

It is frustrating that my best effort to code a formula for the UI is not sufficient. I was hoping to get suggested changes from other forum members so the formula will give the correct result.

@russman, chart and exploration values should be the same.
When running an exploration, did you set the parameter to the same value you use in the chart?

image

2 Likes

@Russman I believe that @beppe has found your problem. I think you need to match up the number of bars in your backtest with your U.I. calculation. I did a simple version and ran the exploration against a buy-and-hold (single instrument) over a couple of different periods and the results appear to match.

uiPERIODS  = Cum( Status( "barinrange" ) ); 
HH_Close 	= HHV( C, uiPERIODS );
pctDD		= 100 * ( ( Close - HH_Close ) / HH_Close );
myUI 		= sqrt( Sum( pctDD*pctDD, uiPERIODS ) / uiPERIODS );

///////////////////////////////////////////////////////////////////////////
// Exploration
///////////////////////////////////////////////////////////////////////////
if( Status( "action" ) == actionExplore )
{
    Filter = 1;
    AddColumn( myUI, "myUI", 1.2 );
}


1 Like

Many thanks to both @beppe and @portfoliobuilder for pointing out the problem with my formula. Especially to @portfoliobuilder for providing working code that gave the correct Ulcer Index values, both in an Exploration and on a Chart. Their guidance also led me to realize the reason why my coding attempt failed, and allowed me to advance a little further my understanding of AFL.

2 Likes