untitled

Pasted Oct 11, 2026, 6:24 AM1 file780 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgsz10pvbk42eym
untitled
//+------------------------------------------------------------------+
//|                                EA_Grid_Fibo_NewsFilter_MT5.mq5 |
//|                                  Copyright 2026, Algorithmic Dev |
//+------------------------------------------------------------------+
#property copyright "Algorithmic Dev"
#property link      ""
#property version   "3.30"

#include 
CTrade trade;

//--- INPUT PARAMETERS
input group "=== SETTING TRADING & AUTO-COMPOUNDING ==="
input double   InpLotSize            = 0.01;      // Lot Size Awal
input double   InpLotMultiplier      = 1.3;       // Pengali Lot (1.0 = Fixed Lot)
input ulong    InpMagicNumber        = 888111;    // Magic Number
input ulong    InpSlippage           = 3;         // Max Slippage (Points)

input group "=== RISK & TARGET (DYNAMIC AUTO-COMPOUNDING) ==="
input bool     InpUsePercentageTarget= true;      // Gunakan Target % Balance (Untuk TP/SL)
input double   InpDailyTargetPercent = 3.0;       // Target Profit Harian (% Balance)
input double   InpBasketTPPercent    = 1.0;       // Basket TP (% Balance)
input double   InpBasketSLPercent    = 8.0;       // Basket SL (% Balance) - NEW v3.10
input double   InpDailyTargetUSD     = 15.00;     // Target Profit Harian ($)
input double   InpBasketTPUSD        = 10.00;     // Basket TP ($)
input double   InpBasketSLUSD        = 40.00;     // Basket SL ($) - fallback saat mode % OFF

input group "=== FEATURE 1: TRAILING BASKET PROFIT ==="
input bool     InpUseTrailingBasket  = true;      // Aktifkan Trailing Basket TP
input double   InpTrailingStartUSD   = 7.00;      // Trigger Trailing ($)
input double   InpTrailingStepUSD    = 2.00;      // Step Pengunci Profit ($)
input double   InpTrailingStartPercent = 0.6;     // Trigger Trailing (% Balance)
input double   InpTrailingStepPercent  = 0.2;     // Step Pengunci Profit (% Balance)

input group "=== FEATURE 2: SMART LAYER REDUCTION (PARTIAL CLOSE) ==="
input bool     InpUseSmartReduction  = true;      // Aktifkan Reduksi Layer Cerdas
input int      InpMinLayersForSmart  = 3;         // Minimum Layer untuk Aktifkan Reduction
input double   InpNetProfitToReduce  = 0.50;      // Minimum Profit Gabungan ($) untuk Cut Layer Terjauh

input group "=== FEATURE 3: TREND BIAS FILTER (EMA) ==="
input bool     InpUseEMAFilter       = true;      // Aktifkan Filter Tren EMA
input int      InpEMAPeriod          = 200;       // Periode EMA Filter
input ENUM_TIMEFRAMES InpEMATimeframe= PERIOD_M15; // Timeframe EMA Filter

input group "=== FEATURE 4: SPREAD & ROLLOVER PROTECTION ==="
input double   InpMaxSpreadPips      = 50.0;      // Max Spread Diizinkan (Pips)
input bool     InpBlockRollover      = true;      // Tahan Trade saat Rollover (23:00-00:00 Broker)
input int      InpRolloverStartHour  = 23;        // Jam Mulai Rollover (Broker Time)
input int      InpRolloverEndHour    = 0;         // Jam Selesai Rollover (Broker Time)

input group "=== FEATURE 5: WEEKEND & FRIDAY HARD CLOSE ==="
input bool     InpUseFridayProtection= true;      // Aktifkan Filter Proteksi Akhir Pekan
input int      InpFridayStopHour     = 15;        // Jam Stop Entry Baru pada Hari Jumat (Broker Time)
input bool     InpFridayCloseAll     = true;      // Paksa Close All Posisi pada Jumat Malam

