Converting Ultimate Oscillator

 

Hi guys :)

Modifying the Ultimate Oscillator indicator so that it takes a custom symbol, rather than defaulting to the chart symbol. I have made the same changes that have worked with other base indicators but I am getting errors. I suspect the errors are due to the chart querying for data from a different symbol but I don't know how to fix it! Note, this is on MT5.

I have added the following to the parameters:

input string name="GBPUSD"

 and changed Symbol() to name in the init()

//--- get handles
   ExtFastATRhandle=iATR(name,0,InpFastPeriod);
   ExtMiddleATRhandle=iATR(name,0,InpMiddlePeriod);
   ExtSlowATRhandle=iATR(name,0,InpSlowPeriod);

 Error I am getting is Not all data of ExtSlowATRhandle is calculated (-1 bars).

Any ideas or help appreciated :)

Would like to show several currencies on the one chart to see movements on one chart.

Rich 

 

Try using SymbolSelect().

int OnInit()
  {
   if(!SymbolSelect(name,true))
     {
      Alert(name," not available in Market Watch.\nInitialization Failed.");
      return(INIT_FAILED);
     }
 

Hi pipPod

Thanks for your help, I have given it a go but sadly no luck. Here is the top half of the indicator with my modifications commented.

//+------------------------------------------------------------------+
//|                                          Ultimate_Oscillator.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#include <MovingAverages.mqh>
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  DodgerBlue
//--- input parameters
input int InpFastPeriod=7;     // Fast ATR period
input int InpMiddlePeriod=14;  // Middle ATR period
input int InpSlowPeriod=28;    // Slow ATR period
input int InpFastK=4;          // Fast K
input int InpMiddleK=2;        // Middle K
input int InpSlowK=1;          // Slow K

input string name= "GBPUSD";     //--- custom symbol
//--- indicator buffers
double    ExtUOBuffer[];
double    ExtBPBuffer[];
double    ExtFastATRBuffer[];
double    ExtMiddleATRBuffer[];
double    ExtSlowATRBuffer[];
//--- indicator handles
int       ExtFastATRhandle;
int       ExtMiddleATRhandle;
int       ExtSlowATRhandle;
//--- global variable
double    ExtDivider;
int       ExtMaxPeriod;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtUOBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtBPBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,ExtFastATRBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,ExtMiddleATRBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,ExtSlowATRBuffer,INDICATOR_CALCULATIONS);
//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//--- set levels
   IndicatorSetInteger(INDICATOR_LEVELS,2);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,30);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,70);
//--- set maximum and minimum for subwindow 
   IndicatorSetDouble(INDICATOR_MINIMUM,0);
   IndicatorSetDouble(INDICATOR_MAXIMUM,100);
//--- set first bar from which index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpSlowPeriod-1);
//--- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"UOS("+string(InpFastPeriod)+", "+string(InpMiddlePeriod)+", "+string(InpSlowPeriod)+")");
   
   if(!SymbolSelect(name,true))
     {
      Alert(name," not available in Market Watch.\nInitialization Failed.");
      //return(INIT_FAILED);
     }
       
     
//--- get handles
   ExtFastATRhandle=iATR(name,0,InpFastPeriod);       //--- changed Symbol() to name variable
   ExtMiddleATRhandle=iATR(name,0,InpMiddlePeriod);   //--- changed Symbol() to name variable
   ExtSlowATRhandle=iATR(name,0,InpSlowPeriod);       //--- changed Symbol() to name variable
//---
   ExtDivider=InpFastK+InpMiddleK+InpSlowK;
   ExtMaxPeriod=InpSlowPeriod;
   if(ExtMaxPeriod<InpMiddlePeriod) ExtMaxPeriod=InpMiddlePeriod;
   if(ExtMaxPeriod<InpFastPeriod)   ExtMaxPeriod=InpFastPeriod;
//--- initialization done
  }
//+------------------------------------------------------------------+
//| Ultimate Oscillator                                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,

 The OnInit() wouldn't accept a return code so I commented it out. 

It seems really odd as it works for other indicators I have adjusted.

Thanks again for your help. 

 

You can change OnInit() to an integer.

A few other changes to the code are necessary. Haven't thoroughly tested code below, but it seems to work.

 

//+------------------------------------------------------------------+
//|                                          Ultimate_Oscillator.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#include <MovingAverages.mqh>
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
//--- input parameters
input int InpFastPeriod=7;     // Fast ATR period
input int InpMiddlePeriod=14;  // Middle ATR period
input int InpSlowPeriod=28;    // Slow ATR period
input int InpFastK=4;          // Fast K
input int InpMiddleK=2;        // Middle K
input int InpSlowK=1;          // Slow K
input int InpBarsToCount=300;  // Bars to count

