Author: Copyright � 2006, Alex Sidd (Executer)
ExCandles2

This MetaTrader script is a specialized technical analysis tool designed to automatically identify and visually signal specific "candlestick patterns" on a trading chart. Instead of requiring a trader to manually squint at price bars to spot reversals or continuations, the script scans historical data in real-time and places colored arrows on the chart to highlight these significant movements.

Core Logic and Functionality

The logic of the script can be broken down into three main components:

1. Trend Analysis

Before identifying specific shapes, the script evaluates the broader market direction. It looks back at a user-defined period (defaulting to 24 bars) to calculate the sum of all "positive" price movements versus "negative" ones. This creates a foundation for the "Trend Filter." Depending on how you configure this, the script can either look for patterns that align with the current trend or focus exclusively on reversal patterns that contradict it.

2. Pattern Recognition Engine

The script contains a library of distinct mathematical rules used to identify various Japanese Candlestick formations. Each pattern has its own unique criteria based on the relationship between the "Open," "High," "Low," and "Close" prices:

  • Single Candle Patterns: It identifies high-probability individual bars like Hammers, Inverted Hammers, Falling Stars, and Wingnuts (Viselnik). These are identified by looking at the ratio of the candle's "body" (the area between open and close) to its "wicks" (the thin lines representing price extremes).
  • Multi-Candle Formations: It scans sequences of 2 or 3 candles to find more complex structures, such as:
    • Engulfing Patterns: Where one candle completely overlaps the previous one.
    • Morning and Evening Stars: Three-candle sequences signaling potential trend shifts.
    • Doji Stars: Identifying "indecision" marks within specific multi-candle structures.
    • Specific Complex Shapes: It even looks for niche patterns like "Curtain of Dark Clouds" and "Light in the Darkness," which rely on very specific price overlaps between two consecutive candles.

3. Visual Output

Once the logic identifies a match, the script performs the following actions:

  • Object Creation: It automatically draws an arrow on the chart at the exact time the pattern occurred.
  • Color Coding: It assigns specific colors to different types of signals (e.g., Red and Maroon for bearish/downward signals, Blue and Royal Blue for bullish/upward signals).
  • Dynamic Placement: The arrows are positioned slightly above or below the price candles to ensure they are easily visible without obstructing the actual price action.

Summary for the User

Essentially, this script acts as an automated "scout." It constantly monitors the price history, calculates the prevailing trend, and applies a complex set of geometric rules to the candles. When it detects a recognized pattern—whether it's a simple reversal candle or a complex three-bar star—it marks it for you visually, allowing you to see potential trading opportunities at a glance.

Miscellaneous
Implements a curve of type %1
15 Views
0 Downloads
0 Favorites
ExCandles2
//+------------------------------------------------------------------+
//|                                                   ExCandles2.mq4 |
//|                           Copyright © 2006, Alex Sidd (Executer) |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Alex Sidd (Executer)"
#property link      "mailto:work_st@mail.ru"
//----

