Phantom variable, how does it work and where does it go?

 

This one burned a full three days dogging it.

I've been trying to call this iCustom indicator. No matter what I do, it keeps returning zeros -- no data. I've coded these many times before and haven't had a problem.

What's been more mind-boggling, the indicator works just fine when added to a chart, so I know them buffers are spilling good data.

So check this out. Here's the top of the indicator I'm calling. Notice that there are 3 input variables:


//+------------------------------------------------------------------+
//|                                                    Slope MJM.mq5 |
//|                                 Copyright 2024, Millard J Melnyk |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Millard J Melnyk"
#property link      ""
#property version   "1.00"


#include <Fudge Factors MJM.mqh>

//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_width1   3
//#property indicator_applied_price 

input int                  InpSlpPrd                  = 17;             // # of Bars back (-n) to calculate Slope
input ENUM_APPLIED_PRICE   InpSlopeAplPrc             = PRICE_CLOSE;    // Price used for calculation
input int                  InpSlopeShift              = 0;              // # of Bars to shift indicator plot (to left)

//--- indicator buffers
//
double   dbSlope[];
double   dbDT[];

//--- supporting data buffers
//
double   daPrice[];
datetime dtaTime[];
bool     bArrayIsSeries       = false;
string   sPrd                 = EnumToString(_Period);
string   sIndShtNme           = "";
int      iCyclCNT             = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()

Here's the documented form for iCustom:

int  iCustom( 
   string           symbol,     // symbol name 
   ENUM_TIMEFRAMES  period,     // period 
   string           name        // folder/custom_indicator_name 
   ...                          // list of indicator input parameters 
   );


And here's where I create the handle, which is when the input variables of the iCustom indicator get processed:

   ResetLastError(); 
   Slope_Hndl             = iCustom(_Symbol,
                                    _Period,
                                    sSlopePath,      // set correctly to the location of Slope MJM.ex5, because the terminal created the handle successfully
                                    InpSlpPrd, 
                                    InpSlopeAplPrc, 
                                    InpSlopeShift
                                    ); 


Should be good, right? Nope.

Then, after I finally put a Print statement in the iCustom indicator to see what it was getting, because it sure wasn't what I gave it, I noticed that the variable to set the length of the period for calculating slope was set to 1. It should have been 17.

It was like the input variables were shifted, so on a hunch just to see what would happen, I did this:

   ResetLastError(); 
   Slope_Hndl             = iCustom(_Symbol,
                                    _Period,
                                    sSlopePath,
                                    0, 
                                    InpSlpPrd, 
                                    InpSlopeAplPrc, 
                                    InpSlopeShift
                                    ); 

Notice the difference?

Just where, exactly, does that zero go, and why does it do anything at all, because NOW IT WORKS! 😱

Anyone have an explanation? Bizzare.

 
Millard Melnyk:

This one burned a full three days dogging it.

Just where, exactly, does that zero go, and why does it do anything at all, because NOW IT WORKS! 😱

Anyone have an explanation? Bizzare.

It goes into the first input    The three inputs are now displaced the first being 0.   The last input is now the optional applied price that can be supplied to icustom 
you need to check your code and the min max criteria for the inputs
 
Paul Anscombe #:
It goes into the first input    The three inputs are now displaced the first being 0.   The last input is now the optional applied price that can be supplied to icustom 
you need to check your code and the min max criteria for the inputs

Well, in fact, no. That would mean the slope period would be 0, the applied price input would be 17 (when its defined range of values is 0 - 6), and that enum value would be fed to an integer which, if it didn't hiccup, would shift the plot on the chart. 

