Summary: This comprehensive project-based guide walks you through building a complete multi-strategy EA. Learn to combine trend following, RSI mean reversion, and breakout strategies, implement multi-currency monitoring, and create a semi-automatic trading panel with buttons.




Why Build a Multi-Strategy EA
A single-strategy EA works well in specific market conditions but fails when conditions change. A multi-strategy EA combines different approaches to adapt to varying market environments. This project-based tutorial will guide you through building a professional EA that monitors multiple currency pairs, uses three complementary strategies, and includes a manual trading panel.

Complete Multi-Strategy EA Architecture
| Component | Description | Key Features |
|-----------|-------------|--------------|
| Trend Following Strategy | MA crossover for trending markets | EMA 10/30, ADX filter |
| Mean Reversion Strategy | RSI oversold/overbought for ranging markets | RSI 14, Bollinger Bands |
| Breakout Strategy | Price range breakout for volatile markets | 20-period high/low, volume filter |
| Multi-Currency Manager | Monitors multiple symbols simultaneously | 8 pairs, time-slicing |
| Trading Panel | Manual control with buttons | Entry, exit, position management |

1. Complete Multi-Strategy EA Source Code
```mql4
//+------------------------------------------------------------------+
//| MultiStrategyEA.mq4 |
//| Multi-Strategy System |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024"
#property version "1.00"
#property strict

//+------------------------------------------------------------------+
//| INPUT PARAMETERS |
//+------------------------------------------------------------------+
//=== Position Management ===
input double InpFixedLot = 0.01; // Fixed lot size
input double InpRiskPercent = 2.0; // Risk percent per trade
input int InpMagic = 12345; // EA magic number
input int InpSlippage = 30; // Slippage in points
input int InpMaxSpread = 30; // Maximum spread

//=== Strategy Toggles ===
input bool InpUseTrend = true; // Use Trend Following
input bool InpUseMeanRev = true; // Use Mean Reversion
input bool InpUseBreakout = true; // Use Breakout

//=== Trend Following Parameters ===
input int InpTrendFastMA = 10; // Fast EMA period
input int InpTrendSlowMA = 30; // Slow EMA period
input int InpTrendADX = 14; // ADX period
input int InpTrendMinADX = 25; // Minimum ADX for trend

//=== Mean Reversion Parameters ===
input int InpMeanRSIPeriod = 14; // RSI period
input int InpMeanOversold = 30; // Oversold level
input int InpMeanOverbought = 70; // Overbought level
input int InpMeanBBPeriod = 20; // Bollinger period
input double InpMeanBBDev = 2.0; // Bollinger deviation

//=== Breakout Parameters ===
input int InpBreakoutPeriod = 20; // Breakout period
input int InpBreakoutMinRange = 30; // Minimum range in points
input bool InpBreakoutVolumeFilter = true;// Use volume filter

//=== Risk Management ===
input int InpMaxConcurrentTrades = 3; // Max positions per pair
input int InpStopLoss = 50; // Stop loss in points
input int InpTakeProfit = 100; // Take profit in points
input int InpTrailingStart = 30; // Trailing start points
input int InpTrailingStep = 10; // Trailing step points
input double InpMaxDailyLoss = 5.0; // Max daily loss %

//=== Multi-Currency Settings ===
input bool InpMultiCurrency = true; // Enable multi-currency
input string InpSymbols = "EURUSD,GBPUSD,USDJPY,USDCHF,AUDUSD,NZDUSD,USDCAD,EURGBP"; // Pairs

//+------------------------------------------------------------------+
//| GLOBAL VARIABLES |
//+------------------------------------------------------------------+
string g_symbols[];
int g_symbolCount;
datetime g_lastBarTime[];
double g_dailyStartBalance;
datetime g_lastReset;
bool g_panelCreated = false;

//+------------------------------------------------------------------+
//| EXPERT INITIALIZATION |
//+------------------------------------------------------------------+
int OnInit() {
Print("========== Multi-Strategy EA Initialized ==========");

// Initialize multi-currency symbols
if(InpMultiCurrency) {
ParseSymbolList();
} else {
ArrayResize(g_symbols, 1);
g_symbols[0] = Symbol();
}
g_symbolCount = ArraySize(g_symbols);

// Initialize arrays
ArrayResize(g_lastBarTime, g_symbolCount);
for(int i = 0; i < g_symbolCount; i++) {
g_lastBarTime[i] = 0;
}

// Initialize daily tracking
g_dailyStartBalance = AccountBalance();
g_lastReset = GetMidnight();

// Create trading panel
CreateTradingPanel();

Print("Monitoring ", g_symbolCount, " symbols");
Print("Trend Strategy: ", InpUseTrend ? "ON" : "OFF");
Print("Mean Reversion: ", InpUseMeanRev ? "ON" : "OFF");
Print("Breakout: ", InpUseBreakout ? "ON" : "OFF");
Print("=================================================");

return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Parse comma-separated symbol list |
//+------------------------------------------------------------------+
void ParseSymbolList() {
string temp = InpSymbols;
int count = 1;

// Count symbols
for(int i = 0; i < StringLen(temp); i++) {
if(StringSubstr(temp, i, 1) == ",") count++;
}

ArrayResize(g_symbols, count);

// Parse each symbol
for(int i = 0; i < count; i++) {
int pos = StringFind(temp, ",");
if(pos > 0) {
g_symbols[i] = StringSubstr(temp, 0, pos);
temp = StringSubstr(temp, pos + 1);
} else {
g_symbols[i] = temp;
}
Print("Adding symbol: ", g_symbols[i]);
}
}

//+------------------------------------------------------------------+
//| EXPERT TICK FUNCTION |
//+------------------------------------------------------------------+
void OnTick() {
// Check for daily reset
ResetDailyIfNeeded();

// Update trading panel
UpdateTradingPanel();

// Process each symbol
for(int i = 0; i < g_symbolCount; i++) {
string currentSymbol = g_symbols[i];

// Check for new bar
if(!IsNewBar(currentSymbol, i)) continue;

// Check if we can trade this symbol
if(!CanTradeSymbol(currentSymbol)) continue;

// Evaluate all active strategies
int signal = EvaluateAllStrategies(currentSymbol);

// Execute signal
if(signal != SIGNAL_NONE) {
ExecuteTrade(currentSymbol, signal);
}
}
}

//+------------------------------------------------------------------+
//| Check for new bar |
//+------------------------------------------------------------------+
bool IsNewBar(string symbol, int index) {
datetime currentBarTime = iTime(symbol, PERIOD_CURRENT, 0);
if(currentBarTime != g_lastBarTime[index]) {
g_lastBarTime[index] = currentBarTime;
return true;
}
return false;
}

//+------------------------------------------------------------------+
//| Check if we can trade this symbol |
//+------------------------------------------------------------------+
bool CanTradeSymbol(string symbol) {
// Check daily loss limit
double currentEquity = AccountEquity();
double lossPercent = (g_dailyStartBalance - currentEquity) / g_dailyStartBalance * 100;
if(lossPercent >= InpMaxDailyLoss) {
Comment("Daily loss limit reached: ", DoubleToString(lossPercent, 1), "%");
return false;
}

// Check concurrent positions for this symbol
int positions = CountOrdersBySymbol(symbol, InpMagic);
if(positions >= InpMaxConcurrentTrades) return false;

// Check spread
int spread = (int)MarketInfo(symbol, MODE_SPREAD);
if(spread > InpMaxSpread) return false;

return true;
}

//+------------------------------------------------------------------+
//| Evaluate all active strategies |
//+------------------------------------------------------------------+
int EvaluateAllStrategies(string symbol) {
int trendSignal = SIGNAL_NONE;
int meanSignal = SIGNAL_NONE;
int breakoutSignal = SIGNAL_NONE;

// Trend Following Strategy (MA Crossover + ADX)
if(InpUseTrend) {
trendSignal = EvaluateTrendStrategy(symbol);
}

// Mean Reversion Strategy (RSI + Bollinger)
if(InpUseMeanRev) {
meanSignal = EvaluateMeanReversion(symbol);
}

// Breakout Strategy (Range Breakout)
if(InpUseBreakout) {
breakoutSignal = EvaluateBreakoutStrategy(symbol);
}

// Weighted voting (2 out of 3 for confirmation)
int buyVotes = 0;
int sellVotes = 0;

if(trendSignal == SIGNAL_BUY) buyVotes++;
if(trendSignal == SIGNAL_SELL) sellVotes++;
if(meanSignal == SIGNAL_BUY) buyVotes++;
if(meanSignal == SIGNAL_SELL) sellVotes++;
if(breakoutSignal == SIGNAL_BUY) buyVotes++;
if(breakoutSignal == SIGNAL_SELL) sellVotes++;

if(buyVotes >= 2) return SIGNAL_BUY;
if(sellVotes >= 2) return SIGNAL_SELL;

// Single strategy signals when others are neutral
if(trendSignal != SIGNAL_NONE) return trendSignal;
if(meanSignal != SIGNAL_NONE) return meanSignal;
if(breakoutSignal != SIGNAL_NONE) return breakoutSignal;

return SIGNAL_NONE;
}

//+------------------------------------------------------------------+
//| TREND FOLLOWING STRATEGY (MA Crossover + ADX) |
//+------------------------------------------------------------------+
int EvaluateTrendStrategy(string symbol) {
double maFast = iMA(symbol, 0, InpTrendFastMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double maSlow = iMA(symbol, 0, InpTrendSlowMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double maFastPrev = iMA(symbol, 0, InpTrendFastMA, 0, MODE_EMA, PRICE_CLOSE, 2);
double maSlowPrev = iMA(symbol, 0, InpTrendSlowMA, 0, MODE_EMA, PRICE_CLOSE, 2);
double adx = iADX(symbol, 0, InpTrendADX, PRICE_CLOSE, MODE_MAIN, 1);

// Need strong trend
if(adx < InpTrendMinADX) return SIGNAL_NONE;

// Bullish crossover (Golden Cross)
if(maFast > maSlow && maFastPrev <= maSlowPrev) {
return SIGNAL_BUY;
}
// Bearish crossover (Death Cross)
else if(maFast < maSlow && maFastPrev >= maSlowPrev) {
return SIGNAL_SELL;
}

return SIGNAL_NONE;
}

//+------------------------------------------------------------------+
//| MEAN REVERSION STRATEGY (RSI + Bollinger Bands) |
//+------------------------------------------------------------------+
int EvaluateMeanReversion(string symbol) {
double rsi = iRSI(symbol, 0, InpMeanRSIPeriod, PRICE_CLOSE, 1);
double rsiPrev = iRSI(symbol, 0, InpMeanRSIPeriod, PRICE_CLOSE, 2);

// Bollinger Bands
double bbUpper = iBands(symbol, 0, InpMeanBBPeriod, InpMeanBBDev, 0, PRICE_CLOSE, MODE_UPPER, 1);
double bbLower = iBands(symbol, 0, InpMeanBBPeriod, InpMeanBBDev, 0, PRICE_CLOSE, MODE_LOWER, 1);
double close = iClose(symbol, 0, 1);

// Oversold bounce (RSI oversold + price near lower band)
if(rsi < InpMeanOversold && rsiPrev < InpMeanOversold && rsi > rsiPrev) {
if(close <= bbLower) {
return SIGNAL_BUY;
}
}

// Overbought bounce (RSI overbought + price near upper band)
if(rsi > InpMeanOverbought && rsiPrev > InpMeanOverbought && rsi < rsiPrev) {
if(close >= bbUpper) {
return SIGNAL_SELL;
}
}

return SIGNAL_NONE;
}

//+------------------------------------------------------------------+
//| BREAKOUT STRATEGY (Range Breakout) |
//+------------------------------------------------------------------+
int EvaluateBreakoutStrategy(string symbol) {
double high20 = iHigh(symbol, 0, iHighest(symbol, 0, MODE_HIGH, InpBreakoutPeriod, 1));
double low20 = iLow(symbol, 0, iLowest(symbol, 0, MODE_LOW, InpBreakoutPeriod, 1));
double range = (high20 - low20) / Point();

// Need sufficient range for meaningful breakout
if(range < InpBreakoutMinRange) return SIGNAL_NONE;

double close = iClose(symbol, 0, 1);
double closePrev = iClose(symbol, 0, 2);
double volume = iVolume(symbol, 0, 1);
double avgVolume = iMA(symbol, 0, 20, 0, MODE_SMA, VOLUME, 1);

// Upside breakout with volume confirmation
if(close > high20 && closePrev <= high20) {
if(!InpBreakoutVolumeFilter || volume > avgVolume * 1.2) {
return SIGNAL_BUY;
}
}

// Downside breakout with volume confirmation
if(close < low20 && closePrev >= low20) {
if(!InpBreakoutVolumeFilter || volume > avgVolume * 1.2) {
return SIGNAL_SELL;
}
}

return SIGNAL_NONE;
}

//+------------------------------------------------------------------+
//| EXECUTE TRADE |
//+------------------------------------------------------------------+
void ExecuteTrade(string symbol, int signal) {
double lotSize = InpFixedLot;
if(InpRiskPercent > 0 && InpStopLoss > 0) {
lotSize = CalculateRiskLot(symbol, InpRiskPercent, InpStopLoss);
}

lotSize = NormalizeDouble(lotSize, 2);
if(lotSize < MarketInfo(symbol, MODE_MINLOT)) {
Print("Lot size too small: ", lotSize);
return;
}

int orderType = (signal == SIGNAL_BUY) ? OP_BUY : OP_SELL;
double price = (orderType == OP_BUY) ? MarketInfo(symbol, MODE_ASK) : MarketInfo(symbol, MODE_BID);
double sl = 0, tp = 0;
int digits = (int)MarketInfo(symbol, MODE_DIGITS);
int stopLevel = (int)MarketInfo(symbol, MODE_STOPLEVEL);
int effectiveSL = MathMax(InpStopLoss, stopLevel);

if(InpStopLoss > 0) {
if(orderType == OP_BUY) {
sl = NormalizeDouble(price - effectiveSL * Point(), digits);
tp = NormalizeDouble(price + InpTakeProfit * Point(), digits);
} else {
sl = NormalizeDouble(price + effectiveSL * Point(), digits);
tp = NormalizeDouble(price - InpTakeProfit * Point(), digits);
}
}

int ticket = OrderSend(symbol, orderType, lotSize, price, InpSlippage, sl, tp, "MultiStrategy EA", InpMagic, 0, clrNONE);

if(ticket > 0) {
Print("[", symbol, "] Order opened. Ticket: ", ticket, " Signal: ", signal == SIGNAL_BUY ? "BUY" : "SELL");
} else {
Print("[", symbol, "] Order failed. Error: ", GetLastError());
}
}

//+------------------------------------------------------------------+
//| Calculate risk-based lot size |
//+------------------------------------------------------------------+
double CalculateRiskLot(string symbol, double riskPercent, int stopPoints) {
double equity = AccountEquity();
double riskAmount = equity * riskPercent / 100;
double tickValue = MarketInfo(symbol, MODE_TICKVALUE);

if(tickValue <= 0 || stopPoints <= 0) return InpFixedLot;

double rawLots = riskAmount / (stopPoints * tickValue);
double stepSize = MarketInfo(symbol, MODE_LOTSTEP);
double minLot = MarketInfo(symbol, MODE_MINLOT);
double maxLot = MarketInfo(symbol, MODE_MAXLOT);

rawLots = MathFloor(rawLots / stepSize) * stepSize;
rawLots = MathMax(minLot, MathMin(maxLot, rawLots));

return rawLots;
}

//+------------------------------------------------------------------+
//| Count orders by symbol and magic |
//+------------------------------------------------------------------+
int CountOrdersBySymbol(string symbol, int magic) {
int count = 0;
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if(OrderSymbol() == symbol && OrderMagicNumber() == magic) {
count++;
}
}
}
return count;
}

//+------------------------------------------------------------------+
//| Apply trailing stop to all positions |
//+------------------------------------------------------------------+
void ManageAllPositions() {
for(int i = 0; i < OrdersTotal(); i++) {
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if(OrderMagicNumber() == InpMagic) {
ApplyTrailingStop(OrderTicket());
}
}
}
}

//+------------------------------------------------------------------+
//| Apply trailing stop to single order |
//+------------------------------------------------------------------+
void ApplyTrailingStop(int ticket) {
if(!OrderSelect(ticket, SELECT_BY_TICKET)) return;

double openPrice = OrderOpenPrice();
double currentStop = OrderStopLoss();
double currentPrice = (OrderType() == OP_BUY) ? MarketInfo(OrderSymbol(), MODE_BID) : MarketInfo(OrderSymbol(), MODE_ASK);
double newStop = 0;
int digits = (int)MarketInfo(OrderSymbol(), MODE_DIGITS);

if(OrderType() == OP_BUY) {
double profitPoints = (currentPrice - openPrice) / Point();
if(profitPoints > InpTrailingStart) {
newStop = NormalizeDouble(currentPrice - InpTrailingStep * Point(), digits);
}
} else {
double profitPoints = (openPrice - currentPrice) / Point();
if(profitPoints > InpTrailingStart) {
newStop = NormalizeDouble(currentPrice + InpTrailingStep * Point(), digits);
}
}

if(newStop > 0 && newStop != currentStop) {
OrderModify(ticket, openPrice, newStop, OrderTakeProfit(), 0, clrNONE);
}
}
```

