构建K线图趋势约束模型(第九部分):多策略EA(第一部分)·综合运用
(3/3)·单一RSI约束在震荡市频频失效,本文用模块化合入多策略与魔法数字补上最后一块拼图
用 Magic 号隔离 EA 持仓再反向清仓
在趋势跟随逻辑里,最容易被忽略的是多 EA 同台时的持仓串味。下面这段先按持仓 ticket 取出当前单,并只用 MagicNumber 做身份过滤,避免把别的脚本开的单误平掉。 ulong ticket = PositionGetInteger(POSITION_TICKET); if (currentMagicNumber == MagicNumber) // Ensure only this EA's orders are checked {
| if ((position_type == POSITION_TYPE_BUY && is_downtrend) |
|---|
(position_type == POSITION_TYPE_SELL && is_uptrend)) { trade.PositionClose(ticket); } } 逐行拆解:第1行用 PositionGetInteger(POSITION_TICKET) 抓出当前遍历到的持仓 ticket;第2行比对 currentMagicNumber 与本 EA 的 MagicNumber,不等就直接跳过;第4~5行判断「持多单却走 downtrend」或「持空单却走 uptrend」这种趋势反转情形;第6行才真正发平仓指令。 实盘里若 MagicNumber 设成 888888 而另一策略也用同值,这段就会交叉平仓。开 MT5 把自家 EA 的 Magic 改成非常规随机数(如 20240517),回测里能直接看到冲突单减少。外汇与贵金属杠杆高,误平可能瞬间吃掉缓冲,参数隔离必须先于信号逻辑。
class="type">class="kw">ulong ticket = PositionGetInteger(POSITION_TICKET); if (currentMagicNumber == MagicNumber) class=class="str">"cmt">// Ensure only this EA&class="macro">#x27;s orders are checked { if ((position_type == POSITION_TYPE_BUY && is_downtrend) || (position_type == POSITION_TYPE_SELL && is_uptrend)) { trade.PositionClose(ticket); } }
「按魔术码隔离持仓再挂卖单与移动止损」
EA 在开仓前会先遍历当前品种的全部持仓,用 PositionGetInteger(POSITION_MAGIC) 读出每单的魔术码,只有与自身 MagicNumber 相等时才置 open_position=true 并 break。这样多 EA 同跑一个品种时,不会把别人的单子误认成自己的,避免重复下单。 若扫完一圈没找到同魔术码持仓,就取 SYMBOL_BID 作为卖价,按 StopLoss*_Point 向上推止损、TakeProfit*_Point 向下推止盈,调 trade.Sell 下卖单。下成功 Print 出魔术码,失败则 Print GetLastError 返回码,方便你直接在 MT5 Experts 日志里抓错误。 移动止损段用 for(int i=0;i<PositionsTotal();i++) 重扫持仓,PositionSelect 按符号选中后再次比对魔术码。以买仓为例:当 SYMBOL_BID 与开仓价之差大于 TrailingStop*_Point,且原 SL 小于 current_price-TrailingStop*_Point 时,才把止损改到 current_price-TrailingStop*_Point。外汇与贵金属杠杆高,移动止损只护住浮盈但无法消除跳空风险,参数请按品种波动微调。
class="type">long currentMagicNumber = PositionGetInteger(POSITION_MAGIC); if (currentMagicNumber == MagicNumber) { open_position = true; class="kw">break; } } } if (!open_position) { class="type">class="kw">double price = SymbolInfoDouble(_Symbol, SYMBOL_BID); class="type">class="kw">double sl = price + StopLoss * _Point; class="type">class="kw">double tp = price - TakeProfit * _Point; class=class="str">"cmt">// Open a sell order if (trade.Sell(Lots, _Symbol, price, sl, tp, "TrendFollowing Sell")) Print("Sell order placed with Magic Number: ", MagicNumber); else Print("Error placing sell order: ", GetLastError()); } } class=class="str">"cmt">// Apply trailing stop for (class="type">int i = class="num">0; i < PositionsTotal(); i++) class=class="str">"cmt">// Correct loop initialization { if (PositionGetSymbol(i) == _Symbol && PositionSelect(PositionGetSymbol(i))) class=class="str">"cmt">// Select position by symbol { class="type">long currentMagicNumber = PositionGetInteger(POSITION_MAGIC); if (currentMagicNumber == MagicNumber) class=class="str">"cmt">// Apply trailing stop only to this EA&class="macro">#x27;s positions { class="type">class="kw">double price = PositionGetDouble(POSITION_PRICE_OPEN); class="type">class="kw">double stopLoss = PositionGetDouble(POSITION_SL); class="type">class="kw">double current_price; if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID); if (current_price - price > TrailingStop * _Point) { if (stopLoss < current_price - TrailingStop * _Point) { trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price - TrailingStop * _Point, PositionGetDouble(POSITION_TP)); } }
◍ 空单 trailing stop 的回调逻辑
这段处理的是已有 SELL 持仓时的移动止损分支。先通过 PositionGetInteger(POSITION_TYPE) 判断持仓类型,若为 POSITION_TYPE_SELL,则取 SYMBOL_ASK 作为当前报价——卖单是用 ask 价平仓,因此追踪基准必须用卖价而非买价。 核心判断是 price - current_price > TrailingStop * _Point:price 一般是曾经的最优价位,当价格从开仓后回撤超过设定的 TrailingStop 点数,才触发保护动作。这里用的是「回撤触发」而非「创新低跟随」,逻辑上更偏向锁定已有浮盈。
| 修改条件里 stopLoss > current_price + TrailingStop * _Point | stopLoss == 0 意味着:要么原止损还远在更上方(说明还没被推过),要么从未设止损,才会把止损位推到 current_price + TrailingStop*_Point。最后调用 trade.PositionModify 只改止损、保留原 TP。外汇与贵金属杠杆高,这类回撤式追踪在剧烈反转行情中可能来不及成交,开 MT5 用策略测试器跑 EURUSD M15 能直接验证触发频率。 |
|---|
}
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if (price - current_price > TrailingStop * _Point)
{
if (stopLoss > current_price + TrailingStop * _Point || stopLoss == class="num">0)
{
trade.PositionModify(PositionGetInteger(POSITION_TICKET), current_price + TrailingStop * _Point, PositionGetDouble(POSITION_TP));
}
}
}
}
}
}
}
class=class="str">"cmt">//+------------------------------------------------------------------+Boom 500 指数上的实测表现
在 Boom 500 指数上跑过这套 EA,主要观察了订单的触发与持仓分布。一个明显的短板是:同屏可能挂出多笔订单,去重逻辑还得补,否则实盘容易被重复信号刷屏。 用 10,000 美元的模拟账户做验证,系统整体走出正向结果;但账户规模一缩、或者切到真实账户,曲线大概率会变形,不能拿模拟表现直接外推。 这套东西本质是用于教学、实验和研究,不保证盈利。外汇与指数类品种杠杆高、滑点跳空频繁,接实盘前务必先在 MT5 策略测试器里用自己的点差重跑一遍。
「把工具请下神坛」
这套趋势约束 EA 只落地了七种策略里的第一种,核心是用双均线判方向、RSI 过滤超买超卖,再靠 Magic Number 把不同策略的订单隔开管理。附件 Trend_Constraint_Expert.mq5 约 7.7 KB,编译跑一遍就能看到均线+RSI 共振的开仓逻辑实际表现。 外汇和贵金属杠杆高、滑点跳空频繁,回测顺滑不等于实盘稳,Magic Number 配错就可能把两套策略的平仓搞混。 剩下六种策略是空位不是承诺,拿这份源码当骨架改参数、加信号,比等现成圣杯实在。