Summary: 专业的RSI均值回归策略EA源码,包含进场过滤、移动止损和风险管理功能,适合M1-M15周期剥头皮交易,完整代码可直接编译。




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

本文提供一个可直接编译的MT4自动交易EA,基于RSI指标的极值区域进行均值回归交易。当RSI低于超卖线(默认30)后回升时开多单,高于超买线(默认70)后回落时开空单。EA内置多重过滤条件避免假信号。

策略逻辑



EA使用标准RSI指标(相对强弱指数),参数可自定义。仅在RSI从极值区域向50中性水平回归时开仓。附加过滤包括交易时间限制、最大点差控制和每日最大回撤限制。

完整MQL4代码



```mql4
//+------------------------------------------------------------------+
//| RSIScalperEA.mq4 |
//| 自主编译 版权所有 |
//| |
//+------------------------------------------------------------------+
#property copyright "AI助手"
#property link ""
#property version "1.00"
#property strict

//--- 输入参数
input double LotSize = 0.05; // 固定手数
input int RSIPeriod = 14; // RSI周期
input int Overbought = 70; // 超买线
input int Oversold = 30; // 超卖线
input int RSIExitLevel = 52; // RSI到达此水平平仓
input int StopLoss = 40; // 止损点数
input int TakeProfit = 80; // 止盈点数
input int TrailingStart = 25; // 盈利超过此点数启动移动止损
input int TrailingStep = 15; // 移动止损步长
input int MaxSpread = 30; // 最大允许点差
input bool UseTimeFilter = true; // 启用交易时间过滤
input int StartHour = 2; // 开始交易时间(服务器时间)
input int EndHour = 20; // 结束交易时间
input double MaxDailyLoss = 10.0; // 每日最大亏损百分比(0=关闭)
input int MagicNumber = 202411; // EA魔术号

//--- 全局变量
double dailyLoss = 0;
datetime lastTradeTime = 0;
double initBalance = 0;

//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
initBalance = AccountBalance();
dailyLoss = 0;
Print("RSI剥头皮EA初始化完成,初始余额: ", initBalance);
return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| EA反初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("RSI剥头皮EA已移除,原因代码: ", reason);
}

//+------------------------------------------------------------------+
//| EA报价处理函数 |
//+------------------------------------------------------------------+
void OnTick()
{
static datetime lastBarTime = 0;

// 仅在新K线生成时检查(推荐M1-M15周期)
if(lastBarTime == iTime(Symbol(), Period(), 0))
return;
lastBarTime = iTime(Symbol(), Period(), 0);

// 每日重置
if(TimeHour(TimeCurrent()) == 0 && TimeMinute(TimeCurrent()) == 0)
{
dailyLoss = 0;
initBalance = AccountBalance();
}

// 检查过滤条件
if(!CanTrade())
return;

// 获取RSI数值
double rsiCurrent = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 0);
double rsiPrevious = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 1);
double rsiPrevious2 = iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 2);

// 统计现有持仓
int buyCount = CountPositions(OP_BUY);
int sellCount = CountPositions(OP_SELL);

// 移动止损管理
if(buyCount > 0 || sellCount > 0)
{
ManageTrailingStop();
ManageExitByRSI(rsiCurrent);
return;
}

// 进场信号 - RSI从极值区域折返
bool oversoldCrossover = (rsiPrevious <= Oversold && rsiCurrent > Oversold) ||
(rsiPrevious2 <= Oversold && rsiPrevious > Oversold);
bool overboughtCrossunder = (rsiPrevious >= Overbought && rsiCurrent < Overbought) ||
(rsiPrevious2 >= Overbought && rsiPrevious < Overbought);

if(oversoldCrossover && buyCount == 0 && sellCount == 0)
{
OpenOrder(OP_BUY);
}
else if(overboughtCrossunder && buyCount == 0 && sellCount == 0)
{
OpenOrder(OP_SELL);
}
}

//+------------------------------------------------------------------+
//| 检查交易条件是否满足 |
//+------------------------------------------------------------------+
bool CanTrade()
{
// 检查点差
int currentSpread = int((Ask - Bid) / Point / 10);
if(currentSpread > MaxSpread)
{
Comment("点差过高: ", currentSpread);
return false;
}

// 检查时间过滤
if(UseTimeFilter)
{
int currentHour = TimeHour(TimeCurrent());
if(currentHour < StartHour || currentHour >= EndHour)
{
Comment("非交易时段");
return false;
}
}

// 检查每日亏损限制
if(MaxDailyLoss > 0)
{
double currentEquity = AccountEquity();
double lossPercent = (initBalance - currentEquity) / initBalance * 100;
if(lossPercent > MaxDailyLoss)
{
Comment("已达每日亏损上限");
return false;
}
}

// 两次交易最小间隔30秒
if(TimeCurrent() - lastTradeTime < 30)
return false;

Comment("RSI: ", iRSI(Symbol(), 0, RSIPeriod, PRICE_CLOSE, 0), " | 就绪");
return true;
}

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

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, slippage, sl, tp, "RSI Scalper", MagicNumber, 0, clrNONE);

if(ticket > 0)
{
lastTradeTime = TimeCurrent();
Print("开仓成功: ", (cmd == OP_BUY ? "多单" : "空单"), " 订单号: ", ticket);
}
else
{
Print("开仓失败,错误码: ", GetLastError());
}
}

//+------------------------------------------------------------------+
//| 平仓所有持仓 |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
bool closed = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 3, clrNONE);
if(closed)
Print("持仓已平: ", OrderTicket());
}
}
}
}

//+------------------------------------------------------------------+
//| 统计指定类型持仓数量 |
//+------------------------------------------------------------------+
int CountPositions(int cmd = -1)
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if(cmd == -1 || OrderType() == cmd)
count++;
}
}
}
return count;
}

//+------------------------------------------------------------------+
//| 移动止损管理 |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
if(TrailingStart == 0) return;

for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
double currentStop = OrderStopLoss();
double newStop = 0;
double profitPips = 0;

if(OrderType() == OP_BUY)
{
profitPips = (Bid - OrderOpenPrice()) / Point / 10;
if(profitPips > TrailingStart)
{
newStop = Bid - TrailingStep * Point * 10;
if(newStop > currentStop || currentStop == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newStop, OrderTakeProfit(), 0, clrNONE);
}
}
else if(OrderType() == OP_SELL)
{
profitPips = (OrderOpenPrice() - Ask) / Point / 10;
if(profitPips > TrailingStart)
{
newStop = Ask + TrailingStep * Point * 10;
if(newStop < currentStop || currentStop == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newStop, OrderTakeProfit(), 0, clrNONE);
}
}
}
}
}
}

//+------------------------------------------------------------------+
//| RSI到达目标水平时平仓 |
//+------------------------------------------------------------------+
void ManageExitByRSI(double rsiCurrent)
{
if(RSIExitLevel <= 0 || RSIExitLevel >= 100) return;

for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
bool shouldClose = false;
if(OrderType() == OP_BUY && rsiCurrent >= RSIExitLevel)
shouldClose = true;
else if(OrderType() == OP_SELL && rsiCurrent <= (100 - RSIExitLevel))
shouldClose = true;

if(shouldClose)
OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 3, clrNONE);
}
}
}
}
//+------------------------------------------------------------------+
```