input string name= "GBPUSD";     //--- custom symbol
//--- indicator buffers
double    ExtUOBuffer[];
double    ExtBPBuffer[];
double    ExtFastATRBuffer[];
double    ExtMiddleATRBuffer[];
double    ExtSlowATRBuffer[];
double    Low[];
double    Close[];
//--- indicator handles
int       ExtFastATRhandle;
int       ExtMiddleATRhandle;
int       ExtSlowATRhandle;
//--- global variable
double    ExtDivider;
int       ExtMaxPeriod;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtUOBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtBPBuffer,INDICATOR_CALCULATIONS);
   //SetIndexBuffer(2,ExtFastATRBuffer,INDICATOR_CALCULATIONS);
   //SetIndexBuffer(3,ExtMiddleATRBuffer,INDICATOR_CALCULATIONS);
   //SetIndexBuffer(4,ExtSlowATRBuffer,INDICATOR_CALCULATIONS);
//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//--- set levels
   IndicatorSetInteger(INDICATOR_LEVELS,2);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,30);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,70);
//--- set maximum and minimum for subwindow 
   IndicatorSetDouble(INDICATOR_MINIMUM,0);
   IndicatorSetDouble(INDICATOR_MAXIMUM,100);
//--- set first bar from which index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,Bars(NULL,0)-InpBarsToCount);
//--- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"UOS("+string(InpFastPeriod)+", "+string(InpMiddlePeriod)+", "+string(InpSlowPeriod)+")");
   
   if(!SymbolSelect(name,true))
     {
      Alert(name," not available in Market Watch.\nInitialization Failed.");
      return(INIT_FAILED);
     }
//--- get handles
   ExtFastATRhandle=iATR(name,0,InpFastPeriod);       //--- changed Symbol() to name variable
   ExtMiddleATRhandle=iATR(name,0,InpMiddlePeriod);   //--- changed Symbol() to name variable
   ExtSlowATRhandle=iATR(name,0,InpSlowPeriod);       //--- changed Symbol() to name variable
//---
   ExtDivider=InpFastK+InpMiddleK+InpSlowK;
   ExtMaxPeriod=InpSlowPeriod;
   if(ExtMaxPeriod<InpMiddlePeriod) ExtMaxPeriod=InpMiddlePeriod;
   if(ExtMaxPeriod<InpFastPeriod)   ExtMaxPeriod=InpFastPeriod;
//--- initialization done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   if(rates_total<=InpBarsToCount+InpSlowPeriod || Bars(name,0)<=InpBarsToCount+InpSlowPeriod)
      return(0);
   ArraySetAsSeries(time,true);
   int toCount,begin=0;
   toCount=(prev_calculated<=0)?InpBarsToCount+1:rates_total-prev_calculated+2;
   if(CopyBuffer(ExtFastATRhandle,0,time[0],time[toCount-1],ExtFastATRBuffer)!=toCount ||
      CopyBuffer(ExtMiddleATRhandle,0,time[0],time[toCount-1],ExtMiddleATRBuffer)!=toCount ||
      CopyBuffer(ExtSlowATRhandle,0,time[0],time[toCount-1],ExtSlowATRBuffer)!=toCount ||
      CopyLow(name,0,time[0],time[toCount-1],Low)!=toCount ||
      CopyClose(name,0,time[0],time[toCount-1],Close)!=toCount)
      return(0);
//---
   double TL,RawUO;
   if(prev_calculated<=0)
     { 
      begin=rates_total-InpBarsToCount;
      ExtBPBuffer[begin-1]=ExtUOBuffer[begin-1]=0.0;
      for(int i=begin-InpSlowPeriod,k=1;i<=begin;i++,k++)
        {
         ExtUOBuffer[i]=0.0;
         TL=MathMin(Low[k],Close[k-1]);
         ExtBPBuffer[i]=Close[k]-TL;
        }
     }
   else
      begin=prev_calculated-1;