input group "=== SETTING GRID & BASKET ==="
input double   InpBaseGridStepUSD    = 0.80;      // Jarak Grid Dasar 
input bool     InpUseFiboMultiplier  = true;      // Pengali Fibonacci untuk Jarak Grid
input int      InpMaxGridLayers      = 4;         // Batas Maksimum Layer Grid
input bool     InpUseATRGrid         = true;      // Dynamic Grid Step (Berdasarkan ATR)
input int      InpATRPeriod          = 14;        // Periode ATR
input double   InpATRFactor          = 1.5;       // Pengali ATR (grid lebih lebar)
input double   InpMaxSpikeUSD        = 5.00;      // Spike Filter ($)

input group "=== SETTING 3 SESI TRADING (BROKER TIME) ==="
input bool     InpUseSessionFilter   = true;      // Aktifkan Filter Sesi
input bool     InpUseAsiaSession     = true;      // Sesi Asia (00:00 - 08:00)
input int      InpAsiaStartHour      = 0;
input int      InpAsiaEndHour        = 8;
input bool     InpUseLondonSession   = true;      // Sesi London 
input int      InpLondonStartHour    = 9;
input int      InpLondonEndHour      = 16;
input bool     InpUseUSSession       = false;     // Sesi New York (OFF default v3.20)
input int      InpUSStartHour        = 15;
input int      InpUSEndHour          = 22;

input group "=== SETTING NEWS FILTER & STOP TRADE ==="
input bool     InpUseNewsFilter      = true;      // News Filter Native
input int      InpNewsBeforeMins     = 30;        // Menit Tahan Sebelum Berita
input int      InpNewsAfterMins      = 30;        // Menit Tahan Setelah Berita
input bool     InpFilterHighImpact   = true;      // Red Folder
input bool     InpFilterMedImpact    = false;     // Orange Folder
input bool     InpEnableStopTrade    = true;      // Auto Stop jika Target / Basket SL Hit

input group "=== EQUITY PROTECTOR (v3.10) ==="
input bool     InpUseEquityProtector = true;      // Stop total saat drawdown akun berlebih
input double   InpMaxEquityDDPercent = 10.0;      // Max Drawdown Akun (% Balance)

input group "=== EXECUTION SAFETY (v3.20) ==="
input int      InpBasketCooldownMins = 30;        // Jeda antar basket setelah close (menit)

input group "=== HIGH WINRATE FILTERS (v3.30) ==="
input bool     InpUseRSIFilter       = true;      // Entry hanya saat RSI ekstrem (jenuh)
input int      InpRSIPeriod          = 14;        // Periode RSI
input double   InpRSIBuyMax          = 35.0;      // Buy hanya jika RSI  ini
input bool     InpUseADXFilter       = true;      // Blokir entry saat tren kuat (musuh grid)
input int      InpADXPeriod          = 14;        // Periode ADX
input double   InpADXMax             = 25.0;      // Max ADX untuk entry
input bool     InpUseTimeStop        = true;      // Tutup basket jika terlalu lama floating
input int      InpMaxBasketHours     = 12;        // Max durasi basket (jam)

input group "=== DASHBOARD DISPLAY ==="
input color    InpBgColor            = C'20,24,35';// Panel Background
input color    InpHeaderColor        = C'30,35,48';// Panel Header
input color    InpTextColor          = clrWhite;  // Text Color
input color    InpProfitColor        = clrLime;   // Profit Color
input color    InpLossColor          = clrRed;    // Loss Color

//--- GLOBAL VARIABLES
datetime g_lastDayChecked     = 0;
bool     g_targetReachedToday = false;
bool     g_stopTradeActive    = false;
bool     g_manualButtonOff    = false;     
string   g_stopReason         = "";
string   g_prefix             = "DB_Panel_";
int      g_handleATR          = INVALID_HANDLE;
int      g_handleEMA          = INVALID_HANDLE;
int      g_handleRSI          = INVALID_HANDLE;
int      g_handleADX          = INVALID_HANDLE;
datetime g_basketStartTime     = 0;      // v3.30: waktu basket mulai dibuka
double   g_basketHighProfit   = 0.0;
datetime g_lastBasketCloseTime = 0;      // v3.20: waktu basket terakhir tutup
int      g_prevOpenCount       = 0;      // v3.20: jumlah posisi tick sebelumnya

