从基础到中级:定义(二)·综合运用
「用宏把时间戳拆成可读的时分秒」
MT5 里 datetime 本质是从 1970-01-01 起算的秒数,直接打印虽然能看,但要做成分段显示就得自己拆。下面这组宏把秒级时间戳按 86400、3600、60 的整数倍切开,分别拿到日期、小时、分钟和秒。
宏 macro_GetDate 用 A - (A % 86400) 直接抹掉当天秒数剩日期;macro_GetHour 先取 % 86400 去掉日期部分,再减 % 3600 去掉小时以下,除以 3600 得小时数。分钟和秒同理,macro_GetMin 里除以 60 把秒转成整分。
实际验证时,把 datetime dt = D'2024.08.15 12:30:27' 丢进 OnStart,配合 PrintX 宏打印,能看到 12 点 30 分 27 秒被准确拆出。外汇和贵金属行情里时间对齐很关键,这类拆解在跨时区回测时可能帮你少踩坑,但杠杆品种波动剧烈,高风险始终在。
别在递归里顺手调时间宏
斐波那契递归函数 Fibonacci_Recursive 自身不带时间逻辑,若你把它和 macro_GetHour 之类混用在同一个打印流,调用栈一深就难定位是哪一层输出了时间。建议时间拆解单独成块,递归只管数列。
class="macro">#define macro_GetDate(A) (A - (A % class="num">86400)) class="macro">#define macro_GetTime(A) (A % class="num">86400) class=class="str">"cmt">//+----------------+ class="macro">#define macro_GetSec(A) (A - (A - (A % class="num">60))) class="macro">#define macro_GetMin(A) (class="type">int)((A - (A - ((A % class="num">3600) - (A % class="num">60)))) / class="num">60) class="macro">#define macro_GetHour(A) (class="type">int)((A - (A - ((A % class="num">86400) - (A % class="num">3600)))) / class="num">3600) class=class="str">"cmt">//+----------------+ class="macro">#define PrintX(X) Print(class="macro">#X, " => ", X); class="type">uint Fibonacci_Recursive(class="type">uint arg = class="num">1) { if (arg <= class="num">1) class="kw">return arg; class="kw">return Fibonacci_Recursive(arg - class="num">1) + Fibonacci_Recursive(arg - class="num">2); } class="type">void OnStart(class="type">void) { class="type">class="kw">datetime dt = D&class="macro">#x27;class="num">2024.08.class="num">15 class="num">12:class="num">30:class="num">27&class="macro">#x27;; class="type">ulong v; Print("Date And Time: ", dt); }
把 datetime 拆成日期时间分秒的十六进制验证
在 MT5 里 datetime 本质是从 1970-01-01 起算的秒数,直接 Print 出来是十进制整数,肉眼难对应到日历时间。上面这段把同一个 dt 分别喂给 macro_GetDate、macro_GetTime、macro_GetSec、macro_GetMin、macro_GetHour,再强制转回 datetime 打印十六进制与十进制,等于把时间结构体各字段单独拎出来看底层值。 以 2024-01-01 00:00:00 为例,macro_GetDate 返回的 datetime 十六进制约为 0x65910000,十进制约 1704067200,而 macro_GetTime 同刻会回到 0x0;若 dt 带 13:45:30,macro_GetHour 对应值十六进制约 0x35E0(十进制 13776 秒 = 3.826 小时偏移)。这种打印能帮你确认宏定义是否真的只掩码了对应字节。 实盘外汇与贵金属波动受杠杆与跳空影响,这类底层时间解析仅用于排查 EA 逻辑错误,不涉及任何方向判断;直接在 MT5 策略测试器里跑这段,改 dt 赋值就能对照自己服务器的时区偏移。
class="num">12. Print("0x", ValueToString(dt, FORMAT_HEX)); class="num">13. PrintX((class="type">class="kw">datetime)(v = macro_GetDate(dt))); class="num">14. Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL)); class="num">15. PrintX((class="type">class="kw">datetime)(v = macro_GetTime(dt))); class="num">16. Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL)); class="num">17. PrintX((class="type">class="kw">datetime)(v = macro_GetSec(dt))); class="num">18. Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL)); class="num">19. PrintX((class="type">class="kw">datetime)(v = macro_GetMin(dt))); class="num">20. Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL)); class="num">21. PrintX((class="type">class="kw">datetime)(v = macro_GetHour(dt))); class="num">22. Print("0x", ValueToString(v, FORMAT_HEX), " :: ", ValueToString(v, FORMAT_DECIMAL)); class="num">23. }
◍ 别急着下结论
宏在 MQL5 里常被误用,也常被完全无视,根子在于多数人对它的存在理由和适用边界没概念。从正确路径起步、先把工具为什么存在弄透,比急着写复杂逻辑更重要;那些曾觉得啃不动的功能,往往只是缺了这一步认知。 写代码这件事没有天生的门外汉,只有还没撞上自己节奏的人。把本文说的宏处理思路在 MT5 里建个空 EA 实测一遍,你会看到不少原先认为做不到的封装方式其实顺手就能落地。 外汇与贵金属波动剧烈、杠杆风险高,任何编码便利都只是降低试错成本,不替你兜底盈亏。方向找对了,剩下的只是时间和练习。