Any ideas why my custom indicators are blank when I start the terminal in the morning? - page 2

 
Millard Melnyk #:
Hey guys, why is there so much disdain on this forum?

Where did you see disdain?

I wrote that without the code to reproduce it, it would be empty chatter and I really think so. But I am friendly towards you.

I had a period when I started to create a topic on this forum, but found the cause of the bug while I was making the code to reproduce it. After which I did not publish a new topic because the problem was solved while I created the code to reproduce it. This has happened to me many times. 

 
Millard Melnyk #:
That's like a driver training student asking his teacher, "What am I doing wrong?" and the guy answers, "You need to drive better!" 🤣

What you're doing is like calling a car repair shop and asking "any idea why my car stopped working"?

 
Vladislav Boyko #:

In order to check whether there are runtime errors in the log, it is not necessary to create a new indicator. I suggested that you make a new simplified indicator so that other users can reproduce the situation you describe.

Dude, of course I check 

Alain Verleyen #:

I am STRONGLY suggesting you to change your tone and attitude when you are replying to people trying to help you.

You don't show any code so it's not possible to help with more details. With a positive attitude you will see that my answer is correct and lead you in the right direction.

Trying to help me? I strongly suggest you drop the disdain, arrogance, and superior air. You have, over a period of months now, offered no help at all except for pointing out that undocumented feature about custom indicator placeholders. And you have a reading comprehension problem, apparently. Exactly where did I ask for help other than if someone had any ideas? You're just pissed because I've criticized your precious MQL5 in the past. Have you ever programmed in another language? I'd be surprised if you had.

 
Vladislav Boyko #:

What you're doing is like calling a car repair shop and asking "any idea why my car stopped working"?

Yes, exactly. And the mechanics who are worth paying either say, (and they do this often,) "Well, it could be x or it could be y, and in rare cases it's sometimes z. Beyond that I'd have to take a look."

That's how experienced experts answer a, "Got any ideas?" question.

A mechanic that showed the kind of attitudes that are the norm for some people on this forum would promptly see my backside, and that's the last they'd see of me.

I code 8-12 hours a day and run into lots of puzzlements every day. Haven't you noticed that I seldom ask questions here anymore? There's a reason for that.

 
Vladislav Boyko #:

Where did you see disdain?

I wrote that without the code to reproduce it, it would be empty chatter and I really think so. But I am friendly towards you.

I had a period when I started to create a topic on this forum, but found the cause of the bug while I was making the code to reproduce it. After which I did not publish a new topic because the problem was solved while I created the code to reproduce it. This has happened to me many times. 

Yes, you've been friendly, and thank you!

The problem isn't really with you. Alain's response here was worthless aside from its veiled chiding quotient. William, too, has been a bucketful of hoo-has, but he's (thankfully) stopped responding to me. You, on the other hand, have been one that actually thinks my questions through and at least tries to take a stab at then. Usually you come up with great points.

I responded in general only because the dissing has been standard fare here for a long time, especially for some, and no one seems to raise an eyebrow about it. Your coffee grounds quip kinda qualifies, tho. It's not "empty chatter and fortune telling" to ask folks if they've run into a similar situation, which is all I did and all I wanted.

I say pretty exactly what I mean, not something else.

 
Millard Melnyk #:

Dude, of course I check 

Trying to help me? I strongly suggest you drop the disdain, arrogance, and superior air. You have, over a period of months now, offered no help at all except for pointing out that undocumented feature about custom indicator placeholders. And you have a reading comprehension problem, apparently. Exactly where did I ask for help other than if someone had any ideas? You're just pissed because I've criticized your precious MQL5 in the past. Have you ever programmed in another language? I'd be surprised if you had.

I can't accept this. Believe it or not I am trying to help, why would I post otherwise, and I just received this rant !?!

I banned you 1 week for this unacceptable attitude and offensive messages.

 
Millard Melnyk:

Here's what I see when I start the MT5 terminal, also when its running but my internet connection is interrupted. The indicator plot shows briefly (subsecond) and then disappears:


All I need to do is switch the timeframe of the chart to anything and then back and the window shows up like it should have to begin with:



In one way, it's a minor annoyance, although it's wearisome when I've got 6 - 10 charts open at the same time.

On the other hand, it indicates that I'm consistently coding my indicators in such a way as to behave like this. I thought it might be a problem with any custom indicator, but if I add one from the Examples or the Bill Williams folder, it doesn't behave this way.

Any ideas of the top of your head what the problem might be or where I should look for it?

Are you using 'CIndicator' derived types?

I had a few custom indicators, and one rewritten macd using CIndicator types on a symbol. 2 of 9 indicators printed the error HISTORY_NOT_FOUND(4401), related to 'CopyRates' function, but did not disappear. I suspect the one with 'CIndicator' derived types may have not handled well such missing data, and it simply disappeared. nothing printed anywhere, no exception thrown at all. at the beginning of OnCalculate event, there's a check for 'BarsCalculated' for supposedly handling when the indicator did not calculate all bars from rates_total. similarly to your report, changing timeframes, or rebuilding the indicator, restores it.

