本文提供一套专业级MQL4 EA源码,融合了RSI、MACD和EMA交叉三种信号类型,并集成了高级资金管理与新闻过滤器。适合希望通过多信号源分散风险并进行智能仓位管理的交易者。
策略逻辑:
高级功能:
参数详解:
MQL4源码:
```mql4
//+------------------------------------------------------------------+
//| MultiStrategyEA_MoneyManagement.mq4 |
//| 自主编译 / Self-compiled |
//+------------------------------------------------------------------+
#property copyright "外汇高级工具"
#property link ""
#property version "2.00"
#property strict
//--- 信号设置
input int SignalVoteRequirement = 1; // 0=任一,1=至少2个,2=全部3个
input int RSI_Period = 14;
input double RSI_Overbought = 70;
input double RSI_Oversold = 30;
input int MACD_Fast = 12;
input int MACD_Slow = 26;
input int MACD_Signal = 9;
input int EMA_Fast = 12;
input int EMA_Slow = 26;
//--- 资金管理
input bool UseFixedRatioMM = true;
input double RiskPercent = 2.0; // 每笔风险占净值百分比
input double FixedLotSize = 0.1;
input int StopLoss = 50;
input int TakeProfit = 150;
//--- 过滤器
input bool UseNewsFilter = true;
input int NewsAvoidHours = 2; // 新闻前后2小时不开仓
input bool UseTimeFilter = true;
input int StartHour = 8;
input int EndHour = 20;
input int MaxSpread = 30; // 最大点差
input int TrailingStop = 40;
input int BreakEvenPips = 30;
//--- EA设置
input int MagicNumber = 202411;
input int Slippage = 3;
double currentSpread;
datetime lastNewsCheck = 0;
string highImpactNewsSymbols[] = {"USD","EUR","GBP","JPY","AUD","CAD","CHF","NZD"};
//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
if(EMA_Fast >= EMA_Slow)
{
Print("错误:EMA快线周期必须小于慢线周期");
return(INIT_PARAMETERS_INCORRECT);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA核心tick函数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 点差检查
currentSpread = (Ask - Bid) / _Point;
if(currentSpread > MaxSpread && MaxSpread > 0)
{
Comment("点差过高:", currentSpread);
return;
}
// 时间过滤
if(UseTimeFilter && !IsTradingTime())
{
Comment("非交易时段");
return;
}
// 新闻过滤
if(UseNewsFilter && IsNewsTime())
{
Comment("新闻过滤激活 - 暂停交易");
return;
}
// 移动止损和保本处理
ManageOpenPositions();
// 检查新开仓信号
if(CountOpenOrders() == 0)
{
int signal = GetCombinedSignal();
if(signal == 1) OpenOrder(OP_BUY);
if(signal == -1) OpenOrder(OP_SELL);
}
}
//+------------------------------------------------------------------+
//| 组合信号投票系统 |
//+------------------------------------------------------------------+
int GetCombinedSignal()
{
int buyVotes = 0, sellVotes = 0;
// RSI信号
double rsi = iRSI(_Symbol,0,RSI_Period,PRICE_CLOSE,1);
double rsi_prev = iRSI(_Symbol,0,RSI_Period,PRICE_CLOSE,2);
if(rsi < RSI_Oversold && rsi_prev <= RSI_Oversold) buyVotes++;
if(rsi > RSI_Overbought && rsi_prev >= RSI_Overbought) sellVotes++;
// MACD信号
double macd_main = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_MAIN,1);
double macd_signal = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_SIGNAL,1);
double macd_main_prev = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_MAIN,2);
double macd_signal_prev = iMACD(_Symbol,0,MACD_Fast,MACD_Slow,MACD_Signal,PRICE_CLOSE,MODE_SIGNAL,2);
if(macd_main > macd_signal && macd_main_prev <= macd_signal_prev) buyVotes++;
if(macd_main < macd_signal && macd_main_prev >= macd_signal_prev) sellVotes++;
// EMA交叉信号
double ema_fast = iMA(_Symbol,0,EMA_Fast,0,MODE_EMA,PRICE_CLOSE,1);
double ema_slow = iMA(_Symbol,0,EMA_Slow,0,MODE_EMA,PRICE_CLOSE,1);
double ema_fast_prev = iMA(_Symbol,0,EMA_Fast,0,MODE_EMA,PRICE_CLOSE,2);
double ema_slow_prev = iMA(_Symbol,0,EMA_Slow,0,MODE_EMA,PRICE_CLOSE,2);
if(ema_fast > ema_slow && ema_fast_prev <= ema_slow_prev) buyVotes++;
if(ema_fast < ema_slow && ema_fast_prev >= ema_slow_prev) sellVotes++;
// 投票逻辑
if(SignalVoteRequirement == 0)
{
if(buyVotes > 0) return 1;
if(sellVotes > 0) return -1;
}
else if(SignalVoteRequirement == 1)
{
if(buyVotes >= 2) return 1;
if(sellVotes >= 2) return -1;
}
else if(SignalVoteRequirement == 2)
{
if(buyVotes == 3) return 1;
if(sellVotes == 3) return -1;
}
return 0;
}
//+------------------------------------------------------------------+
//| 固定比例资金管理 - 动态计算手数 |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
if(!UseFixedRatioMM) return FixedLotSize;
double riskMoney = AccountBalance() * RiskPercent / 100;
double tickValue = MarketInfo(_Symbol,MODE_TICKVALUE);
double stopPoints = StopLoss * 10;
if(stopPoints <= 0) return FixedLotSize;
double lot = riskMoney / (stopPoints * tickValue);
double minLot = MarketInfo(_Symbol,MODE_MINLOT);
double maxLot = MarketInfo(_Symbol,MODE_MAXLOT);
double stepLot = MarketInfo(_Symbol,MODE_LOTSTEP);
lot = MathFloor(lot / stepLot) * stepLot;
lot = MathMax(minLot, MathMin(maxLot, lot));
return NormalizeDouble(lot, 2);
}
//+------------------------------------------------------------------+
//| 开仓函数(动态手数) |
//+------------------------------------------------------------------+
void OpenOrder(int cmd)
{
double lot = CalculateLotSize();
double price, sl, tp;
if(cmd == OP_BUY)
{
price = Ask;
if(StopLoss > 0) sl = price - StopLoss * _Point * 10;
if(TakeProfit > 0) tp = price + TakeProfit * _Point * 10;
}
else
{
price = Bid;
if(StopLoss > 0) sl = price + StopLoss * _Point * 10;
if(TakeProfit > 0) tp = price - TakeProfit * _Point * 10;
}
int ticket = OrderSend(_Symbol,cmd,lot,price,Slippage,sl,tp,"多策略EA",MagicNumber,0,clrNONE);
if(ticket < 0)
{
Print("开仓失败,错误码:", GetLastError());
}
}
//+------------------------------------------------------------------+
//| 统计当前持仓数量 |
//+------------------------------------------------------------------+
int CountOpenOrders()
{
int count = 0;
for(int i=0; i
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
if(OrderMagicNumber() == MagicNumber && OrderSymbol() == _Symbol)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| 移动止损和保本管理 |
//+------------------------------------------------------------------+
void ManageOpenPositions()
{
for(int i=0; i
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if(OrderMagicNumber() != MagicNumber || OrderSymbol() != _Symbol) continue;
double newSL = OrderStopLoss();
double profitPips = 0;
if(OrderType() == OP_BUY)
{
profitPips = (Bid - OrderOpenPrice()) / _Point / 10;
// 保本止损
if(BreakEvenPips > 0 && profitPips >= BreakEvenPips && OrderStopLoss() < OrderOpenPrice())
newSL = OrderOpenPrice();
// 移动止损
if(TrailingStop > 0 && profitPips > TrailingStop)
{
double trailSL = Bid - TrailingStop * _Point * 10;
if(trailSL > OrderStopLoss()) newSL = trailSL;
}
}
else if(OrderType() == OP_SELL)
{
profitPips = (OrderOpenPrice() - Ask) / _Point / 10;
if(BreakEvenPips > 0 && profitPips >= BreakEvenPips && OrderStopLoss() > OrderOpenPrice())
newSL = OrderOpenPrice();
if(TrailingStop > 0 && profitPips > TrailingStop)
{
double trailSL = Ask + TrailingStop * _Point * 10;
if(trailSL < OrderStopLoss() || OrderStopLoss() == 0) newSL = trailSL;
}
}
if(newSL != OrderStopLoss())
OrderModify(OrderTicket(),OrderOpenPrice(),newSL,OrderTakeProfit(),0,clrNONE);
}
}
}
//+------------------------------------------------------------------+
//| 时间过滤函数 |
//+------------------------------------------------------------------+
bool IsTradingTime()
{
datetime now = TimeCurrent();
int hour = TimeHour(now);
return (hour >= StartHour && hour < EndHour);
}
//+------------------------------------------------------------------+
//| 新闻过滤函数(简化版,生产环境需接入真实财经日历API) |
//+------------------------------------------------------------------+
bool IsNewsTime()
{
// 生产环境请接入新闻日历API
// 此处为占位示例:周一早盘和周五晚盘避开
datetime now = TimeCurrent();
if(TimeDayOfWeek(now) == 1 && TimeHour(now) < NewsAvoidHours) return true;
if(TimeDayOfWeek(now) == 5 && TimeHour(now) > 24 - NewsAvoidHours) return true;
return false;
}
//+------------------------------------------------------------------+
//| EA反初始化 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
```
编译与修改教程:
1. 在MetaEditor中编译(F7)– 确保无错误
2. 调整`SignalVoteRequirement`改变信号严格程度
3. 资金管理调优:修改`RiskPercent`(建议1-3%)
4. 新闻过滤器为占位代码,生产环境需接入真实经济日历API
5. 使用MT4策略测试器进行回测,验证参数有效性
常见调试技巧:
参考来源: 自主编译,多策略逻辑参考专业基金管理技术。
需要持续更新、高级技术支持以及访问我们完整的高胜率EA库?欢迎订阅我们的付费EA套餐,获取独家策略和一对一指导。