#property indicator_chart_window
#property indicator_buffers 1
#property  indicator_color1  Black
//---- input parameters
extern int ExPeriod = 24;
extern bool TrendFilter = true;
extern int how_bars = 0;
//---- buffers
double CCodeBuffer[];
//+------------------------------------------------------------------+
//| initialization function                                          |
//+------------------------------------------------------------------+
int init()
  {
   string short_name;
   IndicatorBuffers(1);
   SetIndexStyle(0, DRAW_NONE);
   SetIndexBuffer(0, CCodeBuffer);
   SetIndexDrawBegin(0, ExPeriod);
   short_name = "ExCandles";
   IndicatorShortName(short_name);
   SetIndexLabel(0, short_name);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int deinit()
  {
   ObjectsDeleteAll(0, OBJ_ARROW);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+  
int Trend(int i)
  {
   double negative = 0;
   double positive = 0;
   if(i < Bars - ExPeriod - 1)
     {
       int k = i + ExPeriod;
       while(k > i)
         {
           if(Open[k] < Close[k]) 
               positive += (Close[k] - Open[k]);
           if(Open[k] > Close[k]) 
               negative += (Open[k] - Close[k]);
           k--;
         }
     }
   else 
       return(0);
   if(positive - negative > 0) 
       return(1);
   if(positive - negative < 0) 
       return(-1);
   if(positive == negative) 
       return(0);
  }
//+------------------------------------------------------------------+
//| Executer Candles Indicator                                           |
//+------------------------------------------------------------------+
bool IsViselnik(int i1)
  {
   double buf = Open[i1]-Close[i1];
   if(buf == 0) 
       buf = 1;
   if((TrendFilter == true && Trend(i1) > 0 && ((High[i1] - Open[i1])*100 / 
      buf < 20) && ((Close[i1] - Low[i1])*100 / buf > 180)) ||
      (TrendFilter == false && ((High[i1] - Open[i1])*100 / buf < 20) && 
      ((Close[i1] - Low[i1])*100 / buf > 180))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsHummer(int i1)
  {
   double buf = Close[i1]-Open[i1];
   if(buf == 0) 
       buf = 1;
   if((TrendFilter == true && Trend(i1) < 0 && ((High[i1] - Close[i1])*100 / 
      buf > 180) && ((Open[i1] - Low[i1])*100 / buf < 20))||
      (TrendFilter == false && ((High[i1] - Close[i1])*100 / buf > 180) && 
      ((Open[i1] - Low[i1])*100 / buf < 20))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsBear(int i1, int i2)
  {
   if((TrendFilter == true && Trend(i1) >0 && (Open[i1] - Close[i1] > 0) && 
      (Open[i1] > Close[i2]) && (Close[i1] < Open[i2]) && (Open[i2] - Close[i2] < 0)) ||
      (TrendFilter == false > 0 && (Open[i1] - Close[i1] > 0) && (Open[i1] > Close[i2]) &&
      (Close[i1] < Open[i2]) && (Open[i2] - Close[i2] < 0))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsBull(int i1, int i2)
  {
   if((TrendFilter == true&&Trend(i1) < 0 && (Open[i1] - Close[i1] < 0) && 
      (Open[i2] - Close[i2] > 0) && (Close[i1] > Open[i2]) && (Open[i1] < Close[i2])) ||
      (TrendFilter == false && (Open[i1] - Close[i1] < 0) && (Open[i2] - Close[i2] > 0) &&
      (Close[i1] > Open[i2]) && (Open[i1] < Close[i2]))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool Zavesa_black(int i1, int i2)
  {
   double x = (High[i2] - Low[i2]);
   if(x == 0) 
       x = 0.0001;
   if((TrendFilter == true && Trend(i1) > 0 &&
      (Open[i1] - Close[i1] > 0) &&
      (Open[i2] - Close[i2] < 0) && 
      ((Close[i2] - Open[i2]) / x > 0.6) && 
      (Open[i1] > High[i2]) && 
      (Close[i1] < (Open[i2] + (Close[i2] - Open[i2]) / 2))) ||
      (TrendFilter == false &&
      (Open[i1] - Close[i1] >0) &&
      (Open[i2] - Close[i2] < 0) && 
      ((Close[i2] - Open[i2]) / x > 0.6) && 
      (Open[i1] > High[i2]) && 
      (Close[i1] < (Open[i2] + (Close[i2] - Open[i2]) / 2)))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool Prosvet(int i1, int i2)
  {
   double x = (High[i2] - Low[i2]);
   if(x == 0) 
       x = 0.0001;
   if((TrendFilter == true && Trend(i1) < 0 &&
      (Open[i1] - Close[i1] < 0) &&
      (Open[i2] - Close[i2] > 0) && 
      ((Open[i2] - Close[i2]) / x > 0.6) && 
      (Open[i1] < Low[i2]) && 
      (Close[i1] > (Close[i2] + (Open[i2] - Close[i2]) / 2))) ||
      (TrendFilter == false &&
      (Open[i1] - Close[i1] < 0) &&
      (Open[i2] - Close[i2] > 0) && 
      ((Open[i2] - Close[i2]) / x > 0.6) && 
      (Open[i1] < Low[i2]) && 
      (Close[i1] > (Close[i2] + (Open[i2] - Close[i2]) / 2)))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool morning_star(int i1, int i2, int i3)
  { 
   if((TrendFilter == true && Trend(i1) < 0 &&
      (Open[i3] - Close[i3] > 0) && 
      (Open[i1] - Close[i1] < 0) && 
      (Close[i2] < Open[i3]) && 
      (Close[i2] < Open[i1]) && 
      (Close[i2] < Close[i1]) &&
      (Close[i2] < Close[i3]) &&
      (Open[i2] < Open[i1]) && 
      (Open[i2] < Open[i3]) && 
      (Open[i2] < Close[i3]) && 
      (Open[i2] < Close[i1])) ||
      (TrendFilter == false&&
      (Open[i3] - Close[i3] > 0) && 
      (Open[i1] - Close[i1] < 0) && 
      (Close[i2] < Open[i3]) && 
      (Close[i2] < Open[i1]) && 
      (Close[i2] < Close[i1]) &&
      (Close[i2] < Close[i3]) &&
      (Open[i2] < Open[i1]) && 
      (Open[i2] < Open[i3]) && 
      (Open[i2] < Close[i3]) && 
      (Open[i2] < Close[i1]))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool evening_star(int i1, int i2, int i3)
  {
   if((TrendFilter == true && Trend(i1) > 0 &&
      (Open[i3] - Close[i3]<0) && 
      (Open[i1] - Close[i1]>0) && 
      (Close[i2] > Open[i3]) && 
      (Close[i2] > Open[i1]) && 
      (Close[i2] > Close[i1]) &&
      (Close[i2] > Close[i3]) &&
      (Open[i2] > Open[i1]) && 
      (Open[i2] > Open[i3]) && 
      (Open[i2] > Close[i3]) && 
      (Open[i2] > Close[i1]))||
      (TrendFilter == false&&
      (Open[i3] - Close[i3] < 0) && 
      (Open[i1] - Close[i1] > 0) && 
      (Close[i2] > Open[i3]) && 
      (Close[i2] > Open[i1]) && 
      (Close[i2] > Close[i1]) &&
      (Close[i2] > Close[i3]) &&
      (Open[i2] > Open[i1]) && 
      (Open[i2] > Open[i3]) && 
      (Open[i2] > Close[i3]) && 
      (Open[i2] > Close[i1]))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsEveningDodgiStar(int i1, int i2, int i3)
  {
   if((TrendFilter == true && Trend(i1) > 0 &&
      (Open[i2] == Close[i2]) &&
      (Open[i3] - Close[i3]<0) && 
      (Open[i1] - Close[i1]>0) && 
      (Close[i2] > Open[i3]) && 
      (Close[i2] > Open[i1]) && 
      (Close[i2] > Close[i1]) &&
      (Close[i2] > Close[i3]) &&
      (Open[i2] > Open[i1]) && 
      (Open[i2] > Open[i3]) && 
      (Open[i2] > Close[i3]) && 
      (Open[i2] > Close[i1])) ||
      (TrendFilter == false &&
      (Open[i2] == Close[i2]) &&
      (Open[i3] - Close[i3]<0) && 
      (Open[i1] - Close[i1]>0) && 
      (Close[i2] > Open[i3]) && 
      (Close[i2] > Open[i1]) && 
      (Close[i2] > Close[i1]) &&
      (Close[i2] > Close[i3]) &&
      (Open[i2] > Open[i1]) && 
      (Open[i2] > Open[i3]) && 
      (Open[i2] > Close[i3]) && 
      (Open[i2] > Close[i1]))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsMorningDodgiStar(int i1, int i2, int i3)
  {
   if((TrendFilter == true && Trend(i1) < 0 &&
      (Open[i2] == Close[i2]) &&
      (Open[i3] - Close[i3] > 0) && 
      (Open[i1] - Close[i1] < 0) && 
      (Close[i2] < Open[i3]) && 
      (Close[i2] < Open[i1]) && 
      (Close[i2] < Close[i1]) &&
      (Close[i2] < Close[i3]) &&
      (Open[i2] < Open[i1]) && 
      (Open[i2] < Open[i3]) && 
      (Open[i2] < Close[i3]) && 
      (Open[i2] < Close[i1])) ||
      (TrendFilter == false &&
      (Open[i2] == Close[i2]) &&
      (Open[i3] - Close[i3] > 0) && 
      (Open[i1] - Close[i1] < 0) && 
      (Close[i2] < Open[i3]) && 
      (Close[i2] < Open[i1]) && 
      (Close[i2] < Close[i1]) &&
      (Close[i2] < Close[i3]) &&
      (Open[i2] < Open[i1]) && 
      (Open[i2] < Open[i3]) && 
      (Open[i2] < Close[i3]) && 
      (Open[i2] < Close[i1]))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsFallStar(int i1)
  {
   double buf = Open[i1] - Close[i1];
   if(buf == 0) 
       buf = 1;
   if((TrendFilter == true && Trend(i1) > 0 && ((High[i1] - Open[i1])*100 / 
      buf > 180) && ((Close[i1] - Low[i1])*100 / buf < 20)) ||
      (TrendFilter == false && ((High[i1] - Open[i1])*100 / buf > 180) && 
      ((Close[i1] - Low[i1])*100 / buf < 20))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsTurnedHummer(int i1)
  {
   double buf = Close[i1] - Open[i1];
   if(buf == 0) 
       buf = 1;
   if((TrendFilter == true && Trend(i1) < 0 && ((High[i1] - Close[i1])*100 / 
      buf < 20) && ((Open[i1] - Low[i1])*100 / buf > 180))||
      (TrendFilter == false && ((High[i1] - Close[i1])*100 / buf < 20) && 
      ((Open[i1] - Low[i1])*100 / buf > 180))) 
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   int    i,counted_bars = IndicatorCounted();
   double negative = 0, positive = 0;
//----
   if(Bars <= ExPeriod) 
       return(0);
   if(counted_bars < 1)
       for(i = 1; i <= ExPeriod; i++) 
           CCodeBuffer[Bars-i] = 0.0;
//----
   if(how_bars <= 0 || how_bars > Bars) 
       how_bars = Bars;
   i = how_bars - ExPeriod - 1;
   if(counted_bars >= ExPeriod) 
       i = how_bars - counted_bars - 1;
   while(i >= 0)
     {
       if(IsFallStar(i + 1) == true)
         {
           ObjectCreate("Ïàäàþùàÿ çâåçäà " + i, OBJ_ARROW, 0, Time[i+1], High[i+1] + 
                        20*Point);
           ObjectSet("Ïàäàþùàÿ çâåçäà " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
           ObjectSet("Ïàäàþùàÿ çâåçäà " + i, OBJPROP_COLOR, Red);
           CCodeBuffer[i] = 1;
         }
       if(IsTurnedHummer(i + 1) == true)
         {
           ObjectCreate("Ïåðåâåðíóòûé Ìîëîò " + i, OBJ_ARROW, 0, Time[i+1], Low[i+1] - 
                        20*Point);
           ObjectSet("Ïåðåâåðíóòûé Ìîëîò " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
           ObjectSet("Ïåðåâåðíóòûé Ìîëîò " + i, OBJPROP_COLOR, Blue);
           CCodeBuffer[i] = 2;
         }
       if(IsViselnik(i + 1) == true)
         {
           ObjectCreate("Âèñåëüíèê " + i, OBJ_ARROW, 0, Time[i+1], High[i+1] + 20*Point);
           ObjectSet("Âèñåëüíèê " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
           ObjectSet("Âèñåëüíèê " + i, OBJPROP_COLOR, Red);
           CCodeBuffer[i] = 3;
         }
       if(IsHummer(i + 1) == true)
         {
           ObjectCreate("Ìîëîò " + i, OBJ_ARROW, 0, Time[i+1], Low[i+1] - 20*Point);
           ObjectSet("Ìîëîò " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
           ObjectSet("Ìîëîò " + i, OBJPROP_COLOR, Blue);
           CCodeBuffer[i] = 4;
         }
       if(IsBear(i + 1, i + 2) == true)
         {
           ObjectCreate("Ìåäâåæüå ïîãëîùåíèå " + i, OBJ_ARROW, 0, Time[i+1], High[i+1] + 
                        20*Point);
           ObjectSet("Ìåäâåæüå ïîãëîùåíèå " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
           ObjectSet("Ìåäâåæüå ïîãëîùåíèå " + i, OBJPROP_COLOR, Maroon);
           CCodeBuffer[i] = 5;
         }
       if(IsBull(i+1, i+2)==true)
         {
           ObjectCreate("Áû÷üå ïîãëîùåíèå " + i, OBJ_ARROW, 0, Time[i+1], Low[i+1] - 
                        20*Point);
           ObjectSet("Áû÷üå ïîãëîùåíèå " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
           ObjectSet("Áû÷üå ïîãëîùåíèå " + i, OBJPROP_COLOR, RoyalBlue);
           CCodeBuffer[i] = 6;
         }
       if(Zavesa_black(i + 1, i + 2) == true)
         {
           ObjectCreate("Çàâåñà èç òåìíûõ îáëàêîâ " + i, OBJ_ARROW, 0, Time[i], High[i] +
                        20*Point);
           ObjectSet("Çàâåñà èç òåìíûõ îáëàêîâ " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
           ObjectSet("Çàâåñà èç òåìíûõ îáëàêîâ " + i, OBJPROP_COLOR, OrangeRed);
           CCodeBuffer[i] = 7;
         }
       if(Prosvet(i + 1, i + 2) == true)
         {
           ObjectCreate("Ïðîñâåò â îáëàêàõ " + i, OBJ_ARROW, 0, Time[i], Low[i] - 
                        20*Point);
           ObjectSet("Ïðîñâåò â îáëàêàõ " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
           ObjectSet("Ïðîñâåò â îáëàêàõ " + i, OBJPROP_COLOR, SlateBlue);
           CCodeBuffer[i] = 8;
         }
       if(evening_star(i + 1, i + 2, i + 3) == true)
         {
           ObjectCreate("Âå÷åðíÿÿ çâåçäà " + i, OBJ_ARROW, 0, Time[i+2], High[i+2] + 
                        20*Point);
           ObjectSet("Âå÷åðíÿÿ çâåçäà " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
           ObjectSet("Âå÷åðíÿÿ çâåçäà " + i, OBJPROP_COLOR, Red);
           CCodeBuffer[i] = 9;
         }
       if(morning_star(i + 1, i + 2, i + 3) == true)
         {
           ObjectCreate("Óòðåííÿÿ çâåçäà " + i, OBJ_ARROW, 0, Time[i+2], Low[i+2] - 
                        20*Point);
           ObjectSet("Óòðåííÿÿ çâåçäà " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
           ObjectSet("Óòðåííÿÿ çâåçäà " + i, OBJPROP_COLOR, DodgerBlue);
           CCodeBuffer[i] = 10;
         }
       if(IsEveningDodgiStar(i + 1, i + 2, i + 3) == true)
         {
           ObjectCreate("Âå÷åðíÿÿ äîäæè çâåçäà " + i, OBJ_ARROW, 0, Time[i+2], High[i+2] + 
                        20*Point);
           ObjectSet("Âå÷åðíÿÿ äîäæè çâåçäà " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
           ObjectSet("Âå÷åðíÿÿ äîäæè çâåçäà " + i, OBJPROP_COLOR, DeepPink);
           CCodeBuffer[i] = 11;
         }
       if(IsMorningDodgiStar(i + 1, i + 2, i + 3) == true)
         {
           ObjectCreate("Óòðåííÿÿ äîäæè çâåçäà " + i, OBJ_ARROW, 0, Time[i+2], Low[i+2] - 
                        20*Point);
           ObjectSet("Óòðåííÿÿ äîäæè çâåçäà " + i, OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
           ObjectSet("Óòðåííÿÿ äîäæè çâåçäà " + i, OBJPROP_COLOR, Blue);
           CCodeBuffer[i] = 12;
         }
       i--;
     }
//----
   return(0);
  }
//+------------------------------------------------------------------+

Comments