MT4外部日历指标实战教程
用GetRight与MQL4绘制财经事件竖线
为什么需要在MT4图表显示财经日历
对于手动或半自动交易的交易者来说,重大经济数据发布往往带来瞬时波动与滑点风险。MT4默认不提供内置的新闻日历图层,若每次都切换到网页查看,既打断看盘节奏,也容易错过精确的时间节点。将外部财经事件以竖线形式直接绘制在价格图上,可以让交易者一眼看到过去与未来事件的位置、重要性颜色与标题,从而提前规划仓位或规避数据行情。本文基于Slobodov Gleb在MQL5社区发布的示例,讲解一种轻量、可离线运行的实现思路,适合有一定MQL4基础、希望扩展终端能力的用户。
该方案的核心价值在于“自动化”与“本地化”:指标启动后无需用户干预,自行调用下载器获取当前周CSV,再解析并画图。相比直接嵌入HTML解析,CSV格式规整、字段清晰,大幅降低编码复杂度。需要注意的是,原文针对MT4与MQL4,且依赖外部程序GetRight与系统DLL,因此属于进阶实操,不建议纯新手直接上生产环境。
方案总体设计与外部资源选择
指标的运行逻辑分为三步:第一,从固定网址拉取本周全球财经日历CSV;第二,解析CSV中的日期、时间、货币、描述与重要性;第三,在图表上为每个事件创建竖线对象与旋转90度的文本对象。选择http://www.dailyfx.com/calendar/作为源,是因为它提供Direct CSV链接,避免了解析网页DOM的麻烦。原文使用的链接为Dailyfx_Global_Economic_Calendar.csv,文件默认包含周一到周日事件。
- 指标独立下载本周日历文件,无需手动另存
- 以竖行+标题显示所有事件,包含已发生与未发生
- 从外部资源追踪更新,每15分钟重绘一次
- 依赖GetRight下载器与kernel32.dll的WinExec
GetRight下载器的配置与原理
由于MQL4早期版本没有直接HTTP下载函数(MT4 build 600后才逐步完善),原文借助第三方工具GetRight实现文件获取。GetRight是一款Windows下的下载管理器,可通过命令行调用。我们需要把它安装后,设置默认保存目录为终端的\files\html\,这样指标用相对路径就能打开Calendar.csv。启动方式是在MQL4中用#import导入kernel32.dll的WinExec,以隐藏窗口模式运行getright.exe,并附加参数:/URL指定源、/FILE指定保存名、/W表示等待完成、/O表示覆盖同名文件。
这种设计的巧妙之处在于把“网络不可靠”的部分交给专用软件,指标代码只关心本地文件。但也引入两个外部依赖:一是GetRight必须存在且路径正确;二是调用了系统DLL,终端需允许DLL导入。在现代Windows与MT4版本中,GetRight已显陈旧,读者可理解为“下载代理”的角色,用curl或PowerShell替代亦可,只要保证生成相同的CSV即可。
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);
void DownloadCalendar()
{
Print("Downloading "+HtmlAdress+" to experts\files\html\Calendar.csv");
WinExec(GetrightAdress+" /URL:"+HtmlAdress+" /FILE:Calendar.csv /W /O",0);
}
时间解析:从CSV字符串到MT4时间轴
CSV中的日期是“Mon/Tue...”缩写加时间字符串(可能带AM/PM),并不直接是MT4的datetime。原文提供了两个辅助函数:PerviousMonday返回本周一0点GMT;ToDate先根据星期缩写推算偏移天数,再结合GMT偏移把时间映射到正确datetime。这里依赖Time.mqh中的GetTimeGMT与GetShiftGMT,用于处理经纪商时区与GMT的差异。如果忽略时区,事件竖线会偏离实际发布时间数小时,导致策略误判。
具体实现中,ToDate先用PerviousMonday(GetTimeGMT())得到周一,加WeekPlus天,再用StrToTime取时分秒,最后减GetShiftGMT()把GMT转成终端本地时间。若字符串含PM则加12小时。这种手工解析虽繁琐,但在老MQL4环境稳定。现代改写建议使用MqlDateTime结构与StringToTime,可读性更高。
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);
}
解析CSV并绘制图形对象
GrabNews函数是核心。它用FileOpen以CSV逗号分隔读取\Html\Calendar.csv,逐行读入日期、时间、时区、货币、描述、重要性、实际、预测、前值九个字段。然后根据重要性赋颜色:Low黄、Medium橙、High红,默认绿。每个事件创建两类对象:OBJ_VLINE竖线置于背景,OBJ_TEXT文本旋转90度显示“日期:描述”。对象名加序号避免冲突。这种画法让事件像时间轴上的标签,不遮挡K线。
需要注意的是,原文用Close[0]作为纵坐标,意味着文本和竖线锚定在最新收盘价,随着行情变动对象会上下浮动,但横轴时间不变。若希望固定在某价格,可改为固定值。对象角度OBJPROP_ANGLE设为90实现竖排文字,是MT4图形对象的一个实用技巧。删除旧对象通过DeleteObjects在更新前调用,防止堆积。
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);
}
指标主循环与定时更新机制
start函数里用IndicatorCounted忽略已计算柱,重点在定时逻辑:当TimeCurrent超过上次下载时间15分钟,就删除旧对象、调用DownloadCalendar、等待文件出现后GrabNews。这里用while循环阻塞直到FileOpen成功,确保下载完毕。15分钟间隔平衡了及时性与资源占用,若经纪商日历更新频繁可缩短,但过短会触发源站封禁。
该结构展示了老式指标“轮询+重绘”的范式。现代MT4/MT5可用EventSetTimer替代,但原理相通:外部数据有延迟,必须主动刷新。另外,指标未做品种过滤,所有事件都画在当前图,若交易单一货币对,可加Currency过滤减少噪音。
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);
}
文件部署与DLL启用步骤
按原文,CalendarArticle.mq4放入\experts\indicators;Time.mq4放\experts\library;Time.mqh放\experts\include。GetRight安装后,在MT4菜单工具-选项-Expert Advisors中勾选“允许DLL导入”,否则WinExec无法调用。若提示路径错误,检查GetrightAdress短路径(如progra~1)是否匹配系统。指标加载到图表后,每15分钟自动拉取并画图。
- 编译前确认Time.mqh被include且路径正确
- 指标属性中允许导入DLL
- GetRight设置保存目录为终端files\html
- 首次运行观察日志是否打印Downloading与对象创建
已知缺陷与数据一致性坑
原文附言指出两个坑:一是DailyFX页面与CSV偶尔不一致,尤其GMT 00:00-01:00发布的新闻在CSV中延迟12小时显示;二是指标用外部DLL,必须手动启用相应设置。此外,社区评论有用户反映原地址已不能下载,说明第三方源的稳定性是最大风险。还有,Close[0]锚定会让文字随价格漂,若缩放图表可能重叠。最后,该指标未处理网络失败重试,若GetRight报错,FileOpen可能读空文件导致不画任何线。
对比现代方案:MT5内置经济日历符号、多数第三方指标用WebRequest+JSON,更健壮。但本文价值在于展示“终端+外部程序+图形对象”的集成思路,对理解MQL4文件、对象、时间系统仍有教学意义。若你要产品化,必须解决源失效与DLL信任问题,否则无法通过市场审核。