构建自动运行的 EA(第 02 部分):开始编码·综合运用
◍ 把资金额换算成可下单价差点数
在 MT5 的 EA 风控里,常需要把「允许亏损多少美元」转成「止损摆几个点」。下面这段内联函数就干了这件事:先用杠杆层数算出实际下单手数,再用资金除以手数和合约调整系数,得到价格层面的点值距离。 核心公式是 volume = VolMinimal + VolStep * (Leverage - 1),也就是说杠杆每加一层,手数按平台最小步长递增;外汇与贵金属杠杆放大后爆仓风险陡增,参数一定要用真实账户的最小交易量测过。 AdjustPrice 那行取了绝对值再做价格对齐,避免负资金或奇精度把挂单弄脏。把这段代码直接塞进你的头文件,开 MT5 用不同 Leverage 跑一遍,就能看到同一笔风控金额对应止损点数是怎么跳的。
class="kw">return (((type == ORDER_TYPE_BUY) || (type == ORDER_TYPE_SELL)) ? ToServer() : class="num">0); }; class="kw">inline class="type">class="kw">double FinanceToPoints(class="kw">const class="type">class="kw">double Finance, class="kw">const class="type">uint Leverage) { class="type">class="kw">double volume = m_Infos.VolMinimal + (m_Infos.VolStep * (Leverage - class="num">1)); class="kw">return AdjustPrice(MathAbs(((Finance / volume) / m_Infos.AdjustToTrade))); };
「用方向键快速验证下单通道」
这一篇的重心不是做一个人控 EA,而是用最小代价让初学者看到自动交易程序怎么把订单送出去。想照手工逻辑写 EA 的,另有专门系列讲从手动交易提炼策略,不过那套略旧,很快你会懂原因。 验证订单系统不需要画水平线那种麻烦事。只要在 MT5 图表上按方向键,EA 就按预设参数发单,省去手动填表的步骤。具体做法:先设好入场价,注意不能用当前价;看多按上箭头、看空按下箭头,然后切到工具箱的交易标签,就能看到一笔带 EA 指定条件的挂单出现。 参数面板里 user05 默认 84.00 是入场价,user02=100、user03=75 分别是以金额计的止盈止损,user01=1 是手数增量,user04=true 代表日内模式。这些数据直接决定订单填充内容,开 MT5 把数值改掉就能立刻测不同仓位。 类初始化靠构造函数 new C_Orders(),析构里 delete orders 保证内存不漏。这样在任何内部过程调用前,订单类始终处于已初始化状态,避免空指针发单失败。 别把默认价当万能模板 外汇和贵金属波动剧烈,84.00 只是演示占位,实盘套用可能直接滑点或拒单。先开模拟账户用方向键跑通通道,再谈参数优化。
class="macro">#class="kw">property copyright "Daniel Jose" class="macro">#class="kw">property description "This one is an automatic Expert Advisor" class="macro">#class="kw">property description "for demonstration. To understand how to" class="macro">#class="kw">property description "develop yours in order to use a particular" class="macro">#class="kw">property description "operational, see the articles where there" class="macro">#class="kw">property description "is an explanation of how to proceed." class="macro">#class="kw">property version "class="num">1.03" class="macro">#class="kw">property link "[MQL5官方文档] class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#include <Generic Auto Trader\C_Orders.mqh> class=class="str">"cmt">//+------------------------------------------------------------------+ C_Orders *orders; class="type">class="kw">ulong m_ticket; class=class="str">"cmt">//+------------------------------------------------------------------+ input class="type">int user01 = class="num">1; class=class="str">"cmt">//Lot increase input class="type">int user02 = class="num">100; class=class="str">"cmt">//Take Profit(financial) input class="type">int user03 = class="num">75; class=class="str">"cmt">//Stop Loss(financial) input class="type">bool user04 = true; class=class="str">"cmt">//Day Trade ? input class="type">class="kw">double user05 = class="num">84.00; class=class="str">"cmt">//Entry price... class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { orders = new C_Orders(); class="kw">return INIT_SUCCEEDED; } class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnDeinit(class="kw">const class="type">int reason) { class="kw">delete orders; } class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { } class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnChartEvent(class="kw">const class="type">int id, class="kw">const class="type">long &lparam, class="kw">const class="type">class="kw">double &dparam, class="kw">const class="type">class="kw">string &sparam) { class="macro">#define KEY_UP class="num">38 class="macro">#define KEY_DOWN class="num">40 class="kw">switch (id) { case CHARTEVENT_KEYDOWN: class="kw">switch ((class="type">int)lparam)
键盘方向键触发下单的分支写法
在 EA 的按键事件处理里,用 switch 接 KEY_UP 与 KEY_DOWN 是最直接的手动下单入口。上键发买、下键发卖,订单参数全部走外部变量,不写死在分支里。 下面这段是事件回调末尾的典型结构,先按键值分流,再统一 break 退出 switch,最后用 #undef 清掉宏定义避免污染其他模块。
{
case KEY_UP:
m_ticket = orders.CreateOrder(ORDER_TYPE_BUY, user05, user03, user02, user01, user04);
class="kw">break;
case KEY_DOWN:
m_ticket = orders.CreateOrder(ORDER_TYPE_SELL, user05, user03, user02, user01, user04);
class="kw">break;
}
class="kw">break;
}
class="macro">#undef KEY_DOWN
class="macro">#undef KEY_UP
}
class=class="str">"cmt">//+------------------------------------------------------------------+
{
case KEY_UP:
m_ticket = orders.CreateOrder(ORDER_TYPE_BUY, user05, user03, user02, user01, user04);
class="kw">break;
case KEY_DOWN:
m_ticket = orders.CreateOrder(ORDER_TYPE_SELL, user05, user03, user02, user01, user04);
class="kw">break;
}
class="kw">break;
}
class="macro">#undef KEY_DOWN
class="macro">#undef KEY_UP
}
class=class="str">"cmt">//+------------------------------------------------------------------+◍ 把这条线请下神坛
这个自动下单的雏形 EA 虽然逻辑直白,但已经能让你在 MT5 里实测订单系统的发单链路,附件里的完整工程(EA_Automatico_-_02.zip,3.12 KB)直接拖进终端就能跑。 重点别踩坑:验证时不要用当前市价去比对,否则你根本看不出系统是不是在预设价位、预设手数下进去的——错单也会被误判成正常。 到这一步其实才摸到订单簿操作的大门,后面几篇才会把触发和风控铺开。外汇和贵金属杠杆高、滑点狠,跑任何自动单前先用策略测试器过一遍历史 tick。