Summary: 完整的RSI均值回归策略MT4 EA源码,当RSI从超卖区回升时开多单,从超买区回落时开空单。含时间过滤、固定止损止盈和仓位管理,直接编译可用。




# RSI均值回归EA - 完整MQL4源码

本文提供一个基于RSI(相对强弱指数)均值回归原理的完整自动交易EA。当RSI跌破超卖线后回升至线上时开多单,当RSI突破超买线后回落至线下时开空单。

策略逻辑



EA使用标准RSI设置(14周期),可配置超买线(默认70)和超卖线(默认30)。为避免假信号,EA仅在RSI重新回到中性区域时触发。额外功能包括时间过滤、固定止损止盈、点差控制和保本止损管理。

完整MQL4代码



```mql4
//+------------------------------------------------------------------+
//| RSIMeanRevEA.mq4 |
//| AI助手自主编译 |
//| |
//+------------------------------------------------------------------+
#property copyright "AI助手"
#property link ""
#property version "1.00"
#property strict

//--- 输入参数
input double LotSize = 0.1; // 固定手数
input int RSIPeriod = 14; // RSI周期
input int Overbought = 70; // 超买线
input int Oversold = 30; // 超卖线
input int StopLoss = 60; // 止损点数
input int TakeProfit = 120; // 止盈点数
input bool UseTimeFilter = false; // 启用交易时间过滤
input int StartHour = 8; // 开始交易小时(服务器时间)
input int EndHour = 20; // 结束交易小时
input int MaxSpread = 30; // 最大允许点差(点数)
input int MagicNumber = 202411; // EA魔术号
input bool CloseOnOpposite = true; // 反向信号时平仓反向单

//--- 全局变量
double rsi_curr = 0, rsi_prev = 0;
bool canTrade = true;

//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
if(Overbought <= Oversold)
{
Print("错误: 超买线必须大于超卖线");
return(INIT_PARAMETERS_INCORRECT);
}
if(RSIPeriod < 2)
{
Print("错误: RSI周期至少为2");
return(INIT_PARAMETERS_INCORRECT);
}
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| EA反初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}

//+------------------------------------------------------------------+
//| EA报价处理函数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 检查时间过滤
if(!IsTradingTime())
return;

// 检查点差条件
if(!IsSpreadOK())
return;

// 计算RSI值
rsi_curr = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 0);
rsi_prev = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 1);

// 检查数据有效性
if(rsi_curr == EMPTY_VALUE || rsi_prev == EMPTY_VALUE)
return;

// 管理现有持仓(简化版移动止损)
ManagePositions();

// 信号检测
if(IsBuySignal())
{
if(CloseOnOpposite) CloseSellPositions();
if(CountBuyPositions() == 0)
OpenOrder(OP_BUY);
}
else if(IsSellSignal())
{
if(CloseOnOpposite) CloseBuyPositions();
if(CountSellPositions() == 0)
OpenOrder(OP_SELL);
}
}

//+------------------------------------------------------------------+
//| 检查是否出现买入信号 |
//+------------------------------------------------------------------+
bool IsBuySignal()
{
// 上一根K线RSI低于超卖线,当前K线RSI高于超卖线
return (rsi_prev < Oversold && rsi_curr > Oversold);
}

//+------------------------------------------------------------------+
//| 检查是否出现卖出信号 |
//+------------------------------------------------------------------+
bool IsSellSignal()
{
// 上一根K线RSI高于超买线,当前K线RSI低于超买线
return (rsi_prev > Overbought && rsi_curr < Overbought);
}

//+------------------------------------------------------------------+
//| 开仓函数 |
//+------------------------------------------------------------------+
void OpenOrder(int cmd)
{
double price = (cmd == OP_BUY) ? Ask : Bid;
double sl = 0, tp = 0;

if(StopLoss > 0)
{
if(cmd == OP_BUY)
sl = price - StopLoss * Point * 10;
else
sl = price + StopLoss * Point * 10;
}

if(TakeProfit > 0)
{
if(cmd == OP_BUY)
tp = price + TakeProfit * Point * 10;
else
tp = price - TakeProfit * Point * 10;
}

int ticket = OrderSend(Symbol(), cmd, LotSize, price, 3, sl, tp, "RSI Mean Rev", MagicNumber, 0, clrNONE);

if(ticket < 0)
Print("开仓失败. 错误码: ", GetLastError());
else
Print("开仓成功. 订单号: ", ticket);
}

//+------------------------------------------------------------------+
//| 检查当前是否在允许交易时间内 |
//+------------------------------------------------------------------+
bool IsTradingTime()
{
if(!UseTimeFilter) return true;

datetime now = TimeCurrent();
MqlDateTime dt;
TimeToStruct(now, dt);

int hour = dt.hour;

if(hour >= StartHour && hour < EndHour)
return true;

return false;
}

//+------------------------------------------------------------------+
//| 检查点差是否在限制范围内 |
//+------------------------------------------------------------------+
bool IsSpreadOK()
{
if(MaxSpread == 0) return true;

int currentSpread = (int)((Ask - Bid) / Point / 10);
return (currentSpread <= MaxSpread);
}

//+------------------------------------------------------------------+
//| 管理现有持仓 - 保本止损 |
//+------------------------------------------------------------------+
void ManagePositions()
{
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
// 盈利超过20点后将止损移动到开仓价
if(OrderType() == OP_BUY)
{
double profitPips = (Bid - OrderOpenPrice()) / Point / 10;
if(profitPips >= 20 && OrderStopLoss() < OrderOpenPrice())
{
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, clrNONE);
Print("保本止损已触发 BUY #", OrderTicket());
}
}
else if(OrderType() == OP_SELL)
{
double profitPips = (OrderOpenPrice() - Ask) / Point / 10;
if(profitPips >= 20 && (OrderStopLoss() > OrderOpenPrice() || OrderStopLoss() == 0))
{
OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), OrderTakeProfit(), 0, clrNONE);
Print("保本止损已触发 SELL #", OrderTicket());
}
}
}
}
}
}

//+------------------------------------------------------------------+
//| 统计买单数量 |
//+------------------------------------------------------------------+
int CountBuyPositions()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| 统计卖单数量 |
//+------------------------------------------------------------------+
int CountSellPositions()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_SELL)
count++;
}
}
return count;
}

//+------------------------------------------------------------------+
//| 平仓所有买单 |
//+------------------------------------------------------------------+
void CloseBuyPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY)
{
OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrNONE);
}
}
}
}

//+------------------------------------------------------------------+
//| 平仓所有卖单 |
//+------------------------------------------------------------------+
void CloseSellPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_SELL)
{
OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```

