通过有用的技术组合让您的 MQL5 客户惊叹!·进阶篇
用网页 GUI 给客户攒新闻 CSV
给 MT5 用户交付新闻监控方案时,与其让他们手填日历,不如直接做一个浏览器端 Web GUI 来生成 CSV。整套前端代码放在 news-watcher-csv.html 里,配合 EA 一起发给客户,他们打开页面选时间、填描述,点一下就能拿到标准格式的文件。 加载层走的是 Google Hosted Libraries 的 CDN:JQuery 1.10.2 和 JQuery UI 1.10.3 直接从谷歌服务器拉,浏览器首个 HTTP 请求就搞定,本地不用存库。但 timepicker 这个第三方时间选择组件谷歌没托管,只能把 jquery.timepicker.css 和 jquery.timepicker.min.js 放本地引用——客户看到多余文件会觉得烦,更优解是传到一个公共服务器再指向它,文件越少越好。 GUI 里实际用到的 JQuery 控件就四个:datepicker 选日期、timepicker 选时间(灵感来自谷歌日历)、sortable 拖拽排新闻顺序、dialog 弹窗显示内容。dialog 易用性纯粹主义者不喜欢,神经运动障碍用户操作费劲,但特定场景仍能用,后续可改成不打扰的呈现方式留作练习。 主程序逻辑极短:先修 YouTube iframe 的 zIndex 验证问题,再初始化上述控件,最后给「添加新闻」按钮和「生成 CSV」链接绑行为。下面这段是头文件加载与核心 jQuery 片段的原文,逐行拆完你就能在本地复现。 头文件里前两行 link 引谷歌的 jquery-ui.css 和本地 timepicker.css;三个 script 分别引谷歌 jquery.min.js、jquery-ui.min.js 和本地 timepicker.min.js。JS 部分 $(function(){}) 是就绪事件;iframe 循环加 ?wmode=transparent 修透明层;#datepicker 格式 yy.m.dd、#timepicker 格式 H:i:s;#sortable 启用排序并禁文本选中;#news-calendar 先隐藏;#add-new 点击后淡入日历并向 #sortable 追加一条 li,拼接基础货币、日期、时间、描述用分号隔开;#get-csv 点击后预设表头 Country;Time;Event\n。外汇与贵金属消息面波动剧烈,此类 CSV 仅辅助复盘,实盘仍属高风险。
<span class="tag"><<span class="keyword">link</span><span class="attribute"> rel=<span class="value">"stylesheet"</span></span><span class="attribute"> href=<span class="value">"http:class=class="str">"cmt">//ajax.googleapis.com/ajax/libs/jqueryui/class="num">1.10.class="num">3/themes/smoothness/jquery-ui.css"</span></span> /></span> <span class="tag"><<span class="keyword">link</span><span class="attribute"> rel=<span class="value">"stylesheet"</span></span><span class="attribute"> href=<span class="value">"jquery.timepicker.css"</span></span> /></span> <span class="tag"><<span class="keyword">script</span><span class="attribute"> src=<span class="value">"http:class=class="str">"cmt">//ajax.googleapis.com/ajax/libs/jquery/class="num">1.10.class="num">2/jquery.min.js"</span></span>></span><span></span><span class="tag"></<span class="keyword">script</span>></span> <span class="tag"><<span class="keyword">script</span><span class="attribute"> src=<span class="value">"http:class=class="str">"cmt">//ajax.googleapis.com/ajax/libs/jqueryui/class="num">1.10.class="num">3/jquery-ui.min.js"</span></span>></span><span></span><span class="tag"></<span class="keyword">script</span>></span> <span class="tag"><<span class="keyword">script</span><span class="attribute"> src=<span class="value">"jquery.timepicker.min.js"</span></span>></span><span></span><span class="tag"></<span class="keyword">script</span>></span> $(function() { class=class="str">"cmt">// fix YouTube&class="macro">#x27;s zIndex iframes issue $(<span class="class="type">class="kw">string">&class="macro">#x27;iframe&class="macro">#x27;</span>).each(function(){ var url = $(<span class="keyword">this</span>).attr(<span class="class="type">class="kw">string">"src"</span>); $(<span class="keyword">this</span>).attr(<span class="class="type">class="kw">string">"src"</span>,url+<span class="class="type">class="kw">string">"?wmode=transparent"</span>); }); class=class="str">"cmt">// Init GUI elements $(<span class="class="type">class="kw">string">"class="macro">#datepicker"</span>).datepicker({ <span class="class="type">class="kw">string">&class="macro">#x27;dateFormat&class="macro">#x27;</span>: <span class="class="type">class="kw">string">&class="macro">#x27;yy.m.dd&class="macro">#x27;</span> }); $(<span class="class="type">class="kw">string">"class="macro">#timepicker"</span>).timepicker({ <span class="class="type">class="kw">string">&class="macro">#x27;timeFormat&class="macro">#x27;</span>: <span class="class="type">class="kw">string">&class="macro">#x27;H:i:s&class="macro">#x27;</span> }); $(<span class="class="type">class="kw">string">"class="macro">#sortable"</span>).sortable().disableSelection(); $(<span class="class="type">class="kw">string">"class="macro">#news-calendar"</span>).hide(); class=class="str">"cmt">// Buttons behavior $(<span class="class="type">class="kw">string">"class="macro">#add-new"</span>).click(function() { $(<span class="class="type">class="kw">string">"class="macro">#news-calendar"</span>).fadeIn(<span class="class="type">class="kw">string">"class="num">500"</span>); $(<span class="class="type">class="kw">string">"class="macro">#sortable"</span>).append(<span class="class="type">class="kw">string">&class="macro">#x27;<li class="ui-state-class="kw">default"><span class="ui-icon ui-icon-arrowthick-class="num">2-n-s"></span>&class="macro">#x27;</span> + $(<span class="class="type">class="kw">string">&class="macro">#x27;class="macro">#base-currency&class="macro">#x27;</span>).val() + <span class="class="type">class="kw">string">&class="macro">#x27; ;&class="macro">#x27;</span> + $(<span class="class="type">class="kw">string">&class="macro">#x27;class="macro">#datepicker&class="macro">#x27;</span>).val() + <span class="class="type">class="kw">string">&class="macro">#x27; ;&class="macro">#x27;</span> + $(<span class="class="type">class="kw">string">&class="macro">#x27;class="macro">#timepicker&class="macro">#x27;</span>).val() + <span class="class="type">class="kw">string">&class="macro">#x27; ;&class="macro">#x27;</span> + $(<span class="class="type">class="kw">string">&class="macro">#x27;class="macro">#description&class="macro">#x27;</span>).val() + <span class="class="type">class="kw">string">&class="macro">#x27;</li>&class="macro">#x27;</span>); }); $(<span class="class="type">class="kw">string">"class="macro">#get-csv"</span>).click(function() { var csv = <span class="class="type">class="kw">string">"Country;Time;Event\n"</span>;
◍ 把新闻列表导出成 CSV 的弹窗逻辑
这段 jQuery 脚本干的事很直接:遍历页面里 #sortable li 的每个列表项,把文字拼进 csv 变量并用换行符隔开,最终形成一份纯文本日历。
随后清空 #dialog 并弹出一个模态框,宽度锁死在 650 像素,出现用 blind 特效、关闭用 explode 特效,两者时长都是 400 毫秒——这种设定在 MT5 配套的网页小工具里很常见,目的是让交易者点一下就能看到整理好的新闻清单。
弹窗内容会把 csv 里的
全部替换成 <br/> 再追加显示,只留一个 Ok 按钮关闭对话框。整套交互不涉及任何行情判断,纯粹是给 NewsWatcher EA 喂数据的预处理环节,外汇与贵金属新闻驱动行情波动大,用这类工具降低手动抄写出错概率比较务实。
$("class="macro">#sortable li").each(function(){
csv += $(this).text() + "\n";
});
$("class="macro">#dialog").empty().dialog({
modal: true,
width: class="num">650,
show: {
effect: "blind",
duration: class="num">400
},
hide: {
effect: "explode",
duration: class="num">400
},
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
}).append(csv.replace(/\n/g, &class="macro">#x27;<br/>&class="macro">#x27;));
class="kw">return false;
});
});「新闻事件录入界面的 DOM 结构」
给 MT5 用的新闻监控工具,前端其实就一个静态 HTML 片段:用 select 下拉框限定品种(原文示例含 NZD、USD 两个 option),再配 datepicker、timepicker、description 三个文本输入,最后靠 id="add-new" 的按钮把一条事件塞进列表。 这堆标签最终被包在 id="csv-generator" 的 div 里;点完「+ Add new」之后,新闻条目会写进 id="sortable" 的 ul 里,页面右侧 id="news-calendar" 区域提供「Get CSV」链接导出。 导出路径被硬编码在 dialog 的 title 里:data_folder\MQL5\FILES\news_watcher.csv。也就是说你本地 MT5 的 MQL5\Files 目录下必须存在这个 csv,EA 或脚本才可能读得到——外汇和贵金属事件驱动策略本身高风险,文件路径不对 EA 就会静默失效。 CSS 部分只做了极简 reset(* 选择器 margin/padding 归零)和 body 的 Arial 字体声明,没有参与任何逻辑,纯为渲染干净。
<div id="csv-generator"> <div class="form-field"> <label>Symbol:</label> <select id="symbol"> <option>NZD</option> <option>USD</option> </select> </div> <div class="form-field"> <label>Date:</label> <input type="text" id="datepicker"/> </div> <div class="form-field"> <label>Time:</label> <input type="text" id="timepicker"/> </div> <div class="form-field"> <label>Description:</label> <input id="description" type="text"/> </div> <div id="add-new-button" class="form-field"> <label></label> <button id="add-new">+ Add new</button> </div> </div> <div id="news-calendar"> <p><a id="get-csv" href="#">Get CSV</a></p> <ul id="sortable"></ul> </div> <div id="dialog" title="Please, copy and paste in data_folder\MQL5\FILES\news_watcher.csv"></div>
新闻日历面板的样式骨架
这段 CSS 决定了 MT5 网页端新闻日历组件的外观与布局逻辑,直接抄进自定义 HTML 面板就能复用。 整体容器 #csv-generator 占满 100% 宽度并做了跨浏览器渐变(#ffffff 到 #fafafa),#news-calendar 则留出上边距 2em、内边距 0 2em 2em 1em,用 1px 实线收边,视觉上把日历区和表单区切开。 表单区 #form 固定 65% 宽并右浮动,视频块 #video 占 30% 宽左浮动且带 3px 模糊的阴影;两者中间靠 1em 间距缓冲。标签 label 统一 150px 宽、右对齐,输入框按用途限宽:日期/时间框 100px,描述框 300px。 可排序列表 #sortable 去掉了默认项目符号,单行 li 留 0.4em 内边距与 1.5em 左缩进,拖动句柄靠绝对定位的 span 实现 -1.3em 偏移。想验证效果,把这段样式挂到本地 HTML 再用 jQuery UI 初始化 sortable 即可看到拖拽排版。
padding: 0em 2em
}
header { border-bottom: 1px solid class="macro">#cccccc }
footer { border-top: 1px solid class="macro">#cccccc; margin-top: 2em; padding-top: 1em }
h1, h2, h3, h4, h5, p { padding: 1em 0em }
label {
width: 150px;
display: class="kw">inline-block;
margin: 5px;
text-align: right
}
input { border: 1px solid class="macro">#cccccc }
button, option, input { padding: 4px }
select { padding: 3px }
class=class="str">"cmt">/* Custom ids */
class="macro">#csv-generator {
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=&class="macro">#x27;class="macro">#ffffff&class="macro">#x27;, endColorstr=&class="macro">#x27;class="macro">#fafafa&class="macro">#x27;);
background: -webkit-gradient(linear, left top, left bottom, from(class="macro">#ffffff), to(class="macro">#fafafa));
background: -moz-linear-gradient(top, class="macro">#ffffff, class="macro">#fafafa);
width: class="num">100%;
clear: both;
overflow: hidden
}
class="macro">#video {
width: class="num">30%;
class="type">float: left;
margin-right: 1em;
-moz-box-shadow: 0px 3px 5px #class="num">888;
-webkit-box-shadow: 0px 3px 5px #class="num">888;
box-shadow: 0px 3px 5px #class="num">888;
border:class="num">0
}
class="macro">#dialog { font-size: 12px }
class=class="str">"cmt">/* Form for adding the news */
class="macro">#form { width: class="num">65%; class="type">float: right }
inputclass="macro">#datepicker, inputclass="macro">#timepicker { width: 100px }
inputclass="macro">#description { width: 300px }
class="macro">#add-new-button { class="type">float: left; margin-right: 1em }
class=class="str">"cmt">/* Sortable */
class="macro">#news-calendar { clear: both; margin-top: 2em; padding: 0em 2em 2em 1em; background: class="macro">#fafafa; border: 1px solid class="macro">#cccccc }
class="macro">#sortable { list-style-type: none; margin: class="num">0; padding: 0em; width: auto; clear: both }
class="macro">#sortable li { margin: 3px; padding: class="num">0.4em; padding-left: class="num">1.5em; }
class="macro">#sortable li span { position: absolute; margin-left: -class="num">1.3em; }
aclass="macro">#get-csv {
background: url(&class="macro">#x27;http:class=class="str">"cmt">//icons.iconarchive.com/icons/deleket/soft-scraps/class="num">24/File-New-icon.png&class="macro">#x27;) no-repeat 0px 8px;
padding: 10px 58px 20px 30px;
}
class=class="str">"cmt">/* Custom classes */
.form-field { margin-bottom: class="num">0.5em }
class=class="str">"cmt">/* Overwrites */
.ui-dialog-title { font-size: 12px }◍ 把工具请下神坛
这套基于 HTML5、CSS 和 JQuery 的 Web 前端,本质只是给自动新闻 EA 喂 CSV 日历的壳:三个文件以 txt 发出,需手动重命名为 .html / .css / .js 才能跑,jQuery 2.0 已明确不支持 IE 6、7、8,老浏览器直接弃用。 代码经 W3C 标记验证、在 Chrome 与 Firefox 最新版测过,但别把它当跨平台银弹——ActiveX 一类微软交互技术能补 Windows 端能力,也可能成恶意程序入口,信任边界得自己划。 外汇和贵金属本身高风险,新闻波动常让技术位失效;工具再花哨也改不了杠杆和滑点的概率游戏,开 MT5 把重命名后的文件挂上 EA 验证一遍,比信任何「整合方案」都实在。