使用PSAR、Heiken Ashi和深度学习进行交易·综合运用
「多指标联合过滤的开仓判定逻辑」
这段逻辑把 PSAR、SMA、RSI、HA 蜡烛和自研预测分类揉在一起,只有全部同向才放信号。多头条件要求收盘价同时站上 PSAR[1] 和 SMA[1],RSI[1] 必须小于 60 避免追高,且最近两根 HA 蜡烛都是阳线(haClose > haOpen),外加预测类为 PRICE_UP、趋势函数返回 1。 空头是镜像:收盘价低于 PSAR[1] 与 SMA[1],RSI[1] 大于 40,最近两根 HA 为阴线,预测类 PRICE_DOWN、趋势 -1。注意 RSI 阈值刻意留了 40~60 的缓冲带,不是超买超卖那种极端过滤。 调试打印把每个变量都甩进日志,实盘前建议先在策略测试器里跑一遍,看 longCondition / shortCondition 的命中频率。外汇与贵金属波动剧烈,这类多条件共振也只是提高概率,不等于胜率保证。 真正下单前还会查 PositionsTotal()==0 防重复开仓,止损取 ATR 倍数与经纪商最小止损的较大值,止盈用 TPATRMultiple * atrBuffer[1],参数化很清晰,直接调 SLATRMultiple / TPATRMultiple 就能改风险敞口。
Print("Failed to copy indicator data"); class="kw">return; } CalculateHeikinAshi(); if(ArraySize(haOpen) < class="num">3 || ArraySize(haClose) < class="num">3) { Print("Not enough Heikin Ashi data"); class="kw">return; } PredictPrice(); class="type">int trend = GetTrend(); class="type">bool longCondition = close > psarBuffer[class="num">1] && close > smaBuffer[class="num">1] && rsiBuffer[class="num">1] < class="num">60 && haClose[class="num">1] > haOpen[class="num">1] && haClose[class="num">2] > haOpen[class="num">2] && ExtPredictedClass == PRICE_UP && trend == class="num">1; class="type">bool shortCondition = close < psarBuffer[class="num">1] && close < smaBuffer[class="num">1] && rsiBuffer[class="num">1] > class="num">40 && haClose[class="num">1] < haOpen[class="num">1] && haClose[class="num">2] < haOpen[class="num">2] && ExtPredictedClass == PRICE_DOWN && trend == -class="num">1; class=class="str">"cmt">// Debug printing Print("--- Debug Info ---"); Print("Close: ", close, " PSAR: ", psarBuffer[class="num">1], " SMA: ", smaBuffer[class="num">1]); Print("RSI: ", rsiBuffer[class="num">1], " HA Close[class="num">1]: ", haClose[class="num">1], " HA Open[class="num">1]: ", haOpen[class="num">1]); Print("HA Close[class="num">2]: ", haClose[class="num">2], " HA Open[class="num">2]: ", haOpen[class="num">2]); Print("ExtPredictedClass: ", ExtPredictedClass, " Trend: ", trend); Print("Long Condition: ", longCondition, " Short Condition: ", shortCondition); if(longCondition) { Print("Long Condition Met"); if(PositionsTotal() == class="num">0) { class="type">class="kw">double atrStopLoss = SLATRMultiple * atrBuffer[class="num">1]; class="type">class="kw">double minStopLoss = GetMinimumStopLoss(); class="type">class="kw">double sl = close - MathMax(atrStopLoss, minStopLoss); class="type">class="kw">double tp = close + TPATRMultiple * atrBuffer[class="num">1];
◍ 挂单前的止损底线与移动止损循环
空单触发时,止损不是简单用 ATR 倍数算完就提交。代码里先取 atrStopLoss = SLATRMultiple * atrBuffer[1],再拿 GetMinimumStopLoss() 返回的经纪商底线做 MathMax 比较,确保 sl = close + MathMax(atrStopLoss, minStopLoss) 不会因点差或 stops level 被拒单。 GetMinimumStopLoss 这个函数把 SYMBOL_SPREAD 和 SYMBOL_TRADE_STOPS_LEVEL 都乘上 SYMBOL_POINT 转成绝对价格,最后返回 spread*2 与 minStopLevel 的较大值。外汇与贵金属点差跳动频繁,用双倍点差兜底能降低滑点拒单概率。 ManageTrailingStop 从 PositionsTotal()-1 倒序遍历持仓,用 PositionSelectByTicket 锁定当前品种订单,读出开仓价、当前 SL 与 TP 后准备跟踪。倒序是为了在循环内平掉或改单时不破坏未处理仓位索引。 开 MT5 把这段塞进 EA,把 SLATRMultiple 设 2、TPATRMultiple 设 3 跑回测,看 EURUSD 在 2023 年 H1 的拒单率是否明显低于不取最小止损的写法。
class="type">class="kw">double GetMinimumStopLoss() { class="type">class="kw">double spread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) * SymbolInfoDouble(Symbol(), SYMBOL_POINT); class="type">class="kw">double minStopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(Symbol(), SYMBOL_POINT); class="kw">return MathMax(spread * class="num">2, minStopLevel); class=class="str">"cmt">// Usamos el doble del spread como mínimo } class=class="str">"cmt">// Agregar esta función para manejar el trailing stop class="type">void ManageTrailingStop() { for(class="type">int i = PositionsTotal() - class="num">1; i >= class="num">0; i--) { if(PositionSelectByTicket(PositionGetTicket(i))) { if(PositionGetString(POSITION_SYMBOL) == Symbol()) { class="type">class="kw">double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN); class="type">class="kw">double currentStopLoss = PositionGetDouble(POSITION_SL); class="type">class="kw">double currentTakeProfit = PositionGetDouble(POSITION_TP);
多空双向的移动止损改写逻辑
这段代码片段处理的是已开仓部位的追踪止损(trailing stop)调整,分别覆盖多头与空头两种情况。核心思路是:只有当新算出的止损价位比当前止损单向推进了至少一个 TrailingStep 步长时,才允许修改,避免每跳 tick 都发修改指令刷爆服务器。 多头分支里,新止损 = 当前买价 BID 减去 TrailingStop 个点值,再用 NormalizeDouble 按品种精度 Digits 对齐。若 newStopLoss 大于原止损加上 TrailingStep 点值,就调用 trade.PositionModify 把止损推到新位,并打印日志。 空头分支反过来:新止损 = 卖价 ASK 加上 TrailingStop 点值,且只有 newStopLoss 小于原止损减去 TrailingStep 点值时才下移。外汇与贵金属杠杆高,追踪止损能锁利但也可能在毛刺行情中被扫损,参数 TrailingStop 与 TrailingStep 建议在 MT5 策略测试器里按品种波动率实测,EURUSD 常见点值精度为 4~5 位。
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { class="type">class="kw">double newStopLoss = NormalizeDouble(SymbolInfoDouble(Symbol(), SYMBOL_BID) - TrailingStop * SymbolInfoDouble(Symbol(), SYMBOL_POINT), Digits()); if(newStopLoss > currentStopLoss + TrailingStep * SymbolInfoDouble(Symbol(), SYMBOL_POINT)) { if(trade.PositionModify(PositionGetTicket(i), newStopLoss, currentTakeProfit)) { Print("Trailing stop ajustado para posición larga. Nuevo SL: ", newStopLoss); } } } else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) { class="type">class="kw">double newStopLoss = NormalizeDouble(SymbolInfoDouble(Symbol(), SYMBOL_ASK) + TrailingStop * SymbolInfoDouble(Symbol(), SYMBOL_POINT), Digits()); if(newStopLoss < currentStopLoss - TrailingStep * SymbolInfoDouble(Symbol(), SYMBOL_POINT)) { if(trade.PositionModify(PositionGetTicket(i), newStopLoss, currentTakeProfit)) { Print("Trailing stop ajustado para posición corta. Nuevo SL: ", newStopLoss); } } }
「十万美金起步跑出的保守派画像」
把初始存款设为 10,000 美元做历史模拟,EA 最终吐出 17 个单位的净盈利。绝对值很小,但余额曲线是缓慢向右上方的,没有大起大落,说明这套逻辑靠的是时间换空间而不是重仓搏单边。 几个核心比率值得记一下:盈利因子 4.39,意味着每冒 1 单位风险平均拿回 4.39 单位;恢复因子 4.48,说明从回撤里爬出来的效率不差;夏普 5.25 偏高,但结合绝对利润薄,更像是仓位极轻、风险敞口极小换来的「好看」。外汇和贵金属本身高杠杆高风险,这种低波动特征在实盘里可能扛不住滑点与点差突变。 拆交易明细:总共 16 笔,多空各 8 笔。多头胜率 62.5%,空头只有 37.5%,偏多头的捕捉能力明显更强。整体胜率 50%,盈利不靠命中率,而靠盈亏比——最大盈利和平均盈利都为正的数字结构,验证了「赚的时候拿得住」。 回撤端几乎可以忽略:余额回撤绝对值 2 个单位,相对回撤 0.02%。这是把资本保全放在第一位的写法,震荡市里活得久,但也解释了为什么总利润上不去。想在 MT5 里复现,先把 Deposits 和订单手数按原文比例缩放到自己账户,再跑一遍 16 笔的成交分布看多头偏好是否随品种漂移。
◍ 把工具请下神坛
回测里 EURUSD_D1 的 ONNX 模型配合 MT5 EA,走出了低回撤、慢增长的正向曲线,最大回撤压得很低,但规模始终没跑出爆发式利润。这类组合系统的内核定位是风控优先,不是利润最大化,对外汇和贵金属这种高杠杆市场来说,它更适合求稳的人。 人类直觉负责找边界,AI 负责在边界内做系统化执行,两者接起来才像样。真要上实盘,先开 MT5 把 PHD_Final.mq5 跑一遍 2024 年 EURUSD_D1 的回测,看低回撤是不是你能接受的节奏,再谈细化和加仓。