getting last alert when attaching the indicator

 

Hello, I want to ask if someone also has the similar problem. When I attach my indicator on the chart, alert comes up when there is no signal yet, here is my pseudocode

datetime last_alert_time = 0;

if (time[0] != last_alert_time){Alert("Buy Signal Detected"); // Alert for Buy
                last_alert_time  = time[0];}

it was solved if I add the condition i == 0, but I do not want this because the indicator will not alert new signal if it repaints.

 

This is also pseudocode. I haven't tested it

#define _undefinedLastAlertTime 0
datetime last_alert_time = _undefinedLastAlertTime;

void someFunction(const datetime &time[])
  {
   if(time[0] != last_alert_time)
     {
      if(last_alert_time != _undefinedLastAlertTime)
         Alert("Buy Signal Detected");
      last_alert_time = time[0];
     }
  }
 
A A Adhioermawan:
but I do not want this because the indicator will not alert new signal if it repaints.

I don't understand why you store and check the bar time if you want to send notifications about signal changes on the same bar.

 
Vladislav Boyko #:

I don't understand why you store and check the bar time if you want to send notifications about signal changes on the same bar.

Hello thanks for replying. At first, I tried not check the bar time but the alert will comes up many times. When I use my pseudocode above, the alert will triggered once at current bar and when it repaint the new alert triggered at new bar

 

Your problem statement is a bit strange. I'm not sure I understood correctly what you want to do.

My example works according to the following logic:

  • Notify about buy signal if the previous notification was about sell signal;
  • Notify about sell signal if the previous notification was about buy signal;
  • If at the moment of attaching the indicator there was already a signal - ignore it (the next notification only when the opposite signal appears)

Signal generation logic:

  • buy - current candle is bullish and candle body is not less than 10 points
  • sell - current candle is bearish and candle body is not less than 10 points

#property indicator_chart_window
#property indicator_plots 0

enum ENUM_SIGNAL
  {
   NO_SIGNAL = 0,
   BUY_SIGNAL = 1,
   SELL_SIGNAL = 2
  };

class CSignalNotifier
  {
public:
   void        onCalculate(ENUM_SIGNAL signal);
private:
   bool        m_isPrevSignalUndef;
   ENUM_SIGNAL m_prevSignal;
public:
               CSignalNotifier() : m_isPrevSignalUndef(true), m_prevSignal(NO_SIGNAL) {}
  };

CSignalNotifier notifier;

int OnInit()
  {
   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[])
  {
   ArraySetAsSeries(open, true);
   ArraySetAsSeries(close, true);
   notifier.onCalculate(generateSomeSignal(open[0], close[0]));
   return(rates_total);
  }

void CSignalNotifier::onCalculate(ENUM_SIGNAL signal)
  {
   if(m_isPrevSignalUndef) // First call of this method after attaching the indicator
     {
      m_isPrevSignalUndef = false;
      m_prevSignal = signal;
      return;
     }
   if(signal == m_prevSignal) // Signal hasn't changed - skip
      return;
   switch(signal)
     {
      case BUY_SIGNAL:
      case SELL_SIGNAL:
         m_prevSignal = signal;
         Alert(signal == BUY_SIGNAL ? "Buy" : "Sell");
         break;
      //--- No signal - skip
      case NO_SIGNAL:
         return;
      //--- Protect against unexpected addition of values ​​to an enumeration
      default:
         Print(__FUNCTION__" Unexpected signal: ", EnumToString(signal));
         return;
      //---
     }
  }

#define _minBodySizeInt 10
ENUM_SIGNAL generateSomeSignal(double open, double close)
  {
   if(_minBodySizeInt * _Point - MathAbs(close - open) > _Point * 0.5)
      return(NO_SIGNAL);
   return(close > open ? BUY_SIGNAL : SELL_SIGNAL);
  }
#undef _minBodySizeInt

//---
 
Vladislav Boyko #:

My example works according to the following logic:

  • Notify about buy signal if the previous notification was about sell signal;
  • Notify about sell signal if the previous notification was about buy signal;
  • If at the moment of attaching the indicator there was already a signal - ignore it (the next notification only when the opposite signal appears)

That's how I understand your logic. But such logic looks very strange to me.

 
Vladislav Boyko #:

That's how I understand your logic. But such logic looks very strange to me.

thanks for the code, I am still beginner at OOP so I will learn it first. Sorry if you not understand my problem let me explain it again.
So, in my experience if I want to trigger alert from the signal only once instant at bar[0] I always write these

datetime time_alert;

if(i == 0 && Time[0] != time_alert) Alert("Buy"); //Alert 
         time_alert = Time[0];

But when the signal change from buy to sell at same bar[0], the alert only triggered once until new bar appear. Thus, I tried to remove i == 0 condition for the alert, and the new sell signal change alert triggered at new bar when the signal arrow at bar[1]. This condition fine by me, but new problem appeared. Everytime I compile the indicator, the alert always triggered. Because my lack of experience, I do not know what cause this problem

 
A A Adhioermawan #:
So, in my experience if I want to trigger alert from the signal only once instant at bar[0] I always write these

Sorry, I don't understand what you're trying to do. Don't describe your experience, but instead describe in words the rules for alerts (like I did for my example). When do you need an alert? What event must happen for this?

Pretend that you don’t know how to program and describe in ordinary human words when you need an alert.

 

Don't try to think in code right away. First formulate the task in human language, and only then start coding the finished logic.

 
Vladislav Boyko #:

Don't try to think in code right away. First formulate the task in human language, and only then start coding the finished logic.

I think it's better that I share you the full code of my indicator

