RSI 超卖回归 EA(MT4)
RSI 超卖且价格在长期均线上方时做多,固定止损止盈,带每日单数限制
效果示意图 · AI 根据源码绘制
//+------------------------------------------------------------------+
//| EMA趋势过滤 + RSI反转EA |
//| 只在新K线开盘时判断信号,支持4位/5位报价 |
//+------------------------------------------------------------------+
#property copyright "Kiro MQL4 EA Generator"
#property link ""
#property version "1.00"
#property strict
//--- 可调参数
input int RSI_Period = 14; // RSI周期
input double RSI_Oversold = 30.0; // RSI超卖阈值(做多信号)
input double RSI_Overbought = 70.0; // RSI超买阈值(做空信号)
input int EMA_Period = 200; // EMA周期(趋势过滤)
input double LotSize = 0.1; // 固定手数
input int StopLossPips = 50; // 止损点数(pips)
input double TakeProfitMultiplier = 1.5; // 止盈倍数(相对止损)
input int MagicNumber = 20250106; // 魔术号
input int MaxPositions = 1; // 同时最多持仓数
input int MaxOrdersPerDay = 5; // 每天最多下单数
input int Slippage = 3; // 滑点(pips)
//--- 全局变量
datetime LastBarTime = 0; // 上一根K线的时间,用于判断新K线
int OrderCountToday = 0; // 今日已下单数
int LastTradeDay = 0; // 上次交易日期(DayOfYear)
//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
// 参数合法性检查
if(RSI_Period < 2 || RSI_Period > 100)
{
Alert("RSI周期必须在2到100之间");
return(INIT_PARAMETERS_INCORRECT);
}
if(RSI_Oversold >= RSI_Overbought)
{
Alert("RSI超卖阈值必须小于超买阈值");
return(INIT_PARAMETERS_INCORRECT);
}
if(EMA_Period < 2 || EMA_Period > 500)
{
Alert("EMA周期必须在2到500之间");
return(INIT_PARAMETERS_INCORRECT);
}
if(LotSize <= 0)
{
Alert("手数必须大于0");
return(INIT_PARAMETERS_INCORRECT);
}
if(StopLossPips <= 0)
{
Alert("止损点数必须大于0");
return(INIT_PARAMETERS_INCORRECT);
}
if(TakeProfitMultiplier <= 0)
{
Alert("止盈倍数必须大于0");
return(INIT_PARAMETERS_INCORRECT);
}
// 初始化上一根K线时间
LastBarTime = Time[0];
// 初始化今日交易计数
LastTradeDay = DayOfYear();
OrderCountToday = 0;
Print("EA初始化成功 - ", Symbol(), " M", Period());
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA反初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("EA已停止,原因代码: ", reason);
}
//+------------------------------------------------------------------+
//| EA主函数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. 检查是否是新K线
if(Time[0] == LastBarTime)
return; // 不是新K线,直接返回
LastBarTime = Time[0]; // 更新上一根K线时间
// 2. 重置每日交易计数
int currentDay = DayOfYear();
if(currentDay != LastTradeDay)
{
OrderCountToday = 0;
LastTradeDay = currentDay;
Print("新交易日开始,重置今日下单计数");
}
// 3. 检查每日下单限制
if(OrderCountToday >= MaxOrdersPerDay)
{
return; // 今日已达到最大下单数
}
// 4. 检查当前持仓数
int currentPositions = CountMyPositions();
if(currentPositions >= MaxPositions)
{
return; // 已达到最大持仓数
}
// 5. 计算指标值(需要足够的历史数据)
if(Bars < EMA_Period + RSI_Period + 10)
{
Print("历史数据不足,等待更多K线");
return;
}
// 当前K线(索引1,已完成的K线)的RSI和EMA
double rsi_current = iRSI(Symbol(), 0, RSI_Period, PRICE_CLOSE, 1);
double rsi_previous = iRSI(Symbol(), 0, RSI_Period, PRICE_CLOSE, 2);
double ema_current = iMA(Symbol(), 0, EMA_Period, 0, MODE_EMA, PRICE_CLOSE, 1);
double price_current = Close[1];
// 6. 信号判断
bool buySignal = false;
bool sellSignal = false;
// 做多信号:价格在EMA200上方 且 RSI从30以下回升到30以上
if(price_current > ema_current)
{
if(rsi_previous < RSI_Oversold && rsi_current >= RSI_Oversold)
{
buySignal = true;
}
}
// 做空信号:价格在EMA200下方 且 RSI从70以上回落到70以下
if(price_current < ema_current)
{
if(rsi_previous > RSI_Overbought && rsi_current <= RSI_Overbought)
{
sellSignal = true;
}
}
// 7. 执行交易
if(buySignal)
{
OpenBuyOrder();
}
else if(sellSignal)
{
OpenSellOrder();
}
}
//+------------------------------------------------------------------+
//| 统计当前持仓数(仅统计本EA的单子) |
//+------------------------------------------------------------------+
int CountMyPositions()
{
int count = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| 开多单 |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
// 计算止损止盈价格
double sl = 0, tp = 0;
CalculateSLTP(OP_BUY, sl, tp);
// 当前卖价(买入用Ask)
double price = Ask;
// 转换滑点(适配4位/5位报价)
int slippage = NormalizeSlippage(Slippage);
// 下单
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, price, slippage, sl, tp,
"EMA_RSI_Buy", MagicNumber, 0, clrBlue);
if(ticket > 0)
{
Print("多单开仓成功,订单号: ", ticket, " 价格: ", price, " SL: ", sl, " TP: ", tp);
OrderCountToday++;
}
else
{
int error = GetLastError();
Print("多单开仓失败,错误码: ", error, " ", ErrorDescription(error));
}
}
//+------------------------------------------------------------------+
//| 开空单 |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
// 计算止损止盈价格
double sl = 0, tp = 0;
CalculateSLTP(OP_SELL, sl, tp);
// 当前买价(卖出用Bid)
double price = Bid;
// 转换滑点(适配4位/5位报价)
int slippage = NormalizeSlippage(Slippage);
// 下单
int ticket = OrderSend(Symbol(), OP_SELL, LotSize, price, slippage, sl, tp,
"EMA_RSI_Sell", MagicNumber, 0, clrRed);
if(ticket > 0)
{
Print("空单开仓成功,订单号: ", ticket, " 价格: ", price, " SL: ", sl, " TP: ", tp);
OrderCountToday++;
}
else
{
int error = GetLastError();
Print("空单开仓失败,错误码: ", error, " ", ErrorDescription(error));
}
}
//+------------------------------------------------------------------+
//| 计算止损止盈价格 |
//+------------------------------------------------------------------+
void CalculateSLTP(int orderType, double &sl, double &tp)
{
double point = Point;
// 适配5位报价(JPY货币对除外)
if(Digits == 5 || Digits == 3)
{
point = point * 10;
}
double slDistance = StopLossPips * point;
double tpDistance = StopLossPips * TakeProfitMultiplier * point;
if(orderType == OP_BUY)
{
sl = NormalizeDouble(Bid - slDistance, Digits);
tp = NormalizeDouble(Bid + tpDistance, Digits);
}
else if(orderType == OP_SELL)
{
sl = NormalizeDouble(Ask + slDistance, Digits);
tp = NormalizeDouble(Ask - tpDistance, Digits);
}
}
//+------------------------------------------------------------------+
//| 适配滑点(4位/5位报价) |
//+------------------------------------------------------------------+
int NormalizeSlippage(int slippagePips)
{
if(Digits == 5 || Digits == 3)
{
return slippagePips * 10;
}
return slippagePips;
}
//+------------------------------------------------------------------+
//| 错误码描述(简化版) |
//+------------------------------------------------------------------+
string ErrorDescription(int errorCode)
{
switch(errorCode)
{
case 0: return "无错误";
case 1: return "无错误,但结果未知";
case 2: return "通用错误";
case 3: return "无效参数";
case 4: return "交易服务器繁忙";
case 5: return "旧版本客户端";
case 6: return "无法连接到交易服务器";
case 7: return "没有足够的权限";
case 8: return "请求太频繁";
case 9: return "不允许的操作扰乱了交易";
case 64: return "账户被禁用";
case 65: return "无效账户";
case 128: return "交易超时";
case 129: return "无效价格";
case 130: return "无效止损";
case 131: return "无效交易量";
case 132: return "市场关闭";
case 133: return "交易被禁止";
case 134: return "资金不足";
case 135: return "价格改变";
case 136: return "无报价";
case 137: return "经纪商繁忙";
case 138: return "重新报价";
case 139: return "订单被锁定";
case 140: return "只允许买入";
case 141: return "请求太多";
case 145: return "由于价格接近市场,修改被拒绝";
case 146: return "交易子系统繁忙";
case 147: return "使用过期价格";
case 148: return "订单价格与Bid/Ask相差太远";
default: return "未知错误";
}
}
//+------------------------------------------------------------------+作品说明
策略思路
本 EA 采用趋势+超跌超买反转的组合逻辑:用 EMA200 判断主趋势方向,用 RSI(14) 的回升/回落作为入场信号。价格在 EMA200 上方只做多,等待 RSI 从超卖区(<30)回升突破 30 时开多单;价格在 EMA200 下方只做空,等待 RSI 从超买区(>70)回落跌破 70 时开空单。止损止盈采用固定点数,支持 4/5 位报价自动适配。新 K 线开盘时才检测信号,避免同一根 K 线重复开仓。设置了每日最大下单数和最大持仓数限制,防止过度交易。
使用说明
- 安装方法
- 将代码保存为
EMA_RSI_Reversal_EA.mq4 - 放入 MT4 数据文件夹的
MQL4/Experts/目录 - 在 MT4 中点击「编译」按钮,确保无错误
- 拖动 EA 到图表上,勾选「允许自动交易」
- 参数调整建议
- RSI_Period(14):标准周期,短周期(如 9)更敏感,长周期(如 21)更平滑
- RSI_Oversold(30)/ RSI_Overbought(70):超卖超买阈值,可根据品种波动性调整(例如股指可用 20/80)
- EMA_Period(200):趋势过滤周期,常用 100/150/200,周期越长趋势判断越稳定
- StopLossPips(50):止损点数,需根据品种波动率调整(如 EURUSD 用 30-50,GBPJPY 用 80-150)
- TakeProfitMultiplier(1.5):盈亏比,1.5 表示止盈是止损的 1.5 倍
- MaxPositions(1):同时最多持仓数,设为 1 可避免同方向重复开仓
- MaxOrdersPerDay(5):每天最多下单数,防止震荡行情频繁交易
- Slippage(3):滑点容忍度(pips),流动性差的品种可适当放宽到 5-10
- 信号识别
- 做多信号:价格在 EMA200 上方 + RSI 从 30 以下回升突破 30
- 做空信号:价格在 EMA200 下方 + RSI 从 70 以上回落跌破 70
- 只在新 K 线开盘时检测,避免同一根 K 线重复触发
- 注意事项
- 回测建议:先在策略测试器中用历史数据测试,确认参数合理后再实盘
- 品种适配:自动适配 4 位和 5 位报价(如 EURUSD 和 USDJPY)
- 风险控制:固定手数交易,建议先用 0.01 手测试,确认稳定后再加仓
- 日志监控:下单失败会打印错误码到「专家」日志,及时检查连接或账户状态
- 趋势品种:本策略适合有明显趋势的品种(如主要货币对、贵金属),震荡市场建议降低 MaxOrdersPerDay 或暂停
- 时间框架:建议用 H1 或 H4 周期,M15 以下信号过于频繁且噪音大
AI 解读根据源码逐行分析写成,供参考,以实际运行为准
这是什么
这是一个在 MT4 上运行的自动交易 EA,用 EMA200 判断大趋势方向,用 RSI(14) 的超卖超买反转作为进场信号。价格在 EMA200 上方时只做多,等 RSI 从 30 以下回升突破 30 开多单;价格在 EMA200 下方时只做空,等 RSI 从 70 以上回落跌破 70 开空单。止损止盈都是固定点数,自动适配 4 位和 5 位报价。
逻辑原理
EA 在每根新 K 线开盘时检测信号,避免同一根 K 线重复开仓。
做多逻辑:前一根 K 线收盘价在 EMA200 上方,同时 RSI 从前一根的 30 以下回升到当前根的 30 或以上,触发做多信号,按 Ask 价开多单。
做空逻辑:前一根 K 线收盘价在 EMA200 下方,同时 RSI 从前一根的 70 以上回落到当前根的 70 或以下,触发做空信号,按 Bid 价开空单。
止损止盈:多单的止损设在入场价下方若干 pips,空单的止损设在入场价上方若干 pips,止盈距离是止损距离乘以倍数(默认 1.5 倍)。代码会根据品种的小数位数(4 位或 5 位)自动换算 Point 值。
风控机制:每天最多下单 5 次,同时最多持仓 1 单,达到上限后不再开新仓。每天 0 点重置计数。
参数说明
- RSI_Period(14):RSI 指标周期,周期越短越敏感,越长越平滑。
- RSI_Oversold(30.0):RSI 超卖阈值,低于这个值算超卖,回升突破时做多。
- RSI_Overbought(70.0):RSI 超买阈值,高于这个值算超买,回落跌破时做空。
- EMA_Period(200):均线周期,用来过滤趋势方向,常用 100、150、200。
- LotSize(0.1):每单固定手数,不根据账户权益动态调整。
- StopLossPips(50):止损点数(pips),需根据品种波动率调整,如 EURUSD 用 30-50,GBPJPY 用 80-150。
- TakeProfitMultiplier(1.5):止盈是止损的多少倍,1.5 表示盈亏比 1.5:1。
- MagicNumber(20250106):魔术号,用来区分本 EA 开的单子,不影响逻辑。
- MaxPositions(1):同时最多持仓数,设为 1 避免同方向重复开仓。
- MaxOrdersPerDay(5):每天最多下单数,防止震荡行情频繁交易。
- Slippage(3):下单时允许的滑点(pips),流动性差的品种可放宽到 5-10。
怎么用
把代码保存为 .mq4 文件,放到 MT4 数据文件夹的 MQL4/Experts/ 目录,在 MT4 里编译无误后,拖到图表上并勾选「允许自动交易」。建议挂在 H1 或 H4 周期,M15 以下信号太频繁。
图表上会看到 EMA200 这条均线(EA 本身不画线,需手动加指标观察),RSI 指标可以在副图窗口加上。多单开仓后图表会标记蓝色箭头(如果开启了可视化),空单是红色箭头。持仓信息在「终端」窗口的「交易」标签查看,下单日志在「专家」标签查看。
适用场景
适合有明显趋势的品种,比如主要货币对(EURUSD、GBPUSD)、贵金属(XAUUSD)。EMA200 过滤掉了逆势交易,RSI 反转信号在趋势回调时进场,盈亏比固定,适合趋势回调行情。
不适合长期横盘震荡的品种或时段(如亚洲盘的窄幅波动),此时 RSI 会频繁穿越阈值但价格没有跟随,容易连续止损。默认参数适合 H1-H4 周期,日内短周期(M5、M15)噪音大,需降低 MaxOrdersPerDay 或调高 StopLossPips。
风险提示
固定止损风险:不同行情波动率差异大,固定点数可能在高波动时止损过小,在低波动时止损过大。建议根据 ATR 或品种特性调整 StopLossPips。
趋势反转风险:EMA200 是滞后指标,趋势反转初期可能还在旧趋势一侧,导致逆势开仓。代码没有移动止损或追踪止盈,拿不住大行情的后半段。
滑点和点差:代码设了滑点容忍度,但实际成交价可能偏离,影响盈亏比。点差成本在频繁交易时累积明显,回测时需用真实点差模式。
参数敏感性:RSI 阈值、EMA 周期、止损点数都会显著影响结果,默认值不一定适合所有品种和周期,必须先回测优化再实盘。
每日限制可能错过机会:MaxOrdersPerDay 达到上限后当天不再交易,可能错过后续的好信号。可根据品种活跃度调整这个参数。
常见问题
- 这个 EA 适合什么周期?
- 建议用 H1 或 H4 周期。M15 以下信号太频繁且噪音大,日线以上信号太少。默认参数是按 H1-H4 设计的。
- 止损 50 pips 是不是太大了?
- 取决于品种。EURUSD 这类波动小的可以用 30-50 pips,GBPJPY 或黄金波动大需要 80-150 pips。建议根据品种的 ATR 值调整。
- 会重绘吗?
- 不会。代码用 iRSI 和 iMA 读取已完成 K 线(索引 1 和 2)的指标值,不依赖当前未完成 K 线,信号确定后不会改变。
- MaxPositions 设为 1 是不是太保守?
- 看个人风格。设为 1 可以避免同方向加仓和资金过度集中,适合稳健交易。如果想在趋势中多次进场,可以改成 2 或 3,但要注意回撤风险。
- 每天最多 5 单够用吗?
- 默认 5 单是为了防止震荡市反复开平仓。如果品种很活跃、周期偏短,可以改成 8-10 单。但如果一天触发超过 10 次信号,说明参数可能不适合当前行情。
RSI Oversold Reversal EA with EMA Filter (MT4)
An MT4 EA that combines EMA200 trend filter with RSI reversal signals. It buys when RSI crosses above 30 with price above EMA200, sells when RSI crosses below 70 with price below EMA200. Fixed stop-loss and take-profit with daily order limits.
Source code is shown above. Compiled EX4 files are available to VIP members.
评论
还没有人评论,来抢个沙发。