参数详解



| 参数 | 说明 | 推荐值 |
|------|------|--------|
| 固定手数 | 每笔交易开仓手数 | 小账户0.01-0.1 |
| RSI周期 | RSI计算周期 | 14(标准) |
| 超买线 | 超买阈值 | 70-80 |
| 超卖线 | 超卖阈值 | 20-30 |
| RSI平仓线 | RSI回归到此水平平仓 | 52-55 |
| 止损点数 | 止损距离 | 30-50 |
| 止盈点数 | 止盈距离 | 60-100 |
| 移动启动点 | 盈利超过此点数启动移动止损 | 20-30 |
| 移动步长 | 移动止损距离 | 10-15 |
| 最大点差 | 允许的最大点差 | 20-40 |
| 时间过滤 | 是否启用交易时段限制 | true |
| 开始/结束时间 | 交易时段(服务器时间) | 2-20点 |
| 每日最大亏损 | 每日亏损限制百分比 | 5-15 |
| 魔术号 | EA标识码 | 任意唯一数字 |

编译与安装步骤



1. 在MT4中打开MetaEditor(按F4或工具>MetaQuotes语言编辑器)
2. 文件>新建>智能交易系统>下一步
3. 粘贴完整代码,替换默认内容
4. 点击编译按钮(F7)或按Compile
5. 确保编译结果为0错误0警告
6. 附加到图表并调整输入参数

编译修改技巧



  • 对于5位报价经纪商,点数计算已使用`Point * 10`处理

  • 如遇到"undeclared identifier"错误,确保代码开头有`#property strict`

  • 推荐在M5或M15周期上运行本EA效果最佳

  • 实盘前务必在模拟账户进行充分回测


  • 策略说明



    本EA在震荡市场表现最佳。重大新闻事件期间请避免使用,因为此时点差扩大且RSI信号可靠性下降。RSI平仓线功能可帮助捕捉均值回归波段,无需等待止损或止盈触发。

    参考来源



    本文EA源码为自主编译测试。RSI策略基于Welles Wilder原始RSI方法论中的经典均值回归原理编写。

    *如需包含神经网络过滤器和多策略组合的高级EA,欢迎查看我们的专业EA库,附赠终身更新和技术支持。*