从 ForexFactory.com 检索高影响事件并将其显示在您的指标或 Expert Advisor - MetaTrader 4 的 Expert 中

由于我目前正在开发原油和布伦特原油的 EA 交易,因此我想从 ForexFactory.com 获取“原油库存”报告的确切日期和时间。该报告通常于东部时间周三上午 10:30 发布,但遇节假日时,发布日期可能会发生变化。由于这是我的 EA 的重要报告,唯一的方法是检查在线服务以验证发布日期。
首先是添加 OPTIONS | EXPERT ADVISOR 选项卡将用于发出 WebRequest 的网站,即“http://www.forexfactory.com/”(见图 1)

接下来是在代码中定义一个结构来存储事件。它位于代码顶部的某个位置,该代码将“DailyEvents”声明为全局变量,并由“MaxDailyEvents”变量定义存储事件的最大数量。
// 定义事件结构 结构体活动 { 细绳 时间; 细绳 标题; 细绳 货币; 布尔值 显示; };#定义 最大每日事件 20 // 如果您认为您将有超过 20 个高影响事件,请增加此数字。事件 DailyEvents[MaxDailyEvents];
接下来我们需要从 ForexFactory.com 检索 HTML 代码并解析它。如果您不明白 HTML 代码,别担心,我会引导您完成它:)
我们首先需要构建 WebRequest 的 URL。由于我只想要他们当天的日历,而不是默认的(整周)日历,因此我们可以通过将请求的“day”参数设置为今天的日期并发送请求来实现此目的。
细绳 网址=“http://www.forexfactory.com/calendar.php?day=”; url += MthName(月()) +双转字符串(天(),0) +“。”+双转字符串(年(),0);
然后我们发送请求,检查错误代码(如果有)并将返回的字符数组转换为字符串。这使得解析 HTML 代码变得更加容易。
// 将字符数组转换为字符串HTML =字符数组转字符串(结果);现在我们有了一个字符串,我们可以使用“StringFind”函数来定位 HTML 元素。第一件事是确保返回的 HTML 确实是今天的日期,并删除此 HTML 标记之前的任何内容。函数“GetHTMLElement”用于解析 HTML 代码并返回指定 HTML 标记之间的值。请参阅下面的定义。
// 日历已加载,确保是今天的日期 整数我=字符串查找(HTML,"");如果(我==-1)返回(错误的); HTML =字符串子串(HTML,我);细绳日期 = GetHTMLElement(HTML,“<跨度>”,“”);如果(日期!= MthName(月()) +” “+双转字符串(天(),0))返回(错误的);“GetHTMLElement”函数的定义。
//+------------------------------------------------------------------+ //|提取 HTML 元素 //+------------------------------------------------------------------+ 细绳 获取HTML元素(细绳超文本标记语言,细绳元素开始,细绳元素结束) { 细绳 数据=无效的; // 查找元素的开始和结束位置 整数s =字符串查找(HTML、元素开始)+字符串长度(元素开始); 整数e =字符串查找(字符串子串(HTML, s), ElementEnd); // 返回元素内容 如果(e!=0) 数据 =字符串子串(HTML、s、e); 返回(数据); }好的,现在我们已经确保返回的日历是今天的日期,让我们开始解析每个表行并提取我们需要的元素。即活动时间、活动货币、活动影响和活动标题。我们需要对 HTML 代码中的每个表格行执行此操作,直到日历结束或到达 MaxDailyEvents。
提取每行的数据后,我们将其添加到 DailyEvents 结构中。
// 现在获取每个事件的表行上次 =无效的; cnrt =0; 日期=双转字符串(年(),0) +“。”+双转字符串(月(),0) +“。”+双转字符串(天(),0) +” “;做{ // 获取事件信息 时间 = GetHTMLElement(HTML,"",“ ”); 如果(字符串查找(时间,") ==0) 时间 = GetHTMLElement(时间,“类=\”下一个\“>”,“”); 如果(字符串长度(时间)!=0) 上次 = 时间; 如果(字符串长度(时间)==0) 时间 = 上次; 时间=日期+时间; 货币 = GetHTMLElement(HTML,"",“ ”); 影响 = GetHTMLElement(HTML,"<跨度标题=\"",“\”类=\“”); 我=字符串查找(影响,“ 影响”); 如果(我!= -1) 影响 =字符串子串(影响,0, 我); 标题 = GetHTMLElement(HTML,"\"日历__事件标题\">",“”); // 这是一个影响很大的事件吗? 如果(字符串查找(象征(), 货币) != -1&&影响==“高的”) { // 添加到每日事件结构 DailyEvents[cntr].displayed =错误的; DailyEvents[cntr].time = 时间; DailyEvents[cntr].title = 标题; DailyEvents[cntr++].currency = 货币; } // 将 HTML 字符串剪切到下一个表格行 我=字符串查找(HTML,“ ”); 如果(我!= -1) HTML =字符串子串(HTML、i+30); 如果(字符串查找(HTML,"") ==0) 我 = -1; }尽管(我!= -1|| cntr == MaxDailyEvents);一旦我们解析了所有表格行并到达日历末尾,我们就需要在图表上显示事件。如果事件发生在未来,我希望显示一条垂直线,如果发生在过去,则不显示任何线。
// 显示高影响事件(如果有)上次 =无效的;为了(cntr =0; cntr < 最大每日事件数; cntr++) { 如果(字符串长度(DailyEvents[cntr].time) ==0)休息; // 如果最后一个市场时间不同,则在图表上创建事件标记 如果(上次!= DailyEvents[cntr].time) { 资源 = cntr; // 如果字符串中有“pm”,则在时间上添加 12 小时 如果(字符串查找(每日事件[cntr].time,“下午”) != -1) DailyEvents[cntr].time =到达时间(时间到时间(每日事件[cntr].time) +43200); 如果(对象创建(0, 事件 + cntr,对象事件,0,时间到时间(每日事件[cntr].time),0)) { 对象集字符串(0, 事件 + cntr,OBJPROP_TEXT, DailyEvents[cntr].title +”(”+ DailyEvents[cntr].currency +“)”); 对象集整数(0, 事件 + cntr,OBJPROP_COLOR, 红色的); 对象集整数(0, 事件 + cntr,OBJPROP_WIDTH,2); 对象集整数(0, 事件 + cntr,OBJPROP_BACK,真的); 对象集整数(0, 事件 + cntr,OBJPROP_SELECTABLE,错误的); 对象集整数(0, 事件 + cntr,OBJPROP_SELECTED,错误的); 对象集整数(0, 事件 + cntr,OBJPROP_HIDDEN,真的); 对象集字符串(0, 事件 + cntr,OBJPROP_工具提示, DailyEvents[cntr].title +”(”+ DailyEvents[cntr].currency +“)”); } // 如果事件发生在未来,则创建垂直线 如果(时间当前() < TimeOffset(DailyEvents[cntr].time,0)) { 如果(对象创建(0, VLine + cntr,OBJ_VLINE,0, TimeOffset(DailyEvents[cntr].time,0),0)) { 对象集整数(0, VLine + cntr,OBJPROP_COLOR, 红色的); 对象集整数(0, VLine + cntr,OBJPROP_WIDTH,1); 对象集整数(0, VLine + cntr,OBJPROP_BACK,真的); 对象集整数(0, VLine + cntr,OBJPROP_SELECTABLE,错误的); 对象集整数(0, VLine + cntr,OBJPROP_SELECTED,错误的); 对象集整数(0, VLine + cntr,OBJPROP_HIDDEN,真的); 对象集字符串(0, VLine + cntr,OBJPROP_工具提示, DailyEvents[cntr].title +”(”+ DailyEvents[cntr].currency +“)”); } } 别的 DailyEvents[cntr].displayed =真的; } 别的 { 标题=对象获取字符串(0, 事件+资源,OBJPROP_工具提示); 标题+=“\n”+ DailyEvents[cntr].title +”(”+ DailyEvents[cntr].currency +“)”; 对象集字符串(0, 事件+资源,OBJPROP_工具提示, 标题); 如果(时间当前() < TimeOffset(DailyEvents[cntr].time,0))对象集字符串(0, VLine + res,OBJPROP_工具提示, 标题); } 最后时间 = DailyEvents[cntr].time; }如果是未来的事件,我想通知用户即将发生的事件(如果该事件在当前时间的 5 分钟内),并删除垂直线。这是通过在 EA 或指标的“start()”函数中添加一些代码来完成的。
//+------------------------------------------------------------------+ //|专家启动功能 | //+------------------------------------------------------------------+ 空白开始() { 细绳 事件=无效的; // 未来 5 分钟内是否有影响较大的事件? 为了(整数我=0; i < 最大每日事件数;我++) { 如果(字符串长度(每日事件[i].时间) ==0)休息; 如果(时间当前() >=时间到时间(DailyEvents[i].time) -300&&时间当前() <时间到时间(DailyEvents[i].time) && !DailyEvents[i].displayed) { // 5 分钟后的事件... 事件 += DailyEvents[i].title +”(”+ DailyEvents[i].currency +”),“; DailyEvents[i].displayed =真的; // 删除与事件关联的垂直线 如果(对象查找(“V线”+双转字符串(我,0)) >=0)对象删除(“V线”+双转字符串(我,0)); } } // 有什么要显示的吗? 如果(字符串长度(事件)!=0) { 事件+=“5分钟后。”; 警报(事件); } }最后,我们需要获取每日事件。这是通过在 OnInit() 函数中添加一行来完成的。
//+------------------------------------------------------------------+ //|专家初始化函数 | //+------------------------------------------------------------------+ 整数 初始化时() { // 获取今天的事件 获取HighImpactEvents(); 返回(初始化成功); }又好又简单。您当然可以修改代码以显示货币对的所有事件,或者向您的指标或 EA 添加输入参数以指定要显示的影响(高、中或低),当然还可以添加对午夜周转的检查以获取新的每日事件列表,但我会让您尝试一下:)
附件下载
📎 highimpactevents.mq4 (11 KB)
Source: MQL5 #15505
💡 精彩内容推荐
✍️ 楼主最新发布
- •
- •
- •
- •
- •
- •
🔗 您可能感兴趣
- •
- •
- •
- •
- •
- •
🔐请登录后参与评论注册满12小时后评论,即可解锁附件下载立即登录
