Alert и Comment для внешних индикаторов. Мультивалютный анализ посредством внешнего сканирования

Vladimir | 23 ноября, 2009


Введение

В предыдущих статьях мы рассмотрели возможность получения информации от индикаторов, которые используют в качестве источника информации значки из таблицы Wingdings, отображенные на графике. Статья "Alert и Comment для внешних индикаторов" и создание Алертов от индикаторов, которые используют для хранения информации индикаторные буфера статья "Alert и Comment для внешних индикаторов (часть вторая)", а информация выводится изменением цвета.

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

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

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

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

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


Alert мультивалютного индикатора

Вначале рассмотрим код блока обработки информации, получаемой из индикаторных буферов внешнего индикатора.

double buffer1, buffer2, buffer12, buffer22;
// Анализируем первый и второй бар графиков
            buffer1  = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff1, 1);
            buffer12 = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff1, 2);
            buffer2  = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff2, 1);
            buffer22 = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff2, 2);
            if(buffer12<=buffer22&&buffer1>buffer2)
               {
                  Alert (text+"UP"); // Есть пересечение
                  send_email (text+"UP");
                  return (1);
               }
            if(buffer12>=buffer22&&buffer1<buffer2)
               {
                  Alert (text+"DN"); // Есть пересечение
                  send_email (text+"DN");
                  return (1);
               } 
            return (0);

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

Всю эту обработку вынесем в отдельный блок. Мультивалютный и мультитаймфреймный анализ потребует многократного использования этой процедуры.

Список доступных инструментов вынесем во внешний файл, что позволит в дальнейшем упростить процедуру внесения в него изменений и дополнений. При таком подходе, для изменения списка доступных инструментов пользователь может самостоятельно создать заново или внести изменения в файл доступных инструментов, не меняя программного кода индикатора.

В конце статьи показана процедура создания собственного файла доступных инструментов.

Подпрограмма считывания информации из файла взята отсюда.

//+------------------------------------------------------------------+
//|                                           SymbolList_fromSet.mq4 |
//|                                      Copyright © 2006, komposter |
//|                                      mailto:komposterius@mail.ru |
//+------------------------------------------------------------------+
void LoadFileToSymbol()
   {
      {
              int file_handle = FileOpen(SetFile_name + ".set", FILE_READ);
              //---- Если возникла ошибка
              if(file_handle < 0)
                {
                         Print("Ошибка №", GetLastError(), " при открытии файла!!!");
                         return(-1);
                }
              int SymbolsCount = 0;
              while(true)
                {
                         Symbols[SymbolsCount] = FileReadString(file_handle);
                         //---- Если достигнут конец файла, останавливаемся
                         if(GetLastError() == 4099) 
                             break;
                         if(FileIsEnding(file_handle)) 
                             break;
                         SymbolsCount ++;
                         ArrayResize(Symbols, SymbolsCount + 1);
                }
              FileClose(file_handle);
      }
   
   }  
//--------------------------------------------------------------+

Теперь, после подготовки массива инструментов, нам остается сделать мультитаймфреймную обработку каждого инструмента.

Текущий таймфрейм будет использоваться нами для расчетов как стартовый.