const double g_fiboRatios[10] = {1.0, 1.0, 1.618, 2.618, 4.236, 6.854, 11.090, 17.944, 29.034, 46.978};

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   trade.SetExpertMagicNumber(InpMagicNumber);
   trade.SetDeviationInPoints(InpSlippage);

   if(InpUseATRGrid)
   {
      g_handleATR = iATR(_Symbol, PERIOD_CURRENT, InpATRPeriod);
      if(g_handleATR == INVALID_HANDLE)
      {
         Print("Gagal menginisialisasi Indikator ATR.");
         return(INIT_FAILED);
      }
   }

   if(InpUseEMAFilter)
   {
      g_handleEMA = iMA(_Symbol, InpEMATimeframe, InpEMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
      if(g_handleEMA == INVALID_HANDLE)
      {
         Print("Gagal menginisialisasi Indikator EMA.");
         return(INIT_FAILED);
      }
   }

   if(InpUseRSIFilter)
   {
      g_handleRSI = iRSI(_Symbol, InpEMATimeframe, InpRSIPeriod, PRICE_CLOSE);
      if(g_handleRSI == INVALID_HANDLE)
      {
         Print("Gagal menginisialisasi Indikator RSI.");
         return(INIT_FAILED);
      }
   }

   if(InpUseADXFilter)
   {
      g_handleADX = iADX(_Symbol, InpEMATimeframe, InpADXPeriod);
      if(g_handleADX == INVALID_HANDLE)
      {
         Print("Gagal menginisialisasi Indikator ADX.");
         return(INIT_FAILED);
      }
   }

   // v3.10: Grid step memakai satuan harga - EA ini dirancang untuk XAUUSD
   if(StringFind(_Symbol, "XAU")  InpRolloverEndHour)
      return (dt.hour >= InpRolloverStartHour || dt.hour = InpRolloverStartHour && dt.hour = InpFridayStopHour);
}

//+------------------------------------------------------------------+
//| Feature 1: Trailing Basket Profit Logic                          |
//+------------------------------------------------------------------+
void CheckTrailingBasket(double totalFloating)
{
   if(!InpUseTrailingBasket || totalFloating = startUSD)
   {
      if(totalFloating > g_basketHighProfit)
         g_basketHighProfit = totalFloating;

      double lockFloor = g_basketHighProfit - stepUSD;
      if(totalFloating  0)
      {
         CloseAllPositions();
         g_basketHighProfit = 0.0;
      }
   }
}

//+------------------------------------------------------------------+
//| Feature 2: Smart Layer Reduction (Partial Close)                 |
//+------------------------------------------------------------------+
void CheckSmartLayerReduction()
{
   if(!InpUseSmartReduction) return;
   
   int openCount = GetOpenPositionsCount();
   if(openCount = 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
      {
         datetime posTime = (datetime)PositionGetInteger(POSITION_TIME);
         if(posTime  newestTime) { newestTime = posTime; newestTicket = ticket; }
      }
   }

   if(oldestTicket > 0 && newestTicket > 0 && oldestTicket != newestTicket)
   {
      PositionSelectByTicket(oldestTicket);
      double oldestProfit = PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
      
      PositionSelectByTicket(newestTicket);
      double newestProfit = PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);

      if((oldestProfit + newestProfit) >= InpNetProfitToReduce)
      {
         trade.PositionClose(oldestTicket);
         trade.PositionClose(newestTicket);
         Print("Smart Layer Reduction Triggered! Closed Ticket ", oldestTicket, " and ", newestTicket);
      }
   }
}

//+------------------------------------------------------------------+
//| Pengecekan Status 3 Sesi Trading                                 |
//+------------------------------------------------------------------+
bool IsActiveSession(string &activeSessionName)
{
   if(!InpUseSessionFilter)
   {
      activeSessionName = "ALL SESSIONS (24H)";
      return true;
   }

   MqlDateTime dt;
   TimeToStruct(TimeCurrent(), dt);
   int h = dt.hour;

   bool asia   = InpUseAsiaSession   && (h >= InpAsiaStartHour   && h = InpLondonStartHour && h = InpUSStartHour     && h = InpAsiaStartHour   && h = InpLondonStartHour && h = InpUSStartHour     && h  0 &&
      (TimeCurrent() - g_lastBasketCloseTime)  0 && floatingPL = InpMaxGridLayers)
   {
      recommendedColor = clrOrange;
      return "MAX GRID LAYERS REACHED. AWAITING TP.";
   }

   recommendedColor = clrLime;
   if(openCount == 0)
      return "CONDITIONS OPTIMAL. READY FOR FIRST ENTRY.";
   
   return "GRID ACTIVE. MARKET CONDITIONS STABLE.";
}

//+------------------------------------------------------------------+
//| Fungsi Pengecekan News Filter (Calendar Native MT5)              |
//+------------------------------------------------------------------+
bool IsNewsTime()
{
   if(!InpUseNewsFilter) return false;

   static datetime lastCheck = 0;
   static bool isNews = false;

   if(TimeCurrent() - lastCheck  0)
   {
      for(int i = 0; i = 0 || (curr == "USD" && StringFind(sym, "XAU") >= 0))
               {
                  if((InpFilterHighImpact && event.importance == CALENDAR_IMPORTANCE_HIGH) ||
                     (InpFilterMedImpact  && event.importance == CALENDAR_IMPORTANCE_MODERATE))
                  {
                     isNews = true;
                     return true;
                  }
               }
            }
         }
      }
   }

   isNews = false;
   return false;
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   datetime currentDay = iTime(_Symbol, PERIOD_D1, 0);

   if(currentDay != g_lastDayChecked)
   {
      g_lastDayChecked     = currentDay;
      g_targetReachedToday = false;
      g_stopTradeActive    = false;
      g_stopReason         = "";
   }

   double closedProfitToday = GetTodayClosedProfit();
   double totalFloating     = AccountInfoDouble(ACCOUNT_PROFIT);
   int openCount            = GetOpenPositionsCount();

   // v3.20: deteksi basket baru saja tutup -> mulai cooldown antar basket
   if(g_prevOpenCount > 0 && openCount == 0)
   {
      g_lastBasketCloseTime = TimeCurrent();
      g_basketStartTime = 0;
   }
   // v3.30: catat waktu basket mulai dibuka
   if(g_prevOpenCount == 0 && openCount > 0)
      g_basketStartTime = TimeCurrent();
   g_prevOpenCount = openCount;

   double activeTargetUSD = GetDailyTargetUSD();
   double activeBasketTP  = GetBasketTPUSD();
   double activeBasketSL  = GetBasketSLUSD();

   // 1. EVALUASI BASKET TP, BASKET SL & TRAILING BASKET PROFIT
   if(openCount > 0)
   {
      // Check Trailing Basket
      CheckTrailingBasket(totalFloating);

      // Check Smart Layer Reduction
      CheckSmartLayerReduction();

      if(activeBasketTP > 0 && totalFloating >= activeBasketTP)
      {
         CloseAllPositions();
         UpdateDashboard();
         return;
      }
      if(activeBasketSL > 0 && totalFloating  0 && totalFloating  0 &&
         (TimeCurrent() - g_basketStartTime) > InpMaxBasketHours * 3600)
      {
         CloseAllPositions();
         UpdateDashboard();
         return;
      }
   }

   // 2. EVALUASI FRIDAY CLOSE ALL
   if(IsFridayStop() && InpFridayCloseAll && openCount > 0)
   {
      CloseAllPositions();
      g_stopTradeActive = true;
      g_stopReason      = "FRIDAY HARD CLOSE";
      UpdateDashboard();
      return;
   }

   // 3. EVALUASI FILTERS & MANUAL STOP
   string sessionStatusStr = "";
   bool isSessionActive = IsActiveSession(sessionStatusStr);

   if(g_manualButtonOff)
   {
      g_stopTradeActive = true;
      g_stopReason      = "MANUAL OFF";
   }
   else if(!IsSpreadOK())
   {
      g_stopTradeActive = true;
      g_stopReason      = "HIGH SPREAD";
   }
   else if(IsRolloverTime())
   {
      g_stopTradeActive = true;
      g_stopReason      = "ROLLOVER HOUR";
   }
   else if(IsFridayStop())
   {
      g_stopTradeActive = true;
      g_stopReason      = "FRIDAY FILTER";
   }
   else if(IsNewsTime())
   {
      g_stopTradeActive = true;
      g_stopReason      = "NEWS FILTER";
   }
   else if(!isSessionActive)
   {
      g_stopTradeActive = true;
      g_stopReason      = "OUT OF SESSION";
   }
   else if(closedProfitToday >= activeTargetUSD)
   {
      g_targetReachedToday = true;
      g_stopTradeActive    = true;
      g_stopReason         = "TARGET REACHED";
   }
   else
   {
      if(g_stopReason == "NEWS FILTER" || g_stopReason == "OUT OF SESSION" || 
         g_stopReason == "HIGH SPREAD" || g_stopReason == "ROLLOVER HOUR"  || 
         g_stopReason == "FRIDAY FILTER" || (g_stopReason == "MANUAL OFF" && !g_manualButtonOff))
      {
         g_stopTradeActive = false;
         g_stopReason      = "";
      }
   }

   UpdateDashboard();

   if(g_stopTradeActive || g_manualButtonOff) return;

   // 4. EKSEKUSI STRATEGI OPEN PRICE + FIBONACCI GRID & EMA BIAS
   ExecuteOpenPriceFiboGrid();
}

//+------------------------------------------------------------------+
//| Kalkulasi Dynamic Grid Distance                                  |
//+------------------------------------------------------------------+
double CalculateGridDistance(int openCount)
{
   double baseStep = InpBaseGridStepUSD;

   if(InpUseATRGrid && g_handleATR != INVALID_HANDLE)
   {
      double atrBuffer[];
      ArraySetAsSeries(atrBuffer, true);
      if(CopyBuffer(g_handleATR, 0, 1, 1, atrBuffer) > 0)
      {
         double atrStep = atrBuffer[0] * InpATRFactor;
         if(atrStep > baseStep) baseStep = atrStep;
      }
   }

   int fiboIdx = MathMax(0, MathMin(openCount - 1, 9));
   double currentStepMultiplier = InpUseFiboMultiplier ? g_fiboRatios[fiboIdx] : 1.0;
   return baseStep * currentStepMultiplier;
}

//+------------------------------------------------------------------+
//| Logika Hitung Lot                                                |
//+------------------------------------------------------------------+
double CalculateLot(int layerIndex)
{
   double lot = InpLotSize * MathPow(InpLotMultiplier, layerIndex);
   double minLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   
   lot = MathFloor(lot / stepLot) * stepLot;
   if(lot  maxLot) lot = maxLot;
   return NormalizeDouble(lot, 2);
}

//+------------------------------------------------------------------+
//| Logika Strategi Grid + Feature 3 (EMA Trend Filter)              |
//+------------------------------------------------------------------+
void ExecuteOpenPriceFiboGrid()
{
   int openCount = GetOpenPositionsCount();

   if(openCount >= InpMaxGridLayers) return;

   double highCurr = iHigh(_Symbol, PERIOD_CURRENT, 0);
   double lowCurr  = iLow(_Symbol, PERIOD_CURRENT, 0);
   if((highCurr - lowCurr) > InpMaxSpikeUSD) return; 

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   if(openCount == 0)
   {
      // v3.20: cooldown - jangan langsung buka basket baru setelah basket tutup
      if(g_lastBasketCloseTime > 0 &&
         (TimeCurrent() - g_lastBasketCloseTime)  0)
         {
            emaVal = emaBuffer[0];
            allowBuy  = (ask > emaVal);
            allowSell = (bid  0)
         {
            allowBuy  = allowBuy  && (rsiBuffer[0]  InpRSISellMin);
         }
      }

      // v3.30: filter ADX - tolak entry saat tren kuat (pembunuh utama grid)
      if(InpUseADXFilter && g_handleADX != INVALID_HANDLE)
      {
         double adxBuffer[];
         ArraySetAsSeries(adxBuffer, true);
         if(CopyBuffer(g_handleADX, 0, 0, 1, adxBuffer) > 0)
         {
            if(adxBuffer[0] > InpADXMax)
               return;
         }
      }

      if(ask  openPriceD1 && allowSell)
      {
         trade.Sell(currentLot, _Symbol, bid, 0, 0, "GRID SELL APOY #1");
      }
      return;
   }

   ENUM_POSITION_TYPE posType = GetLastPositionType();
   double lastPrice          = GetLastPositionOpenPrice();
   double targetGridDistance = CalculateGridDistance(openCount);
   double nextLot                = CalculateLot(openCount);

   if(posType == POSITION_TYPE_BUY)
   {
      if(ask = (lastPrice + targetGridDistance))
      {
         string comment = "GRID SELL APOY #" + IntegerToString(openCount + 1);
         trade.Sell(nextLot, _Symbol, bid, 0, 0, comment);
      }
   }
}