//---
   for(int i=begin,k=1;i<rates_total&&!IsStopped();i++,k++)
     {
      //--- TL is True Low
      TL=MathMin(Low[k],Close[k-1]);
      //--- buying pressure
      ExtBPBuffer[i]=Close[k]-TL;
      //--- first we calculate "raw" value
      if(ExtFastATRBuffer[k]!=0.0 && 
         ExtMiddleATRBuffer[k]!=0.0 &&
         ExtSlowATRBuffer[k]!=0.0)
        {
         RawUO=InpFastK*SimpleMA(i,InpFastPeriod,ExtBPBuffer)/ExtFastATRBuffer[k]+
               InpMiddleK*SimpleMA(i,InpMiddlePeriod,ExtBPBuffer)/ExtMiddleATRBuffer[k]+
               InpSlowK*SimpleMA(i,InpSlowPeriod,ExtBPBuffer)/ExtSlowATRBuffer[k];
         //--- now we can get current Ultimate value
         ExtUOBuffer[i]=RawUO/ExtDivider*100;
        }
      else
         //--- set current Ultimate value as previous Ultimate value
         ExtUOBuffer[i]=ExtUOBuffer[i-1];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 

Hello,

I am also using indicators from another symbol than the one of the current chart. Often if not always it returns the error you describe (4806 if I recall well). I suppose the rates are not necessarily loaded because they are not from the current symbol.

I've been able to solve the problem using CopyRates() function, followed by a Sleep(50) in a loop until the array of the indicator has the desired size.

My code looks like this:

               MqlRates rates[];
               ArraySetAsSeries(rates,true);
               int copied=CopyRates(symbol,PERIOD_LONG,0,numBars+1,rates);
               int size;
               for(int k=0;k<100;k++)
               {
                  Sleep(50);
                  size=ArraySize(MaLongLong); 
                  message=message+".";
                  Comment(message);
                  if(size>=numBars)
                  {
                     break;
                  }
               }

Use CopyBuffer() before this loading of rates. MaLongLong is the buffer array from the indicator. So the purpose is to wait until the buffer is filled.

 

Thanks Twalk, pipPod for your help.

Have had some (limitied) success with pipPod's code adding the MqlRates section from Twalk. Everything below 1H timeframe seem to work, anything above fails as before. I am guessing the miss-match in calculated vs rates_total is due to the symbol having potentially less data due to different markets bank holidays and closing times, so have removed these.

I am not sure I have put the code snippet in the best place but have tried in Init and in OnCalculate. I think this is a similar problem that I have with some of my other custom indicators, would be good to crack it. Fairly limited coding skills, improving each day though! :)

Twalk, would you mind sharing one of your implementations? Understand if not etc.

Here is the chart working on lower time frames, tempted to name this "Awesome Pairs" if I can get it working!! ;)

 

 

And the code 

 

//+------------------------------------------------------------------+
//|                                          Ultimate_Oscillator.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#include <MovingAverages.mqh>
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
//--- input parameters
input int InpFastPeriod=7;     // Fast ATR period
input int InpMiddlePeriod=14;  // Middle ATR period
input int InpSlowPeriod=28;    // Slow ATR period
input int InpFastK=4;          // Fast K
input int InpMiddleK=2;        // Middle K
input int InpSlowK=1;          // Slow K
input int InpBarsToCount=300;  // Bars to count

input string name= "#US30";     //--- custom symbol
//--- indicator buffers
double    ExtUOBuffer[];
double    ExtBPBuffer[];
double    ExtFastATRBuffer[];
double    ExtMiddleATRBuffer[];
double    ExtSlowATRBuffer[];
double    Low[];
double    Close[];
//--- indicator handles
int       ExtFastATRhandle;
int       ExtMiddleATRhandle;
int       ExtSlowATRhandle;
//--- global variable
double    ExtDivider;
int       ExtMaxPeriod;
string    message;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtUOBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtBPBuffer,INDICATOR_CALCULATIONS);
   //SetIndexBuffer(2,ExtFastATRBuffer,INDICATOR_CALCULATIONS);
   //SetIndexBuffer(3,ExtMiddleATRBuffer,INDICATOR_CALCULATIONS);
   //SetIndexBuffer(4,ExtSlowATRBuffer,INDICATOR_CALCULATIONS);
//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//--- set levels
   IndicatorSetInteger(INDICATOR_LEVELS,2);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,30);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,70);
//--- set maximum and minimum for subwindow 
   IndicatorSetDouble(INDICATOR_MINIMUM,0);
   IndicatorSetDouble(INDICATOR_MAXIMUM,100);
//--- set first bar from which index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,Bars(NULL,0)-InpBarsToCount);
//--- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"UOS("+string(InpFastPeriod)+", "+string(InpMiddlePeriod)+", "+string(InpSlowPeriod)+")");
   
   if(!SymbolSelect(name,true))
     {
      Alert(name," not available in Market Watch.\nInitialization Failed.");
      return(INIT_FAILED);
     }
