Ulcer Performance Index aka Martin Ratio - problems on refresh

 

I've written an indicator for the Ulcer Performance Index, also known as the Martin Ratio. It works, but on chart refresh, it often doesn't recalculate and update the display correctly. I used code from the Ulcer Index to try to prevent constantly recalculating the whole thing, but it still has issues on a chart refresh. What am I missing?

//+------------------------------------------------------------------+
//|                                       UlcerPerformanceIndex.mq5  |
//|                                      Copyright 2024, Scott Allen |
//|                       https://www.mql5.com/en/users/mustaphamond |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Scott Allen"
#property link      "https://www.mql5.com/en/users/mustaphamond"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   1
#property indicator_label1  "UPI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
input int      LookBackPeriod=262;
input int      SmoothPeriod = 10;
double         UPIBuffer[];
double         SmoothedUPIBuffer[];
double         UIBuffer[];
double         DrawDownBuffer[];

int OnInit()
  {
    if(LookBackPeriod <= SmoothPeriod)
    {
        Print("Error: LookBackPeriod must be greater than SmoothPeriod.");
        return(INIT_FAILED); // Initialization failed due to incorrect parameters
    }
    SetIndexBuffer(0, SmoothedUPIBuffer, INDICATOR_DATA);
    SetIndexBuffer(1, UPIBuffer, INDICATOR_DATA);
    SetIndexBuffer(2, UIBuffer, INDICATOR_CALCULATIONS);
    SetIndexBuffer(3, DrawDownBuffer, INDICATOR_CALCULATIONS);
   return(INIT_SUCCEEDED);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int i=(int)MathMax(prev_calculated-1,1);  for(; i<rates_total && !_StopFlag; i++)
     {
      DrawDownBuffer[i]=((close[i]-close[ArrayMaximum(close,LookBackPeriod,i)])/close[ArrayMaximum(close,LookBackPeriod,i)]);
      double squaredDD = 0.0;
      double squaredAvg=0.0;
      if(i>=LookBackPeriod)
        {
            for(int x=i-LookBackPeriod;x<i;x++)
              {
               squaredDD=squaredDD+MathPow(DrawDownBuffer[x],2);
              }
            squaredAvg=squaredDD/LookBackPeriod;
            UIBuffer[i]=MathSqrt(squaredAvg);
            // Calculate Ulcer Performance Index
            double netProfit = (close[i] - close[i-LookBackPeriod]) / close[i-LookBackPeriod];
            UPIBuffer[i] = netProfit / UIBuffer[i];
            double sumUPI = 0.0;
            for(int j = i - SmoothPeriod + 1; j <= i; j++)
            {
               sumUPI += UPIBuffer[j];
            }
            SmoothedUPIBuffer[i] = sumUPI / SmoothPeriod;
         }
     }
   return(i);
  }
Ulcer Index
Ulcer Index
  • www.mql5.com
This Ulcer Index indicator was derived from the stock risk indicator by Peter Martin in the 1987 book "The Investors Guide to Fidelity Funds".
 
   int i=(int)MathMax(prev_calculated-1,1);  for(; i<rates_total && !_StopFlag; i++)

See How to do your lookbacks correctly #9#14 & #19. (2016)

Reason: