Problem Description
Solution
To create a control panel on your chart in MQL4, you need to utilize the Event Handling system (OnChartEvent) to detect mouse clicks and Object Functions to draw the button.
Here is a complete, copy-paste ready solution. This Expert Advisor (EA) creates a button in the top-right corner. Clicking it toggles a boolean flag that allows or blocks the execution of your trading logic in OnTick.
MQL4 Code: Trading Control Panel
//+------------------------------------------------------------------+
//| TradeControlPanel.mq4 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters for Button Styling
input int UI_Corner = CORNER_RIGHT_UPPER; // Panel Corner
input int UI_X_Offset = 20; // X Distance
input int UI_Y_Offset = 20; // Y Distance
input int UI_Width = 120; // Button Width
input int UI_Height = 40; // Button Height
input color UI_ColorOn = clrForestGreen; // Color when Active
input color UI_ColorOff = clrFireBrick; // Color when Inactive
input color UI_TextColor = clrWhite; // Text Color
input int UI_FontSize = 10; // Font Size
//--- Global Variables
string g_ButtonName = "Btn_StrategyToggle";
bool g_IsTradingEnabled = false; // Default state: Trading Disabled
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Create the button interface
CreateButton();
// Update the button visual state based on default
UpdateButtonState();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up: Remove the button when removing the EA
ObjectDelete(0, g_ButtonName);
Comment(""); // Clear chart comments
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Check if trading is enabled via the panel
if(!g_IsTradingEnabled)
{
Comment("Strategy Status: STOPPED (Click button to enable)");
return; // EXIT function immediately, do not execute strategy
}
// 2. If we are here, trading is enabled
Comment("Strategy Status: RUNNING...");
// --- INSERT YOUR STRATEGY LOGIC BELOW ---
// Example:
// if(SignalBuy()) OrderSend(...);
// ----------------------------------------
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//| Handles mouse clicks and object interactions |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
// Check if the event is a mouse click on an object
if(id == CHARTEVENT_OBJECT_CLICK)
{
// Check if the clicked object is our button
if(sparam == g_ButtonName)
{
// Toggle the trading state
g_IsTradingEnabled = !g_IsTradingEnabled;
// Update the visual appearance of the button
UpdateButtonState();
// Force chart redraw to make UI snappy
ChartRedraw();
}
}
}
//+------------------------------------------------------------------+
//| Helper: Create the Button Object |
//+------------------------------------------------------------------+
void CreateButton()
{
// Check if object exists, if not create it
if(ObjectFind(0, g_ButtonName) < 0)
{
ObjectCreate(0, g_ButtonName, OBJ_BUTTON, 0, 0, 0);
}
// Set Button Properties
ObjectSetInteger(0, g_ButtonName, OBJPROP_CORNER, UI_Corner);
ObjectSetInteger(0, g_ButtonName, OBJPROP_XDISTANCE, UI_X_Offset);
ObjectSetInteger(0, g_ButtonName, OBJPROP_YDISTANCE, UI_Y_Offset);
ObjectSetInteger(0, g_ButtonName, OBJPROP_XSIZE, UI_Width);
ObjectSetInteger(0, g_ButtonName, OBJPROP_YSIZE, UI_Height);
ObjectSetInteger(0, g_ButtonName, OBJPROP_FONTSIZE, UI_FontSize);
ObjectSetInteger(0, g_ButtonName, OBJPROP_COLOR, UI_TextColor);
ObjectSetString(0, g_ButtonName, OBJPROP_FONT, "Arial");
// Ensure the button stays pressed/unpressed correctly
ObjectSetInteger(0, g_ButtonName, OBJPROP_STATE, false);
ObjectSetInteger(0, g_ButtonName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, g_ButtonName, OBJPROP_HIDDEN, true); // Hide from object list
ObjectSetInteger(0, g_ButtonName, OBJPROP_ZORDER, 10); // Bring to front
}
//+------------------------------------------------------------------+
//| Helper: Update Button Text and Color |
//+------------------------------------------------------------------+
void UpdateButtonState()
{
if(g_IsTradingEnabled)
{
// State: ON
ObjectSetString(0, g_ButtonName, OBJPROP_TEXT, "Trading: ON");
ObjectSetInteger(0, g_ButtonName, OBJPROP_BGCOLOR, UI_ColorOn);
// Keep the button visually "depressed" if you prefer, or flat
ObjectSetInteger(0, g_ButtonName, OBJPROP_STATE, true);
}
else
{
// State: OFF
ObjectSetString(0, g_ButtonName, OBJPROP_TEXT, "Trading: OFF");
ObjectSetInteger(0, g_ButtonName, OBJPROP_BGCOLOR, UI_ColorOff);
ObjectSetInteger(0, g_ButtonName, OBJPROP_STATE, false);
}
}
How It Works
OnInit(): CallsCreateButton()to draw anOBJ_BUTTONon the chart. It sets the initial state (Disabled by default in this code for safety).OnChartEvent(): This is the critical function. It listens forCHARTEVENT_OBJECT_CLICK. If the object clicked matches our button's name (g_ButtonName), it toggles the boolean variableg_IsTradingEnabledfrom true to false (or vice versa).UpdateButtonState(): Changes the button's background color (Green/Red) and text ("Trading: ON"/"Trading: OFF") to reflect the current state.OnTick(): This is where your strategy lives. The very first line checksif(!g_IsTradingEnabled) return;. If the button is set to OFF, the code stops there, preventing any trade logic from executing.
Integration Instructions
- Copy the code above into your MetaEditor.
- Locate the
OnTick()function in the code. - Paste your existing trading logic (indicator calculations,
OrderSendfunctions, etc.) into the section marked// --- INSERT YOUR STRATEGY LOGIC BELOW ---. - Compile and run. You will see a button in the top-right corner that controls the execution flow.
Q&A
Q: Can I add more buttons?
A: Yes. You would create unique names for each button (e.g., Btn_CloseAll, Btn_BuyOnly), create them in OnInit, and add additional if(sparam == "Btn_Name") checks inside OnChartEvent.
Q: Will the button state be saved if I restart the terminal?
A: No, in this specific code, the state resets to false (OFF) when the EA re-initializes. To save the state across restarts, you would need to use GlobalVariableSet and GlobalVariableGet (Terminal Global Variables) instead of a simple bool variable.
Q: Why does the button sometimes feel slow to react?
A: MQL4 charts update on ticks. We added ChartRedraw() inside the click event to force an immediate visual update, ensuring the button feels responsive even if the market is moving slowly.