Summary: 免费MT4指标,监控RSI并在超买超卖时发送弹窗、推送或邮件提醒。支持自定义周期、超买超卖阈值,可跨周期监控。含完整源码和安装教程。




# 免费RSI报警指标MT4源码 – 多周期超买超卖自动提醒

指标功能说明



RSI(相对强弱指数)是最受欢迎的动力震荡指标之一。但手动盯着多个图表和周期看RSI信号非常耗时。本指标自动化了监控过程:

1. 监控指定周期的RSI数值
2. 当RSI上穿超买线(默认70)或下穿超卖线(默认30)时触发报警
3. 通过弹窗、手机推送、邮件三种方式发送提醒
4. 带冷却计时器,避免报警轰炸

核心功能



| 功能 | 说明 |
| :--- | :--- |
| 多周期支持 | 可监控当前图表周期或任意自定义周期 |
| 超买/超卖报警 | RSI上穿70或下穿30时触发 |
| 回归报警 | 可选:当RSI从超买区回落或从超卖区回升时报警 |
| 冷却计时器 | 避免横盘行情中产生大量重复报警 |
| 三种报警方式 | 弹窗、推送通知、邮件 |
| 可调阈值 | 自定义超买超卖数值 |
| RSI周期可调 | 标准14或任意自定义值 |

完整MQL4源码



复制下方完整代码,保存为 `RSI_Alert_Indicator.mq4` 至 `MQL4/Indicators/` 文件夹,然后编译。

