Обсуждение статьи "Поиск свечных паттернов с помощью MQL5" - страница 2

 
Mohamed Abdelmaaboud #:
Спасибо за ваш комментарий. Сначала мне нужно уточнить, что вы можете сделать это так, как вам нужно, это может быть индикатор, который может обнаружить и показать их, или советник, который может дать вам необходимые действия, такие как торговля, если вы хотите, и вы можете объединить их в продвинутый советник. чтобы получить их все при правильном исполнении, которые будут прикреплены к графику как один советник. здесь нет правды или лжи, цель здесь только образовательная, чтобы поделиться тем, как мы можем кодировать эти типы моделей свечей, после чего вы можете использовать их в своей подходящей программе, будь то индикатор или советник.

Я так и сделал, объединил все в один советник. Но когда попробовал записать как Индикатор, в терминале всё равно загружается как Советник. Что-то нужно менять в Коде, но что именно я не знаю, не сильно разбираюсь. Ещё я заметил, что нужна его доработка в плане, что когда меняется Тайм Фрейм, на другой то сигнал остаётся на графике и уже на новом не соответствует бару на том же месте. По идее при смене нужно, чтобы удалялся или сохранялся только на том Тайм Фрейме где он был обнаружен. На всякий случай выставлю собраный мой Код, посмотрите что можно подправить или оптимизировать, я всего лишь скопировал со всех советников в один, но думаю там можно объявить некоторые переменные в начале, чтобы не повторяться в Коде несколько раз.   

//+------------------------------------------------------------------+
//|                                                PATTERN-INDIK.mq5 |
//|                                            Copyright 2023,VIKTOR |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023,VIKTOR"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//+ createObj1 = Doji                                                |
//+ createObj2 = Hammer                                              |
//+ createObj3 = Engulfing                                           |
//+ createObj4 = Piercing                                            |
//+ createObj5 = Star                                                |
//+ createObj6 = threeInside                                         |
//+------------------------------------------------------------------+
void OnTick()
  {
   getDoji();
   getHammer(0.07,0.7);
   getEngulfing();
   getPiercing();
   getStar(0.5);
   getthreeInside();
  }
int getDoji()
  {
   datetime time  =iTime  (_Symbol,PERIOD_CURRENT,1);
   double   open  =iOpen  (_Symbol,PERIOD_CURRENT,1);
   double   high  =iHigh  (_Symbol,PERIOD_CURRENT,1);
   double   low   =iLow   (_Symbol,PERIOD_CURRENT,1);
   double   close =iClose (_Symbol,PERIOD_CURRENT,1);
   
//Doji
   if(open==close)
     {
      createObj1a(time,low,217, clrBlack,"Doji");
        {
         return 1;
        }
     }
   return 0;
  }
void createObj1a(datetime time, double price, int arrawCode, color clr, string txt)
  {
   string objName=" ";
   StringConcatenate(objName, "Signal at ",time, " at ",DoubleToString(price,_Digits)," (",arrawCode,")");
   if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price))
     {
      ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
     }
   string candleName=objName+txt;
   if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price))
     {
      ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt);
      ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr);
     }
  }
//+------------------------------------------------------------------+
int getHammer(double smallShadowRatio, double longShadowRatio)
  {
//creating variables for prices data - open,  high, low, close
   datetime time=iTime(_Symbol,PERIOD_CURRENT,1);
   double open=iOpen(_Symbol,PERIOD_CURRENT,1);
   double high=iHigh(_Symbol,PERIOD_CURRENT,1);
   double low=iLow(_Symbol,PERIOD_CURRENT,1);
   double close=iClose(_Symbol,PERIOD_CURRENT,1);
   double candleSize=high-low;
//green hammer
   if(open<close)
     {
      if(high-close < candleSize*smallShadowRatio)
        {
         if(open-low>candleSize*longShadowRatio)
            createObj2(time,low,217, clrGreen,"Hammer");
           {
            return 1;
           }
        }
     }
//red hammer
   if(open>close)
     {
      if(high-open<candleSize*smallShadowRatio)
        {
         if(close-low>candleSize*longShadowRatio)
            createObj2(time,high,218,clrRed,"Hammer");
           {
            return 1;
           }
        }
     }
//green inverse hammer
   if(open<close)
     {
      if(open-low < candleSize*smallShadowRatio)
        {
         if(high-close>candleSize*longShadowRatio)
            createObj2(time,low,217, clrGreen,"Inverted Hammer");
           {
            return -1;
           }
        }
     }
//red inverse hammer
   if(open>close)
     {
      if(close-low < candleSize*smallShadowRatio)
        {
         if(high-open>candleSize*longShadowRatio)
            createObj2(time,high,218, clrRed,"Inverted Hammer");
           {
            return -1;
           }
        }
     }
   return 0;
  }