did you find the problem?

 
KeyserSoze42 #:

Are you using 'CIndicator' derived types?

I had a few custom indicators, and one rewritten macd using CIndicator types on a symbol. 2 of 9 indicators printed the error HISTORY_NOT_FOUND(4401), related to 'CopyRates' function, but did not disappear. I suspect the one with 'CIndicator' derived types may have not handled well such missing data, and it simply disappeared. nothing printed anywhere, no exception thrown at all. at the beginning of OnCalculate event, there's a check for 'BarsCalculated' for supposedly handling when the indicator did not calculate all bars from rates_total. similarly to your report, changing timeframes, or rebuilding the indicator, restores it.

did you find the problem?

I've never had that problem iterating in reverse chronological order in my indicator loops and returning rates_total - 1. I generally don't use prev_calculated nor BarsCalculated. One such, and simple, indicator that I coded as an example for another trader in 2024 is attached.

//+------------------------------------------------------------------+
//|                                                    test_dots.mq5 |
//|                            Copyright 2024, Ryan Lawrence Johnson |
//|                         https://www.mql5.com/en/users/rjo/seller |
//+------------------------------------------------------------------+

//--- store price, time, and volume data for access as in MQL4
#define SERIES(name,type)                               \                            
class C##name                                           \
{                                                       \
public:                                                 \
type operator[](const int i){return i##name(NULL,0,i);} \                                                
}name;                                                  
SERIES(Open,double)
SERIES(Low,double)
SERIES(High,double)
SERIES(Close,double)
SERIES(Time,datetime)
SERIES(Volume,long)
SERIES(TickVolume,long)

#property copyright "© 2024, Ryan Lawrence Johnson"
#property link      "https://www.mql5.com/en/users/rjo/seller"
#property version   "1.00"
#property indicator_chart_window

#property indicator_buffers 2
#property indicator_plots 2

#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrAqua
#property indicator_width1 2

#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrRed
#property indicator_width2 2

//--- settings
input int Padding = 30;

//--- variables on global scope
//int handle_indicator;

//--- arrays for indicator data buffers


//--- arrays for calculation buffers
double buff_up[];
double buff_down[];

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- remove indicator handles from memory
   //if(handle_indicator != INVALID_HANDLE) IndicatorRelease(handle_indicator);

//--- delete GlobalVariables
        //GlobalVariableDel("gvariable");

  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, buff_up, INDICATOR_DATA);
   SetIndexBuffer(1, buff_down, INDICATOR_DATA);
        //PlotIndexSetString(0, PLOT_LABEL, "indicator");
        PlotIndexSetInteger(0, PLOT_ARROW_SHIFT, -Padding);
        PlotIndexSetInteger(1, PLOT_ARROW_SHIFT, Padding);
//--- indicator handles
        //handle_indicator = iATR(NULL, 0, period); // or use iCustom if needed

//--- indicator short name
        //IndicatorSetString(INDICATOR_SHORTNAME, "indicator " + (string)period);
        
//---
   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[])
  {
//--- align indicator data direction with price data direction
        ArraySetAsSeries(buff_up, true);
        ArraySetAsSeries(buff_down, true);

   //int copyBars;
   int limit;
   int bar;
   
   //--- calculation of the starting bar index
   //if (prev_calculated == 0) // check for the first call of OnCalculate function
    //{                      
     limit = rates_total - 1;  // starting index for the calculation of all of the bars
     //copyBars = rates_total  - 1;
    //}
   //else
    //{
     //limit = rates_total - 1 - prev_calculated; // starting index for the calculation of new bars
     //copyBars = rates_total - 1 - prev_calculated;
    //}

//--- fill the arrays for buffers with indicator data 
        //if(CopyBuffer(handle_indicator, 0, 0, copyBars, buff_indicator) <= 0)
                 //return(0);

   //--- main loop
   for(bar = limit; bar >= 0; bar--)
    {
     //for(int i = 0; i < 1; i++)
      //{
       buff_up[bar] = High[bar];
       buff_down[bar] = Low[bar];
        //}
    }

//--- return value of prev_calculated for next call
   return(rates_total - 1);
  }
//+------------------------------------------------------------------+
Files:
test_dots.mq5  10 kb
 
Ryan L Johnson #:

I've never had that problem iterating in reverse chronological order in my indicator loops and returning rates_total - 1. I generally don't use prev_calculated nor BarsCalculated. One such, and simple, indicator that I coded as an example for another trader in 2024 is attached.

that is fine, that sample does not refer to any buffer from some indicator function.

I suspect the problem to be related to how CIndicator handles missing data from its buffer. refer to the source code on Indicator.mqh for the next statements. the Refresh function does not return any value, and ignores the value returned by its buffer. when the buffer refreshes, it runs CopyBuffer. when the returned value is < 0, CIndicator does nothing with that information. supposing that is the failure, I cannot see how that would lead to the indicator deleting the data that already populated the custom indicator buffer, and not thrown any exception/error. I expected for previous buffer content to remain, thus leaving the indicator simply not updating, but still shown on screen.

