Sortino Ratio - Custom metric

I consider Sortino Ratio to be the best out of all the "ratios" (Sharpe, payoff ratio, k-ratio, etc etc.) I'm a big fan of Sortino Ratio. Unfortunately it's not built in to Amibroker. Has anyone ever coded this as a custom metric?

Hi @cm111,

Would you like to "kick-off" the process by providing some references, code, illustrations, justification for why it's better than other measures?

A good recap is this article about the Measures of Risk-adjusted Return with many external links to learn more and easy to read code examples (in Python using numpy).

Porting the various ratios to AFL seems a task approachable by someone with a good knowledge of both programming languages and the required math skills to create some functions not directly available in AmiBroker.


@cm111 I'd agree the Sortino ratio may encompass more information than the commonly used Sharpe ratio but disagree that it has more information than other ratio's (see @beppe 's list in the link above) .

In particular something like the Ulcer Performance Index (built into AmiBroker) as you look at the similarities in the formula's


IMHO there is more information in the Ulcer Performance Index as it has the difference in it’s denominator, not only factoring in the severity of the drawdowns but also their duration .

Add to this there are different funds/advisors/data sources using different methods of calculating the Sortino ratio. That can't be good for the rest of us trying to evaluate the indicator,

And although the math is over my head some people use the "continuous" vs the "discrete" version of calculating the Sortino,

I took a crack at the discrete version, but I think there is something not quite correct. I post this with the hope that a superior coder and statistician will be emboldened to do it right.

// Sortino ratio attempt v1.0, doesn't seem correct

// Calcluate gain/Loss in %, Monthly??
Returns = ROC( C, 1 );

// you can and should Paramaterize the next two variables
RequiredReturn = 0.2; // this input, which you the user chooses, will make a huge difference
Periods = 12; // in this example 12 months look back period

ExcessReturn = Returns - RequiredReturn;
AvExcessReturn = MA( ExcessReturn, Periods );

// Need a variable with only % losses, if a gain set to 0;
NegativeExcessReturns = IIf( ExcessReturn < 0, ExcessReturn, 0 ); // NER

// square it
/* in the paper from redrockcapital, they say in this step 

"calculate the square of each value in
the underperformance data set determined in
the first step. Note that percentages need to be
expressed as decimal values before squaring, i.e.
5% = 0.05"

SqNER = ( NegativeExcessReturns/100 ) ^ 2.0;

// Add up each neg % squared over Periods bars;
SumSqNER = Sum( SqNER, Periods );

DownSideRisk = ( SumSqNER / Periods ) ^ 0.5;

Sortino = AvExcessReturn / DownSideRisk;


@cm111 I have found the Sortino coded as a custom metric using the high level CBT in one of @howardbandy 's books. Quantitative Technical Analysis. For those users unfamiliar with Dr Bandy's work, he has published several books on trading system development and has many useful AmiBroker code examples in his books.


Thank you @beppe, that's great information. Thanks @portfoliobuilder and I'll check out the book! Actually was not all that familiar with UPI but sounds like it might indeed be better.

1 Like

Lot's and lot's of ratios out there belonging to the so called Post-modern Portfolio Theorists. From what Id read, the Ulcer uses a discrete return approach (percentage ratio from A to B) as opposed to continuous returns (diff of log returns from all points from A to B). Don't know exactly what this could compromise statistical compounding comparisons of portolio construction.

Anyway, I found some fancy tweaks from this guys at KeyQuant to the original Ulcer (and Martin's ratio) that adds an additional weighting factor from a -penalized risk ratio-. Looks interesting, both papers openly found here and here.


Very nice, thanks for sharing!