6.5 图表对象与交易面板
对象的生命周期
- 创建:ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0)。0 表示当前图表,name 必须唯一。
- 设置:ObjectSetInteger 设置坐标、大小、颜色、层级;ObjectSetString 设置文字。
- 刷新:ChartRedraw() 立即重绘。不调用也能在下一次刷新时显示,但面板操作最好立即反馈。
- 删除:OnDeinit 里 ObjectsDeleteAll(0, 前缀),或 ObjectDelete 逐个删除。
对象名建议统一加前缀,例如 pnl_。删除时按前缀批量清理,不会误删其他指标画的线。重名对象重复创建会失败,所以 OnInit 里可以先 ObjectDelete 再创建,或直接用唯一名字。
坐标与角落
图表对象的坐标有两种锚定方式:按价格/时间锚定(会随图表缩放移动),或按角落像素锚定(面板常用)。OBJPROP_CORNER 可选左上、右上、左下、右下;再配合 OBJPROP_XDISTANCE、OBJPROP_YDISTANCE、OBJPROP_XSIZE、OBJPROP_YSIZE。面板放右上角时,x 从右边缘往左算,y 从上边缘往下算。
按钮还要设置 OBJPROP_SELECTABLE=false,否则用户拖动图表时会把按钮拖走。OBJPROP_HIDDEN=true 可以让对象不出现在对象列表里,界面更干净。
点击事件:OnChartEvent
点击按钮不会进入 OnTick,而是进入 OnChartEvent,id 为 CHARTEVENT_OBJECT_CLICK,sparam 是被点击对象的名字。处理顺序是:先判断 id,再判断 sparam,再执行动作,最后把 OBJPROP_STATE 设回 false。按钮的“按下”状态不会自动复位,忘记复位会一直显示凹陷。
完整示例:三键面板
下面的代码创建背景、三个按钮,并在 OnChartEvent 里处理买入、卖出、全平。全平部分留了注释,调用 6.2 的 CloseAllByMagic 即可。
注意:面板只负责“收集意图”,真正的风控、手数计算、错误处理应该放在统一的下单函数里。否则按钮越多,重复代码越多。
刷新频率
面板上的余额、浮盈、状态文字不需要每个 Tick 都更新。可以在 OnTimer 里每秒刷新一次,减少 ChartRedraw 次数。频繁重绘会让图表在低配机器上明显卡顿。状态没变时跳过刷新,是一个简单有效的优化。
常见错误
- OnDeinit 不删对象:切换参数后旧按钮残留,和新按钮重名,点击无反应。
- 按钮状态不复位:点击后一直显示按下,用户以为没生效。
- 对象名重复:多个图表用同一个名字,后创建的失败。名字加图表 ID 或前缀。
- 用价格坐标画面板:图表一缩放,面板就跑到屏幕外。面板用角落像素坐标。
- 在 OnChartEvent 里做重活:事件回调应快速返回,复杂计算放到 OnTimer 或 OnTick。
小结
面板 = 对象 + 事件 + 清理。创建时统一命名,设置时用角落坐标,点击时判断 sparam,退出时按前缀删除。把这四步做成模板,你就能给任何 EA 加一个不添乱的交易面板。
常用对象类型
- OBJ_LABEL:单行文字,适合标题、状态、数值。用 OBJPROP_TEXT 改内容,用 OBJPROP_FONTSIZE 改字号。
- OBJ_BUTTON:可点击按钮,点击时触发 CHARTEVENT_OBJECT_CLICK。适合买入、卖出、全平、切换参数。
- OBJ_RECTANGLE_LABEL:矩形面板背景,支持背景色、边框色、圆角(部分版本)。适合给文字和按钮做底板。
- OBJ_EDIT:输入框,用户可编辑,适合手数、止损点数等参数。读取时用 ObjectGetString(..., OBJPROP_TEXT)。
对象类型决定了可用属性。给 OBJ_LABEL 设置 OBJPROP_XSIZE 通常无效,给 OBJ_BUTTON 设置 OBJPROP_FONTSIZE 则可能生效。写代码前先查清类型支持的属性,比反复试错快。
事件参数怎么用
OnChartEvent 有四个参数:id 是事件类型,lparam 是长整数参数,dparam 是浮点参数,sparam 是字符串参数。对象点击事件里,sparam 是对象名;图表拖拽、键盘事件里,参数含义不同。不要把所有事件都当成点击处理,先判断 id,再读对应参数。
按钮点击后要复位 OBJPROP_STATE,否则按钮保持按下状态。如果按钮是“切换”语义(例如开启/关闭某种模式),可以用 state 表示开关,但要在状态文字里明确告诉用户当前是开还是关。
面板状态管理
面板上的余额、状态、按钮可用性都来自 EA 的内部状态。不要让面板成为“唯一状态源”:按钮点击只触发动作,动作的结果写回全局变量,再由刷新函数统一更新面板。这样即使面板对象被删除重建,状态也不会丢。
刷新函数应该幂等:同样的状态重复调用,结果一致;状态没变时跳过 ChartRedraw,减少闪烁。面板文字变化频繁时,可以只更新变化的那个对象,而不是删除重建整个面板。
坐标与高 DPI
MT4 在不同显示器缩放下,图表像素坐标可能变化。用角落锚定 + XDISTANCE/YDISTANCE 比用价格坐标稳定;但高 DPI 下按钮可能显得偏小。可以在 OnInit 里根据 `TerminalInfoInteger(TERMINAL_SCREEN_DPI)` 调整尺寸(部分版本支持),或者干脆把按钮做大一点,保证可点击。
面板不要遮挡关键价格区域。右上角是常用位置,但如果图表右上角有均线标签,可以改到左上角或右下角。上线前在 100%、125%、150% 三种缩放下各看一遍。
面板不是下单入口
按钮点击只是“用户意图”,不是“交易指令”。真正的下单必须经过统一的风控与执行函数:检查交易权限、点差、手数、止损距离、最大持仓、当日亏损,再决定发不发。把 OrderSend 直接写在 OnChartEvent 里,短期看很方便,长期会导致“面板能下单、策略不能下单、两套逻辑不一致”。
面板还应显示“为什么不能下单”。例如交易被禁用时,状态栏显示“交易不允许”,而不是点了没反应。用户看到原因,才不会反复点击。
对象命名与清理
对象名在图表内必须唯一。建议用“EA 前缀 + 模块 + 名称”,例如 `pnl_bg`、`pnl_btnBuy`、`pnl_lblStatus`。清理时按前缀 ObjectsDeleteAll(0, "pnl_"),不会误删其他指标的趋势线。若同一图表挂多个 EA,前缀里再加魔术号,避免互相覆盖。
OnDeinit 的 reason 参数可以区分卸载原因:REASON_REMOVE、REASON_RECOMPILE、REASON_CHARTCHANGE、REASON_PARAMETERS 等。参数改变会触发卸载重载,清理逻辑必须能重复执行,不能假设对象只创建一次。
可访问性与可读性
按钮文字要短、对比度要高,深色背景配浅色文字或反过来。面板不要用大面积高饱和色,容易遮挡行情。状态文字用“已买入 0.10 手”而不是“OK”,让用户一眼知道发生了什么。重要操作(全平)可以加二次确认:第一次点击把按钮文字改成“确认全平”,第二次点击才执行。
移动端或小屏幕不在 MT4 桌面端的考虑范围内,但高 DPI 和窄图表窗口要考虑。按钮宽度至少 70 像素,高度至少 24 像素;面板总宽不要超过图表宽度的三分之一,避免遮挡 K 线。
交互演示:交易面板:对象创建与点击事件
先创建背景、标题和三个按钮,再模拟点击“买入”:OnChartEvent 收到 sparam,检查权限,下单,更新状态并复位按钮。
提示:动画默认暂停。点「播放」连续演示,点「单步」自己控制节奏;桌面端也可以用空格播放、方向键单步、R 重置。
练习题
-
6.5 图表对象与交易面板 选择题1.图表按钮被点击时,EA 收到的回调是? (2分) [选择]A. OnTickB. OnTimerC. OnChartEventD. OnCalculate2.面板对象退出时应如何清理? (2分) [选择]A. 不用清理,终端会自动删除B. 在 OnDeinit 中按前缀 ObjectsDeleteAllC. 在 OnTick 中 ObjectDeleteD. 重启终端3.按钮点击后 OBJPROP_STATE 会自动复位为 false。 (2分) [判断]
-
6.5 图表对象与交易面板 编程实战(AI 批改)1.【实战】写一个带买入按钮的面板 (10分) [MQL4自动批改]写一个 EA:OnInit 创建名为 pnl_bg 的矩形背景(右上角,宽 180 高 130),再创建名为 pnl_btnBuy 的按钮(文字“买入”,宽 80 高 26);OnChartEvent 中判断 CHARTEVENT_OBJECT_CLICK 且 sparam=="pnl_btnBuy",先将按钮状态复位,再在 IsTradeAllowed 时 OrderSend 买入 0.10 手;OnDeinit 用 ObjectsDeleteAll(0,"pnl_") 清理。必须出现 ObjectCreate、OBJ_BUTTON、OnChartEvent、ObjectsDeleteAll。
《MQL4 教程与 MT4 EA 编程》课程目录
系统讲解 MQL4 编程:从变量、循环、函数到 OrderSend 下单、iMA 指标调用与 EA 回测。36 节中文教程,覆盖 MT4 编程入门、外汇 EA 编写与外汇量化策略三类实战,每节配可运行代码和 AI 自动批改练习
- 第1章 基本语法
- 1.1 第一个EA
- 1.2 如何学习
- 1.3 变量
- 1.4 语句
- 1.5 运算符
- 1.6 常量与枚举
- 第2章 条件
- 2.1 if语句
- 2.2 关系运算符
- 2.3 逻辑运算符
- 2.4 复合条件
- 2.5 switch语句
- 第3章 循环
- 3.1 for循环
- 3.2 while循环
- 3.3 break和continue
- 3.4 嵌套循环
- 第4章 函数
- 4.1 函数的定义
- 4.2 参数和返回值
- 4.3 变量的作用域
- 4.4 常用内置函数
- 4.5 日期和时间函数
- 4.6 交易函数
- 4.7 账户和市场信息函数
- 4.8 图表和对象函数
- 4.9 文件操作函数
- 4.10 数组函数
- 4.11 技术指标函数
- 第5章 如何写EA
- 5.1 EA的基本结构
- 5.2 常用内置变量
- 5.3 下单函数
- 5.4 技术指标
- 5.5 实战:均线交叉EA
- 第6章 进阶实战:从能跑走向可靠
- 6.1 OnTimer 定时器与事件处理
- 6.2 订单池遍历与 OrderSelect
- 6.3 错误处理与 GetLastError
- 6.4 自定义指标与指标缓冲区
- 6.5 图表对象与交易面板
- 6.6 回测与参数优化