MQL4/MQL5中如何检测MACD与RSI在指标窗口的视觉触碰信号?
MQL4/MQL5 同一指标窗口视觉交互检测与交易信号实现
1. 同一窗口指标线视觉交叉/触碰的成熟方法
核心思路是数值坐标归一化——视觉上的交叉本质是两个指标在指标窗口内的像素位置重叠,而非原始数值相等。业内通用的最佳实践是:
- 将两个指标的当前/历史数值,统一映射到指标窗口的像素坐标系(或0-1的相对刻度范围)
- 对比映射后的坐标值,判断是否出现触碰(坐标差小于设定阈值)或交叉(相邻K线的坐标顺序反转)
这种方案完全依赖MQL内置能力实现,无需外部工具,是跨指标视觉交互检测的标准解法。
2. 模拟图表渲染的关键技术与函数
实现视觉条件检测的核心是MQL提供的窗口坐标转换函数,主要包括:
WindowPriceToY(double price):将指标/价格数值转换为对应窗口内的Y轴像素坐标(注意:图表Y轴从上到下数值递增,因此指标数值越大,返回的Y坐标值越小)WindowFirstVisibleBar()/WindowLastVisibleBar():可选,用于缩小计算范围,优化性能IndicatorSetInteger(INDICATOR_DIGITS, digits):统一指标数值精度,避免转换时的误差
通过WindowPriceToY(),可以把RSI(固定0-100范围)和MACD(波动数值)的原始值,统一转换成指标窗口内的像素位置,直接对比位置关系即可模拟视觉交互。
3. 无外部依赖的实现代码示例
以下是MQL5的实现示例(MQL4仅需少量语法调整),实现MACD峰值/谷值触碰RSI水平时的交易信号:
//+------------------------------------------------------------------+ //| 自定义指标:检测MACD与RSI的视觉交互信号 | //+------------------------------------------------------------------+ #property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 clrRed #property indicator_color2 clrGreen double BuySignal[]; double SellSignal[]; // RSI参数 input int RSI_Period = 14; input int RSI_Overbought = 70; input int RSI_Oversold = 30; // MACD参数 input int MACD_FastEMA = 12; input int MACD_SlowEMA = 26; input int MACD_SignalSMA = 9; // 视觉触碰阈值(像素) input int Touch_Threshold = 2; //+------------------------------------------------------------------+ //| 初始化指标 | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, BuySignal, INDICATOR_DATA); SetIndexBuffer(1, SellSignal, INDICATOR_DATA); ArraySetAsSeries(BuySignal, true); ArraySetAsSeries(SellSignal, true); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 指标主循环 | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { int start = prev_calculated > 0 ? prev_calculated - 1 : 0; // 获取RSI和MACD指标值 double rsi[]; double macd_main[]; ArraySetAsSeries(rsi, true); ArraySetAsSeries(macd_main, true); if(!iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE, 0, start, rates_total - 1, rsi)) return(0); if(!iMACD(_Symbol, _Period, MACD_FastEMA, MACD_SlowEMA, MACD_SignalSMA, PRICE_CLOSE, MODE_MAIN, 0, start, rates_total - 1, macd_main)) return(0); // 遍历K线检测信号 for(int i = start; i < rates_total; i++) { BuySignal[i] = EMPTY_VALUE; SellSignal[i] = EMPTY_VALUE; // 跳过不足够的历史K线 if(i < 2) continue; // 转换为指标窗口的Y像素坐标 int y_rsi = WindowPriceToY(rsi[i]); int y_macd = WindowPriceToY(macd_main[i]); int y_macd_prev = WindowPriceToY(macd_main[i+1]); // 检测MACD谷值触碰RSI且RSI超卖(买入信号) if(macd_main[i] > macd_main[i+1] && macd_main[i] > macd_main[i-1] // MACD谷值判断 && MathAbs(y_rsi - y_macd) <= Touch_Threshold // 视觉触碰判断 && rsi[i] <= RSI_Oversold) // RSI超卖判断 { BuySignal[i] = low[i] - _Point * 5; } // 检测MACD峰值触碰RSI且RSI超买(卖出信号) if(macd_main[i] < macd_main[i+1] && macd_main[i] < macd_main[i-1] // MACD峰值判断 && MathAbs(y_rsi - y_macd) <= Touch_Threshold // 视觉触碰判断 && rsi[i] >= RSI_Overbought) // RSI超买判断 { SellSignal[i] = high[i] + _Point * 5; } } return(rates_total); } //+------------------------------------------------------------------+
代码说明
- 用
WindowPriceToY()实现跨指标的坐标统一,通过像素差判断视觉触碰 - 加入MACD峰值/谷值的相邻K线对比逻辑,确保信号触发在MACD的极值点
Touch_Threshold参数可根据图表分辨率调整,适配不同视觉误差- 信号直接标记在主图上,方便直观验证逻辑正确性
内容的提问来源于stack exchange,提问作者Mr .
相关产品推荐
相关产品推荐