2. Semi-Automatic Trading Panel with Buttons
```mql4
//+------------------------------------------------------------------+
//| TRADING PANEL - Create on chart |
//+------------------------------------------------------------------+
void CreateTradingPanel() {
// Remove existing objects
for(int i = 0; i < ObjectsTotal(); i++) {
string name = ObjectName(i);
if(StringFind(name, "TradingPanel_") == 0) {
ObjectDelete(name);
}
}

// Background rectangle
ObjectCreate(0, "TradingPanel_BG", OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, "TradingPanel_BG", OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, "TradingPanel_BG", OBJPROP_YDISTANCE, 10);
ObjectSetInteger(0, "TradingPanel_BG", OBJPROP_XSIZE, 200);
ObjectSetInteger(0, "TradingPanel_BG", OBJPROP_YSIZE, 150);
ObjectSetInteger(0, "TradingPanel_BG", OBJPROP_BACKCOLOR, clrBlack);
ObjectSetInteger(0, "TradingPanel_BG", OBJPROP_BORDER_COLOR, clrWhite);

// Title
CreateLabel("TradingPanel_Title", "Multi-Strategy EA Control Panel", 15, 25, clrWhite, 10);

// BUY button
CreateButton("TradingPanel_Buy", "BUY", 20, 50, 60, 25, clrGreen);

// SELL button
CreateButton("TradingPanel_Sell", "SELL", 90, 50, 60, 25, clrRed);

// CLOSE ALL button
CreateButton("TradingPanel_CloseAll", "CLOSE ALL", 20, 85, 130, 25, clrOrange);

// Auto-Trade toggle
CreateButton("TradingPanel_Auto", "AUTO: ON", 20, 120, 130, 25, clrBlue);

g_panelCreated = true;
}

//+------------------------------------------------------------------+
//| Create label helper function |
//+------------------------------------------------------------------+
void CreateLabel(string name, string text, int x, int y, color clr, int fontSize = 8) {
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_TOP_LEFT);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
}

//+------------------------------------------------------------------+
//| Create button helper function |
//+------------------------------------------------------------------+
void CreateButton(string name, string text, int x, int y, int width, int height, color bgColor) {
ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, width);
ObjectSetInteger(0, name, OBJPROP_YSIZE, height);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_TOP_LEFT);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_BACKCOLOR, bgColor);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, clrWhite);
}

//+------------------------------------------------------------------+
//| Update panel and handle button clicks |
//+------------------------------------------------------------------+
void UpdateTradingPanel() {
static bool autoTrade = true;

// Check BUY button
if(ObjectGetInteger(0, "TradingPanel_Buy", OBJPROP_STATE) == 1) {
ObjectSetInteger(0, "TradingPanel_Buy", OBJPROP_STATE, 0);
ManualTrade(OP_BUY);
}

// Check SELL button
if(ObjectGetInteger(0, "TradingPanel_Sell", OBJPROP_STATE) == 1) {
ObjectSetInteger(0, "TradingPanel_Sell", OBJPROP_STATE, 0);
ManualTrade(OP_SELL);
}

// Check CLOSE ALL button
if(ObjectGetInteger(0, "TradingPanel_CloseAll", OBJPROP_STATE) == 1) {
ObjectSetInteger(0, "TradingPanel_CloseAll", OBJPROP_STATE, 0);
CloseAllOrders();
}

// Check AUTO toggle
if(ObjectGetInteger(0, "TradingPanel_Auto", OBJPROP_STATE) == 1) {
ObjectSetInteger(0, "TradingPanel_Auto", OBJPROP_STATE, 0);
autoTrade = !autoTrade;
string btnText = autoTrade ? "AUTO: ON" : "AUTO: OFF";
color btnColor = autoTrade ? clrBlue : clrGray;
ObjectSetString(0, "TradingPanel_Auto", OBJPROP_TEXT, btnText);
ObjectSetInteger(0, "TradingPanel_Auto", OBJPROP_BACKCOLOR, btnColor);
Print("Auto-trading: ", autoTrade ? "ENABLED" : "DISABLED");
}
}

//+------------------------------------------------------------------+
//| Manual trade via panel |
//+------------------------------------------------------------------+
void ManualTrade(int orderType) {
double lotSize = InpFixedLot;
string symbol = Symbol();
double price = (orderType == OP_BUY) ? Ask : Bid;

int ticket = OrderSend(symbol, orderType, lotSize, price, InpSlippage, 0, 0, "Manual Trade", InpMagic, 0, clrNONE);

if(ticket > 0) {
Print("Manual trade opened: ", ticket);
} else {
Print("Manual trade failed. Error: ", GetLastError());
}
}

//+------------------------------------------------------------------+
//| Close all orders |
//+------------------------------------------------------------------+
void CloseAllOrders() {
int closed = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--) {
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
if(OrderMagicNumber() == InpMagic) {
double closePrice = (OrderType() == OP_BUY) ? Bid : Ask;
if(OrderClose(OrderTicket(), OrderLots(), closePrice, InpSlippage, clrNONE)) {
closed++;
}
}
}
}
Print("Closed ", closed, " orders");
}
```

