Generate code in 3 minutes
Enter your idea and AI generates runnable code.
To achieve this in MetaTrader 4, the most robust and native method is using Global Variables of the Client Terminal.
Here is the architecture of the solution:
CMD_EURUSD with a value of 1 for Buy or 2 for Sell).0 to prevent duplicate orders.Below are the two separate code files required.
Compile this code and attach it to one chart (e.g., XAUUSD or an empty chart). It will control the others.
//+------------------------------------------------------------------+
//| SignalDashboard.mq4 |
//| Copyright 2023, MetaQuotes |
//| https://mql4.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Assistant"
#property link "https://mql4.com"
#property version "1.00"
#property strict
//--- Input Parameters
input string InpSymbols = "EURUSD,GBPUSD,USDJPY,XAUUSD"; // Comma-separated symbols
input color ColorBuy = clrForestGreen;
input color ColorSell = clrFireBrick;
input int BtnWidth = 80;
input int BtnHeight = 30;
input int X_Start = 20;
input int Y_Start = 50;
//--- Global arrays to store parsed symbols
string symbolArray[];
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Parse the comma-separated string into an array
StringSplit(InpSymbols, ',', symbolArray);
// Create the UI
CreateDashboard();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up all objects created by this EA
ObjectsDeleteAll(0, "Dash_");
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
// Handle Button Clicks
if(id == CHARTEVENT_OBJECT_CLICK)
{
// Check if the clicked object is one of ours
if(StringFind(sparam, "Dash_") >= 0)
{
// Reset button state immediately (visual effect)
ObjectSetInteger(0, sparam, OBJPROP_STATE, false);
// Extract command and symbol from name (Format: Dash_CMD_SYMBOL)
string parts[];
StringSplit(sparam, '_', parts);
if(ArraySize(parts) == 3)
{
string cmdType = parts[1]; // "Buy" or "Sell"
string sym = parts[2]; // "EURUSD", etc.
// Define the Global Variable Name
string gvName = "CMD_" + sym;
// Set Global Variable: 1 for Buy, 2 for Sell
double signal = (cmdType == "Buy") ? 1.0 : 2.0;
// We use GlobalVariableSet.
// The Slave EA will pick this up, execute, and delete/reset it.
GlobalVariableSet(gvName, signal);
Print("Signal Sent: " + cmdType + " for " + sym);
PlaySound("tick.wav");
}
}
}
}
//+------------------------------------------------------------------+
//| Helper: Create the Dashboard UI |
//+------------------------------------------------------------------+
void CreateDashboard()
{
int total = ArraySize(symbolArray);
for(int i = 0; i < total; i++)
{
string sym = symbolArray[i];
// Strip whitespace
StringTrimLeft(sym);
StringTrimRight(sym);
int y = Y_Start + (i * (BtnHeight + 10));
// Create Label
CreateLabel("Dash_Lbl_" + sym, sym, X_Start, y + 5);
// Create Buy Button
CreateButton("Dash_Buy_" + sym, "BUY", X_Start + 80, y, ColorBuy);
// Create Sell Button
CreateButton("Dash_Sell_" + sym, "SELL", X_Start + 80 + BtnWidth + 10, y, ColorSell);
}
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Helper: Create a Button Object |
//+------------------------------------------------------------------+
void CreateButton(string name, string text, int x, int y, color bg)
{
if(ObjectFind(0, name) < 0)
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, BtnWidth);
ObjectSetInteger(0, name, OBJPROP_YSIZE, BtnHeight);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 10);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg);
ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, clrNONE);
ObjectSetInteger(0, name, OBJPROP_STATE, false);
}
//+------------------------------------------------------------------+
//| Helper: Create a Label Object |
//+------------------------------------------------------------------+
void CreateLabel(string name, string text, int x, int y)
{
if(ObjectFind(0, name) < 0)
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_LEFT_UPPER);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 10);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrBlack);
}
//+------------------------------------------------------------------+
Compile this code and attach it to every chart you want to trade (e.g., open a EURUSD chart and attach it, open a GBPUSD chart and attach it).
//+------------------------------------------------------------------+
//| SignalReceiver.mq4 |
//| Copyright 2023, MetaQuotes |
//| https://mql4.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Quantitative Assistant"
#property link "https://mql4.com"
#property version "1.00"
#property strict
//--- Input Parameters
input double InpLotSize = 0.1;
input int InpStopLoss = 200; // Points (0 to disable)
input int InpTakeProfit = 400; // Points (0 to disable)
input int InpMagicNum = 123456;
input int InpSlippage = 3;
//--- Global variable name to listen to
string gvName;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Define the specific variable name for THIS chart's symbol
// Example: If attached to EURUSD, it listens for "CMD_EURUSD"
gvName = "CMD_" + Symbol();
Print("Receiver started. Listening for Global Variable: ", gvName);
// Ensure the variable exists and is 0 to start
if(!GlobalVariableCheck(gvName))
GlobalVariableSet(gvName, 0);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Check if the Global Variable exists
if(GlobalVariableCheck(gvName))
{
// 2. Get the value
double signal = GlobalVariableGet(gvName);
// 3. If signal is 0, do nothing (waiting state)
if(signal == 0) return;
// 4. Process Signal
if(signal == 1.0) // BUY
{
ExecuteTrade(OP_BUY);
}
else if(signal == 2.0) // SELL
{
ExecuteTrade(OP_SELL);
}
// 5. Reset the Global Variable to 0 immediately to prevent double entry
GlobalVariableSet(gvName, 0);
}
}
//+------------------------------------------------------------------+
//| Helper: Execute Trade |
//+------------------------------------------------------------------+
void ExecuteTrade(int type)
{
double price, sl, tp;
color clr;
if(type == OP_BUY)
{
price = Ask;
sl = (InpStopLoss > 0) ? Ask - InpStopLoss * Point : 0;
tp = (InpTakeProfit > 0) ? Ask + InpTakeProfit * Point : 0;
clr = clrBlue;
}
else
{
price = Bid;
sl = (InpStopLoss > 0) ? Bid + InpStopLoss * Point : 0;
tp = (InpTakeProfit > 0) ? Bid - InpTakeProfit * Point : 0;
clr = clrRed;
}
// Normalize prices
price = NormalizeDouble(price, Digits);
sl = NormalizeDouble(sl, Digits);
tp = NormalizeDouble(tp, Digits);
// Send Order
int ticket = OrderSend(Symbol(), type, InpLotSize, price, InpSlippage, sl, tp, "Dashboard Trade", InpMagicNum, 0, clr);
if(ticket > 0)
Print("Order Opened Successfully. Ticket: ", ticket);
else
Print("Error Opening Order: ", GetLastError());
}
//+------------------------------------------------------------------+
SignalReceiver.mq4.SignalReceiver.mq4.SignalDashboard.mq4.InpSymbols matches the charts you opened in Step 2 (e.g., "EURUSD,GBPUSD").CMD_EURUSD to 1.1, executes a Buy order, and resets the variable to 0.GlobalVariableSet(gvName, 0) in the Receiver. Without this, the Receiver would execute a trade on every single tick as long as the variable remained 1.Q: Can I run the Dashboard on a Demo account and the Receiver on a Real account?
A: No, not with this code. Global Variables only work within the same terminal instance. To trade across terminals (or computers), you would need to use File operations (writing/reading CSVs in a shared folder) or Windows Sockets, which is significantly more complex.
Q: What happens if I click the button twice quickly?
A: If the Receiver hasn't processed the first click yet (reset the variable to 0), the second click just overwrites the variable with the same value, resulting in only one trade. If the Receiver has processed it, a second trade will open.
Q: How do I verify the communication is working?
A: In MT4, press F3. This opens the "Global Variables" window. When you click a button on the dashboard, you should briefly see a variable like CMD_EURUSD appear with value 1 or 2, and then almost instantly disappear (or turn to 0) as the Receiver processes it.