// Анализируем массив символов (Расчет на текущем и всех нижних таймфреймах)
         for (int i=0; i<ArraySize(Symbols); i++)
            {  Total = 0;
               switch (Period())
                  {
                     case 43200: Total = Total +  process ( Symbols[i], 43200);
                     case 10080: Total = Total +  process ( Symbols[i], 10080);
                     case  1440: Total = Total +  process ( Symbols[i],  1440);
                     case   240: Total = Total +  process ( Symbols[i],   240);
                     case    60: Total = Total +  process ( Symbols[i],    60);
                     case    30: Total = Total +  process ( Symbols[i],    30);
                     case    15: Total = Total +  process ( Symbols[i],    15);
                     case     5: Total = Total +  process ( Symbols[i],     5);
//                     case     1: Total = Total +  process ( Symbols[i],     1);
                  }

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

Такой подход сделал оперирование перерасчетом индикатора удобным для пользователя: простое переключение рабочего таймфрейма позволяет не вводить в код дополнительные параметры и расчетные функции.

Строка работы на минутном таймфрейме закомментирована. Если кому-то потребуется применять индикатор на минутном таймфрейме, - раскомментируйте строку.

//                     case     1: Total = Total +  AlertComment ( Symbols[i],     1);


В качестве источника информации для нашего индикатора используем индикатор 2MA_forAlert.mq4 в приложении к статье. 2MA_forAlert - это простой индикатор, отображающий две линии МА. Также можно использовать любой другой, имеющий два буфера (две линии). Стохастик, МАКД и др.

Вот как выглядит алерт терминала с применением разных индикаторов:

Буферы, где хранятся значения линий, могут иметь разный порядок. Например:

0 - главная линия

1 - сигнальная линия

или

0 - сигнальная линия

1 - главная линия

Поэтому при использовании внешнего индикатора нужно самостоятельно определить последовательность использования линий. В случае некорректного извещения алерта, изменить входные параметры.

extern int       ExtBuff1      = 0;
extern int       ExtBuff2      = 1;

В качестве параметров можно использовать все 8 допустимых буферов (цифры от 0 до 7)

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

Вначале мы в окне данных создаем все необходимые инструменты, для этого:

1. Открываем все доступные инструменты.


2. Оставляем только те, по которым будем получать сигналы.

Инструментов должно быть ровно столько, сколько предполагается использовать в торговле.


3. Затем сохраняем файл, для чего кликаем в окне "Обзор рынка" правой кнопкой мыши


4. Файл сохраняем в папке для хранения файлов экспертов метатрейдера


Имя файла вы можете назначить произвольное, но расширение файла .set изменять нельзя. В указанном примере используется файл forexall.set

extern string    SetFile_name  = "forexall"; // Файл, содержащий символы инструментов пользователя

После создания файла нужно поочередно открыть каждый график из набора символов, для того, чтобы терминал подкачал историю. Иначе какой-либо инструмент выпадет из обработки.

Если же вы сохранили файл в папке по умолчанию \experts\symbolsets, то обязательно скопируйте его в папку \experts\files метатрейдера, так как это единственная папка, из которой индикатор может открыть файл (ограничения метатрейдера). В дальнейшем в индикаторе нужно ввести имя файла, который будет обрабатываться для считывания из него информации о доступных инструментах.

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

extern bool      Signal_email  = false;

Есть такие пользователи которые создают в дальнейшем переадресацию и получают сигналы посредством СМС на свой телефон. У каждого свой подход.

Все индикаторы должны находиться в папке \experts\indicators Метатрейдера.


Заключение

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

И в заключение, представляю полный код индикатора - Алерта.

//+------------------------------------------------------------------+
//|                                                    Alert_MT4.mq4 |
//|                                      Copyright © 2009, Fibook.ru |
//|                                             http://www.fibook.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Fibook.ru"
#property link      "http://www.fibook.ru"

#property indicator_chart_window

extern string    SetFile_name="forexall"; // Файл содержащий символы инструментов пользователя
extern string    nameIndicator = "input indicator name";
extern int       ExtBuff1      = 0;
extern int       ExtBuff2      = 1;
extern string    UserText      = "Cross";
extern bool      Signal_email  = false;

string Symbols[1],text;
int expBars=0;
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
// Если нет нового бара, то выходим
   if(!isNewBar()) return;
   int Total;
//---- Проверка на ошибки входных параметров
   if(ControlError()==false) return;
//---- Загружаем в массив Symbols символы из файла
   LoadFileToSymbol();
//----

// Анализируем массив символов (Расчет на текущем и всех нижних таймфреймах)
   for(int i=0;i<ArraySize(Symbols);i++)
     {
      Total=0;
      switch(Period())
        {
         case 43200: Total = Total +  process ( Symbols[i], 43200);
         case 10080: Total = Total +  process ( Symbols[i], 10080);
         case  1440: Total = Total +  process ( Symbols[i],  1440);
         case   240: Total = Total +  process ( Symbols[i],   240);
         case    60: Total = Total +  process ( Symbols[i],    60);
         case    30: Total = Total +  process ( Symbols[i],    30);
         case    15: Total = Total +  process ( Symbols[i],    15);
         case     5: Total = Total +  process ( Symbols[i],     5);
         //                     case     1: Total = Total +  process ( Symbols[i],     1);
        }
      if(Total>1)
        {
         text=StringConcatenate(" Warning!!!      ",Symbols[i]," have ",UserText," for ",Total," TF");
         Alert(text);
         send_email(text);
        }
     }

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

int process(string Sym_,int TF)
  {
   text=StringConcatenate(Sym_," ",TF," indicator ",nameIndicator," Crossing line ");
   double buffer1,buffer2,buffer12,buffer22;
// Анализируем первый и второй бар графиков
   buffer1  = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff1, 1);
   buffer12 = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff1, 2);
   buffer2  = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff2, 1);
   buffer22 = iCustom(Sym_, TF, nameIndicator, 0, ExtBuff2, 2);
   if(buffer12<=buffer22 && buffer1>buffer2)
     {
      Alert(text+"UP"); // Есть пересечение
      send_email(text+"UP");
      return(1);
     }
   if(buffer12>=buffer22 && buffer1<buffer2)
     {
      Alert(text+"DN"); // Есть пересечение
      send_email(text+"DN");
      return(1);
     }
   return(0);

  }
//+------------------------------------------------------------------+
//|                                           SymbolList_fromSet.mq4 |
//|                                      Copyright © 2006, komposter |
//|                                      mailto:komposterius@mail.ru |
//+------------------------------------------------------------------+

void LoadFileToSymbol()
  {
     {
      int file_handle=FileOpen(SetFile_name+".set",FILE_READ);
      //---- Если возникла ошибка
      if(file_handle<0)
        {
         Print("Ошибка №",GetLastError()," при открытии файла!!!");
         return(-1);
        }
      int SymbolsCount=0;
      while(true)
        {
         Symbols[SymbolsCount]=FileReadString(file_handle);
         //---- Если достигнут конец файла, останавливаемся
         if(GetLastError()==4099)
            break;
         if(FileIsEnding(file_handle))
            break;
         SymbolsCount++;
         ArrayResize(Symbols,SymbolsCount+1);
        }
      FileClose(file_handle);
     }

  }
//--------------------------------------------------------------+
void send_email(string text)
  {
   if(Signal_email==true) SendMail("Alert ",text);
  }
//--------------------------------------------------------------+
bool ControlError()
  {
// Проверим ввели ли имя индикатора
   if(nameIndicator=="input indicator name")
     {
      Alert("Введите название индикатора ");
      return(false);
     }
// Проверим есть ли файл с символами
   int handle;
   handle=FileOpen(SetFile_name+".set",FILE_CSV|FILE_READ,';');
   if(handle<1)
     {
      Alert("Файл ",SetFile_name,".set не обнаружен, последняя ошибка ",GetLastError());
      return(false);
     }
// Проверим на ошибку назначение входных переменных буферов анализируемого индикатора
   if(ExtBuff1>7 || ExtBuff2>7)
     {
      Alert("Некорректные параметры буфера ExtBuff1 или ExtBuff2");
      return(false);
     }
   if(ExtBuff1==ExtBuff2)
     {
      Alert("Ошибка: ExtBuff1 и ExtBuff2 не могут быть равны");
      return(false);
     }

   return(true);
  }
/*--------------------------------------------------------------+
 |Функция возвращает true, если появится новый бар, иначе false |
 +--------------------------------------------------------------*/
bool isNewBar()
  {
   bool res=false;
   if(expBars!=Bars)
     {
      expBars=Bars;
      res=true;
     }
   return(res);
  }
//+------------------------------------------------------------------+