How to know which price series the user selected when the indicator is added to the chart ?

 

Hi everyone,


I have a problem. If I use the simplified version of OnCalculate, I receive the price series as an array of doubles in the OnCalculate parameters. This is the price series selected by the user in the "Parameters" tab of the dialog box displayed when the indicator is added to the chart. But in this case I don't know, in the OnInit function,  how to figure out what price series the user selected when the indicator was added to the chart. I need this information because I must create handles to technical indicators using that same price series (ENUM_APPLIED_PRICE constant).

Thanks.


PS: by the way, the Price Constants documentation page look flawed to me because the example code creates a handle to the RSI indicator using explicitly the PRICE_CLOSE constant, regardless of what price series the user may have chosen (the simplified version of OnCalculate is used). So, if the user chose the open prices, the code will use close prices. The terminal will not display the indicator the user expects.

Documentation on MQL5: Price Constants / Constants, Enumerations and Structures
Documentation on MQL5: Price Constants / Constants, Enumerations and Structures
  • www.mql5.com
Calculations of technical indicators require price values and/or values of volumes, on which calculations will be performed. There are 7 predefined...
 
You're looking for the _AppliedTo built-in varibable.
Documentation on MQL5: _AppliedTo / Predefined Variables
Documentation on MQL5: _AppliedTo / Predefined Variables
  • www.mql5.com
The _AppliedTo variable allows finding out the type of data, used for indicator calculation:   Example: See also...
 
Stanislav Korotky #:
You're looking for the _AppliedTo built-in varibable.
Thank you very much Sir. I didn't know about it.
 

Hi everyone,

I noticed a strange behavior. The documentation states that when a custom indicator uses the simplified version of the OnCalculate function, the built-in variable _AppliedTo is set to the price series selected in the "Parameters" tab of the dialog box that is displayed when the indicator is added, and when the indicator uses the complicated version of the OnCalculate function, _AppliedTo is set to zero.


So, within OnInit, I ask the code to print the value of _AppliedTo, both as a string with the EnumToString function and as an integer. I realized that if the "Parameters" tab is not selected upon addition (to see which price series is selected), _AppliedTo is set to zero according to the output even though the documentation states otherwise. But when the "Parameters" tab is selected (without actually touching the combo box), the _AppliedTo is set correctly. The capture of the log is attached to the message.


Beside that, it seems that the indicators are created correctly with the _AppliedTo variable set to zero. So, for instance, the iMA function succeeds with the last parameter (applied_price of type ENUM_APPLIED_PRICE) set to zero. The EnumToString output seems to indicate that zero does not belong to the ENUM_APPLIED_PRICE enumeration.

Thank you.

 
Tradingrobot2718 #:

Hi everyone,

I noticed a strange behavior. The documentation states that when a custom indicator uses the simplified version of the OnCalculate function, the built-in variable _AppliedTo is set to the price series selected in the "Parameters" tab of the dialog box that is displayed when the indicator is added, and when the indicator uses the complicated version of the OnCalculate function, _AppliedTo is set to zero.


So, within OnInit, I ask the code to print the value of _AppliedTo, both as a string with the EnumToString function and as an integer. I realized that if the "Parameters" tab is not selected upon addition (to see which price series is selected), _AppliedTo is set to zero according to the output even though the documentation states otherwise. But when the "Parameters" tab is selected (without actually touching the combo box), the _AppliedTo is set correctly. The capture of the log is attached to the message.

0 is correct as nothing is selected, so the default is used : Close prices.

Beside that, it seems that the indicators are created correctly with the _AppliedTo variable set to zero. So, for instance, the iMA function succeeds with the last parameter (applied_price of type ENUM_APPLIED_PRICE) set to zero. The EnumToString output seems to indicate that zero does not belong to the ENUM_APPLIED_PRICE enumeration.

It doesn't, _AppliedTo return an int, not an enum, not the value of ENUM_APPLIED_PRICE.
 
Alain Verleyen #:
0 is correct as nothing is selected, so the default is used : Close prices. It doesn't, _AppliedTo return an int, not an enum, not the value of ENUM_APPLIED_PRICE.

That is readily apparent in the _AppliedTo predefined variable documention:

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
// Getting the type of data used for indicator calculation
   Print("_AppliedTo=",_AppliedTo);
   Print(getIndicatorDataDescription(_AppliedTo));
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Description of data used for indicator calculation               |
//+------------------------------------------------------------------+
string getIndicatorDataDescription(int data_id)
  {
   string descr="";
   switch(data_id)
     {
      case(0):descr="It's first type of OnCalculate() - no data buffer";
         break;
      case(1):descr="Indicator calculates on Close price";
         break;
      case(2):descr="Indicator calculates on Open price";
         break;
      case(3):descr="Indicator calculates on High price";
         break;
      case(4):descr="Indicator calculates on Low price";
         break;
      case(5):descr="Indicator calculates on Median Price (HL/2)";
         break;
      case(6):descr="Indicator calculates on Typical Price (HLC/3)";
         break;
      case(7):descr="Indicator calculates on Weighted Price (HLCC/4)";
         break;
      case(8):descr="Indicator calculates Previous Indicator's data";
         break;
      case(9):descr="Indicator calculates on First Indicator's data";
         break;
      default: descr="Indicator calculates on data of indicator with handle="+string(data_id);
         break;
     }
//---
   return descr;
  }
Documentation on MQL5: _AppliedTo / Predefined Variables
Documentation on MQL5: _AppliedTo / Predefined Variables
  • www.mql5.com
The _AppliedTo variable allows finding out the type of data, used for indicator calculation:   Example: See also...
 

I think I will move the code to the complicated form of OnCalculate. Although not all price series are provided when OnCalculated is called. I think of the PRICE_TYPICAL prices for example. Prices must be calculated for each index.

I wonder if the best method, although probably costly, to obtain an array of prices is to use the simple moving average indicator with a period set to one and the applied_to parameter set to the desired price series.

 
Tradingrobot2718 #:

I think I will move the code to the complicated form of OnCalculate. Although not all price series are provided when OnCalculated is called. I think of the PRICE_TYPICAL prices for example. Prices must be calculated for each index.

I wonder if the best method, although probably costly, to obtain an array of prices is to use the simple moving average indicator with a period set to one and the applied_to parameter set to the desired price series.

input ENUM_APPLIED_PRICE myAppliedPrice = PRICE_TYPICAL;
Documentation on MQL5: Price Constants / Constants, Enumerations and Structures
Documentation on MQL5: Price Constants / Constants, Enumerations and Structures
  • www.mql5.com
Calculations of technical indicators require price values and/or values of volumes, on which calculations will be performed. There are 7 predefined...
 
Ryan L Johnson #:
int  OnCalculate(
   const int        rates_total,       // size of input time series
   const int        prev_calculated,   // number of handled bars at the previous call
   const datetime&  time[],            // Time array
   const double&    open[],            // Open array
   const double&    high[],            // High array
   const double&    low[],             // Low array
   const double&    close[],           // Close array
   const long&      tick_volume[],     // Tick Volume array
   const long&      volume[],          // Real Volume array
   const int&       spread[]           // Spread array
   );
There is no PRICE_TYPICAL price series.
 

Tradingrobot2718 #:

There is no PRICE_TYPICAL price series.

PRICE_TYPICAL is a predefined identifier as documented in the link in Post #7. There is no need to further define it. Simply call myAppliedPrice (or whatever variable you declare in place of it) further down in your code to get the price.

You should probably take things from the top and read the following Article in which ENUM_APPLIED_PRICE is implemented:

Articles

Custom Indicators (Part 1): A Step-by-Step Introductory Guide to Developing Simple Custom Indicators in MQL5

Kelvin Muturi Muigua, 2024.05.02 13:26

Learn how to create custom indicators using MQL5. This introductory article will guide you through the fundamentals of building simple custom indicators and demonstrate a hands-on approach to coding different custom indicators for any MQL5 programmer new to this interesting topic.

 

I am sorry but I think I'm lazy. I will write the code that deals with the "begin" parameter of the simplified version of OnCalculate and then use it with every custom indicator. To me, this parameter is useless. If only the prices starting at index "begin" are relevant, then why isn't the first "begin" prices of the array removed and  the "rates_total" parameter adjusted ?

I think OnCalculate should use this signature:


void OnCalculate(
   const unsigned int       index // The index of the bar on the graphic for which the indicator's value must be calculated.
   )
{
    CustomIndicatorBuffer[index] = CalculateCustomIndicatorValueAtIndex(index);
}