this is the indicator that experiences he problem. it is a copy of mt5's own macd, but simplified using stdlib. it was deliberate the elimination of 2 buffers.

#include <MovingAverages.mqh>
#include <Indicators\Trend.mqh>
#define LOG_MESSAGE(text) PrintFormat("%s | @%s #%d -> %s", __FILE__, __FUNCTION__, __LINE__, text)
#define E2S(X) EnumToString((MQL_ERROR)(X)) + "(" + IntegerToString(X) + ")"

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   2
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_type2   DRAW_LINE
#property indicator_color1  clrDarkSeaGreen, clrGreen, clrTomato, clrRed
#property indicator_color2  clrLime
#property indicator_width1  2
#property indicator_width2  3
#property indicator_label1  "MACD Histogram"
#property indicator_label2  "Signal"

input(name = "Fast EMA period") int FastEMAPeriod = 12;
input(name = "Slow EMA period") int SlowEMAPeriod = 26;
input(name = "Signal SMA period") int SignalSMAPeriod = 9;
input(name = "Applied price") ENUM_APPLIED_PRICE AppliedPriceType = PRICE_CLOSE;

double HistogramBuffer[];
double HistogramColourBuffer[];
double SignalBuffer[];

CiMA FastMAIndicator;
CiMA SlowMAIndicator;

void OnInit() {
   SetIndexBuffer(0, HistogramBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, HistogramColourBuffer, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2, SignalBuffer, INDICATOR_DATA);

   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, fmax(FastEMAPeriod, SlowEMAPeriod)-1);
   PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, SignalSMAPeriod-1);
   string short_name = StringFormat("MACD(%d,%d,%d)", FastEMAPeriod, SlowEMAPeriod, SignalSMAPeriod);
   IndicatorSetString(INDICATOR_SHORTNAME, short_name);
   FastMAIndicator.Create(NULL, 0, FastEMAPeriod, 0, MODE_EMA, AppliedPriceType);
   SlowMAIndicator.Create(NULL, 0, SlowEMAPeriod, 0, MODE_EMA, AppliedPriceType);
   Print("MACD started");
}

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 < SignalSMAPeriod) {
      LOG_MESSAGE("rates_total < SignalSMAPeriod");
      return(0);
   }
   if(FastMAIndicator.BarsCalculated() < rates_total || SlowMAIndicator.BarsCalculated() < rates_total) {
      LOG_MESSAGE("Not all data for MACD indicator is calculated yet (" + fmin(FastMAIndicator.BarsCalculated(), SlowMAIndicator.BarsCalculated()) + " bars). Error " + E2S(GetLastError()));
      return(0);
   }
   for(int i = fmax(fmax(FastEMAPeriod, SlowEMAPeriod), prev_calculated - 1), j = rates_total - i - 1; i < rates_total && !IsStopped(); i++, j--) {
      HistogramBuffer[i] = FastMAIndicator.Main(j) - SlowMAIndicator.Main(j);
      HistogramColourBuffer[i] = HistogramBuffer[i] > 0 ? 1 : 3;
      HistogramColourBuffer[i] = MathAbs(HistogramBuffer[i]) < MathAbs(HistogramBuffer[i - 1])
                                 ? HistogramColourBuffer[i] - 1
                                 : HistogramColourBuffer[i];
   }
   SimpleMAOnBuffer(rates_total, prev_calculated, 0, SignalSMAPeriod, HistogramBuffer, SignalBuffer);
   return(rates_total);
  }

I will try next week the following fragment for refreshing the indicators

int OnCalculate( .....
.....

   WasThereAnError();
   FastMAIndicator.Refresh();
   if(WasThereAnError())
      return(0);
   SlowMAIndicator.Refresh();
   if(WasThereAnError())
      return(0);

.......
}

bool WasThereAnError() {
  const int errorSnapshot = _LastError;
  if(errorSnapshot > 0) {
    LOG_MESSAGE(E2S(errorSnapshot));
    ResetLastError();
    return(true);
  }
  return(false);
}

sadly, since this problem is intermittent, it may take a while to find the result in the logs. if something is logged, but the indicator remains on screen, that was probably the problem.

@MetaQuotes, is it possible that this had been overlooked in stdlib?
 

the fragment above does not work as intended. I replaced it by

   ResetLastError();
   FastMAIndicator.Refresh();
   int errorSnapshot = _LastError;
   if(errorSnapshot > 0) {
      LOG_MESSAGE(E2S(errorSnapshot));
      ResetLastError();
      return(0);
   }
   SlowMAIndicator.Refresh();
   errorSnapshot = _LastError;
   if(errorSnapshot > 0) {
      LOG_MESSAGE(E2S(errorSnapshot));
      ResetLastError();
      return(0);
   }
upon restarting that indicator, the error CUSTOM_WRONG_PROPERTY(4603) briefly appeared, but I could not identify where exactly (before of after indicator refresh, which one?). and now, it does not appear anymore. however, the indicator remained drawn.