Scan to open on your phone
Point a camera at the QR code - it opens this exact paste, no app needed.
https://codepastes.com/zzgsz18jzz0b4rmeuntitledPlain Text
//+------------------------------------------------------------------+
//| EA_Grid_Fibo_NewsFilter_MT5.mq5 |
//| Copyright 2026, Algorithmic Dev |
//+------------------------------------------------------------------+
#property copyright "Algorithmic Dev"
#property link ""
#property version "3.30"
#include <Trade\Trade.mqh>
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 double InpRSISellMin = 65.0; // Sell 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") < 0)
Print("PERINGATAN: EA dioptimalkan untuk XAUUSD. Simbol ", _Symbol, " mungkin tidak cocok (grid step dalam satuan harga).");
EventSetTimer(1);
InitDashboardUI();
UpdateDashboard();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
if(g_handleATR != INVALID_HANDLE) IndicatorRelease(g_handleATR);
if(g_handleEMA != INVALID_HANDLE) IndicatorRelease(g_handleEMA);
if(g_handleRSI != INVALID_HANDLE) IndicatorRelease(g_handleRSI);
if(g_handleADX != INVALID_HANDLE) IndicatorRelease(g_handleADX);
ObjectsDeleteAll(0, g_prefix);
}
//+------------------------------------------------------------------+
//| Expert timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
UpdateDashboard();
}
//+------------------------------------------------------------------+
//| Chart Event Function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_OBJECT_CLICK)
{
if(sparam == g_prefix + "Btn_Toggle")
{
g_manualButtonOff = !g_manualButtonOff;
ObjectSetInteger(0, g_prefix + "Btn_Toggle", OBJPROP_STATE, false);
UpdateDashboard();
}
}
}
//+------------------------------------------------------------------+
//| Dynamic Target & Risk Value Getters |
//+------------------------------------------------------------------+
double GetDailyTargetUSD()
{
if(InpUsePercentageTarget)
return AccountInfoDouble(ACCOUNT_BALANCE) * (InpDailyTargetPercent / 100.0);
return InpDailyTargetUSD;
}
double GetBasketTPUSD()
{
if(InpUsePercentageTarget)
return AccountInfoDouble(ACCOUNT_BALANCE) * (InpBasketTPPercent / 100.0);
return InpBasketTPUSD;
}
double GetBasketSLUSD()
{
// v3.10: SL kini mengikuti mode persen bila InpUsePercentageTarget aktif
if(InpUsePercentageTarget)
return AccountInfoDouble(ACCOUNT_BALANCE) * (InpBasketSLPercent / 100.0);
return InpBasketSLUSD;
}
//+------------------------------------------------------------------+
//| Helper Filters & Conditions |
//+------------------------------------------------------------------+
bool IsSpreadOK()
{
double pipSize = (_Digits == 3 || _Digits == 5) ? _Point * 10.0 : _Point;
double currentSpread = (SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID)) / pipSize;
return (currentSpread <= InpMaxSpreadPips);
}
bool IsRolloverTime()
{
if(!InpBlockRollover) return false;
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
if(InpRolloverStartHour > InpRolloverEndHour)
return (dt.hour >= InpRolloverStartHour || dt.hour < InpRolloverEndHour);
return (dt.hour >= InpRolloverStartHour && dt.hour < InpRolloverEndHour);
}
bool IsFridayStop()
{
if(!InpUseFridayProtection) return false;
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
return (dt.day_of_week == 5 && dt.hour >= InpFridayStopHour);
}
//+------------------------------------------------------------------+
//| Feature 1: Trailing Basket Profit Logic |
//+------------------------------------------------------------------+
void CheckTrailingBasket(double totalFloating)
{
if(!InpUseTrailingBasket || totalFloating <= 0)
{
g_basketHighProfit = 0.0;
return;
}
double startUSD = InpTrailingStartUSD;
double stepUSD = InpTrailingStepUSD;
if(InpUsePercentageTarget)
{
double bal = AccountInfoDouble(ACCOUNT_BALANCE);
startUSD = bal * (InpTrailingStartPercent / 100.0);
stepUSD = bal * (InpTrailingStepPercent / 100.0);
}
if(totalFloating >= startUSD)
{
if(totalFloating > g_basketHighProfit)
g_basketHighProfit = totalFloating;
double lockFloor = g_basketHighProfit - stepUSD;
if(totalFloating <= lockFloor && lockFloor > 0)
{
CloseAllPositions();
g_basketHighProfit = 0.0;
}
}
}
//+------------------------------------------------------------------+
//| Feature 2: Smart Layer Reduction (Partial Close) |
//+------------------------------------------------------------------+
void CheckSmartLayerReduction()
{
if(!InpUseSmartReduction) return;
int openCount = GetOpenPositionsCount();
if(openCount < InpMinLayersForSmart) return;
ulong oldestTicket = 0, newestTicket = 0;
datetime oldestTime = D'2099.12.31', newestTime = 0;
for(int i = PositionsTotal() - 1; i >= 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 < oldestTime) { oldestTime = posTime; oldestTicket = ticket; }
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 < InpAsiaEndHour);
bool london = InpUseLondonSession && (h >= InpLondonStartHour && h < InpLondonEndHour);
bool us = InpUseUSSession && (h >= InpUSStartHour && h < InpUSEndHour);
string sessionStr = "";
if(asia) sessionStr += "[ASIA] ";
if(london) sessionStr += "[LONDON] ";
if(us) sessionStr += "[NY] ";
if(asia || london || us)
{
activeSessionName = sessionStr;
return true;
}
activeSessionName = "OFF-SESSION (PAUSED)";
return false;
}
//+------------------------------------------------------------------+
//| Modul Saran Teknikal Spesifik Sesi |
//+------------------------------------------------------------------+
string GetSessionTechnicalAdvice(color &adviceColor)
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
int h = dt.hour;
bool isAsia = (h >= InpAsiaStartHour && h < InpAsiaEndHour);
bool isLondon = (h >= InpLondonStartHour && h < InpLondonEndHour);
bool isUS = (h >= InpUSStartHour && h < InpUSEndHour);
if(isAsia)
{
adviceColor = clrLime;
return "ASIA: Range Scalping (Ideal Standard Grid)";
}
if(isLondon && isUS)
{
adviceColor = clrOrangeRed;
return "OVERLAP LDN-NY: Volatilitas Max (Target Cepat Hit)";
}
if(isLondon)
{
adviceColor = clrGold;
return "LONDON: Trend Breakout (Pantau Penambahan Layer)";
}
if(isUS)
{
adviceColor = clrOrange;
return "NEW YORK: High Volatility (Perhatikan Basket SL)";
}
adviceColor = clrGray;
return "OFF-SESSION: Sesi Tenang (Fokus Penyelesaian Grid)";
}
//+------------------------------------------------------------------+
//| Modul Sistem Rekomendasi Otomatis (Market Recommendation) |
//+------------------------------------------------------------------+
string GetMarketRecommendation(color &recommendedColor)
{
if(g_manualButtonOff)
{
recommendedColor = clrOrange;
return "EA PAUSED MANUALLY. TURN ON TO RESUME.";
}
if(!IsSpreadOK())
{
recommendedColor = clrRed;
return "HIGH SPREAD DETECTED. ENTRY PAUSED.";
}
if(IsRolloverTime())
{
recommendedColor = clrOrange;
return "ROLLOVER PERIOD. ENTRY PAUSED.";
}
if(IsFridayStop())
{
recommendedColor = clrGold;
return "FRIDAY FILTER ACTIVE. NO NEW GRIDS.";
}
if(IsNewsTime())
{
recommendedColor = clrRed;
return "HIGH IMPACT NEWS NEARBY. HOLD NEW GRIDS.";
}
// v3.20: status cooldown antar basket
if(GetOpenPositionsCount() == 0 && g_lastBasketCloseTime > 0 &&
(TimeCurrent() - g_lastBasketCloseTime) < InpBasketCooldownMins * 60)
{
recommendedColor = clrGold;
return "COOLDOWN AFTER BASKET CLOSE. WAITING.";
}
string sessionName = "";
if(!IsActiveSession(sessionName))
{
recommendedColor = clrGold;
return "OUTSIDE TRADING SESSION. WAIT FOR OPEN.";
}
double floatingPL = AccountInfoDouble(ACCOUNT_PROFIT);
double maxSL = GetBasketSLUSD();
if(maxSL > 0 && floatingPL <= -(maxSL * 0.6))
{
recommendedColor = clrRed;
return "HIGH DRAWDOWN RISK! MONITOR CLOSELY.";
}
int openCount = GetOpenPositionsCount();
if(openCount >= 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 < 30) return isNews;
lastCheck = TimeCurrent();
datetime fromTime = TimeCurrent() - (InpNewsAfterMins * 60);
datetime toTime = TimeCurrent() + (InpNewsBeforeMins * 60);
MqlCalendarValue values[];
int count = CalendarValueHistory(values, fromTime, toTime, NULL, NULL);
if(count > 0)
{
for(int i = 0; i < count; i++)
{
MqlCalendarEvent event;
if(CalendarEventById(values[i].event_id, event))
{
MqlCalendarCountry country;
if(CalendarCountryById(event.country_id, country))
{
string curr = country.currency;
string sym = _Symbol;
if(StringFind(sym, curr) >= 0 || (curr == "USD" && String20,000 chars · codepastes.com