简介:面向MetaTrader平台外汇自动化交易学习者的一份源码整理文档,聚焦锁仓顺势加码EA的订单管理与参数配置思路。正文围绕自动锁仓、顺势加码、手动订单主动止盈、自动平仓及对冲单管理等环节展开,说明USE_ATR、PercentATR、HedgingLevel、AutoTakeProfit等外部参数的默认值与作用,并借助Hedge_Assistante、start、OrderSelect、OrderClose等函数串起订单筛选、止盈修改和平仓流程;同时交代ATR、iHigh、iLow在波动率与高低点判断中的用法,便于读者对照梳理EA的触发条件与风险控制边界。资源包仅含1个doc文档,大小约45KB,内容集中、查阅轻便,适合作为源码阅读和逻辑复盘的辅助材料。文档将参数含义、函数职责与指标应用放在同一脉络中,便于快速定位锁仓、对冲和止盈模块之间的关系,也能为二次开发提供结构参照。已有1381人学习,对希望理解外汇EA订单管理结构、完善对冲与止盈细节的开发者及进阶交易者具有参考意义。
1. 锁仓顺势加码 EA 源码:一份能接管手动单的 MQL4 对冲助手
手动单被行情反向拖住,砍掉心疼,不砍又怕扩大——锁仓顺势加码 EA 源码要解决的就是这个具体动作。它不负责开仓,只接管你手动下的市价单:按日线 ATR 算出一个距离,在反方向挂一张等量的 STOP 单;你把手动单平掉,它跟着撤掉对冲挂单;对冲单成交了,它反过来把手动单的止盈清零,逼你自己决定什么时候开锁。整份代码几百行,V2.0 到 V2.2 的修改注释都留在文件头,适合已经会手动下单、想把「锁单—解锁」这套流程固化成 MQL4 程序的人拿来拆。不适合下载完就挂实盘的人:里面有硬编码点数、有会阻塞十秒的 Sleep、还有两处索引循环写法会漏单,不先改一遍就上线,翻车概率不低。
2. 拆开 Hedge_Assistante:ATR 定距、Magic 配对与三段状态机
这份 EA 的全部动作都塞在一个Hedge_Assistante()里,start()只负责调用它。想改得动,先得把它的三段循环看懂:第一段给没有对冲单的手动单补一张反向 STOP,第二段删掉失去对手方的对冲挂单,第三段处理已经成交的对冲单、把对应手动单的止盈清零。三段之间靠什么串起来?靠 MagicNumber 复用 Ticket 这个小技巧。
2.1 ATR 定价:HedgingLevel 一个变量两种单位
锁仓距离的算法集中在两行,但这两行埋了整份源码最别扭的设计:
// 每个 tick 都重算一次锁仓距离 if (USE_ATR) HedgingLevel = iATR(NULL, PERIOD_D1, 14, 0) * PercentATR / 100; else HedgingLevel = HedgingLevel * Point;iATR(NULL, PERIOD_D1, 14, 0)取的是当前图表品种、日线周期、14 根、shift 为 0 的 ATR 值,返回单位是价格而不是点数。所以USE_ATR=true时,HedgingLevel被覆盖成一个价格距离,比如欧美日线 ATR 是 0.0080,PercentATR=40,算出来就是 0.0032;USE_ATR=false时,HedgingLevel走的是30 * Point,在四位报价平台上等于 0.0030。两条分支算出来的数值碰巧接近,但语义完全不同:一个是绝对价格,一个是「点数 × Point」。参数面板上它叫同一个名字,单位却随开关漂移。
这里还有个容易被忽略的细节:shift=0取的是当天尚未走完的日线 bar,ATR 值会随着日内波动一路变化。早上挂出去的对冲单距离和下午算出来的不是同一个数。代码只在「没有对冲单」时才建仓,建完就不动,所以影响有限;但如果你手动删掉对冲挂单,下一个 tick 它会按新的 ATR 重挂,价格就漂了。常见做法是把 shift 改成 1,用昨天走完的日线 ATR,当天内距离固定,复现和回测都清爽得多。
参数怎么定?PercentATR的 40% 意味着价格反向走出 0.4 倍日 ATR 才触发锁仓。欧美日线 ATR 常见在 60 到 100 个 pip,40% 就是 24 到 40 个 pip,对日内单来说偏紧,对波段单偏松。我一般会先把USE_ATR关掉,用固定 30 点把整个流程跑通,确认挂单、撤单、清止盈三条路径都对,再切回 ATR。反过来直接用 ATR 调试,出了问题是距离算错还是配对错,你分不清。
注意:
extern double HedgingLevel=30在 ATR 分支下会被程序改写成价格值,MT4 的属性面板会跟着显示改写后的数。下次打开参数窗口看到0.0032别以为自己设错了,这是运行期回写,不是你手滑。
2.2 MagicNumber 复用:拿手动单的 Ticket 当对冲单的身份证
配对是这份源码里最巧的一笔。手动单的MagicNumber恒为 0,没法用它区分「谁是谁的对手方」。作者的做法是:建对冲单时,把被保护的那张手动单的 Ticket 直接塞进magic参数。
Tic = OrderSend(Symbol(), OP_SELLSTOP, Lots, NormalizeDouble(OpenPrice - HedgingLevel, Digits), 0, 0, 0, "Hedging " + DoubleToStr(Ticket, 0), Ticket, // 第 9 个参数:magic 复用手动单 ticket 0, Green);OrderSend的参数顺序是:品种、类型、手数、价格、滑点、止损、止盈、注释、magic、过期时间、颜色。第 9 位的Ticket就是配对钥匙。这样不用维护任何外部映射表,靠订单自身属性就能做 O(1) 反查,重启终端、换图表都不丢关系,比存在全局数组里稳。
配套的查找循环长这样:
Hedge = 0; Ticket = OrderTicket(); for (int j = i; j < OrdersTotal(); j++) // 从当前手动单的位置往后扫 { if (OrderSelect(j, SELECT_BY_POS, MODE_TRADES) == false) break; if (Ticket == OrderMagicNumber()) Hedge++; // magic 撞上 ticket,说明对手方在 } if (Hedge == 0) { /* 没有对冲单,建一张 */ }问题出在j = i。订单列表按开仓时间排序,对冲单是后建的,索引通常大于手动单,往后扫能扫到。但只要中途手动平过一次再重开,或者部分平仓打乱了顺序,对冲单就可能排到手动单前面,这个循环扫不到,结果是同一个手动单被重复挂上第二张、第三张对冲单。修正很便宜,把起点改成 0 全表扫一遍就行:
for (int j = 0; j < OrdersTotal(); j++) // 全表扫,别依赖索引顺序 { if (OrderSelect(j, SELECT_BY_POS, MODE_TRADES) == false) continue; if (Ticket == OrderMagicNumber()) { Hedge++; break; } // 找到一个就够 }还有一个隐性风险:magic和ticket都是 int,正常账户里 ticket 是六七位数,别的 EA 很难撞上。但如果同一账户同时挂着别人的策略,对方的 magic 恰好等于某张手动单的 ticket,这份 EA 会把对方的单认成自己的对冲单。多策略共用一个账户时,这条必须查一遍。
2.3 三段状态机:先建、再删、最后清止盈
Hedge_Assistante()的三个for循环不是随便排的,顺序决定了同一 tick 内不会出现「刚删完又重建」的抖动。
第一段扫所有MagicNumber==0 && OrderProfit()!=0的订单,认定为本图表的手动市价单,没有对手方就补一张反向 STOP。用OrderProfit()!=0过滤,是因为挂单的持仓盈亏恒为 0,这一条把 BUY LIMIT、SELL STOP 这类挂单排除在外,只处理已成交的市价单。副作用是刚开仓、点差恰好为 0 的那一瞬间 profit 也是 0,会被跳过一两个 tick,不影响结果。
第二段反过来扫MagicNumber!=0的订单,如果找不到 ticket 等于自己 magic 的手动单,且自己是挂单(OrderType()>1),就OrderDelete。注意条件里的类型判断:已经成交的对冲单类型是 OP_BUY 或 OP_SELL,不能删,删了就是把锁单平掉,锁仓直接失效。所以只删还没触发的 STOP 挂单。
第三段处理已经成交的对冲单:找到MagicNumber!=0 && OrderType()<2的订单,取其 magic 找到手动单,把手动单的止盈改成 0。这就是 V2.2 注释里那句「系统自动生成对冲单后,如果手动订单设置了止盈,则取消止盈」的落地——两边都锁住了,手动单如果还留着止盈,价格反弹到止盈位会自动平掉一条腿,剩下一条裸单,锁仓变成单边持仓。
if (OrderSelect(Ticket, SELECT_BY_TICKET) == false) break; // 这里该用 continue if (OrderTakeProfit() != 0) if (OrderModify(Ticket, OrderOpenPrice(), 0, 0, 0, 0)) Alert(Ticket, "对冲单已生成, 系统将止盈改为零,需要手动开锁!");这段里的break是第三处要改的地方:只要有一张对冲单对应的手动单已经被平掉,OrderSelect失败就跳出整个循环,后面所有对冲单都不再检查。改成continue,让它跳过这一张继续往下走。OrderModify的五个参数依次是价格、止损、止盈、过期时间、颜色,这里把止损和止盈一起清零,是有意为之——锁仓状态下不设止损,避免两条腿被分别打掉。
提示:三段循环的先后顺序不要调。把删单放到建单前面,同一个 tick 里可能先删掉旧挂单、再用新 ATR 重建一张价格不同的,图表上看着没变,实际挂单价已经漂了。
3. 把源码跑起来:编译、挂图与四个参数的取值边界
代码看懂是一回事,让它在终端里动起来是另一回事。这份源码写于 2012 年,那时候的 MQL4 编译器和现在的不是一套东西,直接双击编译大概率先吃一个报错。下面按「放文件、改兼容、挂图、验证」四步走。
3.1 从 .mq4 到图表右上角的笑脸
先把文件放进终端的 Experts 目录,路径随安装位置变化,用终端菜单「文件 → 打开数据文件夹」定位最稳:
# 典型路径,实际以终端数据目录为准 <终端数据目录>/MQL4/Experts/放进去之后在「导航」面板右键刷新,双击或拖到图表上。弹出的参数窗口里有一项「允许实时交易」,不勾选的话 EA 会挂着一个哭脸,OrderSend全部返回错误码 4109。这一步踩过的人不少,表现是 Alert 一直不弹、日志里也没有下单记录,查半天代码其实没问题。
真正要动的是版本兼容。新版编译器不再调用start(),入口改成OnTick(),extern也建议换成input:
// 兼容新版编译器:入口改名,参数声明换成 input input bool USE_ATR = true; input int PercentATR = 40; input double HedgingLevel = 30; input bool AutoTakeProfit = false; void OnTick() { Hedge_Assistante(); // 原 start() 里的唯一一行调用 }改动只有三处:extern换input(语义一样,input不允许运行期被代码改写,顺手把 2.1 里那个「参数自己变了」的问题也堵上)、int start()换void OnTick()、保留Hedge_Assistante()本体不动。#include <stdlib.mqh>保留,ErrorDescription()在里面。如果编译报'j' - variable not defined,把函数里第二个循环的j声明提到函数开头,这是因为老编译器对for内声明变量的作用域处理比较宽松,新编译器按块作用域算,第一个循环里声明的j出了循环就没了。
3.2 四个参数各自管什么,边界在哪
参数只有四个,但每个都有明确的取值区间,设错了不是不工作,是工作得莫名其妙。
| 参数 | 类型 | 默认 | 单位 | 实际作用 | 建议区间 |
|---|---|---|---|---|---|
| USE_ATR | bool | true | 无 | 决定锁仓距离走 ATR 分支还是固定点数分支 | 调试期 false,验证后 true |
| PercentATR | int | 40 | 百分比 | ATR 的放大系数,只在 USE_ATR=true 时生效 | 25 到 60 |
| HedgingLevel | double | 30 | 点 / 价格 | 锁仓距离,两种单位随 USE_ATR 切换 | 固定 20 到 50 点 |
| AutoTakeProfit | bool | false | 无 | 是否接管手动单的止盈 | 先 false,跑通再开 |
PercentATR调到 25 以下,锁仓距离贴近日常噪音,一天能被触发好几次,手续费和点差会吃掉大部分空间;调到 60 以上,等于要等一根大阴大阳才锁得住,很多时候行情已经走完了单子还没锁。40 是个折中值,但不同品种的日 ATR 差异很大,直盘和交叉盘不能共用一套参数。
HedgingLevel在USE_ATR=false时是点数,注意代码里乘的是Point不是 pip。四位报价平台上Point=0.0001,30 点就是 30 个 pip;五位平台上Point=0.00001,30 点只有 3 个 pip,锁仓距离被压缩到十分之一。这是整份源码在新平台上最容易翻车的一处,后面第 4 章展开。
AutoTakeProfit默认关闭是有道理的。打开之后 EA 会主动改你手动单的止盈,甚至直接市价平仓,等于把手动单的控制权交出去一半。先用 false 把锁仓流程跑顺,再决定要不要开。
3.3 冒烟验证:策略测试器测不了,只能手动开单
这份 EA 自己不开仓,策略测试器里跑出来的是一条平线——没有手动单,Hedge_Assistante()三段循环全部空转。这不算 bug,是设计使然。验证只能上模拟账户手动喂单。
步骤不复杂:挂到 EURUSD 的 M15 图上,确认右上角是笑脸,手动买 0.01 手,然后盯三件事。第一,图表左上角的 Comment 有没有刷出 ATR、日高日低、AtrHi/AtrLo 四行信息,刷不出来说明start()或OnTick()根本没进。第二,一两个 tick 之内有没有弹 Alert,提示「某某 ticket 的对冲单:某某 ticket 生成 SELL STOP」,价格应该是开仓价减去HedgingLevel。第三,打开终端订单列表,找到那张 SELL STOP,看它的注释是不是Hedging <手动单ticket>,magic 是不是等于手动单 ticket。这三条对上,配对逻辑就是通的。
接着验证撤单路径:手动平掉那张多单,回到订单列表,对冲挂单应该在下一个 tick 内消失。如果没消失,说明第二段循环没找到手动单,回头查 magic 有没有写进去。最后验证清止盈路径:重新手动开一张带止盈的多单,等对冲 STOP 挂上,然后手动把价格推向对冲价触发它(模拟盘可以直接市价卖一单把价格打下去),观察手动单的止盈是不是被改成 0,同时有没有弹「需要手动开锁」的 Alert。三条路径全过,这份源码才算在你手里活了。
注意:触发对冲单那一步会真实占用保证金,模拟账户里也要留够可用资金,不然
OrderSend返回 134,你会误以为是代码问题。
4. 自动止盈那段最容易翻车:17 点 / 10 点硬编码与 OrderModify 陷阱
AutoTakeProfit这一段的代码量比锁仓还多,也是整份源码里硬编码最重的地方。它做两件事:手动单浮盈够点数就直接市价平,不够但止盈位偏离就改单。听起来直白,落到不同报价精度的平台上,同一段代码的行为能差十倍。
4.1 扫描、平仓、改单的三步流程
先看主干,去掉 Alert 和错误处理后是这样:
if (AutoTakeProfit) { for (i = 0; i < OrdersTotal(); i++) { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) continue; // MagicNumber==0 且 Profit!=0:认定为本图表上的手动市价单 if (Symbol() == OrderSymbol() && OrderMagicNumber() == 0 && OrderProfit() != 0) { TP = (Symbol() == "GBPUSD") ? 17 : 10; // 硬编码点数 if (OrderType() == OP_BUY) { if (Bid - OrderOpenPrice() >= TP * Point) // 浮盈够,直接平 { if (OrderClose(OrderTicket(), OrderLots(), Bid, 2, 0) == true) return(0); // 平一单就退出整个 start } // 止盈位偏离目标超过 1 点,改单 if (OrderTakeProfit() - OrderOpenPrice() < (TP - 1) * Point || OrderTakeProfit() - OrderOpenPrice() > (TP + 1) * Point) { OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), OrderOpenPrice() + TP * Point, 0, 0); } } // OP_SELL 分支逻辑对称,方向相反 } } }逻辑说明三件事。OrderClose的第四个参数 2 是允许滑点,单位是点,五位平台上只有 0.2 个 pip,行情快的时候经常平不掉,会走 else 分支弹错误。return(0)意味着一个 tick 只处理一张手动单,手里有多张单时要等后续 tick 逐张处理,不会漏,但会慢。OrderModify的第三个参数把原止损原样带回去,只改止盈,这一点值得肯定——很多同类代码在这里把止损写成 0,一手滑就把保护单删了。
为什么是 17 和 10?2012 年英镑的点差普遍比直盘高,日内波动也大,17 个点算是给 GBPUSD 留的余量,其他品种统一 10 点。这个设定放在今天的低点差账户里明显偏小,10 个 pip 的止盈扣掉点差和佣金,剩下的空间很薄,而且完全没考虑品种的波动率差异——日元交叉盘和欧元直盘用同一个 10 点,等于用同一把尺子量两种东西。
4.2 点数口径:五位报价把 10 点变成 1 个 pip
TP * Point这一句是整段代码里最危险的一行。Point的取值取决于品种报价精度:四位报价平台Point=0.0001,五位报价平台Point=0.00001。同样是TP=10,前者是 10 个 pip,后者只有 1 个 pip。
| 报价精度 | Point 值 | TP=10 的实际距离 | 结果 |
|---|---|---|---|
| 四位(EURUSD 1.0850) | 0.0001 | 0.0010 | 10 pip,正常 |
| 五位(EURUSD 1.08500) | 0.00001 | 0.0001 | 1 pip,止盈被吃掉 |
| 三位(USDJPY 120.500) | 0.001 | 0.010 | 1 pip,同样被压缩 |
在五位平台上,Bid - OrderOpenPrice() >= 10 * Point只要价格走 1 个 pip 就成立,扣掉点差直接是负期望。表现是手动单刚开仓没几秒就被平掉,日志里一条接一条的「自动止盈」,账户余额却一路往下。这种问题不看代码根本查不出来,因为 EA 的行为完全「符合程序逻辑」。
修法是把 pip 和 point 分开,写一个统一的换算函数:
// 返回 1 个 pip 对应的价格距离 double PipSize() { if (Digits == 3 || Digits == 5) return(10 * Point); // 三位/五位报价 return(Point); // 四位/两位报价 }Digits是当前品种的小数位数,五位报价和三位报价(日元系)都是「多一位」的格式,1 pip 等于 10 个 point。这个判断不依赖品种名,换任何品种都成立。
4.3 把硬编码止盈改成可配置项
改完精度问题,下一刀砍硬编码。把 17 和 10 提成 input,按 pip 配置,不同品种各给各的值:
input double TakeProfitPips = 10; // 默认品种止盈,单位 pip input double GBPUSD_TakeProfitPips = 17; // 英镑单独一档 double TP_Distance() { if (Symbol() == "GBPUSD") return(GBPUSD_TakeProfitPips * PipSize()); return(TakeProfitPips * PipSize()); }调用处把TP * Point全部换成TP_Distance(),TP这个局部变量就可以删掉。这样在四位和五位平台上跑出来的是同一个距离,参数面板上写 10 就是 10 个 pip,不用再心算。
再往前走一步,可以把固定 pip 换成 ATR 的倍数,和锁仓距离用同一套波动率口径:
input double TPMultiplier = 0.5; // 止盈 = 0.5 倍日 ATR double TP_Distance() { return(iATR(NULL, PERIOD_D1, 14, 1) * TPMultiplier); }shift=1用昨天走完的日线,当天内止盈距离固定,不会随盘中波动漂移。波动大的品种自动给宽止盈,波动小的自动收窄,比按品种名写死一档要合理。改到这里,AutoTakeProfit才算是能开的状态。
提示:改完精度换算,先在模拟盘上手动开一张 0.01 手多单,等浮盈刚过 10 pip 看它是不是立刻平。平得太早说明
PipSize()没生效,平得太晚说明Digits判断写反了。
5. 避坑与排查:五个会真金白银交学费的地方
下面这五条都是我在拆这类对冲助手时真实撞过的,每一条都能在日志或订单列表里找到明确现象。碰上了别急着怀疑平台,先按「现象 → 原因 → 解决」对一遍。
5.1 同一个手动单被挂了两三张对冲单
现象:订单列表里一个 ticket 对应多张 SELL STOP,注释都是Hedging <同一个ticket>,锁仓手数变成手动单的两三倍。
原因:2.2 里那个for (int j = i; ...)从当前手动单的位置往后扫,对冲单索引一旦排到前面就扫不到,Hedge保持 0,代码认为没有对手方,再建一张。
解决:起点改成 0 全表扫,找到一张就break。顺手在OrderSend之前加一道检查,同 magic 的挂单数量大于等于 1 就直接跳过,双保险。
5.2 对冲单成交后,手动单的止盈没被清零
现象:对冲单已经变成持仓,手动单的止盈还挂在那里,价格反弹到止盈位手动单被平,剩下一张裸的空单。
原因:第三段循环里的if (OrderSelect(Ticket, SELECT_BY_TICKET) == false) break;。只要循环前面遇到一张已经平仓的手动单,OrderSelect失败就跳出整个for,后面的对冲单全部不处理。
解决:break改continue。改完在模拟盘上故意先平一张手动单、再让另一张的对冲单成交,确认第二张的止盈照样被清零。
5.3 图表卡住十几秒不响应,行情跳空时尤其明显
现象:点差拉大或者数据发布那几秒,图表上的 Comment 停住不动,等恢复之后价格已经跑出去一截。
原因:改止盈成功之后有一句Sleep(10000),整整十秒。start()或OnTick()是单线程的,睡十秒等于十秒内不处理任何 tick,挂单、撤单、清止盈全部停摆。
解决:直接删掉。如果本意是防止同一个 tick 内反复改单,用一个static datetime lastModify记时间戳,两次改单间隔小于 5 秒就跳过,比阻塞整个线程温和得多。
static datetime lastModify = 0; if (TimeCurrent() - lastModify < 5) return; lastModify = TimeCurrent();5.4 参数面板里的 HedgingLevel 自己变成了 0.00xx
现象:明明设的是 30,跑一段时间打开属性窗口,显示的是 0.0032 这种小数,改回 30 之后下次又变了。
原因:extern变量在运行期被HedgingLevel = iATR(...) * PercentATR / 100改写,MT4 会把改写后的值回写到参数面板。这不是 bug,是老版extern的语义。
解决:把extern换成input。input声明的变量在代码里赋值会直接编译报错,逼你用另一个局部变量承接计算结果:
input double HedgingLevelInput = 30; // 面板上只读 double HedgeDistance() { if (USE_ATR) return(iATR(NULL, PERIOD_D1, 14, 1) * PercentATR / 100); return(HedgingLevelInput * PipSize()); }5.5 删掉一张对冲挂单后,另一张没被删掉
现象:手动平了两张单,只消失了一张对冲挂单,另一张留在了订单列表里,变成孤儿单。
原因:第二段循环里边遍历边OrderDelete。删掉一张之后订单总数减一,后面的订单索引整体前移一位,循环变量i照常加一,正好跳过紧跟着的那一张。
解决:倒序遍历,从OrdersTotal()-1往下走,删除操作不影响尚未处理的低位索引。
for (i = OrdersTotal() - 1; i >= 0; i--) // 删单必须倒序 { if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) continue; // ...原有判断与 OrderDelete }6. 从助手到策略:加码接入点与上线前的自查清单
这份源码名字里带「顺势加码」,但正文里其实没有加码逻辑,只有锁仓和止盈。加码要自己接,接入点选在第三段循环之后——对冲单已经成交、方向被市场确认,此时按原方向补一仓才算「顺势」。
// 对冲单成交说明原方向被否定,反方向加码需谨慎; // 更稳的做法是等对冲单被手动平掉、原方向恢复后再加 if (HedgeFilled && AllowAddOn) { double addLots = OrderLots() * AddOnRatio; // 加码手数按比例递减 int t = OrderSend(Symbol(), OP_BUY, NormalizeDouble(addLots, 2), Ask, 3, 0, 0, "AddOn", 88888, 0, Blue); if (t < 0) Print("加码失败,错误码:", GetLastError()); }AddOnRatio建议从 0.5 起步,每加一次乘 0.5 递减,别用等手数加码——锁仓状态下等手数加码,一次方向误判就能把前面几次的浮盈全吐回去。加码单用独立 magic(比如 88888),不要和手动单的 0、对冲单的 ticket 混在一起,否则第二段循环会把它当成对冲单处理。
上线前的自查按这张表走一遍,每一条都能在模拟盘上直接验证:
| 检查项 | 验证方法 | 通过标准 |
|---|---|---|
| 入口是否被调用 | 看图表 Comment | 四行信息随 tick 刷新 |
| 报价精度 | 手动开 0.01 手,看止盈距离 | 五位平台上 10 pip 不是 1 pip |
| 配对正确 | 订单列表看对冲单 magic | 等于手动单 ticket |
| 撤单路径 | 平掉手动单 | 对冲挂单一个 tick 内消失 |
| 清止盈路径 | 触发对冲单 | 手动单止盈变 0 并弹 Alert |
| 多单场景 | 同时开两张手动单 | 各有一张对冲单,互不串号 |
最后一条是我自己的习惯:每次改完这份 EA,哪怕只改了一个参数,也要在模拟盘上把「开单 → 挂对冲 → 平手动单 → 触发对冲 → 清止盈」这条链路完整走一遍,一步不跳。早年我图省事,改完PipSize()直接上实盘,结果五位平台上止盈被压缩成 1 个 pip,一晚上平了四十多单,全是给点差打工。从那以后我每次动点数相关的代码,都强制先在模拟盘上手动喂三张单跑完整链路。希望帮到你。
本文还有配套的精品资源,点击获取