void createObj2(datetime time, double price, int arrawCode, color clr, string txt)
  {
   string objName=" ";
   StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")");
   if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price))
     {
      ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      if(clr==clrGreen)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
      if(clr==clrRed)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
     }
   string candleName=objName+txt;
   if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price))
     {
      ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt);
      ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr);
     }
  }
//+------------------------------------------------------------------+
int getEngulfing()
  {
   datetime time=iTime(_Symbol,PERIOD_CURRENT,1);
   double open=iOpen(_Symbol,PERIOD_CURRENT,1);
   double high=iHigh(_Symbol,PERIOD_CURRENT,1);
   double low=iLow(_Symbol,PERIOD_CURRENT,1);
   double close=iClose(_Symbol,PERIOD_CURRENT,1);
   double open2=iOpen(_Symbol,PERIOD_CURRENT,2);
   double high2=iHigh(_Symbol,PERIOD_CURRENT,2);
   double low2=iLow(_Symbol,PERIOD_CURRENT,2);
   double close2=iClose(_Symbol,PERIOD_CURRENT,2);
   if(open<close)
     {
      if(open2>close2)
        {
         if(high>high2&&low<low2)
           {
            if(close>open2&&open<close2)
              {
               createObj3(time,low,217, clrGreen,"Bullish Engulfing");
                 {
                  return 1;
                 }
              }
           }
        }
     }
   if(open>close)
     {
      if(open2<close2)
        {
         if(high>high2&&low<low2)
           {
            if(close<open2&&open>close2)
              {
               createObj3(time,high,218, clrRed,"Bearish Engulfing");
                 {
                  return -1;
                 }
              }
           }
        }
     }
   return 0;
  }
void createObj3(datetime time, double price, int arrawCode, color clr, string txt)
  {
   string objName=" ";
   StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")");
   if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price))
     {
      ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      if(clr==clrGreen)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
      if(clr==clrRed)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
     }
   string candleName=objName+txt;
   if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price))
     {
      ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt);
      ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr);
     }
  }
//+------------------------------------------------------------------+
int getPiercing()
  {
   datetime time=iTime(_Symbol,PERIOD_CURRENT,1);
   double open=iOpen(_Symbol,PERIOD_CURRENT,1);
   double high=iHigh(_Symbol,PERIOD_CURRENT,1);
   double low=iLow(_Symbol,PERIOD_CURRENT,1);
   double close=iClose(_Symbol,PERIOD_CURRENT,1);
   double open2=iOpen(_Symbol,PERIOD_CURRENT,2);
   double high2=iHigh(_Symbol,PERIOD_CURRENT,2);
   double low2=iLow(_Symbol,PERIOD_CURRENT,2);
   double close2=iClose(_Symbol,PERIOD_CURRENT,2);
   double candleSize2=high2-low2;
   double candleMidPoint2=high2-(candleSize2/2);
   if(open<close)
     {
      if(open2>close2)
        {
         if(open<low2)
           {
            if(close>candleMidPoint2&&close<high2)
              {
               createObj4(time,low,217, clrGreen,"Piercing");
                 {
                  return 1;
                 }
              }
           }
        }
     }
   if(open>close)
     {
      if(open2<close2)
        {
         if(open>high2)
           {
            if(close<candleMidPoint2&&close>low2)
              {
               createObj4(time,high,218, clrRed,"Dark Cloud");
                 {
                  return -1;
                 }
              }
           }
        }
     }
   return 0;
  }