```cpp
//+------------------------------------------------------------------+
//| RSI_Alert_Indicator.mq4 |
//| 自主编译 |
//| |
//+------------------------------------------------------------------+
#property copyright "ForexEA博客"
#property link ""
#property version "1.00"
#property strict
#property indicator_chart_window

//--- 输入参数
input int RSI_Period = 14; // RSI周期
input int RSI_Applied_Price = PRICE_CLOSE; // 应用价格
input double Overbought_Level = 70.0; // 超买水平
input double Oversold_Level = 30.0; // 超卖水平
input int Timeframe = 0; // 周期(0=当前)
input bool Alert_On_Cross_Up = true; // RSI上穿超买线时报警
input bool Alert_On_Cross_Down = true; // RSI下穿超卖线时报警
input bool Alert_On_Return_Up = false; // RSI从超买区回落时报警
input bool Alert_On_Return_Down = false; // RSI从超卖区回升时报警
input int Alert_Cooldown_Seconds = 300; // 最小报警间隔(秒)
input bool Alert_Popup = true; // 弹窗提醒
input bool Alert_Push = false; // 推送通知
input bool Alert_Email = false; // 邮件提醒
input string Alert_Email_Subject = "RSI报警"; // 邮件主题

//--- 全局变量
double last_alert_time = 0;
int last_rsi_state = 0; // -1=超卖, 0=中性, 1=超买
string indicator_shortname;
int applied_timeframe;
int rsi_handle;

//+------------------------------------------------------------------+
//| 初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 设置周期
if(Timeframe == 0)
applied_timeframe = Period();
else
applied_timeframe = Timeframe;

//--- 创建指标名称
indicator_shortname = "RSI报警 (" + IntegerToString(RSI_Period) + ") 周期:" + GetTimeframeName(applied_timeframe);
IndicatorShortName(indicator_shortname);

//--- 创建RSI句柄
rsi_handle = iRSI(Symbol(), applied_timeframe, RSI_Period, RSI_Applied_Price);
if(rsi_handle == INVALID_HANDLE)
{
Print("创建RSI句柄失败,错误码:", GetLastError());
return INIT_FAILED;
}

//--- 在图表上显示状态标签
string label_text = "RSI报警已启动\n";
label_text += "超买: " + DoubleToStr(Overbought_Level, 0) + " | 超卖: " + DoubleToStr(Oversold_Level, 0);
CreateLabel("RSI_Alert_Status", label_text, 10, 30, clrWhite);

Print("RSI报警指标已启动,监控 ", Symbol(), " 周期:", GetTimeframeName(applied_timeframe));

return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| 反初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(rsi_handle != INVALID_HANDLE)
IndicatorRelease(rsi_handle);

DeleteLabel("RSI_Alert_Status");
Print("RSI报警指标已移除");
}

//+------------------------------------------------------------------+
//| 核心计算函数 |
//+------------------------------------------------------------------+
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[])
{
//--- 获取当前RSI值
double rsi_array[1];
int copied = CopyBuffer(rsi_handle, 0, 0, 1, rsi_array);
if(copied != 1)
return 0;

double current_rsi = rsi_array[0];
double previous_rsi = 0;

//--- 获取前一根K线的RSI值用于穿越检测
double rsi_prev_array[1];
copied = CopyBuffer(rsi_handle, 0, 1, 1, rsi_prev_array);
if(copied == 1)
previous_rsi = rsi_prev_array[0];

//--- 更新图表上的RSI状态显示
string color_str = "Gray";
string status_str = "中性";

if(current_rsi >= Overbought_Level)
{
color_str = "Red";
status_str = "超买区";
}
else if(current_rsi <= Oversold_Level)
{
color_str = "Lime";
status_str = "超卖区";
}

string label_text = "RSI报警已启动\n";
label_text += "当前RSI: " + DoubleToStr(current_rsi, 1) + " (" + status_str + ")\n";
label_text += "超买: " + DoubleToStr(Overbought_Level, 0) + " | 超卖: " + DoubleToStr(Oversold_Level, 0);
UpdateLabel("RSI_Alert_Status", label_text, color_str);

//--- 检查报警条件
if(previous_rsi > 0)
{
CheckForAlerts(current_rsi, previous_rsi);
}

return rates_total;
}

//+------------------------------------------------------------------+
//| 检查报警条件 |
//+------------------------------------------------------------------+
void CheckForAlerts(double current_rsi, double previous_rsi)
{
//--- 冷却检查
if(TimeCurrent() - last_alert_time < Alert_Cooldown_Seconds)
return;

string alert_message = "";

//--- RSI上穿超买线(进入超买区)
if(Alert_On_Cross_Up && previous_rsi < Overbought_Level && current_rsi >= Overbought_Level)
{
alert_message = StringFormat("RSI报警:%s %s - RSI上穿超买线 %.0f(当前值:%.1f)",
Symbol(), GetTimeframeName(applied_timeframe), Overbought_Level, current_rsi);
}

//--- RSI下穿超卖线(进入超卖区)
else if(Alert_On_Cross_Down && previous_rsi > Oversold_Level && current_rsi <= Oversold_Level)
{
alert_message = StringFormat("RSI报警:%s %s - RSI下穿超卖线 %.0f(当前值:%.1f)",
Symbol(), GetTimeframeName(applied_timeframe), Oversold_Level, current_rsi);
}

//--- RSI从超买区回落
else if(Alert_On_Return_Up && previous_rsi >= Overbought_Level && current_rsi < Overbought_Level)
{
alert_message = StringFormat("RSI报警:%s %s - RSI从超买区回落至 %.0f 下方(当前值:%.1f)",
Symbol(), GetTimeframeName(applied_timeframe), Overbought_Level, current_rsi);
}

//--- RSI从超卖区回升
else if(Alert_On_Return_Down && previous_rsi <= Oversold_Level && current_rsi > Oversold_Level)
{
alert_message = StringFormat("RSI报警:%s %s - RSI从超卖区回升至 %.0f 上方(当前值:%.1f)",
Symbol(), GetTimeframeName(applied_timeframe), Oversold_Level, current_rsi);
}

//--- 发送报警
if(alert_message != "")
{
last_alert_time = TimeCurrent();

if(Alert_Popup)
{
Alert(alert_message);
}

if(Alert_Push)
{
SendNotification(alert_message);
}

if(Alert_Email)
{
SendMail(Alert_Email_Subject, alert_message);
}

Print(alert_message);
}
}

//+------------------------------------------------------------------+
//| 辅助函数:获取周期名称 |
//+------------------------------------------------------------------+
string GetTimeframeName(int tf)
{
switch(tf)
{
case PERIOD_M1: return "M1";
case PERIOD_M5: return "M5";
case PERIOD_M15: return "M15";
case PERIOD_M30: return "M30";
case PERIOD_H1: return "H1";
case PERIOD_H4: return "H4";
case PERIOD_D1: return "日线";
case PERIOD_W1: return "周线";
case PERIOD_MN1: return "月线";
default: return IntegerToString(tf);
}
}

//+------------------------------------------------------------------+
//| 辅助函数:创建文本标签 |
//+------------------------------------------------------------------+
void CreateLabel(string name, string text, int x, int y, color clr)
{
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 10);
ObjectSetString(0, name, OBJPROP_FONT, "Arial");
ObjectSetString(0, name, OBJPROP_TEXT, text);
}

//+------------------------------------------------------------------+
//| 辅助函数:更新文本标签 |
//+------------------------------------------------------------------+
void UpdateLabel(string name, string text, string color_name)
{
if(ObjectFind(0, name) >= 0)
{
ObjectSetString(0, name, OBJPROP_TEXT, text);

color clr;
if(color_name == "Red")
clr = clrRed;
else if(color_name == "Lime")
clr = clrLime;
else
clr = clrGray;

ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
}
}

//+------------------------------------------------------------------+
//| 辅助函数:删除标签 |
//+------------------------------------------------------------------+
void DeleteLabel(string name)
{
ObjectDelete(0, name);
}
//+------------------------------------------------------------------+
```

