样本: 400 笔 · 盈亏-MAE 相关 -0.37 · 盈亏-MFE 相关 0.72
盈亏与 MAE 负相关 (-0.37):逆向偏移越大越易亏,设 SL 合理。SL 候选 = 亏损笔 MAE 75 分位 ≈ 38 点。
盈亏与 MFE 正相关 (0.72):能跑到 X 点的笔更易盈利,TP 候选 = 盈利笔 MFE 中位 ≈ 45 点。
蓝虚线 = 推荐的 SL/TP 候选阈值。MAE 图:右侧红点=逆向走很远还亏=该早止损;MFE 图:右侧绿点=涨得高最终赚=TP 可放到此处。
圈=理论最优组合。色越绿=净盈利越高。注意"宽绿区"比"单点深绿"更稳健。
MT5 标准 xlsx 报告不含逐笔 MAE/MFE。需在 EA 的 OnDeinit 里加如下代码导出 CSV,再喂给本工具:
// ====== MAE/MFE 日志片段(粘贴进 EA) ====== // 在文件顶部加: #include <Trade\DealInfo.mqh> #include <Trade\PositionInfo.mqh> // 在 OnDeinit(const int reason) 末尾加: void ExportMAEMFE() { string fname = "mae_mfe_" + TimeToString(TimeCurrent(), TIME_DATE) + ".csv"; int h = FileOpen(fname, FILE_WRITE | FILE_CSV | FILE_ANSI, ','); if(h == INVALID_HANDLE) { Print("MAE/MFE: 文件打开失败"); return; } FileWrite(h, "ticket","direction","open_time","close_time","open_price","close_price", "mae_points","mfe_points","profit_money"); HistorySelect(0, TimeCurrent() + 86400); int total = HistoryDealsTotal(); // 按订单(order)配对 in/out for(int i = 0; i < total; i++) { ulong dealIn = HistoryDealGetTicket(i); if(HistoryDealGetInteger(dealIn, DEAL_ENTRY) != DEAL_ENTRY_IN) continue; long order = HistoryDealGetInteger(dealIn, DEAL_ORDER); ulong dealOut = 0; // 找同 order 的 out 成交 for(int j = i + 1; j < total; j++) { ulong d = HistoryDealGetTicket(j); if(HistoryDealGetInteger(d, DEAL_ORDER) == order && HistoryDealGetInteger(d, DEAL_ENTRY) == DEAL_ENTRY_OUT) { dealOut = d; break; } } if(dealOut == 0) continue; datetime tIn = (datetime)HistoryDealGetInteger(dealIn, DEAL_TIME); datetime tOut = (datetime)HistoryDealGetInteger(dealOut, DEAL_TIME); double pIn = HistoryDealGetDouble(dealIn, DEAL_PRICE); double pOut = HistoryDealGetDouble(dealOut, DEAL_PRICE); long type = HistoryDealGetInteger(dealIn, DEAL_TYPE); // DEAL_TYPE_BUY / SELL double profit = HistoryDealGetDouble(dealOut, DEAL_PROFIT) + HistoryDealGetDouble(dealOut, DEAL_SWAP) + HistoryDealGetDouble(dealOut, DEAL_COMMISSION); string dir = (type == DEAL_TYPE_BUY) ? "long" : "short"; // 扫描持仓期间最高/最低价算 MAE/MFE(点) double mfe = 0, mae = 0; double pt = SymbolInfoDouble(_Symbol, SYMBOL_POINT); for(datetime t = tIn; t <= tOut; t += PeriodSeconds()) { double hi = iHigh(_Symbol, PERIOD_M1, iBarShift(_Symbol, PERIOD_M1, t, false)); double lo = iLow (_Symbol, PERIOD_M1, iBarShift(_Symbol, PERIOD_M1, t, false)); if(hi <= 0 || lo <= 0) continue; if(type == DEAL_TYPE_BUY) { double fav = (hi - pIn) / pt; // 有利 double adv = (pIn - lo) / pt; // 不利 if(fav > mfe) mfe = fav; if(adv > mae) mae = adv; } else { double fav = (pIn - lo) / pt; double adv = (hi - pIn) / pt; if(fav > mfe) mfe = fav; if(adv > mae) mae = adv; } } FileWrite(h, order, dir, TimeToString(tIn), TimeToString(tOut), DoubleToString(pIn, _Digits), DoubleToString(pOut, _Digits), DoubleToString(mae, 1), DoubleToString(mfe, 1), DoubleToString(profit, 2)); } FileClose(h); Print("MAE/MFE 已导出: ", fname); } // 在 OnDeinit 里调用: ExportMAEMFE(); // ====== 片段结束 ======