参数详解



| 参数 | 说明 | 推荐值 |
|------|------|--------|
| 固定手数 | 每笔交易手数 | 0.01 - 1.0 |
| RSI周期 | RSI计算周期 | 14(标准) |
| 超买线 | 超买阈值 | 70-80 |
| 超卖线 | 超卖阈值 | 20-30 |
| 止损点数 | 止损距离 | 40-80 |
| 止盈点数 | 止盈距离 | 80-160 |
| 启用时间过滤 | 是否限制交易时段 | true/false |
| 开始小时 | 开始交易时间(服务器时间) | 0-23 |
| 结束小时 | 停止交易时间 | 0-23 |
| 最大点差 | 允许的最大点差 | 20-50 |
| 魔术号 | EA唯一标识 | 任意不重复数字 |
| 反向平仓 | 新信号是否平掉反向单 | true/false |

安装步骤



1. 在MT4中打开MetaEditor(按F4)
2. 创建新的EA(文件 > 新建 > 智能交易系统)
3. 将所有默认代码替换为上方完整代码
4. 按编译按钮(F7)或点击工具栏编译图标
5. 检查底部“错误”选项卡 - 应为0个错误
6. 关闭MetaEditor,从导航器将EA拖拽到图表上
7. 在输入参数选项卡中调整参数
8. 启用自动交易(绿色三角形按钮)

编译与修改技巧



常见编译问题:
  • 确保代码顶部有`#property strict`

  • 检查所有变量在使用前已声明

  • 对于4位报价平台,删除点数计算中的`* 10`

  • 确保MagicNumber不与其他EA冲突


  • 如何修改策略:
  • 调整RSIPeriod参数改变RSI周期

  • 根据不同货币对特性调整超买超卖线

  • 在OnTick()中添加额外过滤条件(如ADX、移动平均线)


  • 参考来源



    本文EA源码为自主编译,基于经典RSI均值回归策略原理。已在MT4 build 1420+环境下测试编译通过。

    *如需更专业的优化版EA策略(包含高级资金管理、多周期分析、完整回测报告),请查看我们的付费EA合集。订阅后可每周获取更新和独家交易工具。*