void createObj4(datetime time, double price, int arrawCode, color clr, string txt)
  {
   string objName=" ";
   StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")");
   if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price))
     {
      ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      if(clr==clrGreen)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
      if(clr==clrRed)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
     }
   string candleName=objName+txt;
   if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price))
     {
      ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt);
      ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr);
     }
  }
//+------------------------------------------------------------------+
int getStar(double middleCandleRatio)
  {
   datetime time=iTime(_Symbol,PERIOD_CURRENT,1);
   double open=iOpen(_Symbol,PERIOD_CURRENT,1);
   double high=iHigh(_Symbol,PERIOD_CURRENT,1);
   double low=iLow(_Symbol,PERIOD_CURRENT,1);
   double close=iClose(_Symbol,PERIOD_CURRENT,1);
   double open2=iOpen(_Symbol,PERIOD_CURRENT,2);
   double high2=iHigh(_Symbol,PERIOD_CURRENT,2);
   double low2=iLow(_Symbol,PERIOD_CURRENT,2);
   double close2=iClose(_Symbol,PERIOD_CURRENT,2);
   double open3=iOpen(_Symbol,PERIOD_CURRENT,3);
   double high3=iHigh(_Symbol,PERIOD_CURRENT,3);
   double low3=iLow(_Symbol,PERIOD_CURRENT,3);
   double close3=iClose(_Symbol,PERIOD_CURRENT,3);
   double candleSize=high-low;
   double candleSize2=high2-low2;
   double candleSize3=high3-low3;
   if(open<close)
     {
      if(open3>close3)
        {
         if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio)
           {
            createObj5(time,low,217, clrGreen,"Morning Star");
              {
               return 1;
              }
           }
        }
     }
   if(open>close)
     {
      if(open3<close3)
        {
         if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio)
           {
            createObj5(time,high,218, clrRed,"Evening Star");
              {
               return -1;
              }
           }
        }
     }
   return 0;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void createObj5(datetime time, double price, int arrawCode, color clr, string txt)
  {
   string objName=" ";
   StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")");
   if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price))
     {
      ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      if(clr==clrGreen)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
      if(clr==clrRed)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
     }
   string candleName=objName+txt;
   if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price))
     {
      ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt);
      ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr);
     }
  }
//+------------------------------------------------------------------+
int getthreeInside()
  {
   datetime time=iTime(_Symbol,PERIOD_CURRENT,1);
   double open=iOpen(_Symbol,PERIOD_CURRENT,1);
   double high=iHigh(_Symbol,PERIOD_CURRENT,1);
   double low=iLow(_Symbol,PERIOD_CURRENT,1);
   double close=iClose(_Symbol,PERIOD_CURRENT,1);
   double open2=iOpen(_Symbol,PERIOD_CURRENT,2);
   double high2=iHigh(_Symbol,PERIOD_CURRENT,2);
   double low2=iLow(_Symbol,PERIOD_CURRENT,2);
   double close2=iClose(_Symbol,PERIOD_CURRENT,2);
   double open3=iOpen(_Symbol,PERIOD_CURRENT,3);
   double high3=iHigh(_Symbol,PERIOD_CURRENT,3);
   double low3=iLow(_Symbol,PERIOD_CURRENT,3);
   double close3=iClose(_Symbol,PERIOD_CURRENT,3);
   if(open3>close3)
     {
      if(open2<close2)
        {
         if(open2>low3&&close2<high3)
           {
            if(open<close&&open>open2&&open<close2)
              {
               if(close>high3)
                 {
                  createObj6(time,low,217, clrGreen,"3 Inside Up");
                    {
                     return 1;
                    }
                 }
              }
           }
        }
     }
   if(open3<close3)
     {
      if(open2>close2)
        {
         if(open2<high3&&close2>low3)
           {
            if(open>close&&open<open2&&open>close2)
              {
               if(close<low3)
                 {
                  createObj6(time,high,218, clrRed,"3 Inside Down");
                    {
                     return -1;
                    }
                 }
              }
           }
        }
     }
   return 0;
  }
void createObj6(datetime time, double price, int arrawCode, color clr, string txt)
  {
   string objName=" ";
   StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")");
   if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price))
     {
      ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode);
      ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
      if(clr==clrGreen)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
      if(clr==clrRed)
         ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
     }
   string candleName=objName+txt;
   if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price))
     {
      ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt);
      ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr);
     }
  }
//+------------------------------------------------------------------+
 
FINANSE-BOND #:

Я так и сделал, объединил все в один советник. Но когда попробовал записать как Индикатор, в терминале всё равно загружается как Советник. Что-то нужно менять в Коде, но что именно я не знаю, не сильно разбираюсь. Ещё я заметил, что нужна его доработка в плане, что когда меняется Тайм Фрейм, на другой то сигнал остаётся на графике и уже на новом не соответствует бару на том же месте. По идее при смене нужно, чтобы удалялся или сохранялся только на том Тайм Фрейме где он был обнаружен. На всякий случай выставлю собраный мой Код, посмотрите что можно подправить или оптимизировать, я всего лишь скопировал со всех советников в один, но думаю там можно объявить некоторые переменные в начале, чтобы не повторяться в Коде несколько раз.   

Советник и индикатор отличаются только тем, что имеют немного разные обработчики событий и индикатор имеет возможность рисования линий либо на самом графике либо в отдельном окне, когда речь идет о свечных паттернах, данный тип кода абсолютно избыточен в остальных случаях и вы лишь ограничите возможности вашего кода данными шагами. Здесь нужна правильная парадигма построения индикаторов, когда то давно я это понял и индикаторы почти не писал, все исполнял в виде эксперта. Кроме того данный код очень легко в последующем адаптировать к торговле, если вы внимательно посмотрите на код вы увидите что там идет работа с объектами, так зачем вам ограничивать себя функционалом индикатора? Все правильно, что вы докопались до человека

 

Я не докопался, я написал, что не силён в Коде поэтому и поделился своими выводами как пользователь, а также попросил немножко урезать что то в Коде что я не знаю где и как объявить некоторые переменные, которые повторяются. Также недавно смотрел видео, что пишут Советник на внешнем индикаторе. Поэтому я и говорил что если делать Индикатор то потом на него можно ссылаться в Советнике и брать от него данные. Может вы что то подправите если можете ?

 
Если кому то, не будет лень прикрутите пожалуйста в Код Приказы на Покупку и продажу, раз уж это Советник.
 
Очень полезно
 
Cyril Bassey #:
Очень полезно

Спасибо за ваш комментарий.

 
Спасибо за понимание, очень хороший пост.
Я хотел спросить относительно обнаружения свечей Engulfing, вы использовали условие
.
if(close>open2&&open<close2)
для бычьего энгульфинга и условие
if(close<open2&&open>close2)
для Bearish Engulfing. Это условие верно только при наличии разрыва. Я имею в виду, как часто возникает разрыв? Я ожидал использовать такой код
if(close>open2&&open<=close2)
для Bullish Engulfing и условие
if(close<open2&&open>=close2)
для Bearish Engulfing. Потому что в нормальных условиях цена открытия бара 1 и цена закрытия бара 2 абсолютно одинаковы. Ваш код обнаружит паттерн Engulfing только при наличии разрыва рыночной цены.
Поэтому мой вопрос заключается в том, как вы думаете, стал ли паттерн недействительным, когда цены закрытия и открытия бара 2 и бара 1 не совпадают.
 
Хорошая статья. Она очень полезна для понимания того, как создать объектный шаблон в mql5.
 

Хороший материал. Большое спасибо.

Каково условие для бычьего и медвежьего Марубозу

 
Sylvanus Phillips #:
Каково условие для бычьего и медвежьего Марубозу

Что-то вроде этого: