mql5/Experts/Archive/PME_Monitor_Dashboard.mq5

403 líneas
16 KiB
MQL5

2025-10-03 10:03:10 +01:00
//+------------------------------------------------------------------+
//| PME_Monitor_Dashboard.mq5 |
//| Real-time Position Monitoring Dashboard |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_plots 0
#include "Modules_PME/DataTypes_PME.mqh"
//+------------------------------------------------------------------+
//| Input Parameters |
//+------------------------------------------------------------------+
input int InpUpdateSeconds = 1; // Update Frequency (seconds)
input int InpDashboardX = 20; // Dashboard X Position
input int InpDashboardY = 100; // Dashboard Y Position
input color InpTextColor = clrWhite; // Text Color
input color InpHeaderColor = clrGold; // Header Color
input color InpWarningColor = clrOrange; // Warning Color
input color InpDangerColor = clrRed; // Danger Color
input color InpSuccessColor = clrLime; // Success Color
input bool InpShowAlerts = true; // Show Alert Warnings
//+------------------------------------------------------------------+
//| Global Variables |
//+------------------------------------------------------------------+
string g_prefix = "PME_MON_";
datetime g_last_update = 0;
int g_positions_count = 0;
double g_total_profit = 0;
double g_total_risk = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Set timer
EventSetTimer(InpUpdateSeconds);
// Create dashboard
CreateDashboard();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
// Remove all dashboard objects
ObjectsDeleteAll(0, g_prefix);
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
UpdateDashboard();
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// Update on new bar
if(prev_calculated != rates_total)
{
UpdateDashboard();
}
return(rates_total);
}
//+------------------------------------------------------------------+
//| Create Dashboard |
//+------------------------------------------------------------------+
void CreateDashboard()
{
int y = InpDashboardY;
// Background
CreateRectangle(g_prefix + "BG", InpDashboardX - 5, y - 5, 300, 450,
clrBlack, STYLE_SOLID, 1, 80);
// Header
CreateLabel(g_prefix + "HEADER", InpDashboardX, y,
"═══ PME POSITION MONITOR ═══", InpHeaderColor, 10, true);
y += 25;
// Time
CreateLabel(g_prefix + "TIME", InpDashboardX, y,
"Last Update: --:--:--", InpTextColor, 8);
y += 20;
// Separator
CreateLabel(g_prefix + "SEP1", InpDashboardX, y,
"────────────────────────", InpTextColor, 8);
y += 15;
// Position Summary
CreateLabel(g_prefix + "POS_HEADER", InpDashboardX, y,
"POSITION SUMMARY", InpHeaderColor, 9, true);
y += 18;
CreateLabel(g_prefix + "POS_COUNT", InpDashboardX, y,
"Active Positions: 0", InpTextColor, 9);
y += 15;
CreateLabel(g_prefix + "TOTAL_PROFIT", InpDashboardX, y,
"Total P/L: $0.00", InpTextColor, 9);
y += 15;
CreateLabel(g_prefix + "TOTAL_RISK", InpDashboardX, y,
"Total Risk: $0.00", InpTextColor, 9);
y += 20;
// Separator
CreateLabel(g_prefix + "SEP2", InpDashboardX, y,
"────────────────────────", InpTextColor, 8);
y += 15;
// Position Details
CreateLabel(g_prefix + "DETAIL_HEADER", InpDashboardX, y,
"POSITION DETAILS", InpHeaderColor, 9, true);
y += 18;
// Create slots for up to 5 positions
for(int i = 0; i < 5; i++)
{
CreateLabel(g_prefix + "POS_" + IntegerToString(i) + "_INFO",
InpDashboardX, y + (i * 45), "", InpTextColor, 8);
CreateLabel(g_prefix + "POS_" + IntegerToString(i) + "_STATUS",
InpDashboardX, y + (i * 45) + 12, "", InpTextColor, 8);
CreateLabel(g_prefix + "POS_" + IntegerToString(i) + "_RISK",
InpDashboardX, y + (i * 45) + 24, "", InpTextColor, 8);
CreateLabel(g_prefix + "POS_" + IntegerToString(i) + "_EXIT",
InpDashboardX, y + (i * 45) + 36, "", InpWarningColor, 8);
}
y += 230;
// Separator
CreateLabel(g_prefix + "SEP3", InpDashboardX, y,
"────────────────────────", InpTextColor, 8);
y += 15;
// Warnings
CreateLabel(g_prefix + "WARNING_HEADER", InpDashboardX, y,
"WARNINGS", InpHeaderColor, 9, true);
y += 18;
CreateLabel(g_prefix + "WARNING_1", InpDashboardX, y, "", InpWarningColor, 8);
y += 12;
CreateLabel(g_prefix + "WARNING_2", InpDashboardX, y + 12, "", InpWarningColor, 8);
y += 12;
CreateLabel(g_prefix + "WARNING_3", InpDashboardX, y + 24, "", InpDangerColor, 8);
}
//+------------------------------------------------------------------+
//| Update Dashboard |
//+------------------------------------------------------------------+
void UpdateDashboard()
{
// Update time
UpdateLabel(g_prefix + "TIME", "Last Update: " + TimeToString(TimeCurrent(), TIME_SECONDS));
// Get positions
int total = PositionsTotal();
double total_profit = 0;
double total_risk = 0;
// Clear warnings
UpdateLabel(g_prefix + "WARNING_1", "");
UpdateLabel(g_prefix + "WARNING_2", "");
UpdateLabel(g_prefix + "WARNING_3", "");
int warning_count = 0;
// Process positions
for(int i = 0; i < MathMin(total, 5); i++)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{
string symbol = PositionGetString(POSITION_SYMBOL);
ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE);
double volume = PositionGetDouble(POSITION_VOLUME);
double profit = PositionGetDouble(POSITION_PROFIT);
double entry = PositionGetDouble(POSITION_PRICE_OPEN);
double current = PositionGetDouble(POSITION_PRICE_CURRENT);
double sl = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
datetime open_time = (datetime)PositionGetInteger(POSITION_TIME);
total_profit += profit;
// Calculate risk
if(sl > 0)
{
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
double tick_value = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
double sl_points = MathAbs(current - sl) / point;
double risk = sl_points * tick_value * volume;
total_risk += risk;
}
// Calculate bars and points
int bars = Bars(symbol, PERIOD_CURRENT, open_time, TimeCurrent());
double points = 0;
if(type == ORDER_TYPE_BUY)
points = (current - entry) / SymbolInfoDouble(symbol, SYMBOL_POINT);
else
points = (entry - current) / SymbolInfoDouble(symbol, SYMBOL_POINT);
// Update position info
string pos_info = StringFormat("#%d %s %s %.2f",
ticket, symbol,
type == ORDER_TYPE_BUY ? "BUY" : "SELL",
volume);
string status = StringFormat("P/L: %s%.2f (%.0f pts)",
profit >= 0 ? "+" : "", profit, points);
string risk_info = StringFormat("Bars: %d | SL: %s | TP: %s",
bars,
sl > 0 ? "YES" : "NO",
tp > 0 ? "YES" : "NO");
// Check exit conditions
string exit_warning = "";
color status_color = InpTextColor;
// Check for potential exits
if(bars < 10)
{
exit_warning = "⏱ New position (< 10 bars)";
status_color = InpSuccessColor;
}
else if(points >= 30 && points < 50)
{
exit_warning = "📊 Approaching BE trigger";
status_color = InpWarningColor;
}
else if(points >= 50)
{
exit_warning = "📈 In trailing zone";
status_color = InpSuccessColor;
}
else if(profit < -50)
{
exit_warning = "⚠️ Significant loss";
status_color = InpDangerColor;
}
// Check RSI
int rsi_handle = iRSI(symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);
double rsi_buffer[1];
if(CopyBuffer(rsi_handle, 0, 0, 1, rsi_buffer) > 0)
{
double rsi = rsi_buffer[0];
if(type == ORDER_TYPE_BUY && rsi > 75)
{
exit_warning += StringFormat(" RSI:%.0f", rsi);
status_color = InpWarningColor;
}
else if(type == ORDER_TYPE_SELL && rsi < 25)
{
exit_warning += StringFormat(" RSI:%.0f", rsi);
status_color = InpWarningColor;
}
}
IndicatorRelease(rsi_handle);
// Update labels
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_INFO", pos_info);
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_STATUS", status,
profit >= 0 ? InpSuccessColor : InpDangerColor);
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_RISK", risk_info);
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_EXIT", exit_warning, status_color);
// Add warnings
if(sl == 0 && warning_count < 3)
{
UpdateLabel(g_prefix + "WARNING_" + IntegerToString(warning_count + 1),
StringFormat("⚠️ #%d has no stop loss!", ticket));
warning_count++;
}
}
}
// Clear unused position slots
for(int i = total; i < 5; i++)
{
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_INFO", "");
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_STATUS", "");
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_RISK", "");
UpdateLabel(g_prefix + "POS_" + IntegerToString(i) + "_EXIT", "");
}
// Update summary
UpdateLabel(g_prefix + "POS_COUNT", StringFormat("Active Positions: %d", total));
UpdateLabel(g_prefix + "TOTAL_PROFIT", StringFormat("Total P/L: %s%.2f",
total_profit >= 0 ? "$" : "-$",
MathAbs(total_profit)),
total_profit >= 0 ? InpSuccessColor : InpDangerColor);
UpdateLabel(g_prefix + "TOTAL_RISK", StringFormat("Total Risk: $%.2f", total_risk));
// Check for global warnings
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double daily_loss = ((balance - equity) / balance) * 100;
if(daily_loss > 5 && warning_count < 3)
{
UpdateLabel(g_prefix + "WARNING_" + IntegerToString(warning_count + 1),
StringFormat("⚠️ Daily loss: %.1f%%", daily_loss), InpDangerColor);
warning_count++;
}
// Alert on significant changes
if(InpShowAlerts)
{
static int last_count = 0;
if(total < last_count && last_count > 0)
{
Alert("PME Monitor: Position closed!");
}
last_count = total;
}
}
//+------------------------------------------------------------------+
//| Create Label |
//+------------------------------------------------------------------+
void CreateLabel(string name, int x, int y, string text, color clr,
int size, bool bold = false)
{
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);
ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
//+------------------------------------------------------------------+
//| Update Label |
//+------------------------------------------------------------------+
void UpdateLabel(string name, string text, color clr = clrNONE)
{
if(ObjectFind(0, name) >= 0)
{
ObjectSetString(0, name, OBJPROP_TEXT, text);
if(clr != clrNONE)
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
}
}
//+------------------------------------------------------------------+
//| Create Rectangle |
//+------------------------------------------------------------------+
void CreateRectangle(string name, int x, int y, int width, int height,
color clr, ENUM_LINE_STYLE style, int line_width, int transparency = 255)
{
ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 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_BGCOLOR, clr);
ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
ObjectSetInteger(0, name, OBJPROP_WIDTH, line_width);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
// Set transparency (0-255, where 255 is opaque)
long color_value = (long)clr;
long alpha = (255 - transparency) << 24;
color_value = (color_value & 0x00FFFFFF) | alpha;
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, (color)color_value);
}
//+------------------------------------------------------------------+