安装步骤



第1步: 复制上方完整代码
第2步: 打开MT4 → 文件 → 打开数据文件夹 → MQL4 → Indicators
第3步: 新建文件 `RSI_Alert_Indicator.mq4`
第4步: 粘贴代码,按F7编译
第5步: 编译成功后,指标出现在导航器 → 指标 → 自定义
第6步: 拖拽到任意图表上即可

参数详解



| 参数 | 默认值 | 说明 |
| :--- | :--- | :--- |
| `RSI_Period` | 14 | RSI计算周期 |
| `RSI_Applied_Price` | PRICE_CLOSE | 价格类型(收盘价、开盘价、最高价、最低价) |
| `Overbought_Level` | 70.0 | 超买阈值 |
| `Oversold_Level` | 30.0 | 超卖阈值 |
| `Timeframe` | 0 | 0=当前图表周期,也可选M1/H1/D1等 |
| `Alert_On_Cross_Up` | true | RSI上穿超买线时报警 |
| `Alert_On_Cross_Down` | true | RSI下穿超卖线时报警 |
| `Alert_On_Return_Up` | false | RSI从超买区回落时报警 |
| `Alert_On_Return_Down` | false | RSI从超卖区回升时报警 |
| `Alert_Cooldown_Seconds` | 300 | 最小报警间隔(秒),防止刷屏 |
| `Alert_Popup` | true | MT4内弹窗提醒 |
| `Alert_Push` | false | 推送到手机MT4 |
| `Alert_Email` | false | 发送邮件 |

使用方法



基础设置


1. 将指标拖拽到任意图表
2. 左上角出现状态标签,显示当前RSI
3. 当RSI穿越超买/超卖线时,收到报警

跨周期监控


想在M15图表上监控H4的RSI:
  • 设置 `Timeframe = 60`(H4)

  • 将指标放到M15图表上

  • 你会收到H4周期的RSI报警,同时查看M15图表


  • 手机推送设置


    1. MT4:工具 → 选项 → 通知
    2. 开启“推送通知”,输入MetaQuotes ID
    3. 下载MT4手机App,在设置中找到ID
    4. 指标中设置 `Alert_Push = true`

    邮件报警设置


    1. MT4:工具 → 选项 → 邮箱
    2. 开启并配置SMTP(QQ邮箱:smtp.qq.com,端口465/587)
    3. 指标中设置 `Alert_Email = true`

    交易策略示例



    | 策略 | 使用方法 |
    | :--- | :--- |
    | 超买回调做空 | 等待RSI上穿70,再等待回落至70下方(开启Alert_On_Return_Up),回落后寻找做空机会 |
    | 超卖反弹做多 | 等待RSI下穿30,再等待回升至30上方(开启Alert_On_Return_Down),回升后寻找做多机会 |
    | 背离信号辅助 | 配合价格行为使用。超卖报警时,检查价格是否创新低而RSI未创新低 |
    | 多周期确认 | 同时在H4和M15上放置指标。仅当两个周期都显示超卖回升时才做多 |

    自定义修改



    | 修改需求 | 代码位置 |
    | :--- | :--- |
    | 修改标签位置 | 调整CreateLabel函数中的x、y值(约180行) |
    | 增加声音报警 | 在SendNotification前加上 `PlaySound("alert.wav")` |
    | 图表上画箭头 | 报警触发时用ObjectCreate画箭头 |
    | 监控RSI趋势方向 | 增加判断RSI连续N根K线上升/下降的条件 |

    常见问题



    | 问题 | 解决方法 |
    | :--- | :--- |
    | 指标不显示 | 检查“EA交易”标签页是否有编译错误,按F7重新编译 |
    | 没有报警 | 检查RSI数值是否真的穿越了阈值。单边行情中RSI可能长期停留在超买/超卖区 |
    | 报警太多 | 增大Alert_Cooldown_Seconds到600或900秒 |
    | 推送通知不工作 | 检查MT4选项→通知中的MetaQuotes ID是否正确,点击“测试”验证 |
    | 邮件不发送 | 检查SMTP设置。QQ邮箱需使用授权码而非密码 |

    ---

    想要更多专业指标和EA? [订阅我们的资讯] 获取完整工具包,包含背离检测器、多周期趋势扫描仪和黄金EA。

    参考来源:
  • MQL4官方文档 – iRSI、CopyBuffer (docs.mql4.com)

  • Welles Wilder, J. 《技术交易系统新概念》. 1978.(RSI原始概念)

  • 自主编译测试于MT4 Build 1420+

  • ```