//+------------------------------------------------------------------+
//| Trading Dashboard EA (MT5) |
//+------------------------------------------------------------------+
#property strict
#include
CTrade trade;
//--- Inputs
input ENUM_BASE_CORNER PanelCorner = CORNER_LEFT_UPPER;
input int Xoffset = 10;
input int Yoffset = 20;
input bool CloseOnlyCurrentSymbol = true; // true = only current chart symbol
//--- Object names
string panelBG = "panelBG";
string buyButton = "btnBuy", sellButton = "btnSell";
string closeButton = "btnCloseAll", partialButton = "btnPartialClose", beButton = "btnBreakEven", tsButton = "btnTrailingStop";
string lotInput = "inpLot", slInput = "inpSL", tpInput = "inpTP", pcInput = "inpPC", beInput = "inpBE", tsInput = "inpTS";
string lotLabel = "lblLot", slLabel = "lblSL", tpLabel = "lblTP", pcLabel = "lblPC", beLabel = "lblBE", tsLabel = "lblTS";
string plLabel = "lblPL", tradesLabel = "lblTrades";
//--- State
bool trailingStopActive = false;
//+------------------------------------------------------------------+
//| OnInit |
//+------------------------------------------------------------------+
int OnInit()
{
// Panel background
if(!ObjectCreate(0, panelBG, OBJ_RECTANGLE_LABEL, 0, 0, 0))
return INIT_FAILED;
ObjectSetInteger(0, panelBG, OBJPROP_CORNER, PanelCorner);
ObjectSetInteger(0, panelBG, OBJPROP_XDISTANCE, Xoffset);
ObjectSetInteger(0, panelBG, OBJPROP_YDISTANCE, Yoffset);
ObjectSetInteger(0, panelBG, OBJPROP_XSIZE, 650);
ObjectSetInteger(0, panelBG, OBJPROP_YSIZE, 120);
ObjectSetInteger(0, panelBG, OBJPROP_BGCOLOR, clrBlack);
ObjectSetInteger(0, panelBG, OBJPROP_COLOR, clrWhite);
int px = Xoffset + 10, py = Yoffset + 10;
// Buttons row 1
if(!CreateButton(buyButton, px, py, 80, 25, "BUY", clrLime))
return INIT_FAILED;
if(!CreateButton(sellButton, px + 90, py, 80, 25, "SELL", clrRed))
return INIT_FAILED;
// Buttons row 2
if(!CreateButton(closeButton, px, py + 35, 100, 25, "CLOSE ALL", clrOrange))
return INIT_FAILED;
if(!CreateButton(partialButton, px + 110, py + 35, 100, 25, "PARTIAL", clrDodgerBlue))
return INIT_FAILED;
if(!CreateButton(beButton, px + 220, py + 35, 100, 25, "BREAK EVEN", clrAqua))
return INIT_FAILED;
if(!CreateButton(tsButton, px + 330, py + 35, 100, 25, "TS: OFF", clrGray))
return INIT_FAILED;
// Inputs row 3
if(!CreateInput(lotInput, px, py + 70, 50, 20, "0.10"))
return INIT_FAILED;
if(!CreateInput(slInput, px + 60, py + 70, 50, 20, "200"))
return INIT_FAILED;
if(!CreateInput(tpInput, px + 120, py + 70, 50, 20, "400"))
return INIT_FAILED;
if(!CreateInput(pcInput, px + 180, py + 70, 50, 20, "50"))
return INIT_FAILED;
if(!CreateInput(beInput, px + 240, py + 70, 50, 20, "20"))
return INIT_FAILED;
if(!CreateInput(tsInput, px + 300, py + 70, 50, 20, "100"))
return INIT_FAILED;
// Labels row 3
if(!CreateLabel(lotLabel, px, py + 55, "Lot: 0.10"))
return INIT_FAILED;
if(!CreateLabel(slLabel, px + 60, py + 55, "SL: 200"))
return INIT_FAILED;
if(!CreateLabel(tpLabel, px + 120, py + 55, "TP: 400"))
return INIT_FAILED;
if(!CreateLabel(pcLabel, px + 180, py + 55, "PC%: 50"))
return INIT_FAILED;
if(!CreateLabel(beLabel, px + 240, py + 55, "BE+: 20"))
return INIT_FAILED;
if(!CreateLabel(tsLabel, px + 300, py + 55, "TS: 100"))
return INIT_FAILED;
// P/L and Trades row 4
if(!CreateLabel(plLabel, px, py + 95, "P/L: $0.00"))
return INIT_FAILED;
if(!CreateLabel(tradesLabel, px + 200, py + 95, "Open Trades: 0"))
return INIT_FAILED;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Helper functions |
//+------------------------------------------------------------------+
bool CreateButton(string name, int x, int y, int w, int h, string text, color bg)
{
if(!ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0))
return false;
ObjectSetInteger(0, name, OBJPROP_CORNER, PanelCorner);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg);
ObjectSetString(0, name, OBJPROP_TEXT, text);
return true;
}
bool CreateInput(string name, int x, int y, int w, int h, string defText)
{
if(!ObjectCreate(0, name, OBJ_EDIT, 0, 0, 0))
return false;
ObjectSetInteger(0, name, OBJPROP_CORNER, PanelCorner);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_XSIZE, w);
ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
ObjectSetString(0, name, OBJPROP_TEXT, defText);
return true;
}
bool CreateLabel(string name, int x, int y, string text)
{
if(!ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0))
return false;
ObjectSetInteger(0, name, OBJPROP_CORNER, PanelCorner);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
ObjectSetString(0, name, OBJPROP_TEXT, text);
return true;
}
//+------------------------------------------------------------------+
//| OnChartEvent |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_OBJECT_CLICK)
{
if(sparam == buyButton)
OpenOrder(ORDER_TYPE_BUY);
if(sparam == sellButton)
OpenOrder(ORDER_TYPE_SELL);
if(sparam == closeButton)
CloseAllOrders();
if(sparam == partialButton)
PartialCloseOrders();
if(sparam == beButton)
BreakEvenOrders();
if(sparam == tsButton)
ToggleTrailingStop();
}
else if(id == CHARTEVENT_OBJECT_ENDEDIT)
{
UpdateLabels();
}
}
//+------------------------------------------------------------------+
//| Update Labels |
//+------------------------------------------------------------------+
void UpdateLabels()
{
ObjectSetString(0, lotLabel, OBJPROP_TEXT, "Lot: " + ObjectGetString(0, lotInput, OBJPROP_TEXT));
ObjectSetString(0, slLabel, OBJPROP_TEXT, "SL: " + ObjectGetString(0, slInput, OBJPROP_TEXT));
ObjectSetString(0, tpLabel, OBJPROP_TEXT, "TP: " + ObjectGetString(0, tpInput, OBJPROP_TEXT));
ObjectSetString(0, pcLabel, OBJPROP_TEXT, "PC%: " + ObjectGetString(0, pcInput, OBJPROP_TEXT));
ObjectSetString(0, beLabel, OBJPROP_TEXT, "BE+: " + ObjectGetString(0, beInput, OBJPROP_TEXT));
ObjectSetString(0, tsLabel, OBJPROP_TEXT, "TS: " + ObjectGetString(0, tsInput, OBJPROP_TEXT));
}
//+------------------------------------------------------------------+
//| Open Order |
//+------------------------------------------------------------------+
void OpenOrder(int type)
{
MqlTick tick;
if(!SymbolInfoTick(_Symbol, tick))
{
Print("Error getting tick data for symbol: ", _Symbol);
return;
}
double lot = StrToDouble(ObjectGetString(0, lotInput, OBJPROP_TEXT));
int slPoints = (int)StrToInteger(ObjectGetString(0, slInput, OBJPROP_TEXT));
int tpPoints = (int)StrToInteger(ObjectGetString(0, tpInput, OBJPROP_TEXT));
double price, sl, tp;
if(type == ORDER_TYPE_BUY)
{
price = tick.ask;
sl = price - slPoints * _Point;
tp = price + tpPoints * _Point;
trade.Buy(lot, _Symbol, price, sl, tp); // Specify the symbol
}
else
{
price = tick.bid;
sl = price + slPoints * _Point;
tp = price - tpPoints * _Point;
trade.Sell(lot, _Symbol, price, sl, tp); // Specify the symbol
}
}
//+------------------------------------------------------------------+
//| Close All Orders |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i); // Correct way to get symbol
if(symbol == NULL)
continue; // Skip if symbol is invalid
if(CloseOnlyCurrentSymbol && symbol != _Symbol)
continue;
long type = PositionGetInteger(symbol, POSITION_TYPE);
double volume = PositionGetDouble(symbol, POSITION_VOLUME);
if(type == POSITION_TYPE_BUY)
trade.Sell(volume, symbol);
else
trade.Buy(volume, symbol);
}
}
//+------------------------------------------------------------------+
//| Partial Close Orders |
//+------------------------------------------------------------------+
void PartialCloseOrders()
{
double percent = StrToDouble(ObjectGetString(0, pcInput, OBJPROP_TEXT));
if(percent <= 0 || percent >= 100)
return;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i); // Correct way to get symbol
if(symbol == NULL)
continue; // Skip if symbol is invalid
if(CloseOnlyCurrentSymbol && symbol != _Symbol)
continue;
long type = PositionGetInteger(symbol, POSITION_TYPE);
double volume = PositionGetDouble(symbol, POSITION_VOLUME);
double closeVolume = volume * (percent / 100.0);
double minVolume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
if(closeVolume < minVolume)
continue;
if(type == POSITION_TYPE_BUY)
trade.Sell(closeVolume, symbol);
else
trade.Buy(closeVolume, symbol);
}
}
//+------------------------------------------------------------------+
//| Break Even Orders |
//+------------------------------------------------------------------+
void BreakEvenOrders()
{
double buffer = StrToDouble(ObjectGetString(0, beInput, OBJPROP_TEXT)) * _Point;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i); // Correct way to get symbol
if(symbol == NULL)
continue; // Skip if symbol is invalid
if(CloseOnlyCurrentSymbol && symbol != _Symbol)
continue;
long type = PositionGetInteger(symbol, POSITION_TYPE);
double entry = PositionGetDouble(symbol, POSITION_PRICE_OPEN);
double tp = PositionGetDouble(symbol, POSITION_TP);
if(type == POSITION_TYPE_BUY && SymbolInfoDouble(symbol, SYMBOL_BID) > entry + buffer)
trade.PositionModify(symbol, entry + buffer, tp);
if(type == POSITION_TYPE_SELL && SymbolInfoDouble(symbol, SYMBOL_ASK) < entry - buffer)
trade.PositionModify(symbol, entry - buffer, tp);
}
}
//+------------------------------------------------------------------+
//| Trailing Stop Toggle |
//+------------------------------------------------------------------+
void ToggleTrailingStop()
{
trailingStopActive = !trailingStopActive;
if(trailingStopActive)
{
ObjectSetInteger(0, tsButton, OBJPROP_BGCOLOR, clrGreen);
ObjectSetString(0, tsButton, OBJPROP_TEXT, "TS: ON");
}
else
{
ObjectSetInteger(0, tsButton, OBJPROP_BGCOLOR, clrGray);
ObjectSetString(0, tsButton, OBJPROP_TEXT, "TS: OFF");
}
}
//+------------------------------------------------------------------+
//| OnTick - trailing stop + P/L update |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Trailing Stop
if(trailingStopActive)
{
int tsPoints = (int)StrToInteger(ObjectGetString(0, tsInput, OBJPROP_TEXT));
double tsDistance = tsPoints * _Point;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i); // Correct way to get symbol
if(symbol == NULL)
continue; // Skip if symbol is invalid
if(CloseOnlyCurrentSymbol && symbol != _Symbol)
continue;
long type = PositionGetInteger(symbol, POSITION_TYPE);
double entry = PositionGetDouble(symbol, POSITION_PRICE_OPEN);
double sl = PositionGetDouble(symbol, POSITION_SL);
double tp = PositionGetDouble(symbol, POSITION_TP);
double priceBid = SymbolInfoDouble(symbol, SYMBOL_BID);
double priceAsk = SymbolInfoDouble(symbol, SYMBOL_ASK);
if(type == POSITION_TYPE_BUY)
{
double newSL = priceBid - tsDistance;
if(newSL > entry && newSL > sl)
trade.PositionModify(symbol, newSL, tp);
}
else if(type == POSITION_TYPE_SELL)
{
double newSL = priceAsk + tsDistance;
if(newSL < entry && (sl == 0 || newSL < sl))
trade.PositionModify(symbol, newSL, tp);
}
}
}
//--- P/L and Open Trades update
double totalPL = 0;
int openTrades = 0;
for(int i = 0; i < PositionsTotal(); i++)