Enjoy the content and feel free to discuss in the comments section below.
Imagine piloting your trades from a precision trading cockpit, using a graphical interface to set and execute pending orders with seamless control. The Trade Assistant GUI Tool with Panel EA is your advanced trading tool, designed to enhance manual trading on MetaTrader 5 with a dynamic panel. The panel, created via "createControlPanel()", features buttons for selecting buy/sell stop or limit orders ("BUY_STOP_BTN", "SELL_LIMIT_BTN", etc.), an editable lot size field ("LOT_EDIT"), and draggable horizontal lines ("PR_HL", "SL_HL", "TP_HL") for setting entry price, stop loss (SL), and take profit (TP). Traders can adjust levels visually, place orders with 24-hour expiration ("placeOrder()", "obj_Trade.BuyStop()", etc.), and validate setups ("isOrderValid()") to ensure correct price alignment. The panel supports drag-and-drop repositioning ("OnChartEvent()") and includes cancel ("CANCEL_BTN") and close ("CLOSE_BTN") options. Managed via "CTrade", this EA suits traders seeking intuitive trade management, requiring external signal confirmation for entries.
This article is crafted with a professional, engaging, and seamless narrative, flowing like a well-calibrated trading cockpit, designed to inform and captivate readers. Tailored for both novice and experienced traders, we’ll dissect each code component with clear, precise explanations, as if guiding an apprentice pilot through a trade execution project. With vivid examples—like placing a buy stop on EURUSD—and a polished tone, we’ll explore how the EA initializes, builds the panel, handles interactions, executes orders, and ensures cleanup. Using a precision trading cockpit metaphor, this guide will illuminate the code’s technical rigor, empowering you to trade with confidence. Let’s activate the system and begin this trading expedition!
Let’s outline the EA’s trading framework, like drafting specifications for a trading cockpit:
Panel Setup: Creates a draggable panel ("PANEL_BG", "createControlPanel()") with buttons for order types, lot size input, and control actions.
Order Configuration: Selects order types (buy/sell stop/limit, "selected_order_type") and sets entry, SL, and TP via draggable lines ("PR_HL", "SL_HL", "TP_HL", "createHL()", "OnChartEvent()") with lot size input ("LOT_EDIT").
Order Execution: Places pending orders ("placeOrder()", "obj_Trade.BuyStop()", etc.) with 24-hour expiration, validated by "isOrderValid()".
User Interaction: Supports panel dragging, button hover effects ("updateButtonHoverState()"), and price line adjustments, with cancel/close options.
Execution: Updates lot size on tick ("OnTick()") and handles interactions via "OnChartEvent()", using "CTrade" for order placement.
Enhancements: Adding signal-based triggers, configurable expirations, or error logging could improve functionality. This framework streamlines manual trading with precision, offering a visual interface for pending orders. See below.
Let’s step into the trading cockpit and dissect the MQL5 code that powers this Trade Assistant GUI Tool with Panel EA. We’ll guide you through each phase like expert pilots, ensuring the narrative flows seamlessly with professional clarity and engaging precision that captivates readers. We’ll cover initialization, panel creation, interaction handling, order execution, and cleanup, with detailed explanations and examples—like placing a buy stop on EURUSD—to make it accessible for beginners. Each phase will build on the last, crafting a cohesive technical narrative that transforms code into a compelling trading project. Let’s power up the system and begin!
We start by building the trading system, initializing the panel and mouse events.
//+------------------------------------------------------------------+
//| Trade Assistant GUI Tool with Panel.mq5 |
//| Copyright 2025, Allan Munene Mutiiria. |
//| https://t.me/Forex_Algo_Trader |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Allan Munene Mutiiria."
#property link "https://t.me/Forex_Algo_Trader"
#property version "1.00"
#include <Trade/Trade.mqh>
#define PANEL_BG "PANEL_BG"
#define PANEL_HEADER "PANEL_HEADER"
#define LOT_EDIT "LOT_EDIT"
#define PRICE_LABEL "PRICE_LABEL"
#define SL_LABEL "SL_LABEL"
#define TP_LABEL "TP_LABEL"
#define BUY_STOP_BTN "BUY_STOP_BTN"
#define SELL_STOP_BTN "SELL_STOP_BTN"
#define BUY_LIMIT_BTN "BUY_LIMIT_BTN"
#define SELL_LIMIT_BTN "SELL_LIMIT_BTN"
#define PLACE_ORDER_BTN "PLACE_ORDER_BTN"
#define CANCEL_BTN "CANCEL_BTN"
#define CLOSE_BTN "CLOSE_BTN"
#define REC1 "REC1"
#define REC2 "REC2"
#define REC3 "REC3"
#define REC4 "REC4"
#define REC5 "REC5"
#define TP_HL "TP_HL"
#define SL_HL "SL_HL"
#define PR_HL "PR_HL"
double Get_Price_d(string name){return ObjectGetDouble(0,name,OBJPROP_PRICE);}
string Get_Price_s(string name){return DoubleToString(ObjectGetDouble(0,name,OBJPROP_PRICE),_Digits);}
string update_Text(string name, string val){return (string)ObjectSetString(0,name,OBJPROP_TEXT,val);}
int xd1,yd1,xs1,ys1,xd2,yd2,xs2,ys2,xd3,yd3,xs3,ys3,xd4,yd4,xs4,ys4,xd5,yd5,xs5,ys5;
bool tool_visible = false;
string selected_order_type = "";
double lot_size = 0.01;
CTrade obj_Trade;
int panel_x = 10, panel_y = 30;
bool panel_dragging = false;
int panel_drag_x = 0, panel_drag_y = 0;
int panel_start_x = 0, panel_start_y = 0;
bool buy_stop_hovered = false;
bool sell_stop_hovered = false;
bool buy_limit_hovered = false;
bool sell_limit_hovered = false;
bool place_order_hovered = false;
bool cancel_hovered = false;
bool close_hovered = false;
bool header_hovered = false;
bool rec1_hovered = false;
bool rec3_hovered = false;
bool rec5_hovered = false;
int OnInit(){
createControlPanel();
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
ChartRedraw(0);
return(INIT_SUCCEEDED);
}
The system begins with the #property header, establishing copyright and contact details, like calibrating a trading cockpit’s core. The "OnInit()" function initializes the setup, including "Trade/Trade.mqh" for trading ("CTrade", "obj_Trade"), defining panel constants ("PANEL_BG", "BUY_STOP_BTN", etc.), and variables for positions ("xd1", "yd1", etc.), visibility ("tool_visible"), and order type ("selected_order_type"). It creates the panel ("createControlPanel()") and enables mouse move events ("CHART_EVENT_MOUSE_MOVE") for dragging. Returning INIT_SUCCEEDED signals, “Cockpit is ready, let’s pilot trades!” This primes the EA for interactive trading, like a cockpit poised for action.
We create the graphical panel and price lines, like assembling cockpit controls.
void createControlPanel(){
ObjectCreate(0,PANEL_BG,OBJ_RECTANGLE_LABEL,0,0,0);
ObjectSetInteger(0,PANEL_BG,OBJPROP_XDISTANCE,panel_x);
ObjectSetInteger(0,PANEL_BG,OBJPROP_YDISTANCE,panel_y);
ObjectSetInteger(0,PANEL_BG,OBJPROP_XSIZE,250);
ObjectSetInteger(0,PANEL_BG,OBJPROP_YSIZE,280);
ObjectSetInteger(0,PANEL_BG,OBJPROP_BGCOLOR,C'070,070,070');
ObjectSetInteger(0,PANEL_BG,OBJPROP_BORDER_COLOR,clrWhite);
ObjectSetInteger(0,PANEL_BG,OBJPROP_BACK,false);
createButton(PANEL_HEADER,"",panel_x+2,panel_y+2,250-2-2,28-3,clrBlue,C'050,050,050,',12,C'050,050,050',false);
createButton(CLOSE_BTN,CharToString(203),panel_x+209,panel_y+1,40,25,clrWhite,clrCrimson,12,clrBlack,false,"Wingdings");
ObjectCreate(0,LOT_EDIT,OBJ_EDIT,0,0,0);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_XDISTANCE,panel_x+70);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_YDISTANCE,panel_y+40);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_XSIZE,110);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_YSIZE,25);
ObjectSetString(0,LOT_EDIT,OBJPROP_TEXT,"0.01");
ObjectSetInteger(0,LOT_EDIT,OBJPROP_COLOR,clrBlack);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_BGCOLOR,clrWhite);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_BORDER_COLOR,clrBlack);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_ALIGN,ALIGN_CENTER);
ObjectSetString(0,LOT_EDIT,OBJPROP_FONT,"Arial");
ObjectSetInteger(0,LOT_EDIT,OBJPROP_FONTSIZE,13);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_BACK,false);
ObjectCreate(0,PRICE_LABEL,OBJ_LABEL,0,0,0);
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_XDISTANCE,panel_x+10);
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_YDISTANCE,panel_y+70);
ObjectSetString(0,PRICE_LABEL,OBJPROP_TEXT,"Entry: -");
ObjectSetString(0,PRICE_LABEL,OBJPROP_FONT,"Arial Bold");
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_FONTSIZE,13);
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_COLOR,clrWhite);
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_ALIGN,ALIGN_CENTER);
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_BACK,false);
ObjectCreate(0,SL_LABEL,OBJ_LABEL,0,0,0);
ObjectSetInteger(0,SL_LABEL,OBJPROP_XDISTANCE,panel_x+10);
ObjectSetInteger(0,SL_LABEL,OBJPROP_YDISTANCE,panel_y+95);
ObjectSetString(0,SL_LABEL,OBJPROP_TEXT,"Sl: -");
ObjectSetString(0,SL_LABEL,OBJPROP_FONT,"Arial Bold");
ObjectSetInteger(0,SL_LABEL,OBJPROP_FONTSIZE,12);
ObjectSetInteger(0,SL_LABEL,OBJPROP_COLOR,clrYellow);
ObjectSetInteger(0,SL_LABEL,OBJPROP_ALIGN,ALIGN_CENTER);
ObjectSetInteger(0,SL_LABEL,OBJPROP_BACK,false);
ObjectCreate(0,TP_LABEL,OBJ_LABEL,0,0,0);
ObjectSetInteger(0,TP_LABEL,OBJPROP_XDISTANCE,panel_x+130);
ObjectSetInteger(0,TP_LABEL,OBJPROP_YDISTANCE,panel_y+95);
ObjectSetString(0,TP_LABEL,OBJPROP_TEXT,"Tp: -");
ObjectSetString(0,TP_LABEL,OBJPROP_FONT,"Arial Bold");
ObjectSetInteger(0,TP_LABEL,OBJPROP_FONTSIZE,12);
ObjectSetInteger(0,TP_LABEL,OBJPROP_COLOR,clrLime);
ObjectSetInteger(0,TP_LABEL,OBJPROP_ALIGN,ALIGN_CENTER);
ObjectSetInteger(0,TP_LABEL,OBJPROP_BACK,false);
createButton(BUY_STOP_BTN,"Buy Stop",panel_x+10,panel_y+140,110,30,clrWhite,clrForestGreen,10,clrBlack,false,"Arial");
createButton(SELL_STOP_BTN,"Sell Stop",panel_x+130,panel_y+140,110,30,clrWhite,clrFireBrick,10,clrBlack,false,"Arial");
createButton(BUY_LIMIT_BTN,"Buy Limit",panel_x+10,panel_y+180,110,30,clrWhite,clrForestGreen,10,clrBlack,false,"Arial");
createButton(SELL_LIMIT_BTN,"Sell Limit",panel_x+130,panel_y+180,110,30,clrWhite,clrFireBrick,10,clrBlack,false,"Arial");
createButton(PLACE_ORDER_BTN,"Place Order",panel_x+10,panel_y+240,110,30,clrWhite,clrDodgerBlue,10,clrBlack,false,"Arial");
createButton(CANCEL_BTN,"Cancel",panel_x+130,panel_y+240,110,30,clrWhite,clrSlateGray,10,clrBlack,false,"Arial");
}
In the interface assembly hub, "createControlPanel()" builds a 250x280 panel ("PANEL_BG", "OBJ_RECTANGLE_LABEL") with a header ("PANEL_HEADER") and close button ("CLOSE_BTN", Wingdings). It includes an editable lot size field ("LOT_EDIT", default 0.01) and labels for entry, SL, and TP ("PRICE_LABEL", "SL_LABEL", "TP_LABEL") using "ObjectCreate()", "ObjectSetInteger()", and "ObjectSetString()". Buttons for order types ("BUY_STOP_BTN", "SELL_LIMIT_BTN", etc.) and actions ("PLACE_ORDER_BTN", "CANCEL_BTN") are created via "createButton()". For example, on EURUSD, the panel appears at (10,30) with green/red buttons and lot size input, like cockpit controls ready for action.
We manage user interactions for order setup and panel dragging, like operating cockpit controls.
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam){
if (id == CHARTEVENT_OBJECT_CLICK){
if (sparam == BUY_STOP_BTN){
selected_order_type = "BUY_STOP";
showTool();
update_Text(PLACE_ORDER_BTN,"Place Buy Stop");
updateRectangleColors();
}
else if (sparam == SELL_STOP_BTN){
selected_order_type = "SELL_STOP";
showTool();
update_Text(PLACE_ORDER_BTN,"Place Sell Stop");
updateRectangleColors();
}
else if (sparam == BUY_LIMIT_BTN){
selected_order_type = "BUY_LIMIT";
showTool();
update_Text(PLACE_ORDER_BTN,"Place Buy limit");
updateRectangleColors();
}
else if (sparam == SELL_LIMIT_BTN){
selected_order_type = "SELL_LIMIT";
showTool();
update_Text(PLACE_ORDER_BTN,"Place Sell limit");
updateRectangleColors();
}
else if (sparam == PLACE_ORDER_BTN){
if (isOrderValid()){
placeOrder();
deleteObjects();
showPanel();
}
else{
Print("Cannot place order: Invalid price setup for ",selected_order_type);
}
}
else if (sparam == CANCEL_BTN){
deleteObjects();
showPanel();
}
else if (sparam == CLOSE_BTN){
deleteObjects();
deletePanel();
ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, false);
}
ObjectSetInteger(0, sparam, OBJPROP_STATE, false);
updateButtonHoverState((int)lparam,(int)dparam);
ChartRedraw(0);
}
if (id == CHARTEVENT_MOUSE_MOVE){
int MouseD_X = (int)lparam;
int MouseD_Y = (int)dparam;
int MouseState = (int)sparam;
updateButtonHoverState(MouseD_X,MouseD_Y);
int header_xd = (int)ObjectGetInteger(0,PANEL_HEADER,OBJPROP_XDISTANCE);
int header_yd = (int)ObjectGetInteger(0,PANEL_HEADER,OBJPROP_YDISTANCE);
int header_xs = (int)ObjectGetInteger(0,PANEL_HEADER,OBJPROP_XSIZE);
int header_ys = (int)ObjectGetInteger(0,PANEL_HEADER,OBJPROP_YSIZE);
if (prevMouseState == 0 && MouseState == 1){
if (MouseD_X >= header_xd && MouseD_X <= header_xd + header_xs &&
MouseD_Y >= header_yd && MouseD_Y <= header_yd + header_ys){
panel_dragging = true;
panel_drag_x = MouseD_X;
panel_drag_y = MouseD_Y;
panel_start_x = header_xd;
panel_start_y = header_yd;
ChartSetInteger(0,CHART_MOUSE_SCROLL,false);
}
}
if (panel_dragging && MouseState == 1){
int dx = MouseD_X - panel_drag_x;
int dy = MouseD_Y - panel_drag_y;
panel_x = panel_start_x + dx;
panel_y = panel_start_y + dy;
ObjectSetInteger(0,PANEL_BG,OBJPROP_XDISTANCE,panel_x);
ObjectSetInteger(0,PANEL_BG,OBJPROP_YDISTANCE,panel_y);
ObjectSetInteger(0,PANEL_HEADER,OBJPROP_XDISTANCE,panel_x+2);
ObjectSetInteger(0,PANEL_HEADER,OBJPROP_YDISTANCE,panel_y+2);
ObjectSetInteger(0,CLOSE_BTN,OBJPROP_XDISTANCE,panel_x+209);
ObjectSetInteger(0,CLOSE_BTN,OBJPROP_YDISTANCE,panel_y+1);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_XDISTANCE,panel_x+70);
ObjectSetInteger(0,LOT_EDIT,OBJPROP_YDISTANCE,panel_y+40);
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_XDISTANCE,panel_x+10);
ObjectSetInteger(0,PRICE_LABEL,OBJPROP_YDISTANCE,panel_y+70);
ObjectSetInteger(0,SL_LABEL,OBJPROP_XDISTANCE,panel_x+10);
ObjectSetInteger(0,SL_LABEL,OBJPROP_YDISTANCE,panel_y+95);
ObjectSetInteger(0,TP_LABEL,OBJPROP_XDISTANCE,panel_x+130);
ObjectSetInteger(0,TP_LABEL,OBJPROP_YDISTANCE,panel_y+95);
ObjectSetInteger(0,BUY_STOP_BTN,OBJPROP_XDISTANCE,panel_x+10);
ObjectSetInteger(0,BUY_STOP_BTN,OBJPROP_YDISTANCE,panel_y+140);
ObjectSetInteger(0,SELL_STOP_BTN,OBJPROP_XDISTANCE,panel_x+130);
ObjectSetInteger(0,SELL_STOP_BTN,OBJPROP_YDISTANCE,panel_y+140);
ObjectSetInteger(0,BUY_LIMIT_BTN,OBJPROP_XDISTANCE,panel_x+10);
ObjectSetInteger(0,BUY_LIMIT_BTN,OBJPROP_YDISTANCE,panel_y+180);
ObjectSetInteger(0,SELL_LIMIT_BTN,OBJPROP_XDISTANCE,panel_x+130);
ObjectSetInteger(0,SELL_LIMIT_BTN,OBJPROP_YDISTANCE,panel_y+180);
ObjectSetInteger(0,PLACE_ORDER_BTN,OBJPROP_XDISTANCE,panel_x+10);
ObjectSetInteger(0,PLACE_ORDER_BTN,OBJPROP_YDISTANCE,panel_y+240);
ObjectSetInteger(0,CANCEL_BTN,OBJPROP_XDISTANCE,panel_x+130);
ObjectSetInteger(0,CANCEL_BTN,OBJPROP_YDISTANCE,panel_y+240);
ChartRedraw(0);
}
if (MouseState == 0){
if (panel_dragging){
panel_dragging = false;
ChartSetInteger(0,CHART_MOUSE_SCROLL,true);
}
}
if (tool_visible){
int XD_R1 = (int)ObjectGetInteger(0,REC1,OBJPROP_XDISTANCE);
int YD_R1 = (int)ObjectGetInteger(0,REC1,OBJPROP_YDISTANCE);
int XS_R1 = (int)ObjectGetInteger(0,REC1,OBJPROP_XSIZE);
int YS_R1 = (int)ObjectGetInteger(0,REC1,OBJPROP_YSIZE);
int XD_R3 = (int)ObjectGetInteger(0,REC3,OBJPROP_XDISTANCE);
int YD_R3 = (int)ObjectGetInteger(0,REC3,OBJPROP_YDISTANCE);
int XS_R3 = (int)ObjectGetInteger(0,REC3,OBJPROP_XSIZE);
int YS_R3 = (int)ObjectGetInteger(0,REC3,OBJPROP_YSIZE);
int XD_R5 = (int)ObjectGetInteger(0,REC5,OBJPROP_XDISTANCE);
int YD_R5 = (int)ObjectGetInteger(0,REC5,OBJPROP_YDISTANCE);
int XS_R5 = (int)ObjectGetInteger(0,REC5,OBJPROP_XSIZE);
int YS_R5 = (int)ObjectGetInteger(0,REC5,OBJPROP_YSIZE);
if (prevMouseState == 0 && MouseState == 1 && !panel_dragging){
mlbDownX1 = MouseD_X;
mlbDownY1 = MouseD_Y;
mlbDownXD_R1 = XD_R1;
mlbDownYD_R1 = YD_R1;
mlbDownX3 = MouseD_X;
mlbDownY3 = MouseD_Y;
mlbDownXD_R3 = XD_R3;
mlbDownYD_R3 = YD_R3;
mlbDownX5 = MouseD_X;
mlbDownY5 = MouseD_Y;
mlbDownXD_R5 = XD_R5;
mlbDownYD_R5 = YD_R5;
if (MouseD_X >= XD_R1 && MouseD_X <= XD_R1+XS_R1 && MouseD_Y >= YD_R1 && MouseD_Y <= YD_R1+YS_R1){
movingState_R1 = true;
ChartSetInteger(0, CHART_MOUSE_SCROLL, false);
}
if (MouseD_X >= XD_R3 && MouseD_X <= XD_R3+XS_R3 && MouseD_Y >= YD_R3 && MouseD_Y <= YD_R3+YS_R3){
movingState_R3 = true;
ChartSetInteger(0, CHART_MOUSE_SCROLL, false);
}
if (MouseD_X >= XD_R5 && MouseD_X <= XD_R5+XS_R5 && MouseD_Y >= YD_R5 && MouseD_Y <= YD_R5+YS_R5){
movingState_R5 = true;
ChartSetInteger(0, CHART_MOUSE_SCROLL, false);
}
}
if (movingState_R1){
bool canMove = false;
if (selected_order_type == "BUY_STOP" || selected_order_type == "BUY_LIMIT"){
if (YD_R1 + YS_R1 < YD_R3){
canMove = true;
ObjectSetInteger(0,REC1,OBJPROP_YDISTANCE,mlbDownYD_R1 + MouseD_Y - mlbDownY1);
ObjectSetInteger(0,REC2,OBJPROP_YDISTANCE,YD_R1 + YS_R1);
ObjectSetInteger(0,REC2,OBJPROP_YSIZE,YD_R3 - (YD_R1 + YS_R1));
}
}
else {
if (YD_R1 > YD_R3 + YS_R3){
canMove = true;
ObjectSetInteger(0,REC1,OBJPROP_YDISTANCE,mlbDownYD_R1 + MouseD_Y - mlbDownY1);
ObjectSetInteger(0,REC4,OBJPROP_YDISTANCE,YD_R3 + YS_R3);
ObjectSetInteger(0,REC4,OBJPROP_YSIZE,YD_R1 - (YD_R3 + YS_R3));
}
}
if (canMove){
datetime dt_TP=0;
double price_TP=0;
int window = 0;
ChartXYToTimePrice(0,XD_R1,YD_R1+YS_R1,window,dt_TP,price_TP);
ObjectSetInteger(0,TP_HL,OBJPROP_TIME,dt_TP);
ObjectSetDouble(0,TP_HL,OBJPROP_PRICE,price_TP);
update_Text(REC1,"TP: "+DoubleToString(MathAbs((Get_Price_d(TP_HL)-Get_Price_d(PR_HL))/_Point),0)+" Points | "+Get_Price_s(TP_HL));
update_Text(TP_LABEL, "TP: "+Get_Price_s(TP_HL));
}
updateRectangleColors();
ChartRedraw(0);
}
if (movingState_R5){
bool canMove = false;
if (selected_order_type == "BUY_STOP" || selected_order_type == "BUY_LIMIT"){
if (YD_R5 > YD_R4){
canMove = true;
ObjectSetInteger(0,REC5,OBJPROP_YDISTANCE,mlbDownYD_R5 + MouseD_Y - mlbDownY5);
ObjectSetInteger(0,REC4,OBJPROP_YDISTANCE,YD_R3 + YS_R3);
ObjectSetInteger(0,REC4,OBJPROP_YSIZE,YD_R5 - (YD_R3 + YS_R3));
}
}
else {
if (YD_R5 + YS_R5 < YD_R3){
canMove = true;
ObjectSetInteger(0,REC5,OBJPROP_YDISTANCE,mlbDownYD_R5 + MouseD_Y - mlbDownY5);
ObjectSetInteger(0,REC2,OBJPROP_YDISTANCE,YD_R5 + YS_R5);
ObjectSetInteger(0,REC2,OBJPROP_YSIZE,YD_R3 - (YD_R5 + YS_R5));
}
}
if (canMove){
datetime dt_TP=0;
double price_TP=0;
int window = 0;
ChartXYToTimePrice(0,XD_R5,YD_R5+YS_R5,window,dt_TP,price_TP);
ObjectSetInteger(0,SL_HL,OBJPROP_TIME,dt_TP);
ObjectSetDouble(0,SL_HL,OBJPROP_PRICE,price_TP);
update_Text(REC5,"SL: "+DoubleToString(MathAbs((Get_Price_d(PR_HL)-Get_Price_d(SL_HL))/_Point),0)+" Points | "+Get_Price_s(SL_HL));
update_Text(SL_LABEL, "SL: "+Get_Price_s(SL_HL));
}
updateRectangleColors();
ChartRedraw(0);
}
if (movingState_R3){
ObjectSetInteger(0,REC3,OBJPROP_XDISTANCE,mlbDownXD_R3 + MouseD_X - mlbDownX3);
ObjectSetInteger(0,REC3,OBJPROP_YDISTANCE,mlbDownYD_R3 + MouseD_Y - mlbDownY3);
ObjectSetInteger(0,REC1,OBJPROP_XDISTANCE,mlbDownXD_R1 + MouseD_X - mlbDownX1);
ObjectSetInteger(0,REC1,OBJPROP_YDISTANCE,mlbDownYD_R1 + MouseD_Y - mlbDownY1);
ObjectSetInteger(0,REC2,OBJPROP_XDISTANCE,mlbDownXD_R2 + MouseD_X - mlbDownX2);
ObjectSetInteger(0,REC2,OBJPROP_YDISTANCE,mlbDownYD_R2 + MouseD_Y - mlbDownY2);
ObjectSetInteger(0,REC4,OBJPROP_XDISTANCE,mlbDownXD_R4 + MouseD_X - mlbDownX4);
ObjectSetInteger(0,REC4,OBJPROP_YDISTANCE,mlbDownYD_R4 + MouseD_Y - mlbDownY4);
ObjectSetInteger(0,REC5,OBJPROP_XDISTANCE,mlbDownXD_R5 + MouseD_X - mlbDownX5);
ObjectSetInteger(0,REC5,OBJPROP_YDISTANCE,mlbDownYD_R5 + MouseD_Y - mlbDownY5);
datetime dt_PRC=0,dt_SL1=0,dt_TP1=0;
double price_PRC=0,price_SL1=0,price_TP1=0;
int window = 0;
ChartXYToTimePrice(0,XD_R3,YD_R3+YS_R3,window,dt_PRC,price_PRC);
ChartXYToTimePrice(0,XD_R5,YD_R5+YS_R5,window,dt_SL1,price_SL1);
ChartXYToTimePrice(0,XD_R1,YD_R1+YS_R1,window,dt_TP1,price_TP1);
ObjectSetInteger(0,PR_HL,OBJPROP_TIME,dt_PRC);
ObjectSetDouble(0,PR_HL,OBJPROP_PRICE,price_PRC);
ObjectSetInteger(0,TP_HL,OBJPROP_TIME,dt_TP1);
ObjectSetDouble(0,TP_HL,OBJPROP_PRICE,price_TP1);
ObjectSetInteger(0,SL_HL,OBJPROP_TIME,dt_SL1);
ObjectSetDouble(0,SL_HL,OBJPROP_PRICE,price_SL1);
update_Text(REC1,"TP: "+DoubleToString(MathAbs((Get_Price_d(TP_HL)-Get_Price_d(PR_HL))/_Point),0)+" Points | "+Get_Price_s(TP_HL));
update_Text(REC3,selected_order_type + ": | Lot: "+ ObjectGetString(0,LOT_EDIT,OBJPROP_TEXT) + " | " + Get_Price_s(PR_HL));
update_Text(REC5,"SL: "+DoubleToString(MathAbs((Get_Price_d(PR_HL)-Get_Price_d(SL_HL))/_Point),0)+" Points | "+Get_Price_s(SL_HL));
update_Text(PRICE_LABEL,"Entry: "+Get_Price_s(PR_HL));
update_Text(SL_LABEL,"SL: "+Get_Price_s(SL_HL));
update_Text(TP_LABEL,"TP: "+Get_Price_s(TP_HL));
updateRectangleColors();
ChartRedraw(0);
}
if (MouseState == 0){
movingState_R1 = false;
movingState_R3 = false;
movingState_R5 = false;
ChartSetInteger(0,CHART_MOUSE_SCROLL,true);
}
}
prevMouseState = MouseState;
}
}
In the interaction hub, "OnChartEvent()" handles button clicks ("CHARTEVENT_OBJECT_CLICK") and mouse movements ("CHARTEVENT_MOUSE_MOVE"). Clicking order buttons ("BUY_STOP_BTN", etc.) sets "selected_order_type", calls "showTool()" to display draggable lines ("REC1", "REC3", "REC5", "TP_HL", etc.), and updates "PLACE_ORDER_BTN". Clicking "PLACE_ORDER_BTN" validates the setup ("isOrderValid()") and places the order ("placeOrder()") or logs an error. "CANCEL_BTN" resets to the panel ("deleteObjects()", "showPanel()"), and "CLOSE_BTN" removes everything ("deletePanel()"). Mouse movements update button hover states ("updateButtonHoverState()") and enable panel dragging ("panel_dragging") or line dragging ("movingState_R1", "movingState_R3", "movingState_R5") with price updates via "ChartXYToTimePrice()", "update_Text()", and "updateRectangleColors()". For example, on EURUSD H1, selecting “Buy Stop” shows lines at 1.2050 (entry), 1.2000 (SL), 1.2100 (TP), draggable with real-time point calculations, like adjusting cockpit controls.
We validate and place pending orders, like executing cockpit commands.
bool isOrderValid(){
if (!tool_visible) return true;
double current_price = SymbolInfoDouble(_Symbol,SYMBOL_BID);
double entry_price = Get_Price_d(PR_HL);
double sl_price = Get_Price_d(SL_HL);
double tp_price = Get_Price_d(TP_HL);
if (selected_order_type == "BUY_STOP"){
if (entry_price <= current_price || tp_price <= entry_price || sl_price >= entry_price){
return false;
}
}
else if (selected_order_type == "SELL_STOP"){
if (entry_price >= current_price || tp_price >= entry_price || sl_price <= entry_price){
return false;
}
}
else if (selected_order_type == "BUY_LIMIT"){
if (entry_price >= current_price || tp_price <= entry_price || sl_price >= entry_price){
return false;
}
}
else if (selected_order_type == "SELL_LIMIT"){
if (entry_price <= current_price || tp_price >= entry_price || sl_price <= entry_price){
return false;
}
}
return true;
}
void placeOrder(){
double price = Get_Price_d(PR_HL);
double sl = Get_Price_d(SL_HL);
double tp = Get_Price_d(TP_HL);
string symbol = _Symbol;
datetime expiration = TimeCurrent()+3600*24;
lot_size = StringToDouble(ObjectGetString(0,LOT_EDIT,OBJPROP_TEXT));
if (lot_size <= 0){
Print("Invalid lot size: ",lot_size);
return;
}
if (price <=0 || sl <= 0 || tp <= 0){
Print("Invalid prices: Entry=",price,", SL=",sl,", TP=",tp," (all must be positive)");
return;
}
if (selected_order_type == "BUY_STOP" || selected_order_type == "BUY_LIMIT"){
if (sl >= price){
Print("Invalid SL for ",selected_order_type,": SL=",sl," must be below Entry=",price);
return;
}
if (tp <= price){
Print("Invalid TP for ",selected_order_type,": TP=",tp," must be above Entry=",price);
return;
}
}
else if (selected_order_type == "SELL_STOP" || selected_order_type == "SELL_LIMIT"){
if (sl <= price){
Print("Invalid SL for ",selected_order_type,": SL=",sl," must be above Entry=",price);
return;
}
if (tp >= price){
Print("Invalid TP for ",selected_order_type,": TP=",tp," must be below Entry=",price);
return;
}
}
else {
Print("Invalid order type: ",selected_order_type);
return;
}
if (selected_order_type == "BUY_STOP"){
if (!obj_Trade.BuyStop(lot_size,price,symbol,sl,tp,ORDER_TIME_DAY,expiration)){
Print("Buy Stop failed: Entry=",price,", SL=",sl,", TP=",tp,", Error=",GetLastError());
}
else {
Print("Buy Stop placed: Entry=",price,", SL=",sl,", TP=",tp);
}
}
else if (selected_order_type == "SELL_STOP"){
if (!obj_Trade.SellStop(lot_size,price,symbol,sl,tp,ORDER_TIME_DAY,expiration)){
Print("Sell Stop failed: Entry=",price,", SL=",sl,", TP=",tp,", Error=",GetLastError());
}
else {
Print("Sell Stop placed: Entry=",price,", SL=",sl,", TP=",tp);
}
}
else if (selected_order_type == "BUY_LIMIT"){
if (!obj_Trade.BuyLimit(lot_size,price,symbol,sl,tp,ORDER_TIME_DAY,expiration)){
Print("Buy Limit failed: Entry=",price,", SL=",sl,", TP=",tp,", Error=",GetLastError());
}
else {
Print("Buy Limit placed: Entry=",price,", SL=",sl,", TP=",tp);
}
}
else if (selected_order_type == "SELL_LIMIT"){
if (!obj_Trade.SellLimit(lot_size,price,symbol,sl,tp,ORDER_TIME_DAY,expiration)){
Print("Sell Limit failed: Entry=",price,", SL=",sl,", TP=",tp,", Error=",GetLastError());
}
else {
Print("Sell Limit placed: Entry=",price,", SL=",sl,", TP=",tp);
}
}
}
In the execution hub, "isOrderValid()" checks price alignment ("Get_Price_d()", "SymbolInfoDouble()") against rules (e.g., for "BUY_STOP", entry > bid, TP > entry, SL < entry). "placeOrder()" retrieves lot size ("LOT_EDIT", "StringToDouble()") and prices, validates them, and places orders via "obj_Trade.BuyStop()", "SellLimit()", etc., with 24-hour expiration ("TimeCurrent()+3600*24"). Errors are logged ("GetLastError()") if placement fails. For example, on EURUSD H1, a buy stop at 1.2050, SL=1.2000, TP=1.2100, lot=0.01 is placed, like executing a cockpit command.
As our expedition concludes, we shut down the system, ensuring a clean chart.
void OnDeinit(const int reason){
deleteObjects();
deletePanel();
ChartRedraw(0);
}
void deleteObjects(){
ObjectDelete(0,REC1);
ObjectDelete(0,REC2);
ObjectDelete(0,REC3);
ObjectDelete(0,REC4);
ObjectDelete(0,REC5);
ObjectDelete(0,TP_HL);
ObjectDelete(0,SL_HL);
ObjectDelete(0,PR_HL);
ChartRedraw(0);
}
void deletePanel(){
ObjectDelete(0, PANEL_BG);
ObjectDelete(0, PANEL_HEADER);
ObjectDelete(0, LOT_EDIT);
ObjectDelete(0, PRICE_LABEL);
ObjectDelete(0, SL_LABEL);
ObjectDelete(0, TP_LABEL);
ObjectDelete(0, BUY_STOP_BTN);
ObjectDelete(0, SELL_STOP_BTN);
ObjectDelete(0, BUY_LIMIT_BTN);
ObjectDelete(0, SELL_LIMIT_BTN);
ObjectDelete(0, PLACE_ORDER_BTN);
ObjectDelete(0, CANCEL_BTN);
ObjectDelete(0, CLOSE_BTN);
ChartRedraw(0);
}
In the shutdown control room, "OnDeinit()" calls "deleteObjects()" and "deletePanel()" to remove price lines ("REC1", "TP_HL", etc.) and panel objects ("PANEL_BG", "BUY_STOP_BTN", etc.) using "ObjectDelete()", ensuring a clean chart. This is like dismantling the cockpit for the next mission.
The Trade Assistant GUI Tool with Panel EA is a trading triumph, enabling precise pending order placement with a dynamic interface, like a master-crafted cockpit. Its draggable price lines ("PR_HL", "SL_HL") and robust validation ("isOrderValid()") ensure accurate setups, with potential for signal integration or configurable parameters. Picture placing a buy stop on EURUSD with visual precision—strategic brilliance! Beginners will value the intuitive controls, while experts can enhance its functionality, making it essential for manual traders seeking efficiency.
To deploy this EA:
Open MetaEditor in MetaTrader 5, like entering your trading cockpit.
Copy the code, compile with F5, and verify no errors—no pilot wants a faulty system!
Attach the EA to your chart (e.g., EURUSD H1) to display the panel.
Select an order type, drag price lines, set lot size, and place the order; use cancel/close as needed.
Test on a demo account first—real trading deserves a trial run!
We’ve engineered a Trade Assistant GUI system that pilots trading with precision, like a master-crafted cockpit. This MQL5 code is your strategic tool, brought to life with a seamless, professional narrative packed with clear explanations and vivid examples to fuel your trading confidence. Whether you’re a novice pilot or a seasoned market strategist, this EA empowers you to execute orders with ease. Ready to trade? Watch our video guide on the website for a step-by-step creation process. Now, pilot your trading with precision! 🔍
Disclaimer: Trading is like navigating complex markets—challenging and risky. Losses can exceed deposits. Test strategies on a demo account before going live.
Recent Comments
Go to discussion to Comment or View other CommentsNo comments yet. Be the first to comment!