//+------------------------------------------------------------------+
//| Helper Fungsi Posisi & Transaksi                                 |
//+------------------------------------------------------------------+
int GetOpenPositionsCount()
{
   int count = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
         count++;
   }
   return count;
}

double GetLastPositionOpenPrice()
{
   ulong maxTicket = 0;
   double price = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
      {
         if(ticket > maxTicket)
         {
            maxTicket = ticket;
            price = PositionGetDouble(POSITION_PRICE_OPEN);
         }
      }
   }
   return price;
}

ENUM_POSITION_TYPE GetLastPositionType()
{
   ulong maxTicket = 0;
   ENUM_POSITION_TYPE type = POSITION_TYPE_BUY;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
      {
         if(ticket > maxTicket)
         {
            maxTicket = ticket;
            type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         }
      }
   }
   return type;
}

void CloseAllPositions()
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
      {
         trade.PositionClose(ticket);
      }
   }
}

double GetTodayClosedProfit()
{
   double totalProfit = 0.0;
   datetime todayStart = iTime(_Symbol, PERIOD_D1, 0);

   if(HistorySelect(todayStart, TimeCurrent()))
   {
      int deals = HistoryDealsTotal();
      for(int i = 0; i  0)
         {
            ulong magic = HistoryDealGetInteger(dealTicket, DEAL_MAGIC);
            long entry  = HistoryDealGetInteger(dealTicket, DEAL_ENTRY);

            if(magic == InpMagicNumber && (entry == DEAL_ENTRY_OUT || entry == DEAL_ENTRY_INOUT))
            {
               totalProfit += (HistoryDealGetDouble(dealTicket, DEAL_PROFIT) + 
                               HistoryDealGetDouble(dealTicket, DEAL_SWAP) + 
                               HistoryDealGetDouble(dealTicket, DEAL_COMMISSION));
            }
         }
      }
   }
   return totalProfit;
}

