//+-----------------------------------------------------+ //| INDICATOR AudioAlerts.mq4 | //| copy to [experts\indicators] and recompile | //| status messages printed in Experts tab of terminal | //+-----------------------------------------------------+ //| This is free experimental software. | //| No guarantees are expressed or implied. | //| Feedback welcome via Forex Factory private message. | //+-----------------------------------------------------+ #property copyright "Copyright © 2009 Robert Dee" #property link "www.forexfactory.com/member.php?u=12983" #define INDICATOR_VERSION 20090201 #define INDICATOR_NAME "AudioAlerts" #property indicator_chart_window #property indicator_buffers 4 #property indicator_color1 DarkBlue // BUY alert arrows #property indicator_color2 Red // SELL alert arrows #property indicator_color3 DarkBlue // BULLISH signal candle body #property indicator_color4 Red // BEARISH signal candle body #property indicator_width1 5 #property indicator_width2 5 #property indicator_width3 3 #property indicator_width4 3 extern bool BasicForceAlerts = True; // macd + stochastics + emas (includes all stoch OB & OS restrictions) extern bool AdvancedForceAlerts = True; // macd + stochastics + emas (ignores stoch OB & OS restrictions also ignores divergence) extern bool LineAlerts = False; // when price touches a line (any trend line or horizontal line object on the price chart) extern bool AlertPopups = True; // enable alert popup window extern string AlertSoundFile = "alert2.wav"; // the WAV file must be located in the MT4\sounds folder, ("" = empty = disable sounds) extern int AlertSoundRepeats = 3; // number of times the WAV file will be repeated after the first alert sound extern bool ShowChartArrows = False; // printing of alert arrows on the price chart (default = disabled) extern bool PaintSignalCandles = True; // painting of signal candle bodies on the price chart (default = disabled) //---- global vars int LastAlert, AlertSoundCount; bool osreset, obreset; datetime signalcandletime, lastcandletime, lastlinealert; double BuyAlerts[]; double SellAlerts[]; double CandleBodyLow[]; double CandleBodyHigh[]; int lastsignal; #define NONE 0 #define BASICBUY 1 #define BASICSELL 2 #define ADVANCEDBUY 3 #define ADVANCEDSELL 4 //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { if(ShowChartArrows == True) SetIndexStyle(0,DRAW_ARROW); else SetIndexStyle(0,DRAW_NONE); SetIndexArrow(0,SYMBOL_ARROWUP); SetIndexEmptyValue(0,0); if(ShowChartArrows == True) SetIndexStyle(1,DRAW_ARROW); else SetIndexStyle(1,DRAW_NONE); SetIndexArrow(1,SYMBOL_ARROWDOWN); SetIndexEmptyValue(1,0); if(PaintSignalCandles == True) {SetIndexStyle(2,DRAW_HISTOGRAM); SetIndexStyle(3,DRAW_HISTOGRAM);} SetIndexBuffer(0,BuyAlerts); SetIndexBuffer(1,SellAlerts); SetIndexBuffer(2,CandleBodyLow); SetIndexBuffer(3,CandleBodyHigh); IndicatorDigits(Digits); IndicatorShortName(INDICATOR_NAME); SetIndexLabel(0,""); SetIndexLabel(1,""); SetIndexLabel(2,""); SetIndexLabel(3,""); // cleanup buffers int i = 0; while(i < Bars) { BuyAlerts[i] = 0; SellAlerts[i] = 0; CandleBodyLow[i] = 0; CandleBodyHigh[i] = 0; i++; } Print("version "+INDICATOR_VERSION+" Copyright © 2009 Robert Dee"); } //+------------------------------------------------------------------+ //| Paints the candle body at position (shift) using a histogram //+------------------------------------------------------------------+ void PaintCandleBody(int shift) { CandleBodyLow[shift] = Close[shift]; CandleBodyHigh[shift] = Open[shift]; } //+------------------------------------------------------------------+ //| Indicator start() function called every time price changes (tic) //+------------------------------------------------------------------+ int start() { int count; int multi = MathPow(10,Digits); // calc multiplier for this currency int daycandles = (3600*24)/(Time[0]-Time[1]); // candles per day in this timeframe int spread = MarketInfo(Symbol(),MODE_SPREAD); // spread for this pair double macd1, macd2, stoch1, stoch2, stochsig1, stochsig2, oema5, cema5, objvalue; string objname, objdesc, msg; // find starting position at beginning of chart int shift; int limit; int counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars; shift = limit; while(shift >= 0) { ///////////////////////////// // DATA from CLOSED CANDLES macd1 = iMACD(NULL,0,12,26,1,PRICE_CLOSE,MODE_MAIN,shift+1); macd2 = iMACD(NULL,0,12,26,1,PRICE_CLOSE,MODE_MAIN,shift+2); stoch1 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_MAIN,shift+1); stoch2 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_MAIN,shift+2); stochsig1 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,shift+1); stochsig2 = iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,shift+2); oema5 = NormalizeDouble(iMA(NULL,0,5,0,MODE_EMA,PRICE_OPEN,shift+1),Digits); cema5 = NormalizeDouble(iMA(NULL,0,5,0,MODE_EMA,PRICE_CLOSE,shift+1),Digits); ////////////////////////////////// // BASIC FORCE STOCH RESET RULES if(stoch1 < 20 && stochsig1 < 20) {osreset = True; obreset = False;} // oversold reset allows new BuyAlerts if(stoch1 > 80 && stochsig1 > 80) {obreset = True; osreset = False;} // overbought reset allows new SellAlerts if(lastsignal == BASICBUY && cema5 < oema5) lastsignal = NONE; if(lastsignal == BASICSELL && cema5 > oema5) lastsignal = NONE; //if(lastsignal == ADVANCEDBUY && cema5 < oema5) lastsignal = NONE; //if(lastsignal == ADVANCEDSELL && cema5 > oema5) lastsignal = NONE; ///////////////////////////////// // BASIC FORCE BUY ALERT RULES if(BasicForceAlerts == True) if(osreset == True) if(macd1 > macd2) if(stoch1 >= stochsig1+1 && stoch1 > stoch2 && stoch1 > 20 && stoch1 < 80 && stochsig1 > 20) if(cema5 >= oema5+1*Point) { BuyAlerts[shift] = Low[shift]-5*Point; if(PaintSignalCandles == True) PaintCandleBody(shift+1); osreset = False; lastsignal = BASICBUY; signalcandletime = Time[shift+1]; } ///////////////////////////////// // BASIC FORCE SELL ALERT RULES if(BasicForceAlerts == True) if(obreset == True) if(macd1 < macd2) if(stoch1 <= stochsig1-1 && stoch1 < stoch2 && stoch1 < 80 && stoch1 > 20 && stochsig1 < 80) if(cema5 <= oema5-1*Point) { SellAlerts[shift] = High[shift]+5*Point; if(PaintSignalCandles == True) PaintCandleBody(shift+1); obreset = False; lastsignal = BASICSELL; signalcandletime = Time[shift+1]; } /////////////////////////////////// // ADVANCED FORCE BUY ALERT RULES if(AdvancedForceAlerts == True) if(lastsignal != ADVANCEDBUY && lastsignal != BASICBUY) if(macd1 > macd2) if(stoch1 >= stochsig1+1 && stoch1 > stoch2 && stoch1 < 80) if(cema5 >= oema5+1*Point) { BuyAlerts[shift] = Low[shift]-5*Point; if(PaintSignalCandles == True) PaintCandleBody(shift+1); osreset = False; lastsignal = ADVANCEDBUY; signalcandletime = Time[shift+1]; } /////////////////////////////////// // ADVANCED FORCE SELL ALERT RULES if(AdvancedForceAlerts == True) if(lastsignal != ADVANCEDSELL && lastsignal != BASICSELL) if(macd1 < macd2) if(stoch1 <= stochsig1-1 && stoch1 < stoch2 && stoch1 > 20) if(cema5 <= oema5-1*Point) { SellAlerts[shift] = High[shift]+5*Point; if(PaintSignalCandles == True) PaintCandleBody(shift+1); obreset = False; lastsignal = ADVANCEDSELL; signalcandletime = Time[shift+1]; } shift--; // move forward one candle } // end of while() loop ///////////////////// // LINE ALERT RULES if(LineAlerts == True && lastlinealert != Time[0]) // only one line alert per candle { shift = ObjectsTotal()-1; // objects index starts at zero while(shift >= 0) { // get data from the object objname = ObjectName(shift); objdesc = ObjectDescription(objname); if(objdesc == "") objdesc = objname; objdesc = StringTrimLeft(objdesc); objvalue = NormalizeDouble(ObjectGetValueByShift(objname,0),Digits); if(ObjectType(objname) == OBJ_HLINE) objvalue = NormalizeDouble(ObjectGet(objname,OBJPROP_PRICE1),Digits); // line alert rules if(ObjectType(objname) == OBJ_TREND || ObjectType(objname) == OBJ_HLINE) // trend line or horizontal line if(Bid <= objvalue+1*Point && Bid >= objvalue-1*Point) // 1 pip above or below the line { Alert("Line Alert for '"+objdesc+"' at " + DoubleToStr(objvalue,Digits)); PlaySound(AlertSoundFile); lastlinealert = Time[0]; break; } shift--; // move to next object in the list } } // end of line alert while() loop /////////////////////////////////////////////////////////////////////// // a status message is printed in the experts log for each new candle if(lastcandletime != Time[0]) { if(AlertPopups == True) { if(BuyAlerts[0] != 0 && lastsignal == BASICBUY) {Alert("Basic Force BUY candle "+TimeToStr(signalcandletime,TIME_MINUTES));PlaySound(AlertSoundFile);} if(SellAlerts[0] != 0 && lastsignal == BASICSELL) {Alert("Basic Force SELL candle "+TimeToStr(signalcandletime,TIME_MINUTES));PlaySound(AlertSoundFile);} if(BuyAlerts[0] != 0 && lastsignal == ADVANCEDBUY) {Alert("Advanced Force BUY candle "+TimeToStr(signalcandletime,TIME_MINUTES));PlaySound(AlertSoundFile);} if(SellAlerts[0] != 0 && lastsignal == ADVANCEDSELL) {Alert("Advanced Force SELL candle "+TimeToStr(signalcandletime,TIME_MINUTES));PlaySound(AlertSoundFile);} } msg = "status"; if(lastsignal == NONE) msg = msg + " NO ALERTS"; if(lastsignal == BASICBUY) msg = msg + " BasicForceBUY " +TimeToStr(signalcandletime,TIME_MINUTES); if(lastsignal == BASICSELL) msg = msg + " BasicForceSELL " +TimeToStr(signalcandletime,TIME_MINUTES); if(lastsignal == ADVANCEDBUY) msg = msg + " AdvancedForceBUY " +TimeToStr(signalcandletime,TIME_MINUTES); if(lastsignal == ADVANCEDSELL) msg = msg + " AdvancedForceSELL " +TimeToStr(signalcandletime,TIME_MINUTES); if(osreset == True) msg = msg + " OSReset"; if(obreset == True) msg = msg + " OBReset"; Print(msg); lastcandletime = Time[0]; AlertSoundCount = 0; // reset the counter with each new candle } //////////////////////////////////////////////////////////////////////// // AlertSoundFile played again depending on value of AlertSoundRepeats if(Seconds() < LastAlert) LastAlert = Seconds(); // reset counter each minute if(AlertSoundFile != "" && Seconds() >= LastAlert+5) // five seconds delay then repeating on next price tick { if(BuyAlerts[0] != 0 && AlertSoundCount < AlertSoundRepeats) {PlaySound(AlertSoundFile);LastAlert = Seconds();AlertSoundCount++;} if(SellAlerts[0] != 0 && AlertSoundCount < AlertSoundRepeats) {PlaySound(AlertSoundFile);LastAlert = Seconds();AlertSoundCount++;} if(lastlinealert == Time[0] && AlertSoundCount < AlertSoundRepeats) {PlaySound(AlertSoundFile);LastAlert = Seconds();AlertSoundCount++;} } return(0); } // end of start() //+------------------------------------------------------------------+ void deinit() { // cleanup buffers int i = 0; while(i < Bars) { BuyAlerts[i] = 0; SellAlerts[i] = 0; CandleBodyLow[i] = 0; CandleBodyHigh[i] = 0; i++; } }
Sample
Analysis
Market Information Used:
Series array that contains the lowest prices of each bar
Series array that contains the highest prices of each bar
Series array that contains close prices for each bar
Series array that contains open prices of each bar
Series array that contains open time of each bar
Indicator Curves created:
Implements a curve of type DRAW_ARROW
Implements a curve of type DRAW_NONE
Implements a curve of type DRAW_HISTOGRAM
Indicators Used:
MACD Histogram
Stochastic oscillator
Moving average indicator
Custom Indicators Used:
Order Management characteristics:
Other Features:
It issuies visual alerts to the screen
It plays sound alerts