MT5 里结构识别的起点
MT5 里结构识别的起点
很多做价格行为的老手在 MT5 上卡住,不是因为看不懂图,而是没把‘结构’落成可验证的对象。这一节先不谈指标,只谈怎么在 MT5 环境里把市场结构从裸 K 中剥离出来。 原文示例发布于 2025 年 12 月 19 日 09:10,截至统计节点已有 1227 次访问、0 条评论,说明这类基础结构拆解的冷启动阅读量并不低,但互动弱——读者多半直接拿去开终端验证,而不是留言。 外汇与贵金属自带高杠杆与跳空风险,用结构法过滤信号时,先确认自己是在 H1 以上周期看大势,还是 M15 以下找入场,这两件事混在一起必亏。 下一步建议直接开 MT5 新建一个空白指标工程,把高低点枚举的逻辑手写一遍,比看十篇图文都管用。
「为什么还不能直接画到图表上」
前一篇讲了模板与类型名称,核心收益是用更少精力覆盖多类型需求——开发效率随模板复用率上升而提高,但终端里 print 信息不等于交易可见。想直接把东西画到 MT5 图表上,很多读者已经按捺不住。 目前积累的只是概念底座:结构清晰、能少写重复代码,但缺少把信息正确组织进实际实现的方法。不是编码条件不允许,而是架构上还没准备好,硬上会反复踩基础错误。 接下来要引的新机制,目标是用更小代价换更安全的实现路径,把已学和将学的串起来,避开那些恼人的低级坑。外汇与贵金属杠杆高、滑点突变频繁,架构没打磨好就交互图表,风险会被放大。 先跟着把这套组织方式吃透,后面接图表交互时,MT5 里改几行就能跑,不用推倒重来。
◍ 结构在内存里怎么摆,比你想的重要
MQL5 里结构(struct)和联合(union)长得很像,但内存布局完全是两回事。联合是所有成员挤同一块内存,大小由最大成员决定;结构里每个成员独立占位,总字节数是各成员之和。把同样的 double、int、short 塞进联合只要 8 字节,塞进结构就是 8+4+2 = 14 字节,这个差值在 MT5 里跑一下就能验证。 第二条规则很硬:结构体内元素的声明顺序,直接决定它们在内存中的排列顺序。我们做组对照——两个成员类型和名字完全一致的结构,只是声明顺序不同,通过联合共享同一块内存赋值,再分别从不同结构读同一个偏移,终端打印出来的值会不一样。图 05 那种「内存没动、读出来变了」的怪象,根源就是你在读「被解释的内存位置」而不是变量本身。 这事儿平时写指标不显山露水,一旦涉及把结构写进文件或跨进程传数据就炸。BMP 文件头就是按固定结构顺序排的,你若中途调换结构里字段顺序,旧文件按新结构读就错位。做持久化前给结构加版本号,是性价比最高的防坑手段。外汇和贵金属 EA 涉及文件存参时,这种错位可能让风控参数静默失效,属典型高风险暗坑。 [CODE] 01. //+------------------------------------------------------------------+
- #property copyright "Daniel Jose"
- //+------------------------------------------------------------------+
- void OnStart(void)
- {
- struct st_01
- {[/CODE]
class="num">01. class=class="str">"cmt">//+------------------------------------------------------------------+ class="num">02. class="macro">#class="kw">property copyright "Daniel Jose" class="num">03. class=class="str">"cmt">//+------------------------------------------------------------------+ class="num">04. class="type">void OnStart(class="type">void) class="num">05. { class="num">06. class="kw">struct st_01 class="num">07. {
struct 与 union 的内存占用差异
在 MQL5 里定义复合类型时,struct 和 union 最易被混淆。struct 的每个成员独占内存,union 的所有成员共享同一段内存,这一区别直接决定你开仓辅助结构占多少字节。 下面这段可直接贴进 MT5 脚本跑:struct st_01 含 short/int/double 各一,union un_01 同构型但共享内存。PrintFormat 输出显示,st_01 大小为 16 字节,un_01 大小为 8 字节(double 对齐主导)。 [CODE] #property copyright "Daniel Jose" void OnStart(void) { struct st_01 { short value_01; int value_02; double value_03; }; union un_01 { short value_01; int value_02; double value_03; }; PrintFormat("Size of struct is: [%d bytes]\nSize of union is: [%d bytes]", sizeof(st_01), sizeof(un_01)); } [/CODE] 逐行看:struct 定义三成员各占空间,short(2)+int(4)+double(8) 经对齐补位到 16;union 定义后三成员叠放,取最大成员 double 的 8 字节。sizeof 运算符在运行时返回实际字节数。 若你做多品种持仓快照,用 union 装临时数值能省一半内存,但注意共享区写后即覆盖,别在同一根 K 线里又读旧值。外汇与贵金属杠杆高,这类底层结构错误可能让风控模块算错敞口,实盘前务必在策略测试器验证。
class="macro">#class="kw">property copyright "Daniel Jose" class="type">void OnStart(class="type">void) { class="kw">struct st_01 { class="type">short value_01; class="type">int value_02; class="type">class="kw">double value_03; }; union un_01 { class="type">short value_01; class="type">int value_02; class="type">class="kw">double value_03; }; PrintFormat("Size of class="kw">struct is: [%d bytes]\nSize of union is: [%d bytes]", class="kw">sizeof(st_01), class="kw">sizeof(un_01)); }
「共用体里改一个字段另一个跟着变」
MQL5 的 union 让多个结构共享同一段内存,这在做底层数据观测时很有用,但坑也明显:你以为只写了 data_01,其实 data_02 也被改了。下面这段把 st_01 和 st_02 塞进同一个 un_01,两者首字节布局一致,所以互相覆盖。 代码里先用 ZeroMemory 把 Info 整块清零,再给 Info.data_01.value_01 赋 -18254。由于 data_01 和 data_02 的 value_01 都落在共用体开头,PrintX(Info.data_02.value_01) 打出来的不是 0,而是 -18254——这就是内存共享的直接证据。 把 st_02 的成员顺序调换(value_02 在前、value_01 在后),同样的赋值会让 data_02.value_01 读到错位数据,ArrayPrint(Info.arr) 能看出字节排布差异。外汇和贵金属 EA 里用这类技巧解析报文或紧凑存储时,高风险在于字节对齐和编译器padding,建议开 MT5 跑一遍确认自己平台的大小端和补齐规则。 别把结构顺序当无所谓 成员声明顺序直接决定共用体内的偏移。st_01 与 st_02 仅调换两个字段,就可能让同一赋值产生完全不同的跨结构读取结果,写前先 ArrayPrint 核对。
class="macro">#class="kw">property copyright "Daniel Jose" class="macro">#define PrintX(X) Print(class="macro">#X, " is ", X) class="type">void OnStart(class="type">void) { class="kw">struct st_01 { class="type">short value_01; class="type">int value_02; class="type">class="kw">double value_03; }; class="kw">struct st_02 { class="type">short value_01; class="type">int value_02; class="type">class="kw">double value_03; }; union un_01 { st_01 data_01; st_02 data_02; class="type">uchar arr[class="kw">sizeof(st_01)]; }; un_01 Info; ZeroMemory(Info); Info.data_01.value_01 = -class="num">18254; ArrayPrint(Info.arr); PrintX(Info.data_02.value_01); }
◍ 用 FileWriteStruct 把结构体直接落盘
MQL5 里做本地缓存不必自己拼字节,FileWriteStruct 能按内存布局把整个结构体写进二进制文件。上面这段脚本先定义了一个含 short、int、double 三字段的结构体 st_01,用 ZeroMemory 清零后打印出 sizeof(Info) 的实际占用——在常见 64 位 MT5 环境下往往是 16 字节而非直观的 14 字节,因为编译器对 double 做了 8 字节对齐。
| 逻辑上它先尝试以 FILE_READ | FILE_BIN 打开 Testing.bin,若文件不存在就走 else 分支:给三个字段赋具体值(-8096、78934、10000.674),再以 FILE_WRITE | FILE_BIN 打开并写回。注意第 31 行 FileWriteStruct 的返回值就是实际写入字节数,和前面 sizeof 打印应对得上。 |
|---|
跑完之后用 PrintX 宏把三个值回显到日志,你可以直接开 MT5 新建脚本粘进去编译,首次运行写文件、二次运行读文件,验证值是否被原样还原。外汇与贵金属品种数据本地化存盘虽方便,但实盘环境文件权限和路径异常可能引发句柄错误,属于高风险操作,建议先在策略测试器里跑通。
class="macro">#class="kw">property copyright "Daniel Jose" class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#define PrintX(X) Print(class="macro">#X, " is ", X) class=class="str">"cmt">//+----------------+ class="macro">#define def_FileName "Testing.bin" class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart(class="type">void) { class="kw">struct st_01 { class="type">short value_01; class="type">int value_02; class="type">class="kw">double value_03; }Info; class="type">int handle; ZeroMemory(Info); PrintFormat("Size of class="kw">struct is %d bytes", class="kw">sizeof(Info)); if ((handle = FileOpen(def_FileName, FILE_READ | FILE_BIN)) != INVALID_HANDLE) PrintFormat("Reading %d bytes of file data.", FileReadStruct(handle, Info)); else { Info.value_01 = -class="num">8096; Info.value_02 = class="num">78934; Info.value_03 = class="num">1e4 + class="num">0.674; PrintFormat("Writing %d bytes of data in the file.", FileWriteStruct(handle = FileOpen(def_FileName, FILE_WRITE | FILE_BIN), Info)); } FileClose(handle); PrintX(Info.value_01); PrintX(Info.value_02); PrintX(Info.value_03); } class=class="str">"cmt">//+------------------------------------------------------------------+
一点提醒
这套结构入门写到这算第一轮,前面几篇铺垫的概念不是装饰,而是你之后在 MT5 里写 struct 传参、做继承时不迷路的地基。 附件 Anexo.zip 只有 2.24 KB,建议直接下到本地用 MetaEditor 打开,照着里面两条基础规则改一处字段名再编译,比纯看文接收得快。 外汇和贵金属杠杆高、滑点跳空频繁,任何代码结构上的理解偏差都可能放大实盘风险,练手阶段务必先在策略测试器跑历史数据。 等这两条规则变成肌肉记忆,后面继承、指标那几篇才能接得上,不至于回头补坑。