//+----------------------------------------------------------------------------- //| MAStrongTrendDetector.mq4 //| Lukasz Szelag (lukasz74nj@gmail.com) //| http://www.forexabyss.com //| //| A custom indicator for detecting extremely strong trends that are supported //| by institutional traders. These traders are known to create support and //| resistance at the 10-day EMA. The indicator is intended to be used, and //| works only on a daily timeframe. //| //| Strong trends are detected by checking if exponential moving averages are //| aligned in the proper order and 10-day EMA acts as a support (for an //| uptrend) or resistance (for a downtrend) for a period of at least certain //| number of bars (specified by the external variable signalMinBars). //| //| Once the following conditions are met, a trade opportunity to buy or sell //| comes when the price falls to, or rises towards its 10-day EMA. //| //| Uptrend conditions: //| //| 1. EMA(10) > EMA(20) > EMA(50) > EMA(200) //| 2. FOR each i = 0..signalMinBars - 1: Low[i] > EMA(10, i) //| //| Downtrend conditions: //| //| 1. EMA(10) < EMA(20) < EMA(50) < EMA(200) //| 2. FOR each i = 0..signalMinBars - 1: High[i] < EMA(10, i) //| //| For every bar that satisfies either group of conditions, little arrow is //| shown pointing upward or downward depending on the trend direction. In //| addition, a bigger arrow is shown in the upper left corner that corresponds //| to conditions calculated for the current (zero) bar. //| //| Once a strong trend has been detected, a stop loss level is shown for every //| bar (orange dots), either below or above the 10-day EMA (depending on the //| trend direction). The stop loss is based on volatility and calculated using //| the the following formulas: //| //| EMA(10) - ATR(14, i) / 2 (for an uptrend) //| EMA(10) + ATR(14, i) / 2 (for an downtrend) //| //| This can be used to determine the stop loss placement when opening a new //| position (using the stop loss level that corresponds to the zero bar), and //| also when updating the stop loss for the existing position once the current //| candle closes (using the stop loss level that corresponds to the closed //| candle). //| //| Date Version Comments //| 2/15/2009 1.0 Initial version. //| 2/23/2009 1.1 Stop loss level is shown correctly. //| //| 3/01/2009 1.2 Removed stop loss hit marker and changed the way how //| the stop loss level is calculated. //| //| 3/03/2009 1.3 In deinit(), delete only the object created by this //| indicator instead of all objects. //| //| 3/03/2009 1.4 The main trend indicator is cleared if no strong trend //| is detected for the zero bar. Changed signalMinBars to //| 4. //+----------------------------------------------------------------------------- #property copyright "Lukasz Szelag (lukasz74nj@gmail.com)" #property link "http://www.forexabyss.com" #property indicator_chart_window #property indicator_buffers 4 #property indicator_color1 Green #property indicator_color2 Red #property indicator_color3 Blue #property indicator_color4 Orange //+----------------------------------------------------------------------------- //| Constants. //+----------------------------------------------------------------------------- #define TREND_UP_ARROW 236 #define TREND_DOWN_ARROW 238 #define STOP_LOSS_LEVEL 108 #define TREND_OBJ_NAME "Trend" #define TREND_NONE 0 #define TREND_UP 1 #define TREND_DOWN 2 //+----------------------------------------------------------------------------- //| External variables. These can be changed in the program properties window. //+----------------------------------------------------------------------------- /* * The number of bars for which the price should stay above (in an uptrend) or * below (in a downtrend) 10-day EMA to show a strong trend signal. */ extern int signalMinBars = 4; //+----------------------------------------------------------------------------- //| Global variables. //+----------------------------------------------------------------------------- double buf0[], buf1[], buf2[], buf3[]; /* * The direction of a strong trend once it has been detected. The direction will * remain the same until a new strong trend is established in the opposite * direction). */ int trendDir = TREND_NONE; //+----------------------------------------------------------------------------- //| Indicator initialization special function. //+----------------------------------------------------------------------------- int init() { IndicatorShortName("MAStrongTrendDetector"); // uptrend indicator arrow SetIndexBuffer(0, buf0); SetIndexStyle(0, DRAW_ARROW); SetIndexArrow(0, TREND_UP_ARROW); SetIndexEmptyValue(0, EMPTY_VALUE); // downtrend indicator arrow SetIndexBuffer(1, buf1); SetIndexStyle(1, DRAW_ARROW); SetIndexArrow(1, TREND_DOWN_ARROW); SetIndexEmptyValue(1, EMPTY_VALUE); // 10-day EMA line SetIndexBuffer(2, buf2); SetIndexStyle(2, DRAW_LINE); SetIndexEmptyValue(2, EMPTY_VALUE); SetIndexLabel(2, "EMA(10)"); // stop loss level based on ATR SetIndexBuffer(3, buf3); SetIndexStyle(3, DRAW_ARROW); SetIndexArrow(3, STOP_LOSS_LEVEL); SetIndexEmptyValue(3, EMPTY_VALUE); SetIndexLabel(3, "Stop Loss Level"); // main trend indicator for the current (zero) bar ObjectCreate(TREND_OBJ_NAME, OBJ_LABEL, 0, 0, 0, 0, 0); ObjectSet(TREND_OBJ_NAME, OBJPROP_XDISTANCE, 20); ObjectSet(TREND_OBJ_NAME, OBJPROP_YDISTANCE, 20); ObjectSetText(TREND_OBJ_NAME, " "); return(0); } //+----------------------------------------------------------------------------- //| Indicator deinitialization special function. //+----------------------------------------------------------------------------- int deinit() { ObjectDelete(TREND_OBJ_NAME); return(0); } //+----------------------------------------------------------------------------- //| Indicator start special function. //+----------------------------------------------------------------------------- int start() { // the indicator can be used on a daily timeframe only if (Period() != PERIOD_D1) { ObjectSetText(TREND_OBJ_NAME, "The indicator works only on a daily timeframe", 15, "Tahoma", Blue); return(0); } // not enough bars for calculations if (Bars < 200) { return(0); } int countedBars = IndicatorCounted(); // check for possible errors if (countedBars < 0) { return(-1); } // index of the first uncounted bar int firstIndex = Bars - countedBars - 1; int j; for(int i = firstIndex; i >= 0; i--) { double ema10 = iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, i); double ema20 = iMA(NULL, 0, 20, 0, MODE_EMA, PRICE_CLOSE, i); double ema50 = iMA(NULL, 0, 50, 0, MODE_EMA, PRICE_CLOSE, i); double ema200 = iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, i); buf0[i] = EMPTY_VALUE; buf1[i] = EMPTY_VALUE; buf2[i] = ema10; buf3[i] = EMPTY_VALUE; /* * Determine if there is a strong trend in place and its direction. If a * strong trend is detected show an arrow that corresponds to the trend * direction (buf0 or buf1). In addition, update the main trend * indicator for the current (zero) bar. */ bool strongTrend = false; // if moving averages are aligned in the proper order for an uptrend if ((ema10 > ema20) && (ema20 > ema50) && (ema50 > ema200)) { strongTrend = true; /* * An additional filter to make sure it is a strong uptrend. The * 10-day EMA must act as a support for a period of at least * signalMinBars bars. */ for (j = 0; j < signalMinBars; j++) { // if support is broken if (Low[i + j] <= iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, i + j)) { strongTrend = false; break; } } if (strongTrend) { trendDir = TREND_UP; buf0[i] = High[i] + 5 * Point; // if current (zero) bar if (i == 0) { ObjectSetText(TREND_OBJ_NAME, CharToStr(TREND_UP_ARROW), 20, "Wingdings", Green); } } } // if moving averages are aligned in the proper order for a downtrend else if ((ema10 < ema20) && (ema20 < ema50) && (ema50 < ema200)) { strongTrend = true; /* * An additional filter to make sure it is a strong downtrend. The * 10-day EMA must act as a resistance for a period of at least * signalMinBars bars. */ for (j = 0; j < signalMinBars; j++) { // if resistance is broken if (High[i + j] >= iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, i + j)) { strongTrend = false; break; } } if (strongTrend) { trendDir = TREND_DOWN; buf1[i] = Low[i] - 5 * Point; // if current (zero) bar if (i == 0) { ObjectSetText(TREND_OBJ_NAME, CharToStr(TREND_DOWN_ARROW), 20, "Wingdings", Red); } } } /* * If no strong trend has been detected for the current (zero) bar clear * the main trend indicator. */ if ((!strongTrend) && (i == 0)) { ObjectSetText(TREND_OBJ_NAME, " "); } buf3[i] = calculateStopLoss(trendDir, i); } return(0); } //+----------------------------------------------------------------------------- //| Calculates and returns a stop loss level for the given bar. The stop level //| will be either below or above EMA(10) depending on the trend direction. If //| the trend direction is TREND_NONE, EMPTY_VALUE is returned. //+----------------------------------------------------------------------------- double calculateStopLoss(int trendDir, int barIndex, bool topLevel = true) { double stopLossDist = iATR(NULL, 0, 14, barIndex) / 2; double ema10 = iMA(NULL, 0, 10, 0, MODE_EMA, PRICE_CLOSE, barIndex); double stopLossLevel = EMPTY_VALUE; if (trendDir == TREND_UP) { stopLossLevel = ema10 - stopLossDist; } else if (trendDir == TREND_DOWN) { stopLossLevel = ema10 + stopLossDist; } return(stopLossLevel); }