//+------------------------------------------------------------------+
//| Dashboard UI Functions                                           |
//+------------------------------------------------------------------+
void InitDashboardUI()
{
   int x = 20, y = 20, w = 295, h = 520;
   
   CreateRectLabel(g_prefix + "BG", x, y, w, h, InpBgColor);
   CreateRectLabel(g_prefix + "HeaderBG", x, y, w, 25, InpHeaderColor);
   CreateLabel(g_prefix + "Title", "APOY DASHBOARD PRO v3.30", x + 10, y + 5, clrOrange, 9, true);

   CreateLabel(g_prefix + "L_Account", "--- ACCOUNT STATS ---", x + 10, y + 33, clrGray, 8, true);
   CreateLabel(g_prefix + "L_Balance", "Balance:", x + 10, y + 50, InpTextColor, 8);
   CreateLabel(g_prefix + "V_Balance", "$0.00", x + 130, y + 50, InpTextColor, 8, true);
   CreateLabel(g_prefix + "L_Equity", "Equity:", x + 10, y + 68, InpTextColor, 8);
   CreateLabel(g_prefix + "V_Equity", "$0.00", x + 130, y + 68, InpTextColor, 8, true);

   CreateLabel(g_prefix + "L_Perf", "--- TODAY PERFORMANCE ---", x + 10, y + 93, clrGray, 8, true);
   CreateLabel(g_prefix + "L_Realized", "Realized Today:", x + 10, y + 110, InpTextColor, 8);
   CreateLabel(g_prefix + "V_Realized", "$0.00", x + 130, y + 110, InpProfitColor, 9, true);
   CreateLabel(g_prefix + "L_Target", "Daily Target:", x + 10, y + 128, InpTextColor, 8);
   CreateLabel(g_prefix + "V_Target", "$0.00", x + 130, y + 128, clrYellow, 8, true);

   CreateLabel(g_prefix + "L_Floating", "Floating P/L:", x + 10, y + 153, InpTextColor, 8);
   CreateLabel(g_prefix + "V_Floating", "$0.00", x + 130, y + 153, InpTextColor, 8, true);
   CreateLabel(g_prefix + "L_Status", "EA Status:", x + 10, y + 171, InpTextColor, 8);
   CreateLabel(g_prefix + "V_Status", "RUNNING", x + 130, y + 171, clrLime, 8, true);

   CreateLabel(g_prefix + "L_SessHeader", "--- SESSION & TECH ADVICE ---", x + 10, y + 196, clrGray, 8, true);
   CreateLabel(g_prefix + "L_ActiveSession", "Active Session:", x + 10, y + 213, InpTextColor, 8);
   CreateLabel(g_prefix + "V_ActiveSession", "CHECKING...", x + 130, y + 213, clrCyan, 8, true);
   CreateLabel(g_prefix + "L_SessAdvice", "Session Advice:", x + 10, y + 231, InpTextColor, 8);
   CreateLabel(g_prefix + "V_SessAdvice", "ANALYZING...", x + 10, y + 249, clrLime, 8, true);

   CreateLabel(g_prefix + "L_OpenPos", "--- TRADING STATS & FILTERS ---", x + 10, y + 274, clrGray, 8, true);
   CreateLabel(g_prefix + "L_ActiveOrders", "Active Trades:", x + 10, y + 291, InpTextColor, 8);
   CreateLabel(g_prefix + "V_ActiveOrders", "0", x + 130, y + 291, InpTextColor, 8, true);
   CreateLabel(g_prefix + "L_Spread", "Current Spread:", x + 10, y + 309, InpTextColor, 8);
   CreateLabel(g_prefix + "V_Spread", "0.0 Pips", x + 130, y + 309, InpTextColor, 8, true);
   CreateLabel(g_prefix + "L_MarginLevel", "Margin Level:", x + 10, y + 327, InpTextColor, 8);
   CreateLabel(g_prefix + "V_MarginLevel", "0.00%", x + 130, y + 327, InpTextColor, 8, true);

   CreateLabel(g_prefix + "L_RecHeader", "--- AI / ALGO RECOMMENDATION ---", x + 10, y + 352, clrGray, 8, true);
   CreateLabel(g_prefix + "V_Recommendation", "ANALYZING MARKET...", x + 10, y + 372, clrGold, 8, true);

   CreateButton(g_prefix + "Btn_Toggle", "[ SWITCH: EA ON ]", x + 10, y + 460, 275, 30, clrDarkGreen, clrWhite);
}

