Search code examples
concurrencymql4algorithmic-tradingmetatrader4mt4

MQL4 How to alert when a price reaches certain levels?


I have this free indicator is the name is FiboPiv_v2.mq4.

It's a tool I use with good result in trading scalping. I set normally the alert by hand, but I see that the code is open and so I'd like to do a modification but I'm quite newbie in programming MQL4.

I would like to add a pop-up and sound that says something like "AUDUSD has reached S1".

Code of the indicator:

#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
//----
ObjectDelete("S1");
ObjectDelete("S2");
ObjectDelete("S3");
ObjectDelete("R1");
ObjectDelete("R2");
ObjectDelete("R3");
ObjectDelete("PIVIOT");
ObjectDelete("Support 1");
ObjectDelete("Support 2");
ObjectDelete("Support 3");
ObjectDelete("Piviot level");
ObjectDelete("Resistance 1");
ObjectDelete("Resistance 2");
ObjectDelete("Resistance 3");
Comment(" ");
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
double rates[1][6],yesterday_close,yesterday_high,yesterday_low;
ArrayCopyRates(rates,Symbol(),PERIOD_D1);
//----
if(DayOfWeek()==1)
 {
  if(TimeDayOfWeek(iTime(Symbol(),PERIOD_D1,1))==5)
    {
     yesterday_close= rates[1][4];
     yesterday_high = rates[1][3];
     yesterday_low=rates[1][2];
    }
  else
    {
     for(int d=5;d>=0;d--)
       {
        if(TimeDayOfWeek(iTime(Symbol(),PERIOD_D1,d))==5)
          {
           yesterday_close= rates[d][4];
           yesterday_high = rates[d][3];
           yesterday_low=rates[d][2];
          }

       }
    }
 }
else
 {
  yesterday_close= rates[1][4];
  yesterday_high = rates[1][3];
  yesterday_low=rates[1][2];
 }
//---- Calculate Pivots
Comment("\nYesterday quotations:\nH ",yesterday_high,"\nL 
",yesterday_low,"\nC ",yesterday_close);
double R=yesterday_high-yesterday_low;//range
double p=(yesterday_high+yesterday_low+yesterday_close)/3;// Standard Pivot
double r3 = p + (R * 1.000);
double r2 = p + (R * 0.618);
double r1 = p + (R * 0.382);
double s1 = p - (R * 0.382);
double s2 = p - (R * 0.618);
double s3 = p - (R * 1.000);
//----
drawLine(r3,"R3",Lime,0);
drawLabel("Resistance 3",r3,Lime);
drawLine(r2,"R2",Green,0);
drawLabel("Resistance 2",r2,Green);
drawLine(r1,"R1",DarkGreen,0);
drawLabel("Resistance 1",r1,DarkGreen);
drawLine(p,"PIVIOT",Blue,1);
drawLabel("Piviot level",p,Blue);
drawLine(s1,"S1",Maroon,0);
drawLabel("Support 1",s1,Maroon);
drawLine(s2,"S2",Crimson,0);
drawLabel("Support 2",s2,Crimson);
drawLine(s3,"S3",Red,0);
drawLabel("Support 3",s3,Red);
//----
return(0);
}
//+------------------------------------------------------------------+
void drawLabel(string name,double lvl,color Color)
{
if(ObjectFind(name)!=0)
 {
  if(Bars<10) return;
  ObjectCreate(name,OBJ_TEXT,0,Time[10],lvl);
  ObjectSetText(name,name,8,"Arial",EMPTY);
  ObjectSet(name,OBJPROP_COLOR,Color);
 }
else
 {
  if(Bars<10) return;
  ObjectMove(name,0,Time[10],lvl);
 }
}
 //----
 void drawLine(double lvl,string name,color Col,int type)
 {
 if(ObjectFind(name)!=0)
  {
   ObjectCreate(name,OBJ_HLINE,0,Time[0],lvl,Time[0],lvl);
   if(type==1)
     ObjectSet(name,OBJPROP_STYLE,STYLE_SOLID);
   else
     ObjectSet(name,OBJPROP_STYLE,STYLE_DOT);
   ObjectSet(name,OBJPROP_COLOR,Col);
   ObjectSet(name,OBJPROP_WIDTH,1);
   }
   else
    {
    ObjectDelete(name);
    ObjectCreate(name,OBJ_HLINE,0,Time[0],lvl,Time[0],lvl);
    if(type==1)
     ObjectSet(name,OBJPROP_STYLE,STYLE_SOLID);
  else
     ObjectSet(name,OBJPROP_STYLE,STYLE_DOT);
  ObjectSet(name,OBJPROP_COLOR,Col);
  ObjectSet(name,OBJPROP_WIDTH,1);
 }
  }
