MQL5语言帮助文件人话版(十)数据类型之日期时间型

| 发表于 昨天 16:06 | 显示全部楼层 |复制链接
最后由 麻爪 于 2026-9-7 16:10 编辑

第十章 日期时间型


一、编程新手感悟

爱因斯坦说,时间只是人类的错觉。当然这属于物理哲学层面的观点,但是写 EA 编程的时候,这句话给了我很深启发:千万不要拿日常生活的时间直觉,去理解程序里面的时间参数。


在程序世界,时间参数本质上,就是一套用来判定事件绝对先后顺序的标签。


最开始写突破策略的时候,我要标记发生突破的那一根 K 线。教程里常规的做法就是使用 K 线索引编号:当前 K 是 0 号,前一根 1 号,往前依次递增。我照这样子写代码,然后灾难就开始了。


每当一根新 K 线生成,整套索引编号集体向后偏移一位。上一次记录的突破 K 是 10 号,等到新 K 出来,真正那根老 K 已经变成 11 号,可程序牢牢记住 “突破发生在 10 号”,读到的就是一根完全不相干的 K 线。


我抓狂很久之后才明白,MQL5 提供函数获取 K 线的 datetime 时间标签,拿这个时间标签去标记 K 线,针对 K 线级别的事件,就可以做到稳定识别,不会随着新 K 出现而漂移。


后面又遇到另一个让人崩溃的坑。我写代码识别 K 线的顶底分型,可以顺利抓取历史 K 线上全部的顶底点,再交给绘图函数把点依次相连,预期得到一条起伏波折的线段。


可跑起来一看:线条从最新的顶底点开始,一路反向连向最古老的顶底点,还拖出来一条奇怪的长线。


排查许久才搞懂根源:系统循环从最新 K 向历史 K 扫描,识别到的分型,最新的点会优先存入数组,最古老的点排在数组末尾。直接按数组顺序连线,自然就是逆着时间方向绘制。


当时得到的方案是调用数组反转函数,把整个数组顺序颠倒。这一下绘图看着正常了。


但新的麻烦又来了:当后续出现新的顶底分型,新识别出来的点又会被放到数组最前面,连线再次错乱,直接从最新的分型点一跳连到最古老的点位,真是服了这个老六。


后来又得到一个折中方案:每来一根新 K 线,就把旧数组全部清空,完整重新扫描全部 K 线,重新收集全部顶底点,反转数组,再重新绘图。这个方案确实功能正常。但内心总觉得这种全部推倒重来的方式有点别扭。(补充:很多简易指标确实是这么实现的,只是 K 线数据量大的时候会带来额外计算开销)


反复研究之后,才接触到更加工程化的写法:构建结构体,每识别一个顶底分型,同时保存这根 K 的时间标签、K 线索引、高低点价格。


结构体本身不会自动整理顺序。但是无论分型点以什么先后顺序加入数组,我们可以依据结构体内部的 datetime 时间字段执行排序。时间数值小代表发生的更早,时间数值大代表更新的事件。排序完成,旧的点排在数组靠前位置,新产生的顶底点自然排到数组末尾。从此无论新增多少分型点,点与点之间的先后逻辑永远不会错乱。


这段经历也让我深刻分清两件东西:


(1)K 线索引,只是「距离现在有多远」的相对位置,会动态发生变化,适合读取最近 N 根 K;


(2)datetime 时间标签,是 K 线事件的 “身份证”,适合记住某一根特定的 K,用来做持久标记、排序。


新手入门 MQL5,上手就记住 0、1、2 这个索引体系,很容易默认索引是 K 线的永久编号。


踩过上面这些坑之后才理解:索引是临时座位,时间标签才是真正的身份。


二、日期时间型:


日期时间型是为存储日期时间型预留的,系统的开始日期是1970年1月1日,占8字节内存。


日期时间型常量可以看成是数字串,由 6 个部分的字符组成:年、月、日(或是日、月、年)、时、分、秒,数据以 D 开头, 用单引号括起。


设定日期时间型变量时,至少需要指定年、月和日,时、分、秒可以指定,也可以省略。否则编译器会返回不完全输入的警告 。

三:示例:

datetime NY=D'2015.01.01 00:00';     // 2015年初的时间
datetime d1=D'1980.07.19 12:30:27';  // 年 月 日 小时 分钟 秒 的格式
datetime d2=D'19.07.1980 12:30:27';  // 日 月 年 小时 分钟 秒 的格式
datetime d3=D'19.07.1980 12';        // 省略了分和秒
datetime d4=D'01.01.2004';           // 省略了时、分和秒
datetime compilation_date=__DATE__;             // 编译日期,__DATE__是一个特殊常量,你按下“编译”按钮那一刻的时间
datetime compilation_date_time=__DATETIME__;    // 编译日期和时间,带time可以精确到秒,不带的话时分秒默认都是0
datetime warning1=D'12:30:27';       // 等于 D'[编译日期] 12:30:27',省略编译当天年月日的写法
datetime warning2=D'';               // 等于 __DATETIME__
最近访问 头像模式
举报

评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册