Отображение новостного календаря

Slobodov Gleb | 21 ноября, 2007

Введение


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



Опишем список требований, которые мы предъявим к индикатору:
  • Индикатор должен сам (без вмешательства пользователя) скачивать необходимый файл календаря с событиями на текущую неделю
  • Индикатор должен отображать все события (как прошедшие, так и будущие) из этого файла в виде вертикальных линий с подписями названий новостей
  • Индикатор должен следить за обновлением событий на внешнем ресурсе
После того как мы поставили задачу, можно перейти к рассмотрению некоторых технических ньюансов.


Техническая Часть


В качестве внешнего ресурса будем использовать сайт http://www.dailyfx.com/calendar/. Удобство этого источника в том, что там есть возможность скачивать календарь в расширении .csv, и не приходится мучаться с расшифровкой html файла. Вот сам адрес файла на текущую неделю: http://www.dailyfx.com/calendar/Dailyfx_Global_Economic_Calendar.csv.

Обратимся теперь непосредственно к вопросу процесса скачивания файла из Интернета. Для этого мы будем использовать известную программу GetRight. Скачать ее можно здесь: http://www.getright.com/get.html или в списке файлов в конце статьи.

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




Написание Индикатора


Теперь, после того как все преграды на пути разработки нашего индикатора разрушены, можно смело приступать к его написанию!


extern string HtmlAdress = "http://www.dailyfx.com/calendar/Dailyfx_Global_Economic_Calendar.csv";
extern string GetrightAdress = "c:\progra~1\getright\getright.exe";
 
#include <Time.mqh>
#import "kernel32.dll"
int WinExec(string NameEx, int dwFlags);

Внешних переменных будет всего 2, это адрес внешнего ресурса (в принципе менять этот параметр не надо) и адрес программы GetRight (по хорошему, чтобы не менять постоянно значение этой переменной при запуске индикатора, если вы установили GetRight в другую директорию, советую один раз поменять начальное значение в самом индикаторе). Для, непосредственно, запуска екзешника (GetRight.exe) нам потребуется воскользоваться функцией WinExec, которую мы импортируем из библиотеки Kernel32.dll. В библиотеке Time.mqh находятся функции для работы со временем в GMT поясе.


void DownloadCalendar()
{
 Print("Downloading "+HtmlAdress+" to experts\files\html\Calendar.csv");
 WinExec(GetrightAdress+" /URL:"+HtmlAdress+" /FILE:Calendar.csv /W /O",0);
}

Как вы можете видеть благодаря использованию GetRight’а функция скачивания файла с внешнего ресурса выглядит очень просто. Параметр /W означает, что процесс не будет возвращен обратно в программу до полного скачивания файла, а /O, что при наличии файла с таким же именем, он будет перезаписан (overwrite). Напомню, что если Вы правильно изменили настройки GetRight’а, то календарь будет скачан по адресу \files\html\. Далее показаны две вспомогательные функции:


datetime PerviousMonday(datetime d)
{
 datetime res = d - (TimeDayOfWeek(d)-1)*24*60*60;
 return(res);
}
datetime ToDate(string stDate,string stTime)  
{
 string WeekDay = StringSubstr(stDate,0,3);
 int WeekPlus = 0;
 if (WeekDay=="Mon") WeekPlus=0;
 if (WeekDay=="Tue") WeekPlus=1;
 if (WeekDay=="Wed") WeekPlus=2;
 if (WeekDay=="Thu") WeekPlus=3;
 if (WeekDay=="Fri") WeekPlus=4;
 if (WeekDay=="Sat") WeekPlus=5;
 if (WeekDay=="Sun") WeekPlus=-1;
 datetime Res = PerviousMonday(GetTimeGMT())+WeekPlus*24*60*60;
 datetime Tm = StrToTime(stTime);
 Res=Res+TimeHour(Tm )*60*60+TimeMinute(Tm )*60+TimeSeconds(Tm )
 -TimeHour(Res)*60*60-TimeMinute(Res)*60-TimeSeconds(Res);  
 if (StringFind(stTime,"PM")>=0)  
 Res+=12*60*60;
 Res=Res-GetShiftGMT();
 return (Res);
}

Функция PerviousMonday() возвращает дату начала текущей недели. А функция ToDate() переводит дату и время из формата календаря в datetime.


void GrabNews()  
{
 int file = FileOpen("\Html\Calendar.csv",FILE_READ|FILE_CSV,',');
 if (file==-1||FileSize(file)==0)
 return;
 int i=0;
 while (!FileIsEnding(file))
 {
 string stDate="";
 while (!FileIsEnding(file)&&stDate=="")
 stDate = FileReadString(file);
 string stTime = FileReadString(file);
 string stTimeZone = FileReadString(file);
 string stCurrency = FileReadString(file);
 string stDescription = FileReadString(file);
 string stImportance = FileReadString(file);
 string stActual = FileReadString(file);
 string stForecast = FileReadString(file);
 string stPrevious = FileReadString(file);
 datetime Date = ToDate(stDate,stTime);
 color c=Green;
 if (stImportance=="Low") c = Yellow;
 if (stImportance=="Medium") c = Orange;
 if (stImportance=="High") c = Red;
 ObjectCreate("CalendarText"+i, OBJ_TEXT, 0, Date, Close[0]);
 ObjectSet("CalendarText"+i, OBJPROP_COLOR, c);  
 ObjectSetText("CalendarText"+i, stDate + " : "+ stDescription, 8);  
 ObjectSet("CalendarText"+i, OBJPROP_ANGLE, 90);  
 ObjectCreate("CalendarLine"+i, OBJ_VLINE, 0, Date, Close[0]);
 ObjectSet("CalendarLine"+i, OBJPROP_COLOR, c);  
 ObjectSet("CalendarLine"+i, OBJPROP_STYLE, STYLE_DOT);  
 ObjectSet("CalendarLine"+i, OBJPROP_BACK, true);  
 ObjectSetText("CalendarLine"+i, stDescription, 8);  
 i++;
 }
 Max = i;
 if (file!=-1)
 FileClose(file);
}

Основная процедура GrabNews() открывает уже скачанный файл \Html\Calendar. csv, считывает все параметры события и создает два объекта для каждой новости: вертикальную линию и текст. При этом календарь с событиями обновляется каждые 15 минут:

int start()
  {
   int    counted_bars=IndicatorCounted();
//----
   if (TimeCurrent()>LastTimeDownloading+15*60)
     {
       DeleteObjects();
       DownloadCalendar();
       LastTimeDownloading = TimeCurrent();
       
       int file=-1;
       while (file==-1)
         file = FileOpen("\Html\Calendar.csv",FILE_READ|FILE_CSV,',');
       FileClose(file);
 
       GrabNews();
     }
//----
   return(0);
  }

Выводы


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

P.S. Хочу отметить замеченную ошибку в работе календаря /go?link=https://www.dailyfx.com/calendar. Имейте ввиду, что иногда события из файла .csv с адреса http://www.dailyfx.com/calendar/Dailyfx_Global_Economic_Calendar.csv не совпадают со страничкой http://www.dailyfx.com/calendar/. Происходит это с новостями со временем выхода от 00:00 до 01:00 по GMT. В файле .csv эти новости указываются на 12 часов позже.

P.S.S. Так же хочу заметить, что индикатор пользуется внешними dll (kernell32.dll) поэтому необходимо во время запуска индикатора поставить соотеветствующую галочку в настройках.

Файл CalendarArticle.mq4 должен лежать в папке \experts\indicators. Time.mq4 - expers\library, Time.mqh - experts\include.