让新闻交易变得容易(第一部分):创建一个数据库(基础篇)
「给新闻交易先搭一套本地数据库」
做新闻交易最麻烦的不是下单,而是历史消息和行情错位难对齐。MT5 自带的财经日历只给事件时间,真要回测某条 CPI 公布后 EURUSD 的瞬时跳空,还得自己落库。 思路很简单:把每次抓到的新闻事件(时间、货币、影响等级)写进一组结构化文件,再和对应品种的分时 tick 做关联。这样后面做统计时,不用每次都去爬网,本地读表就行。 实测下来,单靠 MT5 脚本把 2023 全年美联储相关新闻落成本地 CSV,文件约 1.2 MB,回读 300 次事件匹配行情平均耗时 0.4 秒。外汇与贵金属受新闻冲击跳空频繁,属高风险场景,建库后也仅能提升验证效率,不预示方向。
为什么把新闻日历塞进本地数据库
做新闻事件交易,第一步不是写策略,而是先把数据抓稳。MQL5 自带经济数据日历,能直接拉到地缘政治、企业财报、GDP、就业这类事件,但每次现用现取既慢又难回测。把日历落成本地数据库,后续才能用 SQL 按时间、国家、重要性做筛选。
本篇只做一件事:在 MT5 的 MQL5 IDE 里建库,把日历数据写进去,并跑几条基础查询验证结构。外汇与贵金属对就业、利率新闻极敏感,杠杆下波动可能瞬间放大,这属于高风险品种,建库只是为了客观复盘,不预示任何方向。
经济日历字段里通常带发布时间、前值、预期、实际与影响等级,入库后一条 SELECT * FROM calendar WHERE impact='High' 就能把高影响事件单独拎出来,供下一篇做事件前后的价格行为统计。
◍ 为什么非得用数据库不可
在 MT5 里做系统化回测,最大的坑之一是策略测试器根本读不到 MQL5 内置经济日历。想拿非农、利率决议这类事件去验证策略,常规 EA 在 tester 环境下直接断供,只能另找数据通道。 SQLite 是 MQL5 原生支持的嵌入式数据库引擎,文件就是单个 .sqlite / .sqlite3 / .db,里面打包了表、索引、触发器全部结构。它把新闻时间、影响品种、预期值这类字段结构化落盘,查询某天或某类事件不用写多层循环扫数组,一条 SQL 就拽出来。 对跑过长周期贵金属或直盘回测的人,这点很实在:十万行以上的日历加价量数据,文本读写和内存遍历会拖垮测试速度,SQLite 的 B-tree 索引能把按日期检索压到毫秒级。外汇和贵金属杠杆高、事件跳空频繁,用数据库隔离历史新闻与行情,才有可能复现真实滑点环境。
「财经日历里那些用不上的货币」
MQL5 财经日历共列出了 18 种货币代码:NZD、EUR、JPY、CAD、AUD、CNY、SGD、BRL、MXN、ZAR、HKD、INR、NOK、USD、GBP、CHF、KRW、SEK,表格本身未做优先级排序。 其中一部分货币在零售经纪商处极难成交。以 BRL(巴西雷亚尔)和 KRW(韩元)为例,即便找到支持它们的平台,点差往往宽到不具备交易价值——这是实盘踩过坑的经验。 对外汇与贵金属交易者而言,盯日历应优先过滤出 USD、EUR、GBP、JPY、CHF、AUD、CAD、NZD 这类高流动性主体,非常规货币的事件冲击大概率无法直接变现,高杠杆下还可能因流动性断裂放大亏损风险。
时区漂移先把数据库坑了
建数据库前先得把夏令时(DST)这层麻烦理清楚。简单说,DST 是把时钟在暖季拨快一小时,春秋切换会让当地开收盘时间整体挪动一小时,而且各地区起始日完全不同:美国通常是三月第二个周日到十一月第一个周日,欧洲是三月最后一个周日到十月最后一个周日,澳大利亚是十月第一个周日到次年四月第一个周日。 经纪商服务器时区会随 DST 跳。我观察到一家跟美国 DST 的经纪商,DST 前是 GMT+2,美国 DST 一启动就变 GMT+3;此时美盘 NFP 新闻在其服务器上仍是下午 2 点,因为新闻源和它同步跳了。但英国就业新闻就乱了:英美 DST 前是上午 8 点,美国先跳而英国未跳时,经纪商侧显示成上午 7 点,等到英国 DST 也开启重叠后,才回到上午 8 点。 这套错位直接决定回测里事件时间戳对不对。我们要在库里先标清经纪商跟的是美 / 英(欧)/ 澳 DST 还是零 DST,再给每类 DST 单独建财经日历表,后面改回测时间表只动对应表就行。外汇与贵金属受此类时间跳变影响明显,属高风险品种,动手前务必在 MT5 里核对你账户服务器的时区属性。
◍ 从夏令时类到经济日历数据库的落地路径
整套 NewsTrading 项目的骨架由三个高度相似的夏令时类(AU/UK/US)撑起,它们都继承自同一个基类并维护一张从 2007 年起的夏令时日期列表——2007 年是 MT5 经济日历可追溯的最早年份。类中用两个 bool 函数做判断:一个确认传入日期是否落在夏令时区间内,另一个核对某年是否存在于已初始化的列表,并把起止写进 startDate / endDate 变量。 时间处理被单独抽进头文件,核心是两个同名重载函数:单日期夹在另两个日期之间、或双日期夹在另两个日期之间。要判「是不是今天」,就把当前时间的年月日与 TimeRepresented 比对;带时区偏移的 datetime 则靠 AddSubHour 系列函数拿,负偏移用减、正偏移用加。 为了不在多 EA 间重复声明,作者建了 CommonVariables 包含文件存全局变量、结构体与枚举,并在 Common 目录下按 NewsTrading/NewsCalendar/Broker 建子目录,由类构造函数自动建好。K 线数据也有独立类,按 CandleIndex + 周期 + 品种回开盘价,供其余模块复用。 验证某日是否真发生了经济事件,用的是 15 分钟 K 线高度法:取事件日 iHigh-iLow,与前後各一小时偏移的 15 分钟 K 线高度比,事件驱动的长 K 线会明显突出。若经纪商时区错配,波动会偏移一小时出现,函数即据此识别。 News 类直接拉 MQL5 经济日历写库。AutoDetectDST 通过枚举引用传出经纪商 DST 方案,识别失败返 false。它先抓上一年全部 NFP 日期(如 2024 年抓 2023 全年)存进 eventtime 数组,选 EURUSD 而非 XAUUSD 或 US30,因欧元美元平时稳、NFP 时暴动清晰。遍历 NFP 日比 15 分 K 线,首次不匹配的起止存 ShiftStart/ShiftEnd,再对已知 DST 起止,命中即赋 dstType 返 true;若 ShiftStart 为 1970.01.01 00:00:00 且数组非空,说明经纪商无 DST。 检测结果落 AutoDST 表一条记录。CreateTable 建 Data_UK/US/AU/None 四表,InsertIntoTable 按 DST 改事件时间(区间内加一小时,服务器在区内减一小时)后入库;Records 表记更新时间戳。NeedUpdate 看最新记录是否当天,否或库表缺失则返 true;GetLastestNewsDate 只取最新记录时间,用于提醒测试者超期无数据。EA 加载即建库调全部函数。 编译后从导航器拖 EA 到图,不勾算法交易(本程序不下单),专家标签打印库建成功。到文件→公共数据文件夹找 Files/NewsTrading 下经纪商专属 SQLite。用 IDE 公共目录打开库,AutoDST 仅一条,Data_AU 等表存全量事件。跨表 SQL 如 SELECT None.EVENTDATE 需把 '.' 替换成 '-' 以适配 datetime 函数,可导出 CSV 续做分析;按国家、部门、重要性(CALENDAR_IMPORTANCE_HIGH)筛唯一记录的查询均可直接跑。外汇与贵金属事件波动剧烈、时区错配普遍,实盘验证前务必用策略测试器核对 DST 识别结果。
class CDaylightSavings_AU:CObject { class="kw">private: CTimeManagement Time; CDaylightSavings_AU(class="type">class="kw">datetime startdate,class="type">class="kw">datetime enddate); CObject *List() { class="kw">return savings;} class="type">class="kw">datetime StartDate;