根据品种和 EA 的 ORDER_MAGIC 分析余额/净值图形·综合运用
(3/3)· 一个账户跑多个EA却看不出谁在赚谁在亏?本篇用分策略余额/净值图与MFE-MAE分布收尾整套诊断
◍ 用符号与魔术码过滤成交记录
在 MT5 的成交历史遍历里,先按交易品种和 EA 魔术码做双重过滤,能避免把别的品种或手动单误算进策略统计。上面这段代码就是典型的入口筛子:若指定了品种字符串且当前成交不属于该品种,直接 continue 跳过;若指定了非 ULONG_MAX 的魔术码且成交魔术码不匹配,也同样跳过。 这种写法在写持仓监控或盈亏汇总脚本时很实用。比如你只关心黄金 XAUUSD 上魔术码为 888 的网格单,把 sSymbol 设为 "XAUUSD"、uMagic 设为 888,循环里其余成交一律不处理,回测或实盘统计速度都会更干净。 外汇与贵金属杠杆高、滑点跳空频繁,过滤逻辑写错可能把跨品种亏损并进来误导判断,上线前建议在策略测试器用历史成交跑一遍确认条数。
if(sSymbol!="") if(deal_symbol!=sSymbol) class="kw">continue; if(uMagic!=ULONG_MAX) if(deal_magic!=uMagic) class="kw">continue; class=class="str">"cmt">//--- 仅买入或卖出
「把每笔持仓的极端浮动盈亏记进数组」
MFE(最大盈利)和 MAE(最大亏损)捕捉的是单笔订单从开仓到平仓期间出现过的最佳与最差浮动状态。把它们和该笔订单的最终财务结果放在一起,X 轴放盈亏点数、Y 轴放 MFE 或 MAE 点数,就能画出分布散点图,直观看策略是“拿不住利润”还是“扛不住回撤”。 记账靠两个全局数组:m_arr_pos_id 存持仓 ID,m_arr_mfe_mae 是二维数组,第二维三个槽分别是 [0] MFE、[1] 最终财务结果、[2] MAE。两个数组下标 i 严格一一对应,m_arr_pos_id[i] 永远指向 m_arr_mfe_mae[i] 的那一笔,尺寸在 GetHistory 里统一扩。 入场时新建元素,三个值先清零;持仓在列且浮亏 -20.2 时记浮亏、财务结果 0;浮盈 +5.81 时记浮盈、财务结果 0;浮盈 -3.06 同理。规则只有一条:只要还没平仓,总体财务结果就是 0,浮盈归到 MFE 或 MAE 里。 出场分四种 deal_entry:IN 建仓、OUT 平仓、INOUT 反转、OUT_BY 反向单抵销。OUT 和 OUT_BY 要按手数比对 ArrOpenPositions,量相同就删记录写 [0.0][财务结果],量不同就调剩余仓量;INOUT 反转直接改类型和量。每类收尾都把浮盈置 0、写入总体财务结果到 m_arr_mfe_mae。 对话框要加两块画布:余额/净值线图,以及 MFE、MAE 散点图。重算历史时若在 GetHistory 里刷浮盈,就写 [浮盈][财务结果 0.0] 进数组,别和已平仓的 [0.0][财务结果] 弄混。外汇与贵金属杠杆高,MFE/MAE 只揭示历史分布,不代表未来回撤可控。
class="type">long m_arr_pos_id[]; class="type">class="kw">double m_arr_mfe_mae[][class="num">3]; class=class="str">"cmt">// [][class="num">0] - mfe, [][class="num">1] - 最终财务结果,[][class="num">2] - mae if(deal_symbol=="") DebugBreak(); ArrOpenPositions.Add(HistoryDeal); class=class="str">"cmt">//--- mfe, mae class="type">int size=ArraySize(m_arr_pos_id); ArrayResize(m_arr_pos_id,size+class="num">1,class="num">10); ArrayResize(m_arr_mfe_mae,size+class="num">1,class="num">10); m_arr_pos_id[size]=deal_position_ID; class=class="str">"cmt">// [][class="num">0] - mfe, [][class="num">1] - 最终财务结果,[][class="num">2] - mae m_arr_mfe_mae[size][class="num">0]=class="num">0.0; m_arr_mfe_mae[size][class="num">1]=class="num">0.0; m_arr_mfe_mae[size][class="num">2]=class="num">0.0; class="kw">continue; } class=class="str">"cmt">//--- if(deal_entry==DEAL_ENTRY_OUT) class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 加入 Mfe Mae 结果 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void AddResultMfeMae(class="kw">const class="type">long pos_id,class="kw">const class="type">class="kw">double floating_profit,class="kw">const class="type">class="kw">double financial_result) { class=class="str">"cmt">// [][class="num">0] - mfe(盈利), [][class="num">1] - 最终财务结果,[][class="num">2] - mae(亏损) class=class="str">"cmt">//--- 搜索 pos_id class="type">int position=-class="num">1; class="type">int size=ArraySize(m_arr_pos_id); for(class="type">int i=class="num">0;i<size;i++) if(m_arr_pos_id[i]==pos_id) { position=i; class="kw">break; } if(position==-class="num">1)
用 MFE/MAE 数组抓取浮盈浮亏极值
这段代码负责在持仓生命周期内持续刷新最大有利变动(MFE)与最大不利变动(MAE)。逻辑很直接:浮亏为 0 时直接 return 不做记录;浮盈为正时,若当前 floating_profit 超过已存 MFE(数组索引 0)则更新;浮亏为负时,若比已存 MAE(数组索引 2)更小则更新,索引 1 始终存 financial_result。 下面三行调用给出了具体数值样本:AddResultMfeMae(pos_id,-20.2,0.0) 表示某笔持仓曾浮亏 20.2 点但平仓盈亏为 0;AddResultMfeMae(pos_id,5.81,0.0) 是浮盈 5.81 点未实现离场;AddResultMfeMae(pos_id,0.0,-3.06) 则是无浮盈、实亏 3.06。 在 MT5 里把这套数组接进你自己的持仓管理类,就能复盘每笔单子“曾经走到过哪里”。外汇与贵金属杠杆高,浮盈回吐和放大亏损都很快,MFE/MAE 统计只描述历史分布,不预示下一笔走向。
class="kw">return; class=class="str">"cmt">//--- if(floating_profit==class="num">0.0) class="kw">return; if(floating_profit>class="num">0.0) class=class="str">"cmt">// profit { if(m_arr_mfe_mae[position][class="num">0]<floating_profit) m_arr_mfe_mae[position][class="num">0]=floating_profit; } else class=class="str">"cmt">// loss { if(m_arr_mfe_mae[position][class="num">2]>floating_profit) m_arr_mfe_mae[position][class="num">2]=floating_profit; } m_arr_mfe_mae[position][class="num">1]=financial_result; } AddResultMfeMae(pos_id,-class="num">20.2,class="num">0.0); AddResultMfeMae(pos_id,class="num">5.81,class="num">0.0); AddResultMfeMae(pos_id,class="num">0.0,-class="num">3.06);
◍ 最后一句大实话
把多个 EA 跑在同一个对冲账户里,靠 ORDER_MAGIC 拆开看每个策略的余额与净值曲线,这套思路在 MT5 上确实能落地。原文附的 Accounting_positions_on_history.mq5 主程序 81.59 KB,配套 HistoryDeal.mqh 仅 6.66 KB,读者可直接下载 MQL5.zip(26.34 KB)在 MT5 里加载验证。 但评论区 Sergei Lebedev 指出的坑得记牢:MT5 的 DEAL_PROFIT 默认不按 MAGIC 隔离,跨周期或多 EA 同品种平仓时,原文里 _balance=m_balance+deal_commission+deal_swap+deal_profit 的求和方式可能算错真实盈亏,尤其涉及非美元基准的跨市场品种。外汇与贵金属本身杠杆高、回撤快,这类拆分统计只帮你看清贡献度,不预示任何盈利。 真要拿去用,先开个模拟账户把默认起始日期改成开户日,避免 EgorKim 遇到的挂起吃 2GB 内存的问题,再逐 Magic 比对曲线。