//+------------------------------------------------------------------+ //| PriceAlert.mq4 | //| Copyright © M00SE 2011 | //| | //| P R I C E A L E R T | //| | //| This indicator will draw two trendlines on the chart upon which | //| it is placed. The trendlines, which may be moved around, act as | //| upper and lower alert levels. When the mid-price crosses either | //| level the warning alert will be triggered. | //| | //| Version 1.2 - 25 Jul 2011 | //| Added mode flag to get only a single alert per time bar | //| Added email flag to send email as well as audio/visual alert | //| Added flag to select line type (trendline or horizontal) | //| Added setting to specify line width | //| Added TidyOnExit flag to remove trendlines from chart upon exit | //| | //| Version 1 - 16 Jun 2011 | //| | //| | //| Instructions | //| | //| Choose the symbol you're interested in and display it in a chart | //| window at the appropriate timeframe. Load PriceAlert Indicator | //| and optionally choose desired colour for each trendline. | //| Optionally set flag to receive single or multiple alerts per | //| time bar and flag to send email with each alert. (You must have | //| previously configured your email details.) | //| Reposition the trendlines to the level at which you wish to be | //| notified should the mid-price get there. | //| Remember to have your speakers on! | //| | //| That's it! | //| Hope you like it, MOOSE. | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © M00SE 2011" #property indicator_chart_window //---- input parameters extern color UpperColour = Blue; extern color LowerColour = Red; extern int LineWidth = 2; extern string NoteDrawTrendline = "true=trendline; false=horizontal line"; extern bool DrawTrendline = true; extern bool SendEmail = false; extern string NoteSingleAlert = "true ==> only one hi/lo alert per bar"; extern bool SingleAlertMode = true; extern bool TidyOnExit = false; //---- data static int prevTime = 0; static double prevPrice; string upperName = "Upper Alert"; string lowerName = "Lower Alert"; double hiAlert; double loAlert; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- prevTime = Time[0]; prevPrice = ((Ask + Bid) / 2.0); double topPrice = WindowPriceMax() - (WindowPriceMax() - WindowPriceMin())*0.2; double bottomPrice = WindowPriceMax() - (WindowPriceMax() - WindowPriceMin())*0.8; if(DrawTrendline) { SetTrendlineObject(upperName, Time[30], topPrice, Time[0], topPrice, UpperColour); SetTrendlineObject(lowerName, Time[30], bottomPrice, Time[0], bottomPrice, LowerColour); } else { SetHorizlineObject(upperName, topPrice, UpperColour); SetHorizlineObject(lowerName, bottomPrice, LowerColour); } //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- Avoid deleting these upper and lower alert trendlines so they are not lost if chart is reloaded (unless flag is set) if(TidyOnExit) { ObjectDelete(upperName); ObjectDelete(lowerName); } //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { string alertMsg = ""; double midPrice = ((Ask + Bid) / 2.0); static bool lowerAlertLatch = false; static bool upperAlertLatch = false; if(prevTime != Time[0]) { //Print("NewTimeFrame=", TimeToStr(Time[0])); lowerAlertLatch = false; upperAlertLatch = false; prevTime = Time[0]; } hiAlert = 0.0; if(ObjectFind(upperName) == 0) { if(DrawTrendline) hiAlert = NormalizeDouble(ObjectGetValueByShift(upperName,0),Digits); else hiAlert = NormalizeDouble(ObjectGet(upperName, OBJPROP_PRICE1),Digits); } loAlert = 0.0; if(ObjectFind(lowerName) == 0) { if(DrawTrendline) loAlert = NormalizeDouble(ObjectGetValueByShift(lowerName,0),Digits); else loAlert = NormalizeDouble(ObjectGet(lowerName, OBJPROP_PRICE1),Digits); } if(hiAlert > 0.0 && prevPrice < hiAlert && midPrice > hiAlert) { //Print("hi alert cond"); if(!upperAlertLatch || !SingleAlertMode) { alertMsg = "Upper Level " + Symbol() + " " + DoubleToStr(midPrice, Digits); Alert(alertMsg); if (SendEmail) SendMail("Upper Alert on " + Symbol(), alertMsg); upperAlertLatch = true; } } if(loAlert > 0.0 && prevPrice > loAlert && midPrice < loAlert) { //Print("lo alert cond"); if(!lowerAlertLatch || !SingleAlertMode) { alertMsg = "Lower Level " + Symbol() + " " + DoubleToStr(midPrice, Digits); Alert(alertMsg); if (SendEmail) SendMail("Lower Alert on " + Symbol(), alertMsg); lowerAlertLatch = true; } } /* * Print("mid=" + DoubleToStr( midPrice, Digits) * + " prev=" + prevPrice * + " hi=" + hiAlert * + " lo=" + loAlert); */ prevPrice = midPrice; return(0); } //+------------------------------------------------------------------+ //| SetTrendlineObject | //+------------------------------------------------------------------+ void SetTrendlineObject(string name, datetime T1, double P1, datetime T2, double P2, color colour) { if(ObjectFind(name) == -1) { ObjectCreate(name, OBJ_TREND, 0, T1, P1, T2, P2); ObjectSet(name, OBJPROP_COLOR, colour); ObjectSet(name, OBJPROP_BACK, false); ObjectSet(name, OBJPROP_WIDTH, LineWidth); } } //+------------------------------------------------------------------+ //| SetHorizlineObject | //+------------------------------------------------------------------+ void SetHorizlineObject(string name, double P1, color colour) { if(ObjectFind(name) == -1) { ObjectCreate(name, OBJ_HLINE, 0, 0, P1); ObjectSet(name, OBJPROP_COLOR, colour); ObjectSet(name, OBJPROP_BACK, false); ObjectSet(name, OBJPROP_WIDTH, LineWidth); } } //+------------------------------------------------------------------+