//+------------------------------------------------------------------+ //| RecentHighLowAlert.mq5 | //| Copyright 2013, EarnForex.com | //| http://www.earnforex.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2013, EarnForex.com" #property link "http://www.earnforex.com" #property version "1.00" #property indicator_chart_window #property description "Draws lines on the high/low of the recent N bars." #property description "Alerts when the Bid price of the current bar crosses previous high/low." #property indicator_buffers 2 #property indicator_plots 2 #property indicator_width1 1 #property indicator_color1 clrDodgerBlue #property indicator_type1 DRAW_LINE #property indicator_style1 STYLE_SOLID #property indicator_label1 "High" #property indicator_width2 1 #property indicator_color2 clrYellow #property indicator_type2 DRAW_LINE #property indicator_style2 STYLE_SOLID #property indicator_label2 "Low" #define HIGH 1 #define LOW 0 input int N = 20; input bool SoundAlert = true; input bool PopupAlert = false; input bool EmailAlert = false; double HighBuf[]; double LowBuf[]; datetime LastHighAlert = D'1970.01.01'; datetime LastLowAlert = D'1970.01.01'; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, N); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, N); SetIndexBuffer(0, HighBuf); SetIndexBuffer(1, LowBuf); return(0); } //+------------------------------------------------------------------+ //| 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 start; if (rates_total <= N) return(0); // Skip calculated bars start = prev_calculated - 1; // First run if (start < N) start = N; for (int i = start; i < rates_total; i++) { HighBuf[i] = High[ArrayMaximum(High, i - N + 1, N)]; LowBuf[i] = Low[ArrayMinimum(Low, i - N + 1, N)]; } double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); // rates_total - 2 because wee need to check the current price against the max/min of the latest closed bar if ((Bid > HighBuf[rates_total - 2]) && (LastHighAlert != Time[rates_total - 1])) SendAlert(HIGH, HighBuf[rates_total - 2], Time[rates_total - 1]); else if ((Bid < LowBuf[rates_total - 2]) && (LastLowAlert != Time[rates_total - 1])) SendAlert(LOW, LowBuf[rates_total - 2], Time[rates_total - 1]); return(rates_total); } //+------------------------------------------------------------------+ //| Issues alerts and remembers last sent alert time. | //+------------------------------------------------------------------+ void SendAlert(int direction, double price, datetime time) { string alert = " Local "; string subject; if (direction == HIGH) { alert = alert + "high"; subject = "High broken"; LastHighAlert = time; } else if (direction == LOW) { alert = alert + "low"; subject = "Low broken"; LastLowAlert = time; } alert = alert + " broken at " + DoubleToString(price, _Digits) + "."; if (SoundAlert) PlaySound("alert.wav"); if (PopupAlert) Alert(alert); if (EmailAlert) SendMail(subject, TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS) + alert); } //+------------------------------------------------------------------+