3. Dashboard Display for Monitoring
```mql4
//+------------------------------------------------------------------+
//| DASHBOARD - Display real-time info on chart |
//+------------------------------------------------------------------+
void UpdateDashboard() {
string dashboard = "";
dashboard += "========== MULTI-STRATEGY EA ==========\n";
dashboard += "Time: " + TimeToString(TimeCurrent()) + "\n";
dashboard += "Balance: " + DoubleToString(AccountBalance(), 2) + "\n";
dashboard += "Equity: " + DoubleToString(AccountEquity(), 2) + "\n";
dashboard += "Free Margin: " + DoubleToString(AccountFreeMargin(), 2) + "\n";
dashboard += "=======================================\n";
dashboard += "ACTIVE STRATEGIES:\n";
dashboard += " - Trend Following: " + (InpUseTrend ? "ON" : "OFF") + "\n";
dashboard += " - Mean Reversion: " + (InpUseMeanRev ? "ON" : "OFF") + "\n";
dashboard += " - Breakout: " + (InpUseBreakout ? "ON" : "OFF") + "\n";
dashboard += "=======================================\n";
dashboard += "CURRENCY MONITORING:\n";

for(int i = 0; i < MathMin(g_symbolCount, 8); i++) {
string symbol = g_symbols[i];
double bid = MarketInfo(symbol, MODE_BID);
double ask = MarketInfo(symbol, MODE_ASK);
int spread = (int)MarketInfo(symbol, MODE_SPREAD);
int positions = CountOrdersBySymbol(symbol, InpMagic);

dashboard += symbol + ": " + DoubleToString(bid, 5) +
" | Spread: " + IntegerToString(spread) +
" | Pos: " + IntegerToString(positions) + "\n";
}

dashboard += "=======================================";
Comment(dashboard);
}

//+------------------------------------------------------------------+
//| Reset daily tracking |
//+------------------------------------------------------------------+
void ResetDailyIfNeeded() {
datetime currentDay = GetMidnight();
if(currentDay != g_lastReset) {
g_dailyStartBalance = AccountBalance();
g_lastReset = currentDay;
Print("Daily reset. Start balance: ", g_dailyStartBalance);
}
}

datetime GetMidnight() {
MqlDateTime tm;
TimeToStruct(TimeCurrent(), tm);
tm.hour = 0;
tm.min = 0;
tm.sec = 0;
return StructToTime(tm);
}
```

Project Completion Checklist
  • [ ] EA compiles with 0 errors

  • [ ] Trading panel appears on chart after loading

  • [ ] Multi-currency parsing works correctly

  • [ ] Each strategy can be toggled independently

  • [ ] Manual buttons execute trades

  • [ ] Dashboard updates correctly

  • [ ] Backtest shows positive results on 70%+ of pairs

  • [ ] Risk management limits positions correctly


  • Reference:
  • MetaQuotes Ltd. "MQL4 Documentation - Object Functions" (2024)

  • Kaufman, Perry J. "Trading Systems and Methods" (2019)


  • 9. Next Step
    Part 18 will explain Advanced EA Optimization Techniques – Genetic algorithms, walk-forward analysis, Monte Carlo simulation, and robust parameter selection.