input int                  InpSlpPrd                  = 17;             // # of Bars back (-n) to calculate Slope
input ENUM_APPLIED_PRICE   InpSlopeAplPrc             = PRICE_CLOSE;    // Price used for calculation
input int                  InpSlopeShift              = 0;              // # of Bars to shift indicator plot (to left)
What kind of results would you anticipate from that? As I stated, putting the zero there made the indicator plot the slope correctly, which you can see from the print statement I inserted to make sure I wasn't trippin.
JI      0       13:29:36.330    Slope iCustom MJM (USDJPY,H4)   [Slope iCustom MJM.mq5 [OnInit] LINE 44 MS: TOP of OnInite - _Symbol<USDJPY> _Period,16388> InpSlpPrd<17> InpSlopeAplPrc<1=PRICE_CLOSE> InpSlopeShift<0>
 
Millard Melnyk #:

Well, in fact, no. That would mean the slope period would be 0, the applied price input would be 17 (when its defined range of values is 0 - 6), and that enum value would be fed to an integer which, if it didn't hiccup, would shift the plot on the chart. 

What kind of results would you anticipate from that? As I stated, putting the zero there made the indicator plot the slope correctly, which you can see from the print statement I inserted to make sure I wasn't trippin.

well difficult to help further as you are only providing snippets, so we have to take your word that it is as you say. History tells us these things are normally user/code error.

With regard to iCustom it will take that 0 as the first input as I have already said.

If you think that is not the case you need to provide all the code otherwise nobody can help.                                        

 
Paul Anscombe #:

well difficult to help further as you are only providing snippets, so we have to take your word that it is as you say. History tells us these things are normally user/code error.

With regard to iCustom it will take that 0 as the first input as I have already said.

If you think that is not the case you need to provide all the code otherwise nobody can help.                                        

Well, it in fact did not take it as the first input, as the journal print verifies. When a conflict between expectation and facts arises, best to go with facts. It's also always best to assume the facts presented are true until you actually have contradictory facts, which you do not. Surmise and expectations to facts are like knives and brass knuckles to guns. 

 
Millard Melnyk #:

Well, it in fact did not take it as the first input, as the journal print verifies. When a conflict between expectation and facts arises, best to go with facts. It's also always best to assume the facts presented are true until you actually have contradictory facts, which you do not. Surmise and expectations to facts are like knives and brass knuckles to guns. 

we will have to disagree, I have no knowledge where that journal print comes from, if you ran the right code, if it had been recompiled between changes, etc etc etc.  What we do have knowledge of, is that iCustom will apply those values to the inputs in order, and nobody else is saying it doesn't, only you. So if you want it checked then you need to supply the code, otherwise we could debate all day eh.

I'm happy to check it, send me the code in a PM if you don't want to publish it.
 
Paul Anscombe #:

we will have to disagree, I have no knowledge where that journal print comes from, if you ran the right code, if it had been recompiled between changes, etc etc etc.  What we do have knowledge of, is that iCustom will apply those values to the inputs in order, and nobody else is saying it doesn't, only you. So if you want it checked then you need to supply the code, otherwise we could debate all day eh.

Here you go:

//+------------------------------------------------------------------+
//|                                                    Slope MJM.mq5 |
//|                                 Copyright 2024, Millard J Melnyk |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Millard J Melnyk"
#property link      ""
#property version   "1.00"


#include <Fudge Factors MJM.mqh>

//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
//#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_width1   3
//#property indicator_applied_price 

input int                  InpSlpPrd                  = 11;             // # of Bars back (-n) to calculate Slope
input ENUM_APPLIED_PRICE   InpSlopeAplPrc             = PRICE_CLOSE;    // Price used for calculation
input int                  InpSlopeShift              = 0;              // # of Bars to shift indicator plot (to left)

//--- indicator buffers
//
double   dbSlope[];
double   dbDT[];

//--- supporting data buffers
//
double   daPrice[];
datetime dtaTime[];
bool     bArrayIsSeries       = false;
string   sPrd                 = EnumToString(_Period);
string   sIndShtNme           = "";
int      iCyclCNT             = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {

Print("["+__FILE__+" ["+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: TOP of OnInite - ",
         "_Symbol<",_Symbol,"> _Period,",_Period,"> InpSlpPrd<",InpSlpPrd,"> InpSlopeAplPrc<",(int)InpSlopeAplPrc,"=",EnumToString(InpSlopeAplPrc),
         "> InpSlopeShift<",InpSlopeShift,"> InpSlopeAplPrc<","> ");


//--- set accuracy
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
   
//--- name for DataWindow
   sPrd                             = IntegerToString(InpSlpPrd);
   
   string sSfx                      = "("+sPrd+","+EnumToString(InpSlopeAplPrc)+")";
   sIndShtNme                       = "Slope"+sSfx;
   
   IndicatorSetString(INDICATOR_SHORTNAME, sIndShtNme);
   
//--- indicator buffers mapping

   SetIndexBuffer          (0,dbSlope,INDICATOR_DATA);
      PlotIndexSetInteger  (0,PLOT_DRAW_TYPE,DRAW_LINE);
      PlotIndexSetInteger  (0,PLOT_SHOW_DATA,true);
      PlotIndexSetInteger  (0,PLOT_SHIFT, InpSlopeShift);
      PlotIndexSetInteger  (0,PLOT_DRAW_BEGIN,InpSlpPrd);
      PlotIndexSetString   (0,PLOT_LABEL,"Slope ("+EnumToString(InpSlopeAplPrc)+")");
      
   IndicatorSetString(INDICATOR_SHORTNAME, sIndShtNme);
   
   SetIndexBuffer          (1,dbDT,INDICATOR_DATA);
      PlotIndexSetInteger  (1,PLOT_DRAW_TYPE,DRAW_NONE);
      PlotIndexSetInteger  (1,PLOT_SHOW_DATA,true);
      PlotIndexSetInteger  (1,PLOT_SHIFT, InpSlopeShift);
      PlotIndexSetInteger  (1,PLOT_DRAW_BEGIN,InpSlpPrd);
      PlotIndexSetString   (1,PLOT_LABEL,"Date (YYYYMMDDHHMM)");
   
   return(INIT_SUCCEEDED);   
  }

//+---------------------------------------------------------------------------------------------------------+
//+---------------------------------------------------------------------------------------------------------+
//--- ON CALCULATE FUNCTION
//+---------------------------------------------------------------------------------------------------------+
//+---------------------------------------------------------------------------------------------------------+
int  OnCalculate( 
                  const int        rates_total,       // price[] array size 
                  const int        prev_calculated,   // number of handled bars at the previous call 
                  const int        begin,             // index number in the price[] array meaningful data starts from 
                  const double&    price[]            // array of values for calculation 
                  )

{   

   if(rates_total<InpSlpPrd-1)
      return(0);

   if(IsStopped()) return(0);
   
   iCyclCNT++;
   
//--- first calculation or number of bars was changed
   if(prev_calculated==0)
   {
      ArrayInitialize(dbSlope,0);
   }
   
   int iUsePrc                   = GetAppliedPrices(_Symbol,_Period,InpSlopeAplPrc,daPrice,dtaTime);
   if(iUsePrc < 0)
   {
      Print("["+__FILE__+" ["+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - GetAppliedPrices FAILED:     ",
         "returned: iUsePrc<",iUsePrc,"> _Symbol<",_Symbol,"> _Period<",_Period,"> InpSlopeAplPrc<",EnumToString(InpSlopeAplPrc),
         "> ");
      return(iUsePrc);
   }


   int iAraySZ                   = ArraySize(dtaTime);

   for(int ix = 0;ix < iAraySZ;ix++)
      dbDT[ix]                   = Mql_DTtoDouble(dtaTime[ix]);

   if(bArrayIsSeries == true)
   {
      for(int ix = iAraySZ - 1;ix >= 0 && !IsStopped();ix--)
      {
         dbSlope[ix]             = (ix < InpSlpPrd) ? 0 : (daPrice[ix] - daPrice[ix-InpSlpPrd]) / InpSlpPrd; 
//         if(ix < 50 && ix >= InpSlpPrd)
//Print("["+__FILE__+" ["+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - for loop, bArrayIsSeries == true:     ",
//   "InpSlopeAplPrc<",EnumToString(InpSlopeAplPrc),"> ix<",ix,"> InpSlpPrd<",InpSlpPrd,"> dbSlope[ix]<",dbSlope[ix],"> daPrice[",ix,"]<",daPrice[ix],
//   "> daPrice[",(ix < InpSlpPrd) ? 0 : ix-InpSlpPrd,"]<",(ix < InpSlpPrd) ? 0 : daPrice[ix-InpSlpPrd],
//   "< dbDT[ix]<",dbDT[ix],"> ");
//
      }
   
   }
   else
   {
      for(int ix = 1;ix < iAraySZ && !IsStopped();ix++)
      {
         dbSlope[ix]             = (ix < InpSlpPrd) ? 0 : (daPrice[ix] - daPrice[ix-InpSlpPrd]) / InpSlpPrd; 
//         if(ix < 50 && ix >= InpSlpPrd)
//Print("["+__FILE__+" ["+__FUNCTION__+"] LINE "+(string)__LINE__+" MS: "+(string)GetMicrosecondCount()+" - for loop, bArrayIsSeries == false:     ",
//   "InpSlopeAplPrc<",EnumToString(InpSlopeAplPrc),"> ix<",ix,"> InpSlpPrd<",InpSlpPrd,"> dbSlope[ix]<",dbSlope[ix],"> daPrice[",ix,"]<",daPrice[ix],
//   "> daPrice[",(ix < InpSlpPrd) ? 0 : ix-InpSlpPrd,"]<",(ix < InpSlpPrd) ? 0 : daPrice[ix-InpSlpPrd],
//   "> dbDT[ix]<",dbDT[ix],"> ");      
      }
//
   }
   
   
//--- return value of prev_calculated for next call
   return(rates_total);
   
}

 
Millard Melnyk #:

Here you go:

doesn't compile,  probably because there is an include file missing

I have tested iCustom calling the standard MACD indicator with only an added line to print the supplied inputs.  It works fine, and if I add an extra value into the iCustom call (value 5) then it shifts the inputs along as expected.

I stubbed your code to ignore the include and repeated the test inserting a 0 and it shifts the values as expected.

Therefore, as expected you are not testing it correctly if you didn't see the shift. maybe you didn't recompile, or used the wrong version or whatever, but there is nothing wrong with iCustom the problem is in your code or version control.


 
Paul Anscombe #:

doesn't compile,  probably because there is an include file missing

I have tested iCustom calling the standard MACD indicator with only an added line to print the supplied inputs.  It works fine, and if I add an extra value into the iCustom call (value 5) then it shifts the inputs along as expected.

I stubbed your code to ignore the include and repeated the test inserting a 0 and it shifts the values as expected.

Therefore, as expected you are not testing it correctly if you didn't see the shift. maybe you didn't recompile, or used the wrong version or whatever, but there is nothing wrong with iCustom the problem is in your code or version control.


Sorry dude, you're making no sense. With the zero where I showed it, it shifted the input parameter values so that the iCustom call worked. What can I say when you sit there and remote-judge that what happened could not have happened? That's an opinion based on blind belief.

What you showed me was what you said would happen, which was exactly whatI already described in my initial response to you. But it did not happen, as I showed you. You say it did happen as you described, but I have no knowledge where that journal print comes from, if you ran the right code, if it had been recompiled between changes, etc etc etc. (Why people do what you're doing, as if the doubt can only go in one direction, has always amazed me.)

What you have not accounted for was the fact that when I ran it with the zero, it did not shift them like you said it would, as evidenced by my printout, which is just as valid as yours.

You don't want to accept it as a fact? That's your problem -- but it leaves you with nothing to say about the situation that I asked about, because as far as you're concerned, it didn't actually happen as I showed you it did. 

What puzzles me is why you thought this would be helpful?

 
Millard Melnyk #:

What you have not accounted for was the fact that when I ran it with the zero, it did not shift them like you said it would, as evidenced by my printout, which is just as valid as yours.

You don't want to accept it as a fact? That's your problem -- but it leaves you with nothing to say about the situation that I asked about, because as far as you're concerned, it didn't actually happen as I showed you it did. 

What puzzles me is why you thought this would be helpful?

Which part of me showing you the journal from your indicator with the extra 0 input shifting the input values is not registering for you?

So it is not icustom. It is you and your code that is the problem 
If you can recreate what you claim post all the code intact that will compile and show the problem.  






 
Millard Melnyk #:Sorry dude, you're making no sense.
  1. No, you are making nonsense. If your code doesn't compile, the problem is you.

    It is almost always your code.
          How To Ask Questions The Smart Way. (2004)
              Don't rush to claim that you have found a bug.
          Questions Not To Ask
              My program doesn't work. I think system facility X is broken.

  2. There are no mind readers here and our crystal balls are cracked, so we can't see your machine.
         How To Ask Questions The Smart Way. (2004)
              Be precise and informative about your problem

    Always post all relevant code (using Code button) or attach the source file. Like your include file.