Navigation:Home > Content >

NextBarType.mq4

Time: 2012-01-18 | Download file:NextBarType.mq4

#property copyright "Scriptong"
#property link      "http://autograf.dp.ua"

#property indicator_chart_window
#property indicator_buffers 0

extern string A1 = "Количество свечей для анализа";
extern int    AnalysisBars  = 3; 
extern string A2 = "Минимальное количество схожих паттернов (глубина выборки)";
extern int    MinHistory    = 30;
extern string A3 = "Для скольки последних баров производить расчет (0 - все)";
extern int    BarsCount     = 100;
extern string A4 = "Цвет верхних линий";
extern color  UpColor       = Blue;
extern string A5 = "Цвет нижних линий";
extern color  DownColor     = Red;
extern string A6 = "Толщина линий (0-4)";
extern int    LineWidth     = 4;
extern string A7 = "Стиль линий для 0 толщины (0-4): сплошная, штриховая и т.д.";
extern int    LineStyle     = 0;
extern string A8 = "Выводить линии на заднем фоне (true) или переднем плане (false)";
extern bool   LineBack      = true;
extern string A9 = "Цвет эталонного паттерна";
extern color  EtalonColor   = DodgerBlue;
extern string A10 = "Цвет исторического паттерна";
extern color  HistoricalPatternColor = Aqua;

int high[],                                        // Соотношение максимумов свечей в..
                                                   // ..эталонном паттерне (-1 - первая..
                                                   // ..свеча ниже второй, 0 - равна,..
                                                   // ..1 - выше)
    low[],                                         // Соотношение минимумов свечей в..
                                                   // ..эталонном паттерне (-1 - первая..
                                                   // ..свеча ниже второй, 0 - равна,..
                                                   // ..1 - выше)
    candle_type[],                                 // Соотношение цен закрытия и открытия
                                                   // ..свечи в эталонном паттерне..
                                                   // ..(-1 - свеча медвежья, 0 - додж,..
                                                   // ..1 - свеча бычья)
    AverHighToOpen,                                // Среднее расстояние между High и..
                                                   // ..и Open в пунктах
    MaxHighToOpen,                                 // Максимальное расстояние между High..
                                                   // ..и Open в пунктах
    AverOpenToLow,                                 // Среднее расстояние между Open и..
                                                   // ..и Low в пунктах
    MaxOpenToLow,                                  // Максимальное расстояние между Open..
                                                   // ..и Low в пунктах
    PatternsTotal;                                 // Общее кол-во найденных паттернов
int LastnBar;                                      // Номер выделенного на предыдущей..
                                                   // ..итерации бара (выделение - при..
                                                   // ..помощи вертикальной линии)
string prefix = "NBT_NR_";                         // Префикс для объектов индикатора

//+-------------------------------------------------------------------------------------+
//| Custom indicator initialization function                                            |
//+-------------------------------------------------------------------------------------+
int init()
{
// - 1 - == Проверка корректности входных параметров ====================================
   if (AnalysisBars < 2)
   {
      Alert("Установлено недопустимое значение AnalysisBars. Принято значение 5");
      AnalysisBars = 5;
   }
   if ((BarsCount < 2 && BarsCount != 0) || BarsCount > Bars)
   {
      Alert("Установлено недопустимое значение BarsCount. Принято значение 2");
      BarsCount = 2;
   }
   if (MinHistory < 0)
   {
      Alert("Установлено недопустимое значение MinHistory. Принято значение 5");
      MinHistory = 5;
   }
   if (LineWidth < 0 || LineWidth > 4)
   {
      Alert("Установлено недопустимое значение LineWidth. Принято значение 4");
      LineWidth = 4;
   }
   if (LineStyle < 0 || LineStyle > 4)
   {
      Alert("Установлено недопустимое значение LineStyle. Принято значение 0");
      LineStyle = 0;
   }
// - 1 - == Окончание блока =============================================================
   
// - 2 - == Инициализация массивов ======================================================
   ArrayResize(high, AnalysisBars);
   ArrayResize(low, AnalysisBars);
   ArrayResize(candle_type, AnalysisBars);
// - 2 - == Окончание блока =============================================================
   
   ShowVLine(Time[0]);                             // Отобразим вертикальную линию на..
                                                   // ..текущем баре
   LastnBar = -1;                                  // Т.к. расчета еще не было, то индекс
                                                   // ..бара не определен
   
   return(0);
}

//+-------------------------------------------------------------------------------------+
//| Функция деинициализации                                                             |
//+-------------------------------------------------------------------------------------+
void deinit()
{
   for (int i = ObjectsTotal()-1; i >= 0; i--)     // Удалим все свои объекты
      if (StringSubstr(ObjectName(i), 0, StringLen(prefix)) == prefix)
         ObjectDelete(ObjectName(i));
}
//+-------------------------------------------------------------------------------------+
//| Сравнение двух чисел типа double с заданной точностью                               |
//+-------------------------------------------------------------------------------------+
int DoubleCompare(double d1, double d2, double precision)
{
   double temp = d1 - d2;                          // Получим разность первого и второго
                                                   // ..числа
   if (temp >= precision)                          // Если первое число больше второго,..
      return(1);                                   // ..то вернем 1
   else                                            // Если первое число меньше второго,
      if (temp <= -precision)                      // ..то вернем -1
         return(-1);
   return(0);                                      // Во всех остальных случаях считаем,
                                                   // ..что числа равны - вернем 0
}
//+-------------------------------------------------------------------------------------+
//| Формирование эталонного паттерна                                                    |
//+-------------------------------------------------------------------------------------+
void CreateEtalonPattern(int i)
{
   int last_index = i + AnalysisBars;              // Расчет индекса первого бара, не..
                                                   // ..входящего в паттерн
   int cnt = 0;                                    // Счетчик индексов эталонного..
                                                   // ..паттерна
   for (int k = i; k < last_index; k++)            // Пройдем по всем барам паттерна
   {
      high[cnt] = DoubleCompare(High[k], High[k+1], Point);// Соотношение максимумов
      low[cnt] = DoubleCompare(Low[k], Low[k+1], Point);// Соотношение минимумов
      candle_type[cnt] = DoubleCompare(Close[k], Open[k], Point);// Типы свечей
      cnt++;
   }
}
//+-------------------------------------------------------------------------------------+
//| Сравнение текущего паттерна с эталонным                                             |
//+-------------------------------------------------------------------------------------+
bool CompareWithEtalon(int i)
{
   int last_index = i + AnalysisBars;              // Расчет индекса первого бара, не..
                                                   // ..входящего в паттерн
   int cnt = 0;                                    // Счетчик индексов эталонного..
                                                   // ..паттерна
   for (int k = i; k < last_index; k++)            // Пройдем по всем барам паттерна   
   {
      if (DoubleCompare(High[k], High[k+1], Point) // Если соотношение максимумов..
                        != high[cnt])              // ..рассматриваемого паттерна не..
         return(false);                            // ..похоже на эталонный паттерн, то..
                                                   // ..сразу бракуем найденный паттерн
      if (DoubleCompare(Low[k], Low[k+1], Point)   // То же самое при рассмотрении..
                        != low[cnt])               // ..соотношения минимумов
         return(false);
      if (DoubleCompare(Close[k], Open[k], Point)  // Типы свечей найденного паттерна..
                        != candle_type[cnt])       // ..также должны соответствовать..
         return(false);                            // ..типам свечей эталонного паттерна
      cnt++;
   }
   return(true);
}
//+-------------------------------------------------------------------------------------+
//| Нахождение среднего из двух значений                                                |
//+-------------------------------------------------------------------------------------+
int Average(int v1, int v2)                        // В качестве v1 передается предыдущее
{                                                  // ..среднее значение
   if (v1 == 0)                                    // Если v2 - первое число в ряду, то..
      return(v2);                                  // ..среднее значение не вычисляется
   else                                            // В противном случае вычисляем..
      return(MathRound((v1 + v2)/2.0));            // ..среднее
}
//+-------------------------------------------------------------------------------------+
//| Нахождение в истории паттернов, похожих на эталонный                                |
//+-------------------------------------------------------------------------------------+
void FindDublicateEtalonPattern(int i)
{
   int last_index = Bars - AnalysisBars - 1;       // Расчет индекса бара, на котором..
                                                   // ..начинается первый в имеющейся..
                                                   // ..истории паттерн
   PatternsTotal = 0;                              // Инициализируем количество паттернов
   AverHighToOpen = 0;                             // Средняя длина свечи в каждом из..
   AverOpenToLow = 0;                              // ..направлений
   MaxHighToOpen = 0;                              // Максимальные длины свечей в каждом
   MaxOpenToLow = 0;                               // ..из направлений
   for (int k = i; k < last_index; k++)            // Пройдем по истории от указанного..
                                                   // ..бара до начала истории
      if (CompareWithEtalon(k))                    // Если найденный паттерн..
      {                                            // ..соответствует эталонному, то..
         PatternsTotal++;                          // Увеличим кол-во найденных паттернов
         int hto = MathRound((High[k-1] - Open[k-1])/Point);// Длина свечи от максимума..
                                                   // ..до цены открытия
         int otl = MathRound((Open[k-1] - Low[k-1])/Point);// Длина свечи от цены..
                                                   // ..открытия до минимума
         AverHighToOpen = Average(AverHighToOpen, hto);// Вычислим средние значения
         AverOpenToLow = Average(AverOpenToLow, otl);// Вычислим средние значения
         MaxHighToOpen = MathMax(hto, MaxHighToOpen);// Вычислим также максимальные..
         MaxOpenToLow = MathMax(otl, MaxOpenToLow);// ..значения
      }
}
//+-------------------------------------------------------------------------------------+
//| Отображение прямоугольника выделения                                                |
//+-------------------------------------------------------------------------------------+
void ShowRectangle(datetime time1, double price1, datetime time2, double price2, 
                   color Color)
{
   string name = prefix + "Rectangle" + time1;        // Генерация имени объекта:..
                                                      // ..префикс + "Rectangle" +время
   if (ObjectFind(name) < 0)                          // Если объект не существует
   {
      ObjectCreate(name, OBJ_RECTANGLE, 0, time1, price1, time2, price2); // Создаем его
      ObjectSet(name, OBJPROP_COLOR, Color);          // Назначим цвет и..
      ObjectSet(name, OBJPROP_BACK, true);            // ..выведем его на задний план
   }
}
//+-------------------------------------------------------------------------------------+
//| Отображение вертикальной линии                                                      |
//+-------------------------------------------------------------------------------------+
void ShowVLine(datetime time1)
{
   string name = prefix + "VLine";                    // Генерация имени объекта:..
                                                      // ..префикс + "VLine"
   if (ObjectFind(name) < 0)                          // Если объект не существует
   {
      ObjectCreate(name, OBJ_VLINE, 0, time1, 1);     // Создаем его
      ObjectSet(name, OBJPROP_COLOR, Red);            // Назначим цвет и..
      ObjectSet(name, OBJPROP_BACK, false);           // ..выведем его на передний план
      ObjectSet(name, OBJPROP_STYLE, STYLE_DOT);      // Пунктирная линия
   }
}
//+-------------------------------------------------------------------------------------+
//| Получение индекса бара, на котором находится вертикальная линия                     |
//+-------------------------------------------------------------------------------------+
int GetVLineBarIndex()
{
   string name = prefix + "VLine";                    // Генерация имени объекта:..
                                                      // ..префикс + "VLine"
   if (ObjectFind(name) < 0)                          // Если линия не существует, то..
      ShowVLine(Time[0]);                             // ..отобразим ее на нулевом баре
   datetime time = ObjectGet(name, OBJPROP_TIME1);    // Определим время открытия бара,..
                                                      // ..на котором находитяс линия
   return(iBarShift(NULL, 0, time));                  // Вернем индекс этого бара
}
//+-------------------------------------------------------------------------------------+
//| Удаление всех прямоугольников выделения                                             |
//+-------------------------------------------------------------------------------------+
void DeleteAllRectangle()
{
   for (int i = ObjectsTotal()-1; i >= 0; i--)        // По всем объектам графика
      if (StringSubstr(ObjectName(i), 0, StringLen(prefix)) == prefix)// Если имя объекта
                                                      // ..имеет префикс prefix
         if (ObjectType(ObjectName(i)) == OBJ_RECTANGLE)// Если объект типа прямоугольник
            ObjectDelete(ObjectName(i));              // Удалим его
   
}
//+-------------------------------------------------------------------------------------+
//| Отображение линии между средней и максимальной ценой                                |
//+-------------------------------------------------------------------------------------+
void ShowLine(datetime time1,                         // Время отображения объекта
              double price1,                          // Цена 1 отображения объекта
              double price2,                          // Цена 2 отображения объекта
              bool up,                                // true - объект выше свечи, а..
                                                      // ..false - ниже
               string text)                           // Описание объекта
{                                                     
   if (up)                                            // Если линия должна находиться..
   {                                                  // ..выше свечи, то назначим..
      color Color = UpColor;                          // ..цвет, указанный в UpColor
      string name = prefix + "LineUp" + time1;        // Генерация имени объекта:..
                                                      // ..префикс + "LineUp" + время
   }                        
   else                                               // Если линия должна находиться..
   {                                                  // ..ниже свечи, то назначим..
      Color = DownColor;                              // ..цвет, указанный в DownColor
      name = prefix + "LineDn" + time1;               // Генерация имени объекта:..
                                                      // ..префикс + "LineDn" + время
   }                              
   if (ObjectFind(name) < 0)                          // Если объект не существует
   {
      ObjectCreate(name, OBJ_TREND, 0, time1, price1, time1, price2);// Создаем его
      ObjectSet(name, OBJPROP_COLOR, Color);          // Назначим цвет,..
      ObjectSet(name, OBJPROP_STYLE, LineStyle);      // ..стиль,
      ObjectSet(name, OBJPROP_WIDTH, LineWidth);      // ..ширину,..
      ObjectSet(name, OBJPROP_BACK, LineBack);        // ..принадлежность заднему плану..
      ObjectSet(name, OBJPROP_RAY, false);            // ..продолжительность и..
      ObjectSetText(name, text);                      // ..добавим описание для линии
   }
}
//+-------------------------------------------------------------------------------------+
//| Главная функция индикатора                                                          |
//+-------------------------------------------------------------------------------------+
int start()
{
// - 1 - == Определение значения индекса бара, с которого начнется расчет индикатора ====
   int cb = IndicatorCounted();                    // Кол-во баров, посчитанных во время
                                                   // ..предыдущего вызова функции start
   if (cb > 0) cb--;                               // Последний посчитанный бар будет..
                                                   // ..пересчитан
   int limit = MathMin(Bars - cb, BarsCount);      // Расчет индекса нового бара
// - 1 - == Окончание блока =============================================================      

// - 2 - == Расчет сигналов на истории ==================================================
   for (int i = limit; i > 0; i--)                 // По всей обновленной истории
   {
      CreateEtalonPattern(i);                      // Формирование эталонного паттерна
      FindDublicateEtalonPattern(i+AnalysisBars);  // Нахождение паттернов, похожих на..
                                                   // ..эталонный
      if (PatternsTotal >= MinHistory)             // Если найденое количество паттернов
      {                                            // ..не меньше указанного количества
         double AverPrice = Open[i-1] + AverHighToOpen*Point;
         double MaxPrice = Open[i-1] + MaxHighToOpen*Point;
         ShowLine(Time[i-1], AverPrice, MaxPrice,  // Отобразим линию от значения..
                  true, "Средняя длина " +         // .."средняя длина свечи до..
                  DoubleToStr(AverHighToOpen, 0) + // ..максимума" до значения..
                  ", максимальная длина " +        // .."максимальная длина свечи"
                  DoubleToStr(MaxHighToOpen, 0) + " из " +  
                   DoubleToStr(PatternsTotal, 0) + " паттернов");

         AverPrice = Open[i-1] - AverOpenToLow*Point;
         MaxPrice = Open[i-1] - MaxOpenToLow*Point;
         ShowLine(Time[i-1], AverPrice, MaxPrice,  // Отобразим линию от значения..
                  false, "Средняя длина " +        // .."средняя длина свечи до..
                  DoubleToStr(AverOpenToLow, 0) +  // ..минимума" до значения..
                  ", максимальная длина " +        // .."максимальная длина свечи"
                  DoubleToStr(MaxOpenToLow, 0) + " из " +  
                   DoubleToStr(PatternsTotal, 0) + " паттернов");
      }   
   }
// - 2 - == Окончание блока =============================================================      
   
// - 3 - == Отображение паттернов, соответствующих указанному паттерну ==================
   int nBar = GetVLineBarIndex();                  // Определим местоположение..
                                                   // ..вертикальной линии
   if (nBar == LastnBar)                           // Если положение линии не..
      return(0);                                   // ..отличается от предыдущего..
                                                   // ..положения, то на этом заканчиваем
   DeleteAllRectangle();                           // Удалим все старые прямоугольники
   LastnBar = nBar;                                // Запомним новый номер бара
   ShowRectangle(Time[nBar+1],                     // Выделим эталонный паттерн
                 Low[iLowest(NULL, 0, MODE_LOW, AnalysisBars, nBar+1)], 
                 Time[nBar+AnalysisBars], 
                 High[iHighest(NULL, 0, MODE_HIGH, AnalysisBars, nBar+1)], EtalonColor);
   CreateEtalonPattern(nBar+1);                    // Создадим описание эталонного..
                                                   // ..паттерна
   limit = nBar + AnalysisBars + 1;                // Определим индекс начального бара..
                                                   // ..для поиска дубликатов паттерна
   int end = Bars - AnalysisBars - 1;              // Определим конечный бар в истории
   for (i = limit; i < end; i++)                   // Пройдем по всем барам
      if (CompareWithEtalon(i))                    // Если найден дубликат эталонного..
         ShowRectangle(Time[i],                    // ..паттерна, то выделим дубликат..
                       Low[iLowest(NULL, 0, MODE_LOW, AnalysisBars, i)],
                       Time[i+AnalysisBars-1],     // ..прямоугольником
                       High[iHighest(NULL, 0, MODE_HIGH, AnalysisBars, i)], 
                       HistoricalPatternColor);
// - 3 - == Окончание блока =============================================================      
   
   WindowRedraw();                                 // Обновим окно графика
   return(0);
}

Recommend