MQL5 简介(第 11 部分):MQL5 中使用内置指标的初学者指南(二)·综合运用
在图上标出 RSI 与价格的背离低点
做背离识别时,光算数值不够,得把关键拐点直接画在 MT5 图表上,否则复盘时根本分不清哪根 K 线对应哪个 RSI 谷。下面这段脚本把 RSI 子窗口的两个低点标成「L」和「LL」,字体 15、黑色,同时在主图对应价格低点拉一条趋势线并标「L」「HL」。 标价格用的对象是 OBJ_TREND,时间轴取 rsi_low_time 与 new_rsi_low_time,价格轴取 corresponding_low_value 与 new_corresponding_low_value,这样主图趋势线和 RSI 窗口的低点就对齐了。注意 RSI 文本用子窗口号 1,价格文本和趋势线用主窗口 0。 后续要抓高点背离,先声明一批变量:rsi_high_value、corresponding_high_value、corresponding_high_ma、rsi_high_time,以及记录最大价格的整型 maximum_value_high,还有新高点用的 new_rsi_high_value / new_rsi_high_time / new_corresponding_high_value。 实际扫描只循环最近 30 根 K 线。循环里第一道防护是边界判断:i+1、i+2、i+3、i+4 都必须小于 30,否则数组越界直接报错崩脚本。边界过了才进 RSI 高点识别逻辑。
ObjectCreate(ChartID(),"L",OBJ_TEXT,class="num">1,rsi_low_time,rsi_low_value); ObjectSetString(ChartID(),"L",OBJPROP_TEXT,"L"); ObjectSetInteger(ChartID(),"L",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"RSI LOW TREND LINE",OBJPROP_COLOR,clrBlack); ObjectSetInteger(ChartID(),"L",OBJPROP_COLOR,clrBlack); ObjectCreate(ChartID(),"LL",OBJ_TEXT,class="num">1,new_rsi_low_time,new_rsi_low_value); ObjectSetString(ChartID(),"LL",OBJPROP_TEXT,"LL"); ObjectSetInteger(ChartID(),"LL",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"LL",OBJPROP_COLOR,clrBlack); class=class="str">"cmt">//FOR CORRESPONDING PRICE ObjectCreate(ChartID(),"C-CANDLE TREND LINE",OBJ_TREND,class="num">0,rsi_low_time,corresponding_low_value,new_rsi_low_time,new_corresponding_low_value); ObjectCreate(ChartID(),"CL",OBJ_TEXT,class="num">0,rsi_low_time,corresponding_low_value); ObjectSetString(ChartID(),"CL",OBJPROP_TEXT,"L"); ObjectSetInteger(ChartID(),"CL",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"C-CANDLE TREND LINE",OBJPROP_COLOR,clrBlack); ObjectSetInteger(ChartID(),"CL",OBJPROP_COLOR,clrBlack); ObjectCreate(ChartID(),"CLL",OBJ_TEXT,class="num">0,new_rsi_low_time,new_corresponding_low_value); ObjectSetString(ChartID(),"CLL",OBJPROP_TEXT,"HL"); ObjectSetInteger(ChartID(),"CLL",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"CLL",OBJPROP_COLOR,clrBlack); class=class="str">"cmt">//DECLEAR VARIBLE ROR RSI HIGH AND CORESPONDING PRICE class="type">class="kw">double rsi_high_value; class="type">class="kw">double corresponding_high_value; class="type">class="kw">double corresponding_high_ma; class="type">class="kw">datetime rsi_high_time; class=class="str">"cmt">//DECLEAR VARIABLE FOR THE MAXIMUM CORRESPONDING PRICE VALUE class="type">int maximum_value_high; class=class="str">"cmt">// DECLEAR VARIBLE ROR NEW RSI HIGH AND CORESPONDING PRICE class="type">class="kw">double new_rsi_high_value; class="type">class="kw">datetime new_rsi_high_time; class="type">class="kw">double new_corresponding_high_value; class=class="str">"cmt">//LOOP THROUGH THE LAST class="num">30 BARS ON THE CHART for(class="type">int i = class="num">0; i < class="num">30; i++) { class=class="str">"cmt">//PREVENT ARRAY OUT OF RANGE ERROR if((i+class="num">1 < class="num">30) && (i+class="num">2 < class="num">30) && (i < class="num">30) && (i+class="num">3 < class="num">30) && (i+class="num">4 < class="num">30)) { class=class="str">"cmt">//LOGIC TO IDENTIFY THE LATEST RSI HIGH
◍ 把 RSI 顶背离锚点画到图上
当 RSI 缓冲区出现连续 4 根递减(i+4 > i+3 > i+2 > i+1 > i),代码认定 i+3 处是最近的有效 RSI 高点,并抓取该处的 RSI 值、收盘价、MA 值与时间戳存进变量后直接 break。 随后用 Bars() 算出自该 RSI 高点到当前 0 号 K 线共多少根 bar,再靠 ArrayMaximum(close,0,total_bars_3) 捞出这段区间内的最高收盘价下标。若价格仍在 MA 下方、且区间最高收盘不高于当初的对应高价,就倾向判定为弱势反抽后的顶背离结构。 满足上述条件后,脚本在图表上拉出 RSI 高值线、对应 K 线高价线,以及两条连接线,并用 OBJ_TEXT 标注「RSI HIGH」与「C-PRICE」。外汇与贵金属波动剧烈,这类标记只提示结构概率,实盘须自行验证。 把下面代码贴进 MT5 脚本,加载到 EURUSD 的 M15 看是否自动标出黑色背离参考线,比肉眼翻 RSI 快得多。
if(rsi_buffer[i+class="num">4] < rsi_buffer[i+class="num">3] && rsi_buffer[i+class="num">2] < rsi_buffer[i+class="num">3] && rsi_buffer[i+class="num">1] < rsi_buffer[i+class="num">2] && rsi_buffer[i] < rsi_buffer[i+class="num">1]) { class=class="str">"cmt">//GETTING LATEST RSI HIGH, CORRESPONDING PRICE, CORRESPONDING MA VALUE, and RSI TIME rsi_high_value = rsi_buffer[i+class="num">3]; corresponding_high_value = close[i+class="num">3]; corresponding_high_ma = ma_buffer[i+class="num">3]; rsi_high_time = time[i+class="num">3]; break; } } } class=class="str">"cmt">//TOTAL NUMBERS OF BARS FROM THE LAST SIGNIFICANT RSI HIGH class="type">int total_bars_3 = class="num">0; total_bars_3 = Bars(_Symbol,PERIOD_CURRENT,time[class="num">0],rsi_high_time); class=class="str">"cmt">//MAXIMUM CLOSE PRICE FROM THE LAST SIGNIFICANT RSI LOW maximum_value_high = ArrayMaximum(close,class="num">0,total_bars_3); if(corresponding_high_value < corresponding_high_ma && close[class="num">0] < ma_buffer[class="num">0] && close[maximum_value_high] <= corresponding_high_value) { class=class="str">"cmt">//CREATE LINES TO MARK RSI AND CORRESPONDING PRICE ObjectCreate(ChartID(),"RSI HIGH VALUE",OBJ_TREND,class="num">1,rsi_high_time,rsi_high_value,TimeCurrent(),rsi_high_value); ObjectCreate(ChartID(),"C-CANDLE HIGH",OBJ_TREND,class="num">0,rsi_high_time,corresponding_high_value,TimeCurrent(),corresponding_high_value); class=class="str">"cmt">//SETTING OBJECTS COLOUR ObjectSetInteger(ChartID(),"RSI HIGH VALUE",OBJPROP_COLOR,clrBlack); ObjectSetInteger(ChartID(),"C-CANDLE HIGH",OBJPROP_COLOR,clrBlack); class=class="str">"cmt">//CREATE TWO LINES TO CONNECT RSI HIGH AND THE CORRESPONDING PRICE ON THE CHART ObjectCreate(ChartID(),"C-CANDLE LINE HIGH",OBJ_TREND,class="num">0,rsi_high_time,corresponding_high_value,rsi_high_time,class="num">0); ObjectCreate(ChartID(),"RSI HIGH LINE",OBJ_TREND,class="num">1,rsi_high_time,rsi_high_value,rsi_high_time,class="num">100); class=class="str">"cmt">//SETTING OBJECTS COLOUR ObjectSetInteger(ChartID(),"C-CANDLE LINE HIGH",OBJPROP_COLOR,clrBlack); ObjectSetInteger(ChartID(),"RSI HIGH LINE",OBJPROP_COLOR,clrBlack); class=class="str">"cmt">//CREATE TEXTS TO MART RSI HIGH AND CORRESPONDING PRICE(C-PRICE) ObjectCreate(ChartID(),"C-CANDLE TEXT HIGH",OBJ_TEXT,class="num">0,TimeCurrent(),corresponding_high_value); ObjectSetString(ChartID(),"C-CANDLE TEXT HIGH",OBJPROP_TEXT,"C-PRICE"); ObjectCreate(ChartID(),"RSI HIGH TEXT",OBJ_TEXT,class="num">1,TimeCurrent(),rsi_high_value); ObjectSetString(ChartID(),"RSI HIGH TEXT",OBJPROP_TEXT,"RSI HIGH"); class=class="str">"cmt">//SETTING TEXT COLOUR ObjectSetInteger(ChartID(),"C-CANDLE TEXT HIGH",OBJPROP_COLOR,clrBlack);
「RSI顶背离的连线与标记逻辑」
在 MT5 指标脚本里,先给名为 RSI HIGH TEXT 的文本对象上色,用 ObjectSetInteger 把颜色锁成 clrBlack,避免默认色和背景糊在一起。 接下来这段是抓「新 RSI 高点」的核心判断:当最新一根 RSI 小于前一根、前一根又大于再前一根,且前一根 RSI 突破了既定 rsi_high_value,但同根 K 线收盘价 corresponding_high_value 反而更低时,就把这根前一根的 RSI 值、时间、收盘价存进 new_ 系列变量。 //LOGIC TO GET THE NEW RSI HIGH if(rsi_buffer[0] < rsi_buffer[1] && rsi_buffer[1] > rsi_buffer[2] && rsi_buffer[1] > rsi_high_value && close[1] < corresponding_high_value) { new_rsi_high_value = rsi_buffer[1]; new_rsi_high_time = time[1]; new_corresponding_high_value = close[1]; } 当新高点比旧高点 RSI 更高、但对应 K 线收盘价更低,就满足顶背离雏形。此时脚本在 RSI 子窗口画 OBJ_TREND 趋势线连接两点,并打上 H 与 HH 文字标签(字号 15、黑色);同时在主图用 OBJ_TREND 连对应高价,标 CH 与 CLH(原文末行 CLH 文本设为 LH,疑似笔误,实盘建议统一为 HH/LH 体系)。 外汇与贵金属波动大、滑点频繁,这种背离画线只是概率提示,不能直接当进场信号,开 MT5 把这段代码塞进自定义指标跑一遍 EURUSD 小时图,看标记位置和肉眼画的会不会差出几根 K 线。
ObjectSetInteger(ChartID(),"RSI HIGH TEXT",OBJPROP_COLOR,clrBlack); class=class="str">"cmt">//LOGIC TO GET THE NEW RSI HIGH if(rsi_buffer[class="num">0] < rsi_buffer[class="num">1] && rsi_buffer[class="num">1] > rsi_buffer[class="num">2] && rsi_buffer[class="num">1] > rsi_high_value && close[class="num">1] < corresponding_high_value) { new_rsi_high_value = rsi_buffer[class="num">1]; new_rsi_high_time = time[class="num">1]; new_corresponding_high_value = close[class="num">1]; } if(rsi_high_value < new_rsi_high_value && corresponding_high_value > new_corresponding_high_value) { class=class="str">"cmt">//for rsi ObjectCreate(ChartID(),"RSI HIGH TREND LINE",OBJ_TREND,class="num">1,rsi_high_time,rsi_high_value,new_rsi_high_time,new_rsi_high_value); ObjectCreate(ChartID(),"H",OBJ_TEXT,class="num">1,rsi_high_time,rsi_high_value); ObjectSetString(ChartID(),"H",OBJPROP_TEXT,"H"); ObjectSetInteger(ChartID(),"H",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"RSI HIGH TREND LINE",OBJPROP_COLOR,clrBlack); ObjectSetInteger(ChartID(),"H",OBJPROP_COLOR,clrBlack); ObjectCreate(ChartID(),"HH",OBJ_TEXT,class="num">1,new_rsi_high_time,new_rsi_high_value); ObjectSetString(ChartID(),"HH",OBJPROP_TEXT,"HH"); ObjectSetInteger(ChartID(),"HH",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"HH",OBJPROP_COLOR,clrBlack); class=class="str">"cmt">//for candle ObjectCreate(ChartID(),"C-CANDLE TREND LINE HIGH",OBJ_TREND,class="num">0,rsi_high_time,corresponding_high_value,new_rsi_high_time,new_corresponding_high_value); ObjectCreate(ChartID(),"CH",OBJ_TEXT,class="num">0,rsi_high_time,corresponding_high_value); ObjectSetString(ChartID(),"CH",OBJPROP_TEXT,"H"); ObjectSetInteger(ChartID(),"CH",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"C-CANDLE TREND LINE HIGH",OBJPROP_COLOR,clrBlack); ObjectSetInteger(ChartID(),"CH",OBJPROP_COLOR,clrBlack); ObjectCreate(ChartID(),"CLH",OBJ_TEXT,class="num">0,new_rsi_high_time,new_corresponding_high_value); ObjectSetString(ChartID(),"CLH",OBJPROP_TEXT,"LH");
失效即清场的对象回收逻辑
在 MT5 指标脚本里,图形对象若不及时删除,会在切换周期或重绘时层层堆叠,拖慢图表刷新。上面这段逻辑做的是「条件触发即全量清理」:当最新收盘价站上均线缓冲 ma_buffer[0],或前期扫描到的极值高点被对应阈值突破时,一次性把 14 个命名对象全部移除。 被删除的命名对象覆盖了从 RSI 高位线、C 线蜡烛高位到趋势线、文字标签(如 "CLH" "HH" "CH")的完整标注体系,说明这套 Higher High 识别在信号失效后不残留任何视觉噪声。 注意 ObjectSetInteger 在清理分支前的那两行把 "CLH" 字号设为 15、颜色设为 clrBlack,属于绘制期的样式定义;真正决定生命周期的是 else 里的 ObjectDelete 群。外汇与贵金属行情跳空频繁,这类对象若只建不删,复盘时容易误读旧信号,建议你在策略测试器里手动改 close[0] > ma_buffer[0] 的阈值验证清理触发时机。
ObjectSetInteger(ChartID(),"CLH",OBJPROP_FONTSIZE,class="num">15); ObjectSetInteger(ChartID(),"CLH",OBJPROP_COLOR,clrBlack); } } class=class="str">"cmt">//LOGIC TO DELETE THE OBJECTS WHEN ITS NO LONGER RELEVEANT else if((close[class="num">0] > ma_buffer[class="num">0]) || (close[maximum_value_high] > corresponding_high_value)) { ObjectDelete(ChartID(),"RSI HIGH VALUE"); ObjectDelete(ChartID(),"C-CANDLE HIGH"); ObjectDelete(ChartID(),"C-CANDLE LINE HIGH"); ObjectDelete(ChartID(),"RSI HIGH LINE"); ObjectDelete(ChartID(),"C-CANDLE TEXT HIGH"); ObjectDelete(ChartID(),"RSI HIGH TEXT"); ObjectDelete(ChartID(),"RSI HIGH TREND LINE"); ObjectDelete(ChartID(),"H"); ObjectDelete(ChartID(),"HH"); ObjectDelete(ChartID(),"C-CANDLE TREND LINE HIGH"); ObjectDelete(ChartID(),"CH"); ObjectDelete(ChartID(),"CLH"); }
◍ 用随机震荡指标卡死背离窗口
RSI 与价格确认隐藏背离后,随机震荡指标(Stochastic)只作最后一关:它的 %K 线必须出现特定穿越,且穿越发生在背离识别后 11 根柱以内,信号才可能有效。 看涨一侧,%K 要先跌破 20 再站回 20 上方;看跌一侧,要先破 80 再跌回 80 下方。这个 11 柱窗口是硬约束——超期不交叉,设置直接作废。 止损锚定在前 30 根内的最后波动点:看涨用最后低点,看跌用最后高点。波动点抓取逻辑很简单,看跌烛形接看涨烛形取两者最高价为 last_high,反之取最低价为 last_low。 仓位控制上,EA 用 MagicNumber=9097 标记自身订单,OnTick 里扫 PositionsTotal 并比对幻数与符号,保证同品种同 EA 只跑一个仓。配合 CalculateLotSize 按美元风险额与止损点数反推手数,过度交易和随意加码会被系统挡掉。 外汇与贵金属杠杆高、滑点跳空频繁,即便信号齐备也只是概率优势,实盘前请在 MT5 策略测试器用历史数据跑一遍 11 柱窗口与波动点逻辑。
if(total_bars < class="num">11) { if(stoch_buffer_k[class="num">0] < class="num">20 && stoch_buffer_k[class="num">1] > class="num">20 && currentBarTime != lastTradeBarTime && totalPositions < class="num">1) { class=class="str">"cmt">// } } class="type">int total_bars = Bars(_Symbol,PERIOD_CURRENT,new_rsi_high_time,TimeCurrent()); if(total_bars < class="num">11) { if(stoch_buffer_k[class="num">0] < class="num">80 && stoch_buffer_k[class="num">1] > class="num">80) { class=class="str">"cmt">// } } class="type">class="kw">double last_high; class="type">class="kw">double last_low; class=class="str">"cmt">//LOGIC FOR LAST HIGH for(class="type">int i = class="num">0; i < class="num">30; i++) { if(i < class="num">30 && i+class="num">1 < class="num">30) { if(close[i] < open[i] && close[i+class="num">1] > open[i+class="num">1]) { last_high = MathMax(high[i],high[i+class="num">1]); break; } } } class=class="str">"cmt">//LOGIC FOR LAST LOW for(class="type">int i = class="num">0; i < class="num">30; i++) { if(i < class="num">30 && i+class="num">1 < class="num">30) { if(close[i] > open[i] && close[i+class="num">1] < open[i+class="num">1]) { last_low = MathMin(low[i],low[i+class="num">1]); break; } } }
「隐藏背离的 EA 下单骨架」
这段 MQL5 片段把隐藏背离逻辑接进了 CTrade 实盘接口,核心是用 Stochastic 的 K 线穿越 20/80 边界来识别牛/熊隐藏背离。MagicNumber 设成 9097,EA 只在同品种、同魔术号且当前无持仓(totalPositions < 1)时才动手,避免重复开仓。 风险参数写死在 input 里:risk_amount = 20 表示每笔最多亏 20 美元,rrr = 4 即盈亏比锁 4 倍。仓位由 CalculateLotSize 按点风险反推,外汇与贵金属杠杆高,实盘前务必在策略测试器用历史数据校验爆仓概率。 牛隐藏背离条件是 stoch_buffer_k[0] > 20 且前一根 < 20,空单反之。take_profit 直接拿 (ask - last_low) * rrr 加回现价,points_risk 取现价与近期极值的差,代码层已把止损挂在 last_low / last_high。开 MT5 把下面代码贴进 EA,改下品种周期就能跑回测。
class="macro">#include <Trade/Trade.mqh> CTrade trade; input class="type">int MagicNumber = class="num">9097; class=class="str">"cmt">//MAGIC NUMBER class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert initialization function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//SET MAGIC NUMBER trade.SetExpertMagicNumber(MagicNumber); class="kw">return(INIT_SUCCEEDED); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert tick function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class=class="str">"cmt">// Getting total positions class="type">int totalPositions = class="num">0; for(class="type">int i = class="num">0; i < PositionsTotal(); i++) { class="type">class="kw">ulong ticket = PositionGetTicket(i); if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(ChartID())) { totalPositions++; } } } class=class="str">"cmt">//INPUTS input class="type">class="kw">double risk_amount = class="num">20; class=class="str">"cmt">// $ PER TRADE input class="type">class="kw">double rrr = class="num">4; class=class="str">"cmt">//RRR input class="type">int MagicNumber = class="num">9097; class=class="str">"cmt">//MAGIC NUMBER class="type">class="kw">double take_profit; class="type">class="kw">double points_risk; class="type">class="kw">double lot_size; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert tick function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class=class="str">"cmt">//BULLISH HIDDEN DIVERGENCE if(stoch_buffer_k[class="num">0] > class="num">20 && stoch_buffer_k[class="num">1] < class="num">20 && currentBarTime != lastTradeBarTime && totalPositions < class="num">1) { take_profit = ((ask_price - last_low) * rrr) + ask_price; points_risk = ask_price - low[class="num">0]; lot_size = CalculateLotSize(_Symbol, risk_amount, points_risk); trade.Buy(lot_size,_Symbol,ask_price,last_low,take_profit); lastTradeBarTime = currentBarTime; } class=class="str">"cmt">//BEARISH HIDDEN DIVERGENCE if(stoch_buffer_k[class="num">0] < class="num">80 && stoch_buffer_k[class="num">1] > class="num">80 && currentBarTime != lastTradeBarTime && totalPositions < class="num">1) { take_profit = MathAbs(((last_high - ask_price) * rrr) - ask_price); points_risk = high[class="num">0] - ask_price; lot_size = CalculateLotSize(_Symbol, risk_amount, points_risk); trade.Sell(lot_size,_Symbol,ask_price,last_high,take_profit); lastTradeBarTime = currentBarTime; }
按风险金额反推开仓手数
做仓位管理时,最实在的做法是先定这笔单子最多亏多少美元,再根据止损点数反推手数,而不是拍脑袋选 0.1 手。下面这段函数在 MT5 里可以直接用:给定品种、风险金额和止损 pip 数,它返回合规手数。 核心逻辑是先拿到品种的 point 和每跳价值 tickValue,用 tickValue/point 算出每 pip 对应的每标准手价值;止损总代价就是 stopLossPips 乘这个值。风险金额除以止损代价即得理论手数。 手数不能裸奔,必须按券商的 SYMBOL_VOLUME_STEP 向下取整,再用 SYMBOL_VOLUME_MIN / MAX 卡边界,否则 OrderSend 会直接报 4751 无效交易量错误。外汇与贵金属杠杆高,错手数可能在几分钟内放大亏损,实盘前请在策略测试器里用不同 stopLossPips 跑一遍验证。
class="type">class="kw">double CalculateLotSize(class="type">class="kw">string symbol, class="type">class="kw">double riskAmount, class="type">class="kw">double stopLossPips) { class=class="str">"cmt">// Get symbol information class="type">class="kw">double point = SymbolInfoDouble(symbol, SYMBOL_POINT); class="type">class="kw">double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); class=class="str">"cmt">// Calculate pip value per lot class="type">class="kw">double pipValuePerLot = tickValue / point; class=class="str">"cmt">// Calculate the stop loss value in currency class="type">class="kw">double stopLossValue = stopLossPips * pipValuePerLot; class=class="str">"cmt">// Calculate the lot size class="type">class="kw">double lotSize = riskAmount / stopLossValue; class=class="str">"cmt">// Round the lot size to the nearest acceptable lot step class="type">class="kw">double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); lotSize = MathFloor(lotSize / lotStep) * lotStep; class=class="str">"cmt">// Ensure the lot size is within the allowed range class="type">class="kw">double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); class="type">class="kw">double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); class="kw">return lotSize; }
◍ 画得少,看得清
把均线、RSI 与随机指标叠在一起只是为了过滤噪音,真正下单依据仍是价格与动能的隐性背离。附带的 MQL5INDICATORS_PROJECT5.mq5 约 19.45 KB,注释覆盖率够高,直接拖进 MT5 就能跑一套小步快跑的验证流程。 外汇与贵金属杠杆高、滑点随机,任何背离信号都只是概率倾向,实盘前先用策略测试器跑三个月 tick 数据再看曲线。 代码里把背离判定阈值留了外部参数,默认 0.0001,调成 0.0003 可能更适配黄金 5 分钟图,但这事得你自己在终端里试。