This article presents a professional-grade MQL4 EA源码 that combines three signal types – RSI, MACD, and EMA crossover – with advanced money management and an integrated news filter. Perfect for serious traders looking to diversify signal sources and manage risk intelligently.
Strategy Logic:
Advanced Features:
Parameters Explanation:
MQL4 Source Code:
```mql4
//+------------------------------------------------------------------+
//| MultiStrategyEA_MoneyManagement.mq4 |
//| 自主编译 / Self-compiled |
//+------------------------------------------------------------------+
#property copyright "Forex Advanced Tools"
#property link ""
#property version "2.00"
#property strict
//--- Signal settings
input int SignalVoteRequirement = 1; // 0=any,1=at least 2,2=all 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;
//--- Money Management
input bool UseFixedRatioMM = true;
input double RiskPercent = 2.0; // % of equity to risk per trade
input double FixedLotSize = 0.1;
input int StopLoss = 50;
input int TakeProfit = 150;
//--- Filters
input bool UseNewsFilter = true;
input int NewsAvoidHours = 2; // avoid trading 2h before/after news
input bool UseTimeFilter = true;
input int StartHour = 8;
input int EndHour = 20;
input int MaxSpread = 30; // max spread in points
input int TrailingStop = 40;
input int BreakEvenPips = 30;
//--- EA settings
input int MagicNumber = 202411;
input int Slippage = 3;
double currentSpread;
datetime lastNewsCheck = 0;
string highImpactNewsSymbols[] = {"USD","EUR","GBP","JPY","AUD","CAD","CHF","NZD"};
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(EMA_Fast >= EMA_Slow)
{
Print("Error: EMA_Fast must be less than EMA_Slow");
return(INIT_PARAMETERS_INCORRECT);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Spread check
currentSpread = (Ask - Bid) / _Point;
if(currentSpread > MaxSpread && MaxSpread > 0)
{
Comment("Spread too high: ", currentSpread);
return;
}
// Time filter
if(UseTimeFilter && !IsTradingTime())
{
Comment("Outside trading hours");
return;
}
// News filter (simplified - checks if within avoid period)
if(UseNewsFilter && IsNewsTime())
{
Comment("News filter active - no trading");
return;
}
// Trailing stop & break-even
ManageOpenPositions();
// Check for new trade signals
if(CountOpenOrders() == 0)
{
int signal = GetCombinedSignal();
if(signal == 1) OpenOrder(OP_BUY);
if(signal == -1) OpenOrder(OP_SELL);
}
}
//+------------------------------------------------------------------+
//| Combined signal voting system |
//+------------------------------------------------------------------+
int GetCombinedSignal()
{
int buyVotes = 0, sellVotes = 0;
// RSI signal
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 signal
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 crossover signal
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++;
// Voting logic
if(SignalVoteRequirement == 0) // any signal
{
if(buyVotes > 0) return 1;
if(sellVotes > 0) return -1;
}
else if(SignalVoteRequirement == 1) // at least 2 votes
{
if(buyVotes >= 2) return 1;
if(sellVotes >= 2) return -1;
}
else if(SignalVoteRequirement == 2) // all 3 votes
{
if(buyVotes == 3) return 1;
if(sellVotes == 3) return -1;
}
return 0;
}
//+------------------------------------------------------------------+
//| Fixed Ratio Money Management |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
if(!UseFixedRatioMM) return FixedLotSize;
double riskMoney = AccountBalance() * RiskPercent / 100;
double tickValue = MarketInfo(_Symbol,MODE_TICKVALUE);
double stopPoints = StopLoss * 10; // convert to points
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);
}
//+------------------------------------------------------------------+
//| Open order with dynamic lot size |
//+------------------------------------------------------------------+
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,"Multi-Strategy EA",MagicNumber,0,clrNONE);
if(ticket < 0)
{
Print("OrderSend failed: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Count open orders |
//+------------------------------------------------------------------+
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;
}
//+------------------------------------------------------------------+
//| Trailing stop and break-even management |
//+------------------------------------------------------------------+
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;
// Break-even
if(BreakEvenPips > 0 && profitPips >= BreakEvenPips && OrderStopLoss() < OrderOpenPrice())
newSL = OrderOpenPrice();
// Trailing stop
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);
}
}
}
//+------------------------------------------------------------------+
//| Time filter |
//+------------------------------------------------------------------+
bool IsTradingTime()
{
datetime now = TimeCurrent();
int hour = TimeHour(now);
return (hour >= StartHour && hour < EndHour);
}
//+------------------------------------------------------------------+
//| Simplified news filter (placeholder - requires external news API)|
//+------------------------------------------------------------------+
bool IsNewsTime()
{
// In production, integrate with a news calendar API
// This is a placeholder checking last Monday (no real news data)
datetime now = TimeCurrent();
if(TimeDayOfWeek(now) == 1 && TimeHour(now) < NewsAvoidHours) return true;
if(TimeDayOfWeek(now) == 5 && TimeHour(now) > 24 - NewsAvoidHours) return true;
return false;
}
//+------------------------------------------------------------------+
//| Expert deinitialization |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
```
Compilation & Modification Guide:
1. Compile in MetaEditor (F7) – ensure no errors
2. Adjust `SignalVoteRequirement` to change signal strictness
3. For money management tuning, modify `RiskPercent` (recommended 1-3%)
4. News filter is a placeholder – integrate with a real economic calendar API for production use
5. Backtest before live trading (Strategy Tester in MT4)
Reference: 自主编译 / Self-compiled. Multi-strategy logic inspired by professional fund management techniques.
For ongoing updates, premium support, and access to our complete EA library with high-probability setups, subscribe to our paid EA package.