//+--------------------------------------------------------------------+

Solution

  • First:

    Forget to have an Alert() call inside an Indicator type of MQL4-code. For details ref. below + MQL4 Documentation on such and similarly forbidden blocking calls.


    Next :
    The original code was awfully inefficient

    ( see details in documentation on New-MQL4.56789, in 2018/Q2 still runs all ( indeed ALL platform's instances of concurrently operated CustomIndicator + Indicators inside one, single, solo, blocking-vulnerable, SPOF-thread (!!) )

    A sort of efficiency-repaired code that does not "shaking all trees" bottom up per each QUOTE-arrival, that yet performs all the necessary updates and shows the beeping-alarm scheme:

    #property indicator_chart_window
    
    double R, r3, r2, r1, p, s1, s2, s3;                                    // SEMI-GLOBALs for easy runPriceCHECKs()
    
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function                              |
    //+------------------------------------------------------------------+
    int start()
    {   
        static int  aLastVisitedBAR =  EMPTY;                               // INIT
        if (        aLastVisitedBAR == iBars( _Symbol, PERIOD_D1 ) )        // TEST:
        {                              runPriceCHECKs();                    //        Check Price v/s PIVOT levels
                                       return( 0 );                         //                    but PIVOTs never change during the same day ... so JIT/RET--^
        }
        else        aLastVisitedBAR == iBars( _Symbol, PERIOD_D1 );         // SYNC & RE-CALC:
    
        double rates[][6], yesterday_close,
                           yesterday_high,
                           yesterday_low;
        ArrayCopyRates( rates,
                        _Symbol,
                        PERIOD_D1
                        );
    //----
        if (  DayOfWeek() == 1 )
        {     
              if (  TimeDayOfWeek( iTime( _Symbol, PERIOD_D1, 1 ) ) == 5 )
              {     
                    yesterday_close = rates[1][4];
                    yesterday_high  = rates[1][3];
                    yesterday_low   = rates[1][2];
              }
              else
              {     
                    for ( int d = 5; d >= 0; d-- )
                    {       
                          if (  TimeDayOfWeek( iTime( _Symbol, PERIOD_D1, d ) ) == 5 )
                          {     
                                yesterday_close = rates[d][4];
                                yesterday_high  = rates[d][3];
                                yesterday_low   = rates[d][2];
                          }
                    }
              }
        }
        else
        {     
              yesterday_close = rates[1][4];
              yesterday_high  = rates[1][3];
              yesterday_low   = rates[1][2];
        }
    //---- Calculate Pivots
        Comment( "\nYesterday quotations:\nH ",
                    yesterday_high,     "\nL ",
                    yesterday_low,      "\nC ",
                    yesterday_close
                    );
    
        R  =   yesterday_high - yesterday_low;                       // a Day range
        p  = ( yesterday_high + yesterday_low + yesterday_close ) /3;// a Standard Pivot
    
        r3 = p + ( R * 1.000 ); drawLine( r3, "R3",    clrLime,      0 ); drawLabel( "Resistance 3", r3, clrLime      );
        r2 = p + ( R * 0.618 ); drawLine( r2, "R2",    clrGreen,     0 ); drawLabel( "Resistance 2", r2, clrGreen     );
        r1 = p + ( R * 0.382 ); drawLine( r1, "R1",    clrDarkGreen, 0 ); drawLabel( "Resistance 1", r1, clrDarkGreen );
                                drawLine( p,  "PIVOT", clrBlue,      1 ); drawLabel( "Pivot level",  p,  clrBlue      );
        s1 = p - ( R * 0.382 ); drawLine( s1, "S1",    clrMaroon,    0 ); drawLabel( "Support 1",    s1, clrMaroon    );
        s2 = p - ( R * 0.618 ); drawLine( s2, "S2",    clrCrimson,   0 ); drawLabel( "Support 2",    s2, clrCrimson   );
        s3 = p - ( R * 1.000 ); drawLine( s3, "S3",    clrRed,       0 ); drawLabel( "Support 3",    s3, clrRed       );
    //----
        runPriceCHECKs();                                                   //        Check Price v/s PIVOT levels    
    //----
        return( 0 );
      }
    
    //+------------------------------------------------------------------+
    //|  drawLabel( string name, double lvl, color Color )               |
    //+------------------------------------------------------------------+
    void drawLabel( string name, double lvl, color Color )
    {    
         if (  Bars <  10 ) return;
    
         if (  ObjectFind( name ) == 0 ) ObjectMove(    name,                0, Time[10], lvl );
         else
         {                               ObjectCreate(  name, OBJ_TEXT,      0, Time[10], lvl );
                                         ObjectSet(     name, OBJPROP_COLOR, Color );
                                         ObjectSetText( name, name,          8, "Arial", EMPTY );
         }
      }
    //+------------------------------------------------------------------+
    //|  drawLine( double lvl, string name, color Col, int type )        |
    //+------------------------------------------------------------------+
    void drawLine( double lvl, string name, color Col, int type )
    {    
         if (  ObjectFind(   name ) == 0 )
               ObjectDelete( name );
    
         ObjectCreate(       name, OBJ_HLINE, 0,  Time[0], lvl,
                                                  Time[0], lvl );
         ObjectSet(          name, OBJPROP_COLOR, Col );
         ObjectSet(          name, OBJPROP_WIDTH, 1 );
         ObjectSet(          name, OBJPROP_STYLE, (  type == 1 ) ? STYLE_SOLID : STYLE_DOT );
      }
    //+------------------------------------------------------------------+
    //|  runPriceCHECKs()                                                |
    //+------------------------------------------------------------------+
    void runPriceCHECKs()
    {    
    #define DEF_PROXIMITY_TRESHOLD_R3    ( 15 * Point )
    #define DEF_PROXIMITY_TRESHOLD_R2    ( 10 * Point )
    #define DEF_PROXIMITY_TRESHOLD_R1    (  5 * Point )
    #define DEF_PROXIMITY_TRESHOLD_P     (  2 * Point )
    #define DEF_PROXIMITY_TRESHOLD_S1    (  5 * Point )
    #define DEF_PROXIMITY_TRESHOLD_S2    ( 10 * Point )
    #define DEF_PROXIMITY_TRESHOLD_S3    ( 15 * Point )
    
         if (  MathAbs( r3 - Close ) <= DEF_PROXIMITY_TRESHOLD_R3 )
               ...
               PlaySound( aFileNAME_WAV_R3 ); // The file must be located in terminal_directory\Sounds or its sub-directory. Only WAV files are played.
            // Sleep(     250 );              // 250 [ms] AS A LAST RESORT, BETTER MAKE .WAV CUT-SHORT NOT TO LAST LONGER BY ITSELF
            // PlaySound( NULL );
               return;
    
         if (  MathAbs( r2 - Close ) <= DEF_PROXIMITY_TRESHOLD_R2 )
               ...
               return;
    
         if (  MathAbs( r1 - Close ) <= DEF_PROXIMITY_TRESHOLD_R1 )
               ...
               return;
    
         if (  MathAbs( p  - Close ) <= DEF_PROXIMITY_TRESHOLD_P  )
               ...
               return;
    
         if (  MathAbs( s1 - Close ) <= DEF_PROXIMITY_TRESHOLD_S1 )
               ...
               return;
    
         if (  MathAbs( s2 - Close ) <= DEF_PROXIMITY_TRESHOLD_S2 )
               ...
               return;
    
         if (  MathAbs( s3 - Close ) <= DEF_PROXIMITY_TRESHOLD_S3 )
               ...
               return;
    
      // nop
    
      }
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int init()
    {   return( 0 );
      }
    //+------------------------------------------------------------------+
    //| Custom indicator deinitialization function                       |
    //+------------------------------------------------------------------+
    int deinit()
    {   
    //----
        ObjectDelete( "S1"           );
        ObjectDelete( "S2"           );
        ObjectDelete( "S3"           );
        ObjectDelete( "R1"           );
        ObjectDelete( "R2"           );
        ObjectDelete( "R3"           );
        ObjectDelete( "PIVOT"        );
        ObjectDelete( "Support 1"    );
        ObjectDelete( "Support 2"    );
        ObjectDelete( "Support 3"    );
        ObjectDelete( "Piviot level" );
        ObjectDelete( "Resistance 1" );
        ObjectDelete( "Resistance 2" );
        ObjectDelete( "Resistance 3" );
    
        Comment( ":o)" );
    //----
        return( 0 );
      }
    //+------------------------------------------------------------------+