显示新日历

Slobodov Gleb | 16 三月, 2016

简介

本文包含对编写简单快捷的指标的描述,该指标用于在工作区域显示来自外部网络资源的重大经济事件。指标的运算如下:
下面是指标的要求列表:
  • 指标应该独立的(没有用户的帮助下)下载当前周的必要的事件日历文件。
  • 指标应该从该文件以带新闻标题的竖行形式显示所有的事件(过去的和未来的)。
  • 指标应从外部资源追踪事件的更新状态。


技术部分

让我们使用网站 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);

只有两个外部变量:外部资源的地址(实际上,你不必更改这个参数)和 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 参数表示:如果有同名的文件,将会被覆盖。记住:如果你已经正确更改了 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() 函数将日期和时间从日历格式转换为数据时间。

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);
  }


总结

本文解释了如何利用外部资源在工作区域以竖行的形式显示事件日历。指标的编写刻意忽略了多余的参数,比如根据事件相关性或者一致性和当前窗口交易品种过滤新闻的参数。

附言:我要指出日历运行中的一个错误 http://www.dailyfx.com/calendar/。请注意:来自 http://www.dailyfx.com/calendar/Dailyfx_Global_Economic_Calendar.csv 的 .csv 文件中的事件有时跟 http://www.dailyfx.com/calendar/ 页面不一致。这可能出现于 00:00 到 01:00 (GMT) 发布的新闻。在 .csv 文件中,这种新闻在 12 个小时以后显示。

另需注意的是,指标使用外部 dll (kernell32.dll),所以不要忘记在指标设置中启用相应的参数。

CalendarArticle.mq4 文件应该存放在 \experts\indicators 文件夹中。Time.mq4 应存放在 expers\library, Time.mqh - in experts\include。