# Optimizing sortino ratio in OnTester() using genetic algorithms? - page 2

82

Calculating average trade results in pip gives you another good and easily interpretable measure. You immediately see the probable influence of slippage/commissions/swap on your results. If your average trade gains less than 5 pip the probability is high that most of your theoretical gains will be eaten away by trading costs.

Another option in the calulation of the sortino ratio is to not skip positive results but instead skip all results better then the mean. This way your sortino ratio describes all trades worse then the average trade which may make sense, too. It depends on what you prefer/want to know with your stats...

Wow! Thank you so so so much for your quality post and time. You have by far provided the most quality and information to me than any other member on this forum and this is not an exaggeration. I wish there were people like you here. Thank you for helping out a fellow quant.

Anyway, the code you returned gives me a few errors that I cant seem to fix. Maybe they will pop up for you if you compile your code. This is what I have so far:

```void CalculateRatios() {
double totalPips, pips[];
ArrayResize(pips, orders);

int    pipDigits = Digits & (~1);
double pip       = NormalizeDouble(1/MathPow(10, pipDigits), pipDigits);

for (int i=0; i < orders; i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && OrderSymbol()==Symbol() && OrderType()<=OP_SELL) {
pips[trades] = (OrderType()-OrderType()^1) * (OrderOpenPrice()-OrderClosePrice()) / pip;
}
}

double sharpe  = CalculateSharpeRatio(pips, totalPips);
double sortino = CalculateSortinoRatio(pips, totalPips);

Print("trades="+ trades +"  totalPips="+ DoubleToStr(totalPips, 1) +"  avgPips="+ DoubleToStr(avgPips, 2) +"  sharpe="+ DoubleToStr(sharpe, 4) +"  sortino="+ DoubleToStr(sortino, 4));
}

/**
*
*/
double CalculateSharpeRatio(double values[], double sum) {
int size = ArraySize(values);
if (!size) return(NULL);

double mean = sum / size;
double sharpe = mean / MathStdev(values, mean);
return(sharpe);
}

/**
*
*/
double CalculateSortinoRatio(double values[], double sum) {
int size = ArraySize(values);
if (!size) return(NULL);

double losses[];
ArrayResize(losses, size);

for (int i, n=0; i < size; i++) {
if (values[i] <= 0) {
losses[n] = values[i];
n++;
}
}
ArrayResize(losses, n);

double mean = sum / size;
double sortino = mean / MathStdev(losses, mean);
return(sortino);
}

/**
*
*/
double MathStdev(double values[], double mean) {
int size = ArraySize(values);
if (!size) {
double N_INF = MathLog(0);         // negative infinity
double P_INF = -N_INF;             // positive infinity
double NaN   =  N_INF - N_INF;     // not-a-number
return(NaN);
}

double sum;
for (int i=0; i < size; i++) {
sum += MathPow((values[i] - mean), 2);
}
double stdDev = MathSqrt(sum / size);
return(stdDev);
}

double OnTester()
{
CalculateRatios();
return sortino;
}```

Im 100% sure I have the last bit wrong but feel free to correct me, however, the problems are

```'n' - undeclared identifier

'sortino' - undeclared identifier

and

'values' - arrays are passed by reference only
'values' - arrays are passed by reference only
'values' - arrays are passed by reference only
```
94

QuantCoder:..Anyway, the code you returned gives me a few errors that I cant seem to fix. Maybe they will pop up for you if you compile your code. This is what I have so far:

Im 100% sure I have the last bit wrong but feel free to correct me, however, the problems are...

I forgot to compile with "#property strict". Fixed. And I changed the calculation of the standard deviation from the full population to a sample.

```double OnTester() {
double totalPips=0, pips[];
ArrayResize(pips, orders);

int    pipDigits = Digits & (~1);
double pip       = NormalizeDouble(1/MathPow(10, pipDigits), pipDigits);

for (int i=0; i < orders; i++) {
if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && OrderSymbol()==Symbol() && OrderType()<=OP_SELL) {
pips[trades] = (OrderType()-(OrderType()^1)) * (OrderOpenPrice()-OrderClosePrice()) / pip;
}
}

double avgPips=0, sharpe=0, sortino=0;
sharpe  = CalculateSharpeRatio(pips, totalPips);
sortino = CalculateSortinoRatio(pips, totalPips);
}
Print("trades=", trades, "  totalPips=", DoubleToStr(totalPips, 1), "  avgPips=", DoubleToStr(avgPips, 2), "  sharpe="+ DoubleToStr(sharpe, 4), "  sortino=", DoubleToStr(sortino, 4));
return(sortino);
}

/**
*
*/
double CalculateSharpeRatio(double &values[], double sum) {
int size = ArraySize(values);
if (!size) return(NULL);

double mean = sum / size;
double sharpe = mean / MathStdev(values, mean);
return(sharpe);
}

/**
*
*/
double CalculateSortinoRatio(double &values[], double sum) {
int n=0, size = ArraySize(values);
if (!size) return(NULL);

double losses[];
ArrayResize(losses, size);

for (int i=0; i < size; i++) {
if (values[i] <= 0) {
losses[n] = values[i];
n++;
}
}
ArrayResize(losses, n);

double mean = sum / size;
double sortino = mean / MathStdev(losses, mean);
return(sortino);
}

/**
*
*/
double MathStdev(double &values[], double mean) {
int size = ArraySize(values);
if (size < 2) {
double N_INF = MathLog(0);         // negative infinity
double P_INF = -N_INF;             // positive infinity
double NaN   =  N_INF - N_INF;     // not-a-number
return(NaN);
}

double sum = 0;
for (int i=0; i < size; i++) {
sum += MathPow((values[i] - mean), 2);
}
double stdDev = MathSqrt(sum / (size-1));
return(stdDev);
}
```
610

The 1 is caused by this part:

iStdDevOnArray() can be considered undocumented. In the last 10 years I never found a working example here or anywhere at the web. So until some person smarter then me comes up with the right syntax I calculate the std-dev manually if I need it:

Essentially this is the manual way to calculate std-dev. You have to adapt the iMAOnArray() part to your profit series.

If I am not wrong, the distance between one point to the average or other reference is called "location".
Location parameter - Wikipedia
• en.wikipedia.org
f x 0 ( x ) = f ( x − x 0 ) . {\displaystyle f_{x_{0}}(x)=f(x-x_{0}).} [ ] Here, is called the location parameter. Examples of location parameters include the mean, the median, and the mode. Thus in the one-dimensional case if is increased, the probability density or mass function shifts rigidly to the right, maintaining its exact...
610

I decided to study more on Sortino. And I wrote a code to calculate deal by deal, but the core calculation is done by this:

```   double sum    = 0.0; // Simple sum
double sumTDD = 0.0; // Target Downside Deviation
double sumTUD = 0.0; // Target Upside Deviation
for(int l=0;l<ArraySize(Results);l++)
{
sum = sum + Results[l];
sumTDD = sumTDD + MathPow(MathMin(0,Results[l]),2);
sumTUD = sumTUD + MathPow(MathMax(0,Results[l]),2);
}

double average = sum / (1.0*ArraySize(Results));

double variance = 0.0;

for(int l=0;l<ArraySize(Results);l++)
{
variance = variance + pow(Results[l]-average,2);
}

variance = variance / (1.0*ArraySize(Results));

double StdDev = MathSqrt(variance);                  // Standard Deviation
double TDD    = MathSqrt(sumTDD/ArraySize(Results)); // Target Downside Deviation
double TUD    = MathSqrt(sumTUD/ArraySize(Results)); // Target Upside Deviation```

The concept of Target Upside Deviation (TUD) is mine. I do a lot of High Frequency Trading and Scalping in daytrading, but performance indicators such as Sharpe and Sortino applies a little bit different. I am trying to develop a non-parametric indicator that applies to every trade, so I can evaluate better my EA. My target is to skew my EA results as much as possible from normal distribution. To profit direction, of course :)

Sortino A Sharper Ratio Red Rock Capital
• David Cohen