Files
Bell-PriceActionWithEma-EA/Experts/SimpleFVG/Drawing.mqh
T
2026-05-09 23:16:50 +07:00

318 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//+------------------------------------------------------------------+
//| Drawing.mqh Step 4: Visualize FVG zones, EMA info, trend panel |
//+------------------------------------------------------------------+
#ifndef __SIMPLE_FVG_DRAWING_MQH__
#define __SIMPLE_FVG_DRAWING_MQH__
#include "Config.mqh"
#include "Trend.mqh"
#include "FVG.mqh"
#include "Trade.mqh"
//+------------------------------------------------------------------+
//| Object-creation helpers |
//+------------------------------------------------------------------+
void DrawRectangle(string name,
datetime timeStart, double priceTop,
datetime timeEnd, double priceBot,
color clr, bool filled = true)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_RECTANGLE, 0, timeStart, priceTop, timeEnd, priceBot);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FILL, filled);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectMove(0, name, 0, timeStart, priceTop);
ObjectMove(0, name, 1, timeEnd, priceBot);
}
void DrawTrendLine(string name,
datetime t1, double p1,
datetime t2, double p2,
color clr, int style, int width)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_TREND, 0, t1, p1, t2, p2);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectMove(0, name, 0, t1, p1);
ObjectMove(0, name, 1, t2, p2);
}
void DrawLabel(string name, int xDist, int yDist,
string text, color clr, int fontSize)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, xDist);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, yDist);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetString (0, name, OBJPROP_FONT, "Consolas");
ObjectSetString (0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
void DrawTextOnChart(string name, datetime t, double price,
string text, color clr, int fontSize, int anchor)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_TEXT, 0, t, price);
ObjectMove(0, name, 0, t, price);
ObjectSetString (0, name, OBJPROP_TEXT, text);
ObjectSetString (0, name, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
void DrawTradeStatsPanel()
{
int totalTrades, tpTrades, slTrades;
GetTradeStats(totalTrades, tpTrades, slTrades);
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
string name = EA_PREFIX + "PNL_STATS";
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_LOWER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 12);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 40);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
ObjectSetString (0, name, OBJPROP_FONT, "Consolas");
ObjectSetString (0, name, OBJPROP_TEXT,
StringFormat("Balance: %.2f | Trades: %d | TP: %d | SL: %d",
balance, totalTrades, tpTrades, slTrades));
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
//+------------------------------------------------------------------+
//| Draw limit orders (TradingView-style lines) |
//+------------------------------------------------------------------+
void DrawLimitOrders()
{
ObjectsDeleteAll(0, EA_PREFIX + "ORD_");
string symbol = GetTradeSymbol();
datetime currentBar = iTime(symbol, InpTimeframe, 0);
for(int i = 0; i < OrdersTotal(); i++)
{
ulong ticket = OrderGetTicket(i);
if(ticket == 0) continue;
if(!OrderSelect(ticket)) continue;
if((long)OrderGetInteger(ORDER_MAGIC) != InpEAMagic) continue;
if((string)OrderGetString(ORDER_SYMBOL) != symbol) continue;
ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
if(type != ORDER_TYPE_BUY_LIMIT && type != ORDER_TYPE_SELL_LIMIT)
continue;
double entryPrice = OrderGetDouble(ORDER_PRICE_OPEN);
double slPrice = OrderGetDouble(ORDER_SL);
double tpPrice = OrderGetDouble(ORDER_TP);
double volume = OrderGetDouble(ORDER_VOLUME_CURRENT);
datetime setupTime = (datetime)OrderGetInteger(ORDER_TIME_SETUP);
string side = (type == ORDER_TYPE_BUY_LIMIT) ? "BUY" : "SELL";
color entryClr = (type == ORDER_TYPE_BUY_LIMIT) ? clrDeepSkyBlue : clrOrangeRed;
color slClr = clrRed;
color tpClr = clrLime;
string id = IntegerToString((int)ticket);
// Entry line
DrawTrendLine(
EA_PREFIX + "ORD_ENTRY_" + id,
setupTime, entryPrice,
currentBar, entryPrice,
entryClr, STYLE_SOLID, 2
);
// SL line
DrawTrendLine(
EA_PREFIX + "ORD_SL_" + id,
setupTime, slPrice,
currentBar, slPrice,
slClr, STYLE_DASH, 1
);
// TP line
DrawTrendLine(
EA_PREFIX + "ORD_TP_" + id,
setupTime, tpPrice,
currentBar, tpPrice,
tpClr, STYLE_DASH, 1
);
// Label near entry
string labelText = StringFormat("%s LIMIT %.2f | Vol %.2f | RR %.1f",
side, entryPrice, volume, InpRRRatio);
DrawTextOnChart(
EA_PREFIX + "ORD_LBL_" + id,
setupTime,
entryPrice,
labelText,
entryClr,
8,
ANCHOR_LEFT_LOWER
);
}
}
//+------------------------------------------------------------------+
//| Draw all active FVG zones as rectangles on the chart |
//+------------------------------------------------------------------+
void DrawFVGZones()
{
ObjectsDeleteAll(0, EA_PREFIX + "FVG_");
string symbol = GetTradeSymbol();
datetime currentBar = iTime(symbol, InpTimeframe, 0);
for(int i = 0; i < g_FVGCount; i++)
{
if(IsZoneExpired(g_FVGZones[i]))
continue;
string zoneId = IntegerToString(i);
//--- Zone color depends on type and FVG status ---
color zoneColor;
if(IsZoneMitigated(g_FVGZones[i]))
zoneColor = InpColorMitigatedFVG;
else if(g_FVGZones[i].type == FVG_BULLISH)
zoneColor = InpColorBullFVG;
else
zoneColor = InpColorBearFVG;
//--- Draw filled rectangle for the FVG zone ---
DrawRectangle(
EA_PREFIX + "FVG_ZONE_" + zoneId,
g_FVGZones[i].createdTime, g_FVGZones[i].upperEdge,
currentBar, g_FVGZones[i].lowerEdge,
zoneColor, true
);
//--- Draw mid-line (50% of FVG) ---
double midPrice = (g_FVGZones[i].upperEdge + g_FVGZones[i].lowerEdge) / 2.0;
color midColor = IsZoneMitigated(g_FVGZones[i]) ? clrDimGray : clrGold;
DrawTrendLine(
EA_PREFIX + "FVG_MID_" + zoneId,
g_FVGZones[i].createdTime, midPrice,
currentBar, midPrice,
midColor, STYLE_DOT, 1
);
//--- Draw text label ---
if(InpShowFVGLabels)
{
string typeStr = (g_FVGZones[i].type == FVG_BULLISH) ? "BULL" : "BEAR";
string arrow = (g_FVGZones[i].type == FVG_BULLISH) ? "▲" : "▼";
string stateStr = "";
if(IsZoneTouched(g_FVGZones[i]))
stateStr = " [TOUCHED]";
else if(IsZoneMitigated(g_FVGZones[i]))
stateStr = " [MITIGATED]";
if(g_FVGZones[i].tradeLocked)
stateStr += " [LOCKED]";
color labelColor;
if(IsZoneMitigated(g_FVGZones[i]))
labelColor = clrDimGray;
else if(IsZoneTouched(g_FVGZones[i]))
labelColor = clrYellow;
else if(g_FVGZones[i].type == FVG_BULLISH)
labelColor = clrDeepSkyBlue;
else
labelColor = clrOrangeRed;
DrawTextOnChart(
EA_PREFIX + "FVG_LBL_" + zoneId,
g_FVGZones[i].createdTime,
g_FVGZones[i].upperEdge,
StringFormat("%s %s [%.2f%.2f]%s",
arrow, typeStr,
g_FVGZones[i].lowerEdge, g_FVGZones[i].upperEdge,
stateStr),
labelColor, 7, ANCHOR_LEFT_LOWER
);
}
}
}
//+------------------------------------------------------------------+
//| Draw info panel (top-left corner) |
//+------------------------------------------------------------------+
void DrawInfoPanel()
{
if(!InpShowPanel) return;
int bullCount = CountActiveFVGs(FVG_BULLISH);
int bearCount = CountActiveFVGs(FVG_BEARISH);
int mitigCount = CountMitigatedFVGs();
string trendText = TrendToString(g_CurrentTrend);
color trendColor = TrendToColor(g_CurrentTrend);
//--- Row 1: EA header ---
DrawLabel(EA_PREFIX + "PNL_HDR", 12, 22,
StringFormat("SimpleFVG | %s %s",
GetTradeSymbol(), EnumToString(InpTimeframe)),
clrSilver, 10);
//--- Row 2: Trend status ---
DrawLabel(EA_PREFIX + "PNL_TREND", 12, 52,
StringFormat("Trend: %s | EMA%d = %.2f | EMA%d = %.2f",
trendText,
InpEMAFastPeriod, g_EMAFastValue,
InpEMASlowPeriod, g_EMASlowValue),
trendColor, 9);
//--- Row 3: FVG counts ---
DrawLabel(EA_PREFIX + "PNL_FVG", 12, 82,
StringFormat("FVG Active: %d Bull + %d Bear | Mitigated: %d",
bullCount, bearCount, mitigCount),
clrWheat, 9);
}
//+------------------------------------------------------------------+
//| Master draw: call all draw functions |
//+------------------------------------------------------------------+
void DrawAll()
{
DrawFVGZones();
DrawInfoPanel();
DrawLimitOrders();
DrawTradeStatsPanel();
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| Clean up drawn objects (giữ lại PNL_STATS để xem kết quả sau test) |
//+------------------------------------------------------------------+
void DrawCleanup()
{
ObjectsDeleteAll(0, EA_PREFIX + "FVG_");
ObjectsDeleteAll(0, EA_PREFIX + "ORD_");
ObjectDelete(0, EA_PREFIX + "PNL_HDR");
ObjectDelete(0, EA_PREFIX + "PNL_TREND");
ObjectDelete(0, EA_PREFIX + "PNL_FVG");
ChartRedraw(0);
}
#endif