#include <stdlib.mqh>
#include <stderror.mqh>

//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 2

#property indicator_type1 DRAW_ARROW
#property indicator_width1 3
#property indicator_color1 0xFF2B00
#property indicator_label1 "Buy"

#property indicator_type2 DRAW_ARROW
#property indicator_width2 3
#property indicator_color2 0x0000FF
#property indicator_label2 "Sell"

//--- indicator buffers
double Buffer1[];
double Buffer2[];


extern int RSI_Period=3;
extern int RSI_Level=70;
extern int CCI_Period=4;
extern int CCI_Level=125;


datetime last_alert_time = 0; // Tracks the last alert time
extern bool Audible_Alerts = true;
double myPoint; //initialized in OnInit

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | DYMI_Alerts @ "+Symbol()+","+Period()+" | "+message);
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
   else if(type == "indicator")
     {
      Print(type+" | DYMI_Alerts @ "+Symbol()+","+Period()+" | "+message);
      if(Audible_Alerts) Alert(type+" | DYMI_Alerts @ "+Symbol()+","+Period()+" | "+message);
     }
  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
   IndicatorBuffers(4);
   SetIndexBuffer(0, Buffer1);
   SetIndexEmptyValue(0, 0);
   SetIndexArrow(0, 241);
   SetIndexBuffer(1, Buffer2);
   SetIndexEmptyValue(1, 0);
   SetIndexArrow(1, 242);
   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
     }
   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[])
  {
   int limit = rates_total - prev_calculated;
   //--- counting from 0 to rates_total
   ArraySetAsSeries(Buffer1, true);
   ArraySetAsSeries(Buffer2, true);
   //--- initial zero
   if(prev_calculated < 1)
     {
      ArrayInitialize(Buffer1, 0);
      ArrayInitialize(Buffer2, 0);
     }
   else
      limit++;
   
   //--- main loop
for (int i = limit - 1; i >= 0; i--)
{
    if (i >= MathMin(5000 - 1, rates_total - 1 - 50)) continue; // omit old rates for performance


    // Buy Condition
    if (//iCustom(NULL, PERIOD_CURRENT, "DYMI", stdevLength, avgOfStdevLength, DYMILength, DYMILengthLowerLimit, DYMILengthUpperLimit, 0, i) > OVERSOLD
        iRSI(NULL, 0, RSI_Period, 0, i + 1) * 2 - 100 < -(RSI_Level)
        && iCCI(NULL, 0, CCI_Period, 0, i + 1) < -(CCI_Level))
    {
        if (Close[i] < Open[i]) // If the candle is bearish, change to Sell signal
        {
            Buffer1[i] = 0; // Clear Buy signal
            Buffer2[i] = High[i] + iATR(NULL, PERIOD_CURRENT, 14, i); // Generate Sell signal
            
                if (time[0] != last_alert_time){Alert("Sell Signal Detected"); // Alert for Sell
                last_alert_time  = time[0];}
            
        }
        else
        {
            Buffer2[i] = 0; // Clear Sell signal
            Buffer1[i] = Low[i] - iATR(NULL, PERIOD_CURRENT, 14, i); // Generate Buy signal
            
                if (time[0] != last_alert_time){Alert("Buy Signal Detected"); // Alert for Buy
                last_alert_time  = time[0];}
            
        }
    }

    // Sell Condition
    if (//iCustom(NULL, PERIOD_CURRENT, "DYMI", stdevLength, avgOfStdevLength, DYMILength, DYMILengthLowerLimit, DYMILengthUpperLimit, 0, i) < OVERBOUGHT
        iRSI(NULL, 0, RSI_Period, 0, i + 1) * 2 - 100 > RSI_Level
        && iCCI(NULL, 0, CCI_Period, 0, i + 1) > CCI_Level)
    {
        if (Close[i] > Open[i]) // If the candle is bullish, change to Buy signal
        {
            Buffer2[i] = 0; // Clear Sell signal
            Buffer1[i] = Low[i] - iATR(NULL, PERIOD_CURRENT, 14, i); // Generate Buy signal
            
                if (time[0] != last_alert_time){Alert("Buy Signal Detected"); // Alert for Buy
                last_alert_time  = time[0];}
            
        }
        else
        {
            Buffer1[i] = 0; // Clear Buy signal
            Buffer2[i] = High[i] + iATR(NULL, PERIOD_CURRENT, 14, i); // Generate Sell signal
            
                if (time[0] != last_alert_time){Alert("Sell Signal Detected"); // Alert for Sell
                last_alert_time  = time[0];}
            
        }
    }
    
}
for (i = limit - 1; i >= 0; i--)
{
if(Buffer1[2] != 0 && Close[1] > Open[1])
  {
  CreateArrow("ss",233,Low[0],Time[0],clrGreen,ANCHOR_TOP,1);
  }

}
   return(rates_total);
  }
//+------------------------------------------------------------------+

bool CreateArrow(const string name, const int code, const double price, const datetime time, const color col, const ENUM_ARROW_ANCHOR anc, const int size = 1)
  {
   bool create = ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);
   
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE, code);
   ObjectSetDouble(0, name, OBJPROP_PRICE, price);
   ObjectSetInteger(0, name, OBJPROP_TIME, time);
   ObjectSetInteger(0, name, OBJPROP_COLOR, col);
   ObjectSetInteger(0, name, OBJPROP_ANCHOR, anc);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, size);
   
   return(create);
  }

you can try to put it on your chart and see why the alert triggered everytime we put it

 
i would just put in OnInit() a line "time_alert = iTime(Symbol(),PERIOD_CURRENT,0)+PeriodSeconds();"