void UpdateDashboard()
{
   double realizedToday = GetTodayClosedProfit();
   double floatingPL    = AccountInfoDouble(ACCOUNT_PROFIT);
   int openTrades       = GetOpenPositionsCount();
   double marginLevel   = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL);

   double pipSize = (_Digits == 3 || _Digits == 5) ? _Point * 10.0 : _Point;
   double currentSpread = (SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID)) / pipSize;

   SetText(g_prefix + "V_Balance", "$" + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2));
   SetText(g_prefix + "V_Equity", "$" + DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2));
   SetText(g_prefix + "V_Realized", "$" + DoubleToString(realizedToday, 2));
   ObjectSetInteger(0, g_prefix + "V_Realized", OBJPROP_COLOR, (realizedToday >= 0) ? InpProfitColor : InpLossColor);

   SetText(g_prefix + "V_Target", "$" + DoubleToString(GetDailyTargetUSD(), 2));

   SetText(g_prefix + "V_Floating", "$" + DoubleToString(floatingPL, 2));
   ObjectSetInteger(0, g_prefix + "V_Floating", OBJPROP_COLOR, (floatingPL >= 0) ? InpProfitColor : InpLossColor);

   string sessionStr = "";
   IsActiveSession(sessionStr);
   SetText(g_prefix + "V_ActiveSession", sessionStr);

   color adviceColor = clrWhite;
   string adviceText = GetSessionTechnicalAdvice(adviceColor);
   SetText(g_prefix + "V_SessAdvice", adviceText);
   ObjectSetInteger(0, g_prefix + "V_SessAdvice", OBJPROP_COLOR, adviceColor);

   if(g_stopTradeActive || g_manualButtonOff)
   {
      SetText(g_prefix + "V_Status", "STOPPED (" + g_stopReason + ")");
      ObjectSetInteger(0, g_prefix + "V_Status", OBJPROP_COLOR, clrRed);
   }
   else
   {
      SetText(g_prefix + "V_Status", "ACTIVE (TRADING)");
      ObjectSetInteger(0, g_prefix + "V_Status", OBJPROP_COLOR, clrLime);
   }

   SetText(g_prefix + "V_ActiveOrders", IntegerToString(openTrades));
   SetText(g_prefix + "V_Spread", DoubleToString(currentSpread, 1) + " Pips");
   ObjectSetInteger(0, g_prefix + "V_Spread", OBJPROP_COLOR, IsSpreadOK() ? clrLime : clrRed);

   SetText(g_prefix + "V_MarginLevel", DoubleToString(marginLevel, 2) + "%");

   color recColor = clrWhite;
   string recText = GetMarketRecommendation(recColor);
   SetText(g_prefix + "V_Recommendation", recText);
   ObjectSetInteger(0, g_prefix + "V_Recommendation", OBJPROP_COLOR, recColor);

   if(g_manualButtonOff)
   {
      ObjectSetString(0, g_prefix + "Btn_Toggle", OBJPROP_TEXT, "[ SWITCH: EA OFF ]");
      ObjectSetInteger(0, g_prefix + "Btn_Toggle", OBJPROP_BGCOLOR, clrMaroon);
   }
   else
   {
      ObjectSetString(0, g_prefix + "Btn_Toggle", OBJPROP_TEXT, "[ SWITCH: EA ON ]");
      ObjectSetInteger(0, g_prefix + "Btn_Toggle", OBJPROP_BGCOLOR, clrDarkGreen);
   }

   ChartRedraw();
}

void CreateRectLabel(string name, int x, int y, int w, int h, color bg)
{
   if(ObjectFind(0, name) < 0)
   {
      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, w);
      ObjectSetInteger(0, name, OBJPROP_YSIZE, h);
      ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg);
      ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
      ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, name, OBJPROP_BACK, false);
   }
}

void CreateLabel(string name, string text, int x, int y, color clr, int font_size = 8, bool bold = false)
{
   if(ObjectFind(0, name) < 0)
   {
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
      ObjectSetString(0, name, OBJPROP_TEXT, text);
      ObjectSetString(0, name, OBJPROP_FONT, bold ? "Arial Bold" : "Arial");
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, font_size);
      ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
      ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
      ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
      ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   }
}

void CreateButton(string name, string text, int x, int y, int w, int h, color bg, color textClr)
{
   if(ObjectFind(0, name) < 0)
   {
      ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
      ObjectSetString(0, name, OBJPROP_TEXT, text);
      ObjectSetString(0, name, OBJPROP_FONT, "Arial Bold");
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9);
      ObjectSetInteger(0, name, OBJPROP_COLOR, textClr);
      ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg);
      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_CORNER, CORNER_LEFT_UPPER);
      ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   }
}

void SetText(string name, string text)
{
   ObjectSetString(0, name, OBJPROP_TEXT, text);
}

30,700 chars · codepastes.com