//--- get handles
   ExtFastATRhandle=iATR(name,0,InpFastPeriod);       //--- changed Symbol() to name variable
   ExtMiddleATRhandle=iATR(name,0,InpMiddlePeriod);   //--- changed Symbol() to name variable
   ExtSlowATRhandle=iATR(name,0,InpSlowPeriod);       //--- changed Symbol() to name variable
//---
   ExtDivider=InpFastK+InpMiddleK+InpSlowK;
   ExtMaxPeriod=InpSlowPeriod;
   if(ExtMaxPeriod<InpMiddlePeriod) ExtMaxPeriod=InpMiddlePeriod;
   if(ExtMaxPeriod<InpFastPeriod)   ExtMaxPeriod=InpFastPeriod;
//--- initialization done
   return(INIT_SUCCEEDED);
   
 
   
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
  
    MqlRates rates[];
    ArraySetAsSeries(rates,true);
    int copied=CopyRates(name,0,0,rates_total,rates);
    int size;
               for(int k=0;k<100;k++)
               {
                  Sleep(150);
                  size=ArraySize(ExtFastATRBuffer); 
                  message=message+".";
                  Comment(message);
                  if(size>=rates_total-1)
                  {
                     break;
                  }
               }
  
//---
   if(rates_total<=InpBarsToCount+InpSlowPeriod || Bars(name,0)<=InpBarsToCount+InpSlowPeriod)
      return(0);
   ArraySetAsSeries(time,true);
   int toCount,begin=0;
   toCount=(prev_calculated<=0)?InpBarsToCount+1:rates_total-prev_calculated+2;
   if(CopyBuffer(ExtFastATRhandle,0,time[0],time[toCount-1],ExtFastATRBuffer)!=toCount ||
      CopyBuffer(ExtMiddleATRhandle,0,time[0],time[toCount-1],ExtMiddleATRBuffer)!=toCount ||
      CopyBuffer(ExtSlowATRhandle,0,time[0],time[toCount-1],ExtSlowATRBuffer)!=toCount ||
      CopyLow(name,0,time[0],time[toCount-1],Low)!=toCount ||
      CopyClose(name,0,time[0],time[toCount-1],Close)!=toCount)
      return(0);
//---
   double TL,RawUO;
   if(prev_calculated<=0)
     { 
      begin=rates_total-InpBarsToCount;
      ExtBPBuffer[begin-1]=ExtUOBuffer[begin-1]=0.0;
      for(int i=begin-InpSlowPeriod,k=1;i<=begin;i++,k++)
        {
         ExtUOBuffer[i]=0.0;
         TL=MathMin(Low[k],Close[k-1]);
         ExtBPBuffer[i]=Close[k]-TL;
        }
     }
   else
      begin=prev_calculated-1;
//---
   for(int i=begin,k=1;i<rates_total&&!IsStopped();i++,k++)
     {
      //--- TL is True Low
      TL=MathMin(Low[k],Close[k-1]);
      //--- buying pressure
      ExtBPBuffer[i]=Close[k]-TL;
      //--- first we calculate "raw" value
      if(ExtFastATRBuffer[k]!=0.0 && 
         ExtMiddleATRBuffer[k]!=0.0 &&
         ExtSlowATRBuffer[k]!=0.0)
        {
         RawUO=InpFastK*SimpleMA(i,InpFastPeriod,ExtBPBuffer)/ExtFastATRBuffer[k]+
               InpMiddleK*SimpleMA(i,InpMiddlePeriod,ExtBPBuffer)/ExtMiddleATRBuffer[k]+
               InpSlowK*SimpleMA(i,InpSlowPeriod,ExtBPBuffer)/ExtSlowATRBuffer[k];
         //--- now we can get current Ultimate value
         ExtUOBuffer[i]=RawUO/ExtDivider*100;
        }
      else
         //--- set current Ultimate value as previous Ultimate value
         ExtUOBuffer[i]=ExtUOBuffer[i-1];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 

CopyRates is not necessary in this instance, as only Low and Close prices are used.

If it's not displaying on higher timeframes:

1. Open relevant chart/timeframe and scroll back to see if history is available and loading.

2. Reduce the BarsToCount input constant.  

 
Best would be to use iCustom with CopyBuffer. See example below.
Files:
UOS.mq5  7 kb
Multi_UOS.mq5  8 kb
Reason: