Звуковые сигналы в индикаторах

Автор: lexy Среда, Сентябрь 10th, 2014 Нет комментариев

Рубрика: Разное

Не смотря на возрастающую популярность автотрейдинга, многие трейдеры продолжают торговать вручную. И если эксперту для оценки текущей ситуации на рынке требуется несколько миллисекунд, то обычному человеку необходимо потратить много времени, усилий и, главное, внимания.

Как и несколько лет назад, многие трейдеры для анализа пользуются Техническими индикаторами - одним или несколькими сразу. А некоторые стратегии учитывают значения индикаторов одновременно на нескольких периодах.

Как не пропустить важный сигнал? Есть несколько вариантов:

  • Написать эксперта, который будет анализировать рынок и сообщать о важных событиях;
  • Сидеть возле монитора и, переключаясь между десятками графиков, пытаться сопоставить полученную информацию;
  • Добавить во все используемые индикаторы систему оповещения о торговых сигналах.

Первый вариант по моему мнению наиболее правильный, но требует либо навыков программиста либо денег на реализацию. Второй — очень трудоемкий, утомительный и нерациональный. А третий вариант — нечто среднее между первыми двумя. Для его реализации необходимо намного меньше времени и умений, но он значительно облегчит жизнь (работу) трейдеру, торгующему вручную.

Именно реализации третьего варианта и посвящена данная статья. После её прочтения каждый трейдер сможет добавлять в индикаторы удобные для себя сигналы.

Виды сигналов

Способов интерпретации индикаторов существует очень много. Даже стандартные индикаторы терминала MetaTrader 4 можно понимать по разному. О всевозможных пользовательских индикаторах я вообще молчу…

Кто-то покупает, когда главная линия MACD пересекает сигнальную, кто-то ждет пересечения с нулевой линией, а кто-то открывает длинную позицию, когда MACD меньше 0 и начинает движение вверх. Предусмотреть все возможные варианты интерпретации мне не представляется возможным, поэтому я вам расскажу принцип добавления сигнального блока, а вы, отталкиваясь от него, сможете добавить любой тип сигнала в большинство индикаторов.

Итак, какие виды сигналов у нас есть:

  • Пересечение двух линий индикатора (пример приведен выше — главная линия MACD и сигнальная линия);
  • Пересечение линией индикатора определенного уровня (главная линия MACD и нулевая линия, Stoсhastic и уровни 70 и 30, CCI и уровни -100 и 100);
  • Изменение направления движения (AC и AO, обычный MA);
  • Изменение расположения по отношению к цене (Parabolic SAR);
  • Появление стрелочки над или под ценой (Fractals).

Наверное, существуют ещё какие-то способы интерпретации, я просто о них забыл или не знал вообще, поэтому пока остановимся на этих пяти.

Способы оповещения

MetaTrader 4 и MQL 4 позволяют реализовать несколько способов как визуального, так и звукового оповещения:

  • Обычное сообщение на экран (функция Comment);
  • Текст в журнале (функция Print);
  • Окно с сообщением и звуковой сигнал (функция Alert);
  • Отдельный звуковой сигнал с выбором воспроизводимого файла (функция PlaySound).

Кроме того, есть функция отправки файла на FTP-сервер (функция SendFTP()), вывода диалогового окна с сообщением (MessageBox()) и отправки почтового сообщения (SendMail()). Функция SendFTP() вряд ли будет востребована обычным пользователем, MessageBox() не подходит для использования в индикаторе, так как останавливает его работу до закрытия окна сообщения, а SendMail(), хоть и удобна для отправки SMS-сообщений, достаточно «опасна» в использовании — оставив несколько индикаторов на графике, вы обеспечите себе нескончаемый и нерегулируемый поток сообщений. Функцию использовать можно, но лучше из советника, например, отправлять сообщение при появлении сигнала на нескольких индикаторах одновременно, уделив ей достаточно внимания.

В этой статье мы рассмотрим только способы звукового и визуального оповещения терминала MetaTrader 4.

Самый простой и удобный из них — функция Alert, так как содержит и текст и звук. Кроме того, терминал хранит историю Alert-ов и всегда можно посмотреть, какой сигнал был час назад.

Но, как известно, на вкус и цвет товарищей нет. Поэтому я сделаю заготовку для всех упомянутых способов (кроме SendFTP, MessageBox и SendMail), а вы выберете удобный для себя.

Фильтр на частоту сигналов

Если вы уже когда-нибудь пользовались сигналами в индикаторах, то наверняка сталкивались с их чрезмерной частотой, особенно, если речь идет о мелких таймфреймах. Решается эта проблема несколькими способами:

  • Сигналы определять на основании сформировавшихся баров. Это наиболее правильное решение;
  • Чередовать сигналы — после покупки только продажа, и наоборот (тоже очень логичный ход, его можно использовать одновременно с другими);
  • Делать паузу между сигналами (не очень хорошая идея);
  • Давать один сигнал на бар (тоже достаточно искусственное ограничение).

Использовать ли сигнал с нулевого, несформировавшегося, бара для торговли — личное дело каждого. Я, например, считаю что это неправильно. Но есть индикаторы требующие моментальной реакции — для них один бар это слишком много. Поэтому дадим пользователю выбор. Несколько сигналов на покупку подряд вряд ли имеют смысл, поэтому все сигналы будем чередовать. А искусственные паузы вводить, пожалуй, не будем. Если они действительно понадобятся, об этом напишут в комментариях к статье.

Итак, приступим к реализации.

Сигнал первый — пересечение двух индикаторных линий

Начнем с приводимого в примерах MACD.

Главная наша задача — определить в каких массивах хранятся линии индикатора. Для этого посмотрим в код:

//---- indicator settings
#property  indicator_separate_window
#property  indicator_buffers 2
#property  indicator_color1  Silver
#property  indicator_color2  Red
#property  indicator_width1  2
//---- indicator parameters
extern int FastEMA = 12;
extern int SlowEMA = 26;
extern int SignalSMA = 9;
//---- indicator buffers
double MacdBuffer[];
double SignalBuffer[];

Обратите внимание на комментарий «indicator buffers» — это именно то, что мы искали. Такие массивы чаще всего имеют интуитивно понятное имя (MacdBuffer — буфер значения главной линии MACD, SignalBuffer — буфер сигнальной линии) и всегда располагаются вне функций init, deinit и start.

Если массивов много и сложно понять какой из них необходим, посмотрите в функцию init — все массивы, отображенные на графике, «привязываются» к определенному номеру с помощью функции SetIndexBuffer:

int init()
  {
//---- drawing settings
   SetIndexStyle(0, DRAW_HISTOGRAM);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexDrawBegin(1, SignalSMA);
   IndicatorDigits(Digits + 1);
//---- indicator buffers mapping
   SetIndexBuffer(0, MacdBuffer);
   SetIndexBuffer(1, SignalBuffer);
//---- name for DataWindow and indicator subwindow label
   IndicatorShortName("sMACD(" + FastEMA + "," + SlowEMA + "," + SignalSMA + ")");
   SetIndexLabel(0, "sMACD");
   SetIndexLabel(1, "sSignal");
//---- initialization done
   return(0);
  }

И именно в таком порядке (от 0 до 7) значения линий индикатора отображаются в окне DataWindow. Имена, которые вы увидите там же, назначаются функцией SetIndexLabel — это третий способ идентификации.

Теперь, когда мы знаем, где хранятся необходимые данные, можем переходить к реализации сигнального блока. Для этого перемещаемся в самый конец функции start — выше последнего оператора return:

   for(i = 0; i < limit; i++)
       SignalBuffer[i] = iMAOnArray(MacdBuffer, Bars,S ignalSMA, 0, MODE_SMA, i);
//---- done

// а сюда мы добавим наш код

   return(0);
  }
//+------------------------------------------------------------------+

Ни в коем случае нельзя добавлять сигнальный блок в цикл расчета индикатора — это замедлит его работу и не принесет никакой пользы.

Итак, начинаем сочинять:

    //---- Статические переменные, в которых хранятся
    //---- время последнего бара и направление последнего сигнала
    static int PrevSignal = 0, PrevTime = 0;

    //---- Если баром для анализа выбран не 0-й, нам нет смысла проверять сигнал
    //---- несколько раз. Если не начался новый бар, выходим.
    if(SIGNAL_BAR > 0 && Time[0] <= PrevTime )
        return(0);
    //---- Отмечаем, что этот бар проверен
    PrevTime = Time[0];

Каждый раз, когда будет выполняться функция start, будет выполняться наш код. Обычные переменные обнуляются после каждого выполнения функции. Поэтому для хранения последнего сигнала и номера просчитанного бара мы объявили две статические переменные.
Дальше находится простая проверка, начался ли новый бар (работает только, если SIGNAL_BAR больше 0).

Кстати, саму переменную SIGNAL_BAR мы объявили намного раньше, ещё до функции init:

double     SignalBuffer[];

//---- Номер бара, по которому будет искаться сигнал
#define SIGNAL_BAR 1

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {

Обратите внимание на директиву #define — компилятор просто заменит во всем коде переменную SIGNAL_BAR указанным значением (1).

Теперь, собственно, код сигнала:

    //---- Если предыдущий сигнал был СЕЛЛ или это первый запуск (PrevSignal=0)
    if(PrevSignal <= 0)
      {
        //---- Проверяем, не пересеклись ли линии на прошлом баре:
        if(MacdBuffer[SIGNAL_BAR] - SignalBuffer[SIGNAL_BAR] > 0 &&
           SignalBuffer[SIGNAL_BAR+1] - MacdBuffer[SIGNAL_BAR+1] >= 0)
          {
            //---- Если пересеклись, отмечаем что последний сигнал - бай
            PrevSignal = 1;
            //---- и выводим информацию:
            Alert("sMACD (", Symbol(), ", ", Period(), ")  -  BUY!!!");
//            Print("sMACD (", Symbol(), ", ", Period(), ")  -  BUY!!!");
//            Comment("sMACD (", Symbol(), ", ", Period(), ")  -  BUY!!!");
//            PlaySound("Alert.wav");
          }
      }

Тут тоже все просто. Если предыдущий сигнал был на продажу, проверяем пересечение линий:
если  значение главной линии MACD на баре №1 больше, чем значение сигнальной линии на баре №1
И
значение сигнальной линии на баре №2 больше, чем значение линии MACD на баре №2
значит
линии пересеклись.

Дальше отмечаем, что последний сигнал был на покупку, и выводим сообщение. Обратите внимание на три закомментированные строки — это ещё три варианта оповещения. Вы можете разкомментировать или удалить любую из них или все сразу. По умолчанию я оставил только Alert, как самый удобный.
А в функции PlaySound можно указать, какой аудио файл проигрывать. Файл должен находиться в директории MetaTrader 4\sounds\ и иметь расширение wav. Например, сделать свой звук на сигнал бай и свой — на селл или разные звуки разным индикаторам.

Сигнал на продажу полностью аналогичен:

    //---- Полностью аналогично для сигнала СЕЛЛ
    if(PrevSignal >= 0)
      {
        if(SignalBuffer[SIGNAL_BAR] - MacdBuffer[SIGNAL_BAR] > 0 &&
           MacdBuffer[SIGNAL_BAR+1] - SignalBuffer[SIGNAL_BAR+1] >= 0)
          {
            PrevSignal = -1;
            Alert("sMACD (", Symbol(), ", ", Period(), ")  -  SELL!!!");
//            Print("sMACD (", Symbol(), ", ", Period(), ")  -  SELL!!!");
//            Comment("sMACD (", Symbol(), ", ", Period(), ")  -  SELL!!!");
//            PlaySound("Alert.wav");
          }
      }

Остальные сигналы

Теперь, когда мы освоились в коде индикатора, нам будет намного проще написать другие блоки оповещения. Меняться будет только «формула», остальной код будем просто копировать.

Сигнал на пересечение определенного уровня очень похож на пересечение линий. Я его добавил в Stochastic, но вы можете провести аналогию для любого другого индикатора:

    if(PrevSignal <= 0)
      {
        if(MainBuffer[SIGNAL_BAR] - 30.0 > 0 &&
           30.0 - MainBuffer[SIGNAL_BAR+1] >= 0)
          {
            PrevSignal = 1;
            Alert("sStochastic (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(70.0 - MainBuffer[SIGNAL_BAR] > 0 &&
           MainBuffer[SIGNAL_BAR+1] - 70.0 >= 0)
          {
            PrevSignal = -1;
            Alert("sStochastic (", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

Как видите, при пересечении линией %K (MainBuffer) уровня 30 снизу вверх индикатор скажет «Buy», а при пересечении уровня 70 сверху вниз — «Sell».

Третий вид сигнала — изменение направления движения. Его мы рассмотрим на примере индикатора AC. Обратите внимание, в этом индикаторе используется пять буферов:

//---- indicator buffers
double     ExtBuffer0[];
double     ExtBuffer1[];
double     ExtBuffer2[];
double     ExtBuffer3[];
double     ExtBuffer4[];

ExtBuffer3 и ExtBuffer4 используются для промежуточных расчетов, ExtBuffer0 всегда хранит знчение индикатора, а ExtBuffer2 и ExtBuffer3 «разукрашивают» столбики в 2 цвета. Поскольку нам необходимо только значение индикатора, будем использовать ExtBuffer0:

    if(PrevSignal <= 0)
      {
        if(ExtBuffer0[SIGNAL_BAR] - ExtBuffer0[SIGNAL_BAR+1] > 0 &&
           ExtBuffer0[SIGNAL_BAR+2] - ExtBuffer0[SIGNAL_BAR+1] > 0)
          {
            PrevSignal = 1;
            Alert("sAC (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(ExtBuffer0[SIGNAL_BAR+1] - ExtBuffer0[SIGNAL_BAR] > 0 &&
           ExtBuffer0[SIGNAL_BAR+1] - ExtBuffer0[SIGNAL_BAR+2] > 0)
          {
            PrevSignal = -1;
            Alert("sAC (", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

Если значение индикатора уменьшалось, а потом начало увеличиваться, даем сигнал на покупку, если наоборот — увеличивалось и начало уменьшаться — на продажу.

Четвертый вид сигнала — изменение расположения по отношению к цене — достаточно редкий.
Но все равно его можно встретить, например, в Parabolic-е. На его примере мы и напишем «формулу»:

    if(PrevSignal <= 0)
      {
        if(Close[SIGNAL_BAR] - SarBuffer[SIGNAL_BAR] > 0)
          {
            PrevSignal = 1;
            Alert("sParabolic Sub (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(SarBuffer[SIGNAL_BAR] - Close[SIGNAL_BAR] > 0)
          {
            PrevSignal = -1;
            Alert("sParabolic Sub(", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

Тут вообще все просто — сравниваем значение индикатора с ценой закрытия бара. Заметьте, если установить SIGNAL_BAR равным 0, каждое «прикосновение» цены к параболику будет сопровождаться сигналом.

И последний сигнал — появление стрелочки на графике. В стандартных индикаторах он встречается достаточно редко, зато очень распространен в пользовательских «определителях разворотов». Я рассмотрю этот вид сигналов на примере индикатора Fractals (исходный код на MQL 4 находится в Code Base: Fractals).

Общим для всех подобных индикаторов является то, что в тех местах, где они рисуются на графиках, они не равны 0 (или EMPTY_VALUE). На всех остальных барах их буферы пустые. То есть для определения сигнала достаточно сравнить значение буфера с 0:

    if(PrevSignal <= 0 )
      {
        if(ExtDownFractalsBuffer[SIGNAL_BAR] > 0)
          {
            PrevSignal = 1;
            Alert("sFractals (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(ExtUpFractalsBuffer[SIGNAL_BAR] > 0)
          {
            PrevSignal = -1;
            Alert("sFractals (", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

Но если вы присоедините индикатор с таким кодом на график, вы никогда не дождетесь сигнала. У фракталов есть одна особенность — они используют 2 будущих бара для анализа, поэтому стрелочки появляются только на втором по номеру (или третьем по счету — 0-й, 1-й, 2-й) баре. Поэтому для того, чтоб сигналы заработали, надо установить SIGNAL_BAR равным 2:

//---- Номер бара, по которому будет искаться сигнал
#define SIGNAL_BAR 2

Всё, теперь сигналы будут работать!

Заключение

В статье были рассмотрены различные способы добавления звуковых сообщений в индикаторы. Также были определены такие понятия, как способ интерпретации сигнала (вид сигнала), способ оповещения и фильтр частоты сигналов.

Среди видов сигналов были выделены и реализованы:

  • Пересечение двух линий индикатора;
  • Пересечение линией индикатора определенного уровня;
  • Изменение направления движения;
  • Изменение расположения по отношению к цене;
  • Появление стрелочки над или под ценой.

Для оповещения были выбраны функции:

  • Comment() — для обычного сообщения на экран;
  • Print() — для отображения сообщения в журнале;
  • Alert() — для отображения сообщения в специальном окне и звукового сигнала;
  • и PlaySound() — для воспроизведения любого звукового файла.

Для уменьшения частоты сигналов:

  • При определении сигнала использовались сформировавшиеся бары;
  • Все сигналы чередовались — после покупки только продажа, и наоборот.

На примере пяти индикаторов, соответствующих пяти видам сигналов, были рассмотрены их сигнальные блоки. Полученные индикаторы можно скачать — ссылки в конце статьи.

Я надеюсь, вы убедились, что ничего сложного в добавлении сигнального блока в индикаторы нет — это по силам каждому. Может быть, теперь на форумах будет меньше подобных просьб и мы сможем развиваться дальше.

Прикрепленные файлы:
 sAccelerator.mq4 (4.4 Kb)
 sFractals.mq4 (7.4 Kb)
 sMACD.mq4 (4.2 Kb)
 sParabolic Sub.mq4 (8.5 Kb)
 sStochastic.mq4 (5.2 Kb)
Источник: mql4.com

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты