MQL5 简介(第 4 部分):掌握结构、类和时间函数·进阶篇
◍ MQL5 里怎么让策略认时间
做算法交易,时间不是墙上挂钟,而是服务器、本地、GMT 三套轴在同时转。MT5 的策略若要在特定时段开关仓位、切换逻辑,第一步就是能准确拿到这几套时间并互相换算,否则回测和实盘会对不上。 datetime 是 MQL5 承载日期时间的基础类型,本质是一个记录到秒的时间戳。声明时可用 D'YYYY.MM.DD HH:MI:SS' 字面量直接赋值,例如 D'2024.01.15 12:30:00' 就把一个具体时刻钉进了变量。下面这段演示了声明、赋值与打印的最小闭环: [CODE]datetime magicalClock; magicalClock = D'2024.01.15 12:30:00'; Comment(magicalClock);[/CODE] 执行后图表左上角会显示 2024.01.15 12:30:00,确认变量确实抓住了那个时刻。 真正跑策略时靠的是几个核心函数。TimeCurrent() 返回券商服务器当前时间,是多数时段判断的基准;TimeLocal() 返回你电脑系统时钟的本地时间;TimeGMT() 返回经过夏令时调整的格林威治标准时间;TimeGMTOffset() 则直接给出 GMT 与本地时间的秒级差。它们的关系可以一句话点破:TimeGMTOffset 的值就等于 TimeGMT() 减去 TimeLocal() 的秒差。 用 TimeCurrent() 对齐预定义时刻是很常见的写法,比如下面这段: [CODE]datetime magicalClock; magicalClock = D'2024.01.15 12:30:00'; if (TimeCurrent() == magicalClock) Print("The magic moment has arrived!"); else Print("Not yet the magic time...");[/CODE] 实际中服务器时间很难毫秒不差地撞上常量,所以生产代码通常用区间判断而非等号。 拿到 GMT 偏移也只需几行,注意它返回的是秒,要除以 60 才直观: [CODE]int gmtOffsetSeconds, gmtOffsetMinutes; gmtOffsetSeconds = TimeGMTOffset(); gmtOffsetMinutes = gmtOffsetSeconds / 60; Print("Current GMT Offset (in minutes): ", gmtOffsetMinutes);[/CODE] 外汇与贵金属属高杠杆品种,时段切换错误可能让EA在流动性稀薄时误下单,用这几个函数前先在脚本里把三套时间打印出来比对,确认终端时区设置符合预期再接策略。
class="type">class="kw">datetime magicalClock; magicalClock = D&class="macro">#x27;class="num">2024.01.class="num">15 class="num">12:class="num">30:class="num">00&class="macro">#x27;; Comment(magicalClock); class="type">class="kw">datetime magicalClock; magicalClock = D&class="macro">#x27;class="num">2024.01.class="num">15 class="num">12:class="num">30:class="num">00&class="macro">#x27;; if (TimeCurrent() == magicalClock) Print("The magic moment has arrived!"); else Print("Not yet the magic time..."); class="type">int gmtOffsetSeconds, gmtOffsetMinutes; gmtOffsetSeconds = TimeGMTOffset(); gmtOffsetMinutes = gmtOffsetSeconds / class="num">60; Print("Current GMT Offset(in minutes): ", gmtOffsetMinutes);
「把秒数拆成可读时间的 TimeToStruct」
MQL5 里的 TimeToStruct() 负责把 datetime 时间戳(自 1970-01-01 起的秒数)填进 MqlDateTime 结构,年、月、日、时、分、秒、星期、年内第几天都成了独立成员,后面取数不用自己算偏移。 举个具体数:100000 秒经过 TimeToStruct 分解后大约是 27 小时 46 分 40 秒,对应 1970 年以来的第 1 天多。实盘里你拿 TimeCurrent() 喂进去,就能直接读 myTime.year、myTime.hour 做时段过滤,比如只在伦敦时段(hour 在 8~16)触发信号。 下面这段是原文里几个时间相关函数的可直接编译的演示,建议开 MT5 新建脚本逐段跑一遍看输出:TimeCurrent 取本地经纪商时间,TimeGMT 取格林威治时间,TimeGMTOffset 返回秒级偏移(除以 60 即分钟,例如 -60 表示本地比 GMT 早 60 分),TimeToStruct 做结构拆解。外汇与贵金属杠杆高,时区错配可能导致回测与实盘K线对齐偏差,验证前先确认终端时区设置。 别把正态当圣经:MqlDateTime 的 hour 成员按 TimeCurrent 的经纪商服务器时间走,不是你电脑本地时间,跨时区跟单时务必用 TimeGMT 统一基准。
<b><span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="comment">class=class="str">"cmt">// Declaration of class="type">class="kw">datetime variable</span> <span class="keyword">class="type">class="kw">datetime</span> magicalClock; <span class="comment">class=class="str">"cmt">// Assigning a special date and time to our magical clock</span> magicalClock = <span class="class="type">class="kw">string">D&class="macro">#x27;class="num">2024.01.class="num">15 class="num">12:class="num">30:class="num">00&class="macro">#x27;</span>; <span class="comment">class=class="str">"cmt">// Let&class="macro">#x27;s tell the computer to show us the date and time inside our</span> <span class="functions">Comment</span>(magicalClock); }</b> <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="comment">class=class="str">"cmt">// Ask the magical clock for the current time</span> <span class="keyword">class="type">class="kw">datetime</span> currentTime = <span class="functions">TimeCurrent</span>(); <span class="comment">class=class="str">"cmt">// Display the current time on the console</span> <span class="functions">Print</span>(<span class="class="type">class="kw">string">"The magical clock says it&class="macro">#x27;s now: "</span>, currentTime); } <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="comment">class=class="str">"cmt">// Declaration of class="type">class="kw">datetime variable</span> <span class="keyword">class="type">class="kw">datetime</span> magicalClock; <span class="comment">class=class="str">"cmt">// Assigning a special date and time to our magical clock</span> magicalClock = <span class="class="type">class="kw">string">D&class="macro">#x27;class="num">2024.01.class="num">15 class="num">12:class="num">30:class="num">00&class="macro">#x27;</span>; <span class="comment">class=class="str">"cmt">// Check if TimeCurrent is equal to our magical clock</span> <span class="keyword">if</span>(<span class="functions">TimeCurrent</span>() == magicalClock) { <span class="functions">Print</span>(<span class="class="type">class="kw">string">"The magic moment has arrived!"</span>); } <span class="keyword">else</span> { <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Not yet the magic time..."</span>); } } <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="comment">class=class="str">"cmt">// Declaration of a variable to store GMT time</span> <span class="keyword">class="type">class="kw">datetime</span> gmtTime; <span class="comment">class=class="str">"cmt">// Assigning the current GMT time to the variable</span> gmtTime = <span class="functions">TimeGMT</span>(); <span class="comment">class=class="str">"cmt">// Printing the GMT time</span> <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Current GMT Time: "</span>, <span class="functions">TimeToString</span>(gmtTime)); } <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="comment">class=class="str">"cmt">// Declaration of a variable to store local time</span> <span class="keyword">class="type">class="kw">datetime</span> localTime; <span class="comment">class=class="str">"cmt">// Assigning the current local time to the variable</span> localTime = <span class="functions">TimeLocal</span>(); <span class="comment">class=class="str">"cmt">// Printing the local time</span> <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Current Local Time: "</span>, <span class="functions">TimeToString</span>(localTime)); } <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="comment">class=class="str">"cmt">// Declaration of variables</span> <span class="keyword">class="type">int</span> gmtOffsetSeconds, gmtOffsetMinutes; <span class="comment">class=class="str">"cmt">// Assigning the current GMT offset to the variable in seconds</span> gmtOffsetSeconds = <span class="functions">TimeGMTOffset</span>(); <span class="comment">class=class="str">"cmt">// Converting seconds to minutes</span> gmtOffsetMinutes = gmtOffsetSeconds / <span class="number">class="num">60</span>; <span class="comment">class=class="str">"cmt">// Printing the GMT offset in minutes</span> <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Current GMT Offset(in minutes): "</span>, gmtOffsetMinutes); } <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="comment">class=class="str">"cmt">// Declare an class="type">MqlDateTime variable</span> <span class="predefines">class="type">MqlDateTime</span> myTime; <span class="comment">class=class="str">"cmt">// Convert the current timestamp to a structured format</span> <span class="functions">TimeToStruct</span>(<span class="functions">TimeCurrent</span>(), myTime); <span class="comment">class=class="str">"cmt">// Access individual components of the structured time</span>
把秒数拆成可读的年月日时分秒
MT5 里时间底层存的是从 1970-01-01 00:00 起算的秒数,直接看数字没有交易意义。用 TimeToStruct 可以把一个整数秒数转成 MqlDateTime 结构,逐字段读出年、月、日、时、分、秒。 下面这段脚本把 100000 秒喂给 TimeToStruct,转换后打印各字段。100000 秒约等于 27.7 小时,所以 day 会落在 1 附近、hour 在 3 附近(受每月天数与起始偏移影响,实际以终端输出为准)。在 MT5 按 F4 建个脚本跑一遍,你能在专家日志里直接看到分解结果。 别把正态当圣经:MqlDateTime 的 mon 字段是 1–12,不是 0 起始;写条件判断时若按数组习惯从 0 算,会漏掉一月或越界。
Print("Current Year: ", myTime.year); Print("Current Month: ", myTime.mon); Print("Current Day: ", myTime.day); Print("Current Hour: ", myTime.hour); Print("Current Minute: ", myTime.min); Print("Current Second: ", myTime.sec); } class="type">void OnStart() { class=class="str">"cmt">// Declare an class="type">MqlDateTime variable class="type">MqlDateTime myTime; class=class="str">"cmt">// Convert the number of seconds into a structured format TimeToStruct(class="num">100000, myTime); class=class="str">"cmt">// Now, myTime will tell us the breakdown since class="num">1970 Print("Years: ", myTime.year); Print("Months: ", myTime.mon); Print("Days: ", myTime.day); Print("Hours: ", myTime.hour); Print("Minutes: ", myTime.min); Print("Seconds: ", myTime.sec); }
◍ 把工具请下神坛
走到这一节,结构、类和时间这三块基础已经铺开,但别把它们当成能自动印钱的机器。MQL5 只是把你的交易逻辑翻译成 MT5 能跑的指令,写错一行 datetime 比较就可能让订单在错误时点触发,外汇和贵金属的高杠杆会把这个错误放大成实打实的亏损。 下次打开 MT5 按 F4 写段结构体存 K 线时间,再拿 Class 封装一个判断时区的方法,跑回测看是否和你想的一致。工具用熟了,它只是你桌上的一把扳手,不是神龛里的东西。