Vizion-Trading-EA/Experts/gptt3.mq5
2026-02-19 23:19:25 -06:00

1836 lines
No EOL
127 KiB
MQL5

//+------------------------------------------------------------------+
//| QuarterTheory_MFIB_Enhanced.mq5 |
//| MFIB 0.32 + EMA14 Magnet + Stoch Confirmations + Labels |
//| Aggressive Multi-Setup System with Smart Filtering |
//+------------------------------------------------------------------+
#property copyright "MFIB Enhanced System"
#property version "16.00"
#property strict
#include <Trade/Trade.mqh>
CTrade Trade;
//================ INPUT PARAMETERS ==================//
input group "=== GENERAL ==="
input int MagicNumber = 456789;
input double Risk_Per_Trade = 1.2;
input int Min_Active_Entries = 4; // Changed to 4 minimum
input int Max_Simultaneous_Trades = 20;
input group "=== SYMBOL-SPECIFIC RATIOS (AUTO-DETECT) ==="
input bool Use_Auto_Symbol_Config = true; // Auto-configure based on symbol
// Manual overrides (used if Auto_Symbol_Config = false)
input int Manual_SL_Points = 800;
input int Manual_TP_Points = 5000;
input double Manual_RR_Ratio = 6.25;
input group "=== MOVING FIBS (PRIMARY!) ==="
input int MFIB_Lookback = 200;
input bool Show_MFIB_Levels = true;
input int MFIB_Touch_Buffer = 30; // Buffer in points for level detection
input bool Require_MFIB_Interaction = true; // No MFIB = no trade
input group "=== MA MAGNET SYSTEM ==="
input int MA_1 = 7; // Trigger
input int MA_2 = 14; // MAGNET (Core)
input int MA_3 = 21; // Structure
input int MA_4 = 50; // Structure
input int MA_5 = 140; // Flow
input int MA_6 = 230; // Mean
input int MA_7 = 500; // Macro
input int MA_8 = 1000;
input int MA_9 = 1100;
input int MA_10 = 1400; // Gravity
input int MA_Touch_Buffer = 30;
input int Min_MA14_Crosses = 1; // Using MA14 as primary now
input group "=== STOCHASTIC CONFIRMATION ==="
input int Stoch_K_Period = 5;
input int Stoch_D_Period = 3;
input int Stoch_Slowing = 3;
input bool Use_Stoch_Confirmation = true;
input group "=== TRADE SETUP FILTERS ==="
input bool Allow_Structural_Bounce = true; // Setup 1
input bool Allow_Structural_Break = true; // Setup 2
input bool Allow_Magnet_Snapback = true; // Setup 3
input bool Allow_MFIB_Continuation = true; // Setup 4
input bool Allow_Failed_Break = true; // Setup 5
input bool Allow_Triple_Confluence = true; // Setup 6
input bool Filter_Dead_Zones = true; // Block chop zones
input group "=== RISK MANAGEMENT (800pts → 5000pts) ==="
input double Risk_Reward_Ratio = 6.25; // 800 pts risk → 5000 pts profit
input bool Use_Fib_Based_SLTP = true; // SL/TP to nearest Fib
input int Default_SL_Points = 800; // Default SL distance
input int Default_TP_Points = 5000; // Default TP distance
input int Move_BE_At_Points = 300; // Move to BE
input int Trailing_SL_Points = 500; // Trailing distance
input double Partial_TP_Percent = 25.0; // Close 25% per hit
input group "=== DAILY LIMITS ==="
input double Max_Daily_Loss_Percent = 5.0;
input double Max_Daily_Profit_Percent = 30.0;
input int Max_Trades_Per_Day = 40;
//================ GLOBALS ==================//
int Stoch_Handle;
double Stoch_K_Current = 0;
double Stoch_K_Previous = 0;
double Stoch_K_Old = 0;
// Symbol-specific settings (auto-configured)
int Symbol_SL_Points = 800;
int Symbol_TP_Points = 5000;
double Symbol_RR_Ratio = 6.25;
string Symbol_Type = "UNKNOWN";
// MFIB System
double MFIB_ATH = 0;
double MFIB_ATL = 0;
double MFIB_032 = 0; // Key structural level
double MFIB_0236 = 0;
double MFIB_05 = 0;
double MFIB_0618 = 0;
double MFIB_0786 = 0;
bool MFIB_Bull_Mode = false;
bool MFIB_Bear_Mode = false;
datetime Last_MFIB_Calc = 0;
int MA_Handles[10];
double MA_Current[10];
double MA_Previous[10];
double MA_Old[10];
bool Current_Trend_Bullish = false;
bool Current_Trend_Bearish = false;
bool Previous_Trend_Bullish = false;
bool Previous_Trend_Bearish = false;
datetime Last_Trend_Check = 0;
// MA Retest tracking
datetime Last_MA_Retest_Time = 0;
int Retest_Cooldown = 60; // Seconds between retest entries
// RE-ENTRY TRACKING (After SL hit or BE stopped out)
struct ReEntryOpportunity
{
ulong original_ticket;
bool was_buy;
double exit_price;
double original_entry;
datetime exit_time;
string exit_reason;
bool re_entered;
int re_entry_attempts;
};
ReEntryOpportunity ReEntryQueue[];
input group "=== RE-ENTRY SYSTEM ==="
input bool Enable_ReEntry = true; // Re-enter after SL/BE if setup still valid
input int ReEntry_Max_Attempts = 2; // Max re-entries per original trade
input int ReEntry_Cooldown = 30; // Seconds before re-entry allowed
input bool ReEntry_After_SL = true; // Re-enter after stop loss hit
input bool ReEntry_After_BE = true; // Re-enter after BE stop hit
input bool Require_Stronger_Signal = true; // Need stronger confirmation for re-entry
struct Position
{
ulong ticket;
double entry;
double sl_level;
double tp_level;
double original_lot;
bool is_buy;
bool be_set;
int partials_closed;
string setup_type;
};
Position OpenPositions[];
double DailyStart = 0;
int TodayTrades = 0;
datetime LastDay = 0;
//+------------------------------------------------------------------+
//| AUTO-CONFIGURE SYMBOL-SPECIFIC PARAMETERS
//+------------------------------------------------------------------+
void ConfigureSymbolSettings()
{
string symbol = _Symbol;
if(!Use_Auto_Symbol_Config)
{
Symbol_SL_Points = Manual_SL_Points;
Symbol_TP_Points = Manual_TP_Points;
Symbol_RR_Ratio = Manual_RR_Ratio;
Symbol_Type = "MANUAL";
Print("Using MANUAL configuration: SL=", Symbol_SL_Points, " TP=", Symbol_TP_Points);
return;
}
// GOLD (XAUUSD) - Avg daily range: 2000-3000 pips
if(StringFind(symbol, "XAU") >= 0 || StringFind(symbol, "GOLD") >= 0)
{
Symbol_Type = "GOLD";
Symbol_SL_Points = 500; // $5 risk
Symbol_TP_Points = 3500; // $35 target (1:7 RR)
Symbol_RR_Ratio = 7.0;
Print("GOLD detected: SL=500pts ($5) TP=3500pts ($35) RR=1:7");
}
// US30 (Dow Jones) - Avg daily range: 400-800 points
else if(StringFind(symbol, "US30") >= 0 || StringFind(symbol, "DOW") >= 0)
{
Symbol_Type = "US30";
Symbol_SL_Points = 150; // 150 pts risk
Symbol_TP_Points = 1000; // 1000 pts target (1:6.67 RR)
Symbol_RR_Ratio = 6.67;
Print("US30 detected: SL=150pts TP=1000pts RR=1:6.67");
}
// NAS100 (Nasdaq) - Avg daily range: 500-1000 points
else if(StringFind(symbol, "NAS") >= 0 || StringFind(symbol, "NDX") >= 0)
{
Symbol_Type = "NAS100";
Symbol_SL_Points = 200; // 200 pts risk
Symbol_TP_Points = 1400; // 1400 pts target (1:7 RR)
Symbol_RR_Ratio = 7.0;
Print("NAS100 detected: SL=200pts TP=1400pts RR=1:7");
}
// OIL (USOIL/UKOIL) - Avg daily range: 150-300 pips
else if(StringFind(symbol, "OIL") >= 0 || StringFind(symbol, "WTI") >= 0 || StringFind(symbol, "BRENT") >= 0)
{
Symbol_Type = "OIL";
Symbol_SL_Points = 80; // 80 pips risk
Symbol_TP_Points = 600; // 600 pips target (1:7.5 RR)
Symbol_RR_Ratio = 7.5;
Print("OIL detected: SL=80pts TP=600pts RR=1:7.5");
}
// MAJOR FOREX (EUR, GBP, AUD, NZD vs USD) - Avg daily range: 80-150 pips
else if(StringFind(symbol, "EUR") >= 0 || StringFind(symbol, "GBP") >= 0 ||
StringFind(symbol, "AUD") >= 0 || StringFind(symbol, "NZD") >= 0)
{
Symbol_Type = "FOREX_MAJOR";
Symbol_SL_Points = 50; // 50 pips risk
Symbol_TP_Points = 350; // 350 pips target (1:7 RR)
Symbol_RR_Ratio = 7.0;
Print("FOREX MAJOR detected: SL=50pts TP=350pts RR=1:7");
}
// COMMODITY FOREX (USD/CAD, NZD/CAD, etc.) - Avg daily range: 60-120 pips
else if(StringFind(symbol, "CAD") >= 0 || StringFind(symbol, "CHF") >= 0)
{
Symbol_Type = "FOREX_COMMODITY";
Symbol_SL_Points = 40; // 40 pips risk
Symbol_TP_Points = 300; // 300 pips target (1:7.5 RR)
Symbol_RR_Ratio = 7.5;
Print("FOREX COMMODITY detected: SL=40pts TP=300pts RR=1:7.5");
}
// YEN PAIRS (USD/JPY, EUR/JPY, etc.) - Avg daily range: 80-150 pips
else if(StringFind(symbol, "JPY") >= 0)
{
Symbol_Type = "FOREX_YEN";
Symbol_SL_Points = 60; // 60 pips risk
Symbol_TP_Points = 450; // 450 pips target (1:7.5 RR)
Symbol_RR_Ratio = 7.5;
Print("YEN PAIR detected: SL=60pts TP=450pts RR=1:7.5");
}
// CRYPTO (BTC, ETH, etc.) - Avg daily range: 1000-3000 points
else if(StringFind(symbol, "BTC") >= 0 || StringFind(symbol, "ETH") >= 0)
{
Symbol_Type = "CRYPTO";
Symbol_SL_Points = 800; // 800 pts risk
Symbol_TP_Points = 6000; // 6000 pts target (1:7.5 RR)
Symbol_RR_Ratio = 7.5;
Print("CRYPTO detected: SL=800pts TP=6000pts RR=1:7.5");
}
// DEFAULT (Unknown symbol) - Conservative
else
{
Symbol_Type = "DEFAULT";
Symbol_SL_Points = 800;
Symbol_TP_Points = 5000;
Symbol_RR_Ratio = 6.25;
Print("DEFAULT configuration: SL=800pts TP=5000pts RR=1:6.25");
}
}
//+------------------------------------------------------------------+
int OnInit()
{
Print("========================================");
Print("MFIB ENHANCED SYSTEM v16.0");
Print("AGGRESSIVE + SMART RETESTS");
Print("========================================");
// Configure symbol-specific settings
ConfigureSymbolSettings();
Trade.SetExpertMagicNumber(MagicNumber);
Trade.SetDeviationInPoints(50);
Stoch_Handle = iStochastic(_Symbol, PERIOD_CURRENT, Stoch_K_Period, Stoch_D_Period,
Stoch_Slowing, MODE_SMA, STO_LOWHIGH);
if(Stoch_Handle == INVALID_HANDLE)
{
Print("ERROR: Stochastic failed");
return INIT_FAILED;
}
int periods[10] = {MA_1, MA_2, MA_3, MA_4, MA_5, MA_6, MA_7, MA_8, MA_9, MA_10};
for(int i=0; i<10; i++)
{
MA_Handles[i] = iMA(_Symbol, PERIOD_CURRENT, periods[i], 0, MODE_EMA, PRICE_CLOSE);
if(MA_Handles[i] == INVALID_HANDLE)
{
Print("ERROR: MA ", periods[i], " failed");
return INIT_FAILED;
}
}
CalculateMFIB();
if(Show_MFIB_Levels) DrawMFIBLevels();
DailyStart = AccountInfoDouble(ACCOUNT_BALANCE);
Print("Symbol Type: ", Symbol_Type);
Print("Risk:Reward = 1:", Symbol_RR_Ratio);
Print("SL: ", Symbol_SL_Points, " pts | TP: ", Symbol_TP_Points, " pts");
Print("MFIB 0.32 Level: ", MFIB_032);
Print("EMA14 Magnet + MA Retest: ENABLED");
Print("Min Active Entries: ", Min_Active_Entries);
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
for(int i=0; i<10; i++)
if(MA_Handles[i] != INVALID_HANDLE)
IndicatorRelease(MA_Handles[i]);
if(Stoch_Handle != INVALID_HANDLE)
IndicatorRelease(Stoch_Handle);
ObjectsDeleteAll(0, "MFIB_");
ObjectsDeleteAll(0, "Arrow_");
ObjectsDeleteAll(0, "Label_");
}
//+------------------------------------------------------------------+
//| CALCULATE MOVING FIBS (MFIB)
//+------------------------------------------------------------------+
void CalculateMFIB()
{
// Find ATH and ATL over lookback period
MFIB_ATH = iHigh(_Symbol, PERIOD_CURRENT, 0);
MFIB_ATL = iLow(_Symbol, PERIOD_CURRENT, 0);
for(int i=1; i<=MFIB_Lookback; i++)
{
double h = iHigh(_Symbol, PERIOD_CURRENT, i);
double l = iLow(_Symbol, PERIOD_CURRENT, i);
if(h > MFIB_ATH) MFIB_ATH = h;
if(l < MFIB_ATL) MFIB_ATL = l;
}
double range = MFIB_ATH - MFIB_ATL;
// Calculate key Fib levels (Bull Fib: ATL → ATH)
MFIB_0236 = MFIB_ATL + range * 0.236;
MFIB_032 = MFIB_ATL + range * 0.382; // KEY STRUCTURAL LEVEL
MFIB_05 = MFIB_ATL + range * 0.5;
MFIB_0618 = MFIB_ATL + range * 0.618;
MFIB_0786 = MFIB_ATL + range * 0.786;
// Determine MFIB Mode
double current = (SymbolInfoDouble(_Symbol, SYMBOL_BID) + SymbolInfoDouble(_Symbol, SYMBOL_ASK)) / 2;
if(current > MFIB_032)
MFIB_Bull_Mode = true;
else
MFIB_Bull_Mode = false;
if(current < MFIB_032)
MFIB_Bear_Mode = true;
else
MFIB_Bear_Mode = false;
}
void DrawMFIBLevels()
{
ObjectsDeleteAll(0, "MFIB_");
// Draw key MFIB levels
CreateHLine("MFIB_ATH", MFIB_ATH, clrWhite, STYLE_SOLID, 2, "ATH");
CreateHLine("MFIB_ATL", MFIB_ATL, clrWhite, STYLE_SOLID, 2, "ATL");
CreateHLine("MFIB_0786", MFIB_0786, clrDodgerBlue, STYLE_DOT, 1, "0.786");
CreateHLine("MFIB_0618", MFIB_0618, clrDodgerBlue, STYLE_DOT, 1, "0.618");
CreateHLine("MFIB_05", MFIB_05, clrYellow, STYLE_DOT, 1, "0.5");
CreateHLine("MFIB_032", MFIB_032, clrRed, STYLE_SOLID, 3, "0.32 KEY"); // Most important
CreateHLine("MFIB_0236", MFIB_0236, clrDodgerBlue, STYLE_DOT, 1, "0.236");
}
void CreateHLine(string name, double price, color clr, ENUM_LINE_STYLE style, int width, string label)
{
ObjectCreate(0, name, OBJ_HLINE, 0, 0, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
ObjectSetString(0, name, OBJPROP_TEXT, label);
}
//+------------------------------------------------------------------+
void UpdateMAs()
{
for(int i=0; i<10; i++)
{
MA_Old[i] = MA_Previous[i];
MA_Previous[i] = MA_Current[i];
double curr[1];
if(CopyBuffer(MA_Handles[i], 0, 0, 1, curr) > 0)
MA_Current[i] = curr[0];
}
}
void UpdateStochastic()
{
Stoch_K_Old = Stoch_K_Previous;
Stoch_K_Previous = Stoch_K_Current;
double k_curr[1];
if(CopyBuffer(Stoch_Handle, MAIN_LINE, 0, 1, k_curr) > 0)
Stoch_K_Current = k_curr[0];
}
//+------------------------------------------------------------------+
//| MFIB DETECTION FUNCTIONS
//+------------------------------------------------------------------+
bool IsPriceAtMFIB032(double price)
{
double buffer = MFIB_Touch_Buffer * _Point;
return (MathAbs(price - MFIB_032) <= buffer);
}
string GetMFIBLabel(double price, bool is_bullish)
{
if(!IsPriceAtMFIB032(price)) return "";
if(is_bullish)
{
if(price > MFIB_032)
return "MFIB 0.32 SUPPORT";
else if(price <= MFIB_032 && MA_Current[1] > MFIB_032) // EMA14 above
return "MFIB 0.32 RECLAIM";
}
else
{
if(price < MFIB_032)
return "MFIB 0.32 RESIST";
else if(price >= MFIB_032 && MA_Current[1] < MFIB_032) // EMA14 below
return "MFIB 0.32 REJECT";
}
return "MFIB 0.32 TEST";
}
bool IsMFIBStaircase(bool check_bullish)
{
// Check if price is making higher lows (bull) or lower highs (bear) at MFIB levels
double close_curr = iClose(_Symbol, PERIOD_CURRENT, 0);
double close_prev = iClose(_Symbol, PERIOD_CURRENT, 1);
double close_old = iClose(_Symbol, PERIOD_CURRENT, 2);
if(check_bullish)
return (close_curr > close_prev && close_prev > close_old && MFIB_Bull_Mode);
else
return (close_curr < close_prev && close_prev < close_old && MFIB_Bear_Mode);
}
//+------------------------------------------------------------------+
//| EMA14 MAGNET DETECTION
//+------------------------------------------------------------------+
bool IsPriceAtEMA14(double price)
{
double buffer = MA_Touch_Buffer * _Point;
return (MathAbs(price - MA_Current[1]) <= buffer); // MA_Current[1] = EMA14
}
string GetEMA14Label(double price, bool is_bullish)
{
if(!IsPriceAtEMA14(price)) return "";
double ema14 = MA_Current[1];
double ema14_prev = MA_Previous[1];
if(is_bullish)
{
if(price > ema14 && ema14 > ema14_prev)
return "EMA14 MAGNET HOLD";
else if(price >= ema14 && MA_Previous[1] < ema14)
return "EMA14 MAGNET RECLAIM";
else if(MathAbs(price - ema14) < 50 * _Point)
return "EMA14 COILED SPRING";
}
else
{
if(price < ema14 && ema14 < ema14_prev)
return "EMA14 MAGNET REJECT";
else if(price > ema14 * 1.01) // Extended far from EMA14
return "EMA14 SNAPBACK";
}
return "EMA14 TEST";
}
bool IsMicroBullAlign()
{
// 7 > 14 > 21
return (MA_Current[0] > MA_Current[1] && MA_Current[1] > MA_Current[2]);
}
bool IsMicroBearAlign()
{
// 7 < 14 < 21
return (MA_Current[0] < MA_Current[1] && MA_Current[1] < MA_Current[2]);
}
int CountMA14Crosses(bool check_bullish)
{
int crosses = 0;
// Count how many MAs the EMA14 has crossed
for(int i=2; i<6; i++) // Check against 21, 50, 140, 230
{
if(check_bullish && MA_Current[1] > MA_Current[i])
crosses++;
else if(!check_bullish && MA_Current[1] < MA_Current[i])
crosses++;
}
return crosses;
}
//+------------------------------------------------------------------+
//| STOCHASTIC LABELS
//+------------------------------------------------------------------+
string GetStochLabel(bool is_bullish)
{
if(is_bullish)
{
if(Stoch_K_Current >= 20 && Stoch_K_Current <= 30)
return "STOCH OS HOLD";
else if(Stoch_K_Current >= 40 && Stoch_K_Current <= 50 && Stoch_K_Current > Stoch_K_Previous)
return "STOCH BULL RESET";
else if(Stoch_K_Current >= 50 && Stoch_K_Current > Stoch_K_Previous)
return "STOCH 50 HOLD";
else if(Stoch_K_Current < 70)
return "STOCH STRUCTURAL CONFIRM";
}
else
{
if(Stoch_K_Current >= 80 && Stoch_K_Current <= 100)
return "STOCH OB REJECT";
else if(Stoch_K_Current >= 50 && Stoch_K_Current <= 60 && Stoch_K_Current < Stoch_K_Previous)
return "STOCH BEAR RESET";
else if(Stoch_K_Current <= 50 && Stoch_K_Current < Stoch_K_Previous)
return "STOCH 50 FAIL";
else if(Stoch_K_Current > 30)
return "STOCH STRUCTURAL FAIL";
}
return "STOCH NEUTRAL";
}
bool IsStochOversold()
{
return (Stoch_K_Current >= 20 && Stoch_K_Current <= 30);
}
bool IsStochOverbought()
{
return (Stoch_K_Current >= 80);
}
bool IsStochReset(bool check_bullish)
{
if(check_bullish)
return (Stoch_K_Old >= 80 && Stoch_K_Current >= 40 && Stoch_K_Current <= 50);
else
return (Stoch_K_Old <= 20 && Stoch_K_Current >= 50 && Stoch_K_Current <= 60);
}
//+------------------------------------------------------------------+
//| MA RETEST / PULLBACK DETECTION (Catches circled opportunities!)
//+------------------------------------------------------------------+
bool DetectMARetest(bool check_bullish, int &ma_index, string &retest_label)
{
// Check if we're in cooldown period
if(TimeCurrent() - Last_MA_Retest_Time < Retest_Cooldown)
return false;
double close_curr = iClose(_Symbol, PERIOD_CURRENT, 0);
double close_prev = iClose(_Symbol, PERIOD_CURRENT, 1);
double close_old = iClose(_Symbol, PERIOD_CURRENT, 2);
double high_curr = iHigh(_Symbol, PERIOD_CURRENT, 0);
double low_curr = iLow(_Symbol, PERIOD_CURRENT, 0);
// Check key MAs: 14, 21, 50, 140, 230
int test_mas[] = {1, 2, 3, 4, 5}; // MA indices to test
string ma_names[] = {"EMA14", "EMA21", "EMA50", "EMA140", "EMA230"};
for(int i=0; i<ArraySize(test_mas); i++)
{
int idx = test_mas[i];
double ma_value = MA_Current[idx];
double ma_prev = MA_Previous[idx];
double touch_buffer = MA_Touch_Buffer * _Point;
if(check_bullish)
{
// BULLISH RETEST:
// 1. Price was above MA
// 2. Price pulled back to touch/slightly below MA
// 3. Price is now bouncing back up
bool was_above = (close_old > ma_value + 50 * _Point);
bool touched_ma = (low_curr <= ma_value + touch_buffer && low_curr >= ma_value - touch_buffer);
bool bouncing = (close_curr > close_prev) || (close_curr > ma_value);
// Alternative: Price crossed below then reclaimed
bool crossed_below = (close_prev < ma_value && close_old > ma_value);
bool reclaimed = (close_curr > ma_value);
// Check if MA is sloping up (bullish)
bool ma_bullish = (ma_value > ma_prev);
if(ma_bullish && ((was_above && touched_ma && bouncing) || (crossed_below && reclaimed)))
{
ma_index = idx;
retest_label = ma_names[i] + " RETEST LONG";
Last_MA_Retest_Time = TimeCurrent();
return true;
}
}
else
{
// BEARISH RETEST:
// 1. Price was below MA
// 2. Price pulled back to touch/slightly above MA
// 3. Price is now rejecting back down
bool was_below = (close_old < ma_value - 50 * _Point);
bool touched_ma = (high_curr >= ma_value - touch_buffer && high_curr <= ma_value + touch_buffer);
bool rejecting = (close_curr < close_prev) || (close_curr < ma_value);
// Alternative: Price crossed above then rejected
bool crossed_above = (close_prev > ma_value && close_old < ma_value);
bool rejected = (close_curr < ma_value);
// Check if MA is sloping down (bearish)
bool ma_bearish = (ma_value < ma_prev);
if(ma_bearish && ((was_below && touched_ma && rejecting) || (crossed_above && rejected)))
{
ma_index = idx;
retest_label = ma_names[i] + " RETEST SHORT";
Last_MA_Retest_Time = TimeCurrent();
return true;
}
}
}
return false;
}
// Detect MA rejection (price hits MA and bounces hard)
bool DetectMAReject(bool check_bullish, string &reject_label)
{
double close_curr = iClose(_Symbol, PERIOD_CURRENT, 0);
double close_prev = iClose(_Symbol, PERIOD_CURRENT, 1);
double high_prev = iHigh(_Symbol, PERIOD_CURRENT, 1);
double low_prev = iLow(_Symbol, PERIOD_CURRENT, 1);
// Check rejection at EMA14, 21, 50
int test_mas[] = {1, 2, 3};
string ma_names[] = {"EMA14", "EMA21", "EMA50"};
for(int i=0; i<ArraySize(test_mas); i++)
{
int idx = test_mas[i];
double ma_value = MA_Current[idx];
if(check_bullish)
{
// Bullish rejection: Price dipped to MA and shot back up
double wick = high_prev - MathMax(iOpen(_Symbol, PERIOD_CURRENT, 1), close_prev);
double body = MathAbs(close_prev - iOpen(_Symbol, PERIOD_CURRENT, 1));
bool hit_ma = (low_prev <= ma_value + MA_Touch_Buffer * _Point);
bool strong_wick = (wick > body * 2);
bool bullish_close = (close_curr > ma_value);
if(hit_ma && strong_wick && bullish_close)
{
reject_label = ma_names[i] + " REJECT → LONG";
return true;
}
}
else
{
// Bearish rejection: Price spiked to MA and shot back down
double wick = MathMin(iOpen(_Symbol, PERIOD_CURRENT, 1), close_prev) - low_prev;
double body = MathAbs(close_prev - iOpen(_Symbol, PERIOD_CURRENT, 1));
bool hit_ma = (high_prev >= ma_value - MA_Touch_Buffer * _Point);
bool strong_wick = (wick > body * 2);
bool bearish_close = (close_curr < ma_value);
if(hit_ma && strong_wick && bearish_close)
{
reject_label = ma_names[i] + " REJECT → SHORT";
return true;
}
}
}
return false;
}
//+------------------------------------------------------------------+
//| DEAD ZONE DETECTION (with exceptions for strong confirmations)
//+------------------------------------------------------------------+
bool IsDeadZone()
{
if(!Filter_Dead_Zones) return false;
int dead_zone_score = 0; // Count how many dead zone conditions exist
// 1. MFIB whipsaw + MA chop
bool mfib_whipsaw = (IsPriceAtMFIB032(iClose(_Symbol, PERIOD_CURRENT, 0)) &&
IsPriceAtMFIB032(iClose(_Symbol, PERIOD_CURRENT, 1)));
// 2. EMA14 flat
double ema14_change = MathAbs(MA_Current[1] - MA_Previous[1]) / _Point;
bool ema14_flat = (ema14_change < 20);
// 3. Stoch in dead zone (40-60)
bool stoch_chop = (Stoch_K_Current >= 40 && Stoch_K_Current <= 60);
// 4. MFIB mode against EMA500
bool mode_conflict = false;
if(MFIB_Bull_Mode && MA_Current[1] < MA_Current[6]) // EMA14 below EMA500
mode_conflict = true;
if(MFIB_Bear_Mode && MA_Current[1] > MA_Current[6]) // EMA14 above EMA500
mode_conflict = true;
// Count dead zone conditions
if(mfib_whipsaw && ema14_flat) dead_zone_score += 2; // This combo is worst
if(ema14_flat && stoch_chop) dead_zone_score += 1;
if(mode_conflict) dead_zone_score += 2; // Mode conflict is serious
if(stoch_chop && !mfib_whipsaw) dead_zone_score += 1; // Stoch chop alone is minor
// CHECK FOR STRONG CONFIRMATIONS THAT OVERRIDE DEAD ZONES
bool has_strong_confirmations = false;
// Strong confirmation 1: Triple confluence (MFIB + EMA14 + Stoch extreme)
double current = (SymbolInfoDouble(_Symbol, SYMBOL_BID) + SymbolInfoDouble(_Symbol, SYMBOL_ASK)) / 2;
bool triple_confluence = IsPriceAtMFIB032(current) && IsPriceAtEMA14(current) &&
(Stoch_K_Current <= 25 || Stoch_K_Current >= 75);
// Strong confirmation 2: Fresh structural break with momentum
double close_curr = iClose(_Symbol, PERIOD_CURRENT, 0);
double close_prev = iClose(_Symbol, PERIOD_CURRENT, 1);
bool fresh_break = (MathAbs(close_curr - MFIB_032) < 50 * _Point) &&
(MathAbs(close_prev - MFIB_032) > 100 * _Point);
bool has_momentum = (Stoch_K_Current > Stoch_K_Previous + 5) ||
(Stoch_K_Current < Stoch_K_Previous - 5);
bool structural_break_momentum = fresh_break && has_momentum;
// Strong confirmation 3: Strong micro alignment (7-14-21 perfect stack)
bool perfect_bull_stack = (MA_Current[0] > MA_Current[1] + 30 * _Point) &&
(MA_Current[1] > MA_Current[2] + 30 * _Point);
bool perfect_bear_stack = (MA_Current[0] < MA_Current[1] - 30 * _Point) &&
(MA_Current[1] < MA_Current[2] - 30 * _Point);
bool perfect_micro_align = perfect_bull_stack || perfect_bear_stack;
// Strong confirmation 4: MFIB mode + Multiple MA alignment
bool strong_mode = (MFIB_Bull_Mode || MFIB_Bear_Mode);
int ma_alignment = 0;
for(int i=0; i<4; i++)
{
if(MFIB_Bull_Mode && MA_Current[i] > MA_Current[i+1])
ma_alignment++;
else if(MFIB_Bear_Mode && MA_Current[i] < MA_Current[i+1])
ma_alignment++;
}
bool strong_ma_alignment = (ma_alignment >= 3);
// Strong confirmation 5: Failed break (high probability reversal)
double close_old = iClose(_Symbol, PERIOD_CURRENT, 2);
bool failed_break_bull = (close_old > MFIB_032 && close_prev < MFIB_032 && close_curr > MFIB_032);
bool failed_break_bear = (close_old < MFIB_032 && close_prev > MFIB_032 && close_curr < MFIB_032);
bool failed_break = failed_break_bull || failed_break_bear;
// Count strong confirmations
if(triple_confluence) has_strong_confirmations = true;
if(structural_break_momentum) has_strong_confirmations = true;
if(perfect_micro_align && strong_mode) has_strong_confirmations = true;
if(strong_mode && strong_ma_alignment && !mode_conflict) has_strong_confirmations = true;
if(failed_break) has_strong_confirmations = true;
// DECISION LOGIC:
// - Score 0-1: Minor chop → Allow trade if ANY confirmation
// - Score 2-3: Moderate chop → Allow trade if STRONG confirmations
// - Score 4+: Severe chop → Block all trades
if(dead_zone_score >= 4)
{
UpdateStatusLabel("DEAD ZONE — SEVERE CHOP", clrRed);
return true; // Block all trades
}
if(dead_zone_score >= 2 && !has_strong_confirmations)
{
UpdateStatusLabel("DEAD ZONE — Waiting for Strong Signal", clrOrange);
return true; // Block weak trades
}
if(dead_zone_score == 1 && has_strong_confirmations)
{
UpdateStatusLabel("Minor Chop but Strong Confirmation", clrYellow);
return false; // Allow trade
}
// If we have strong confirmations, override minor dead zones
if(has_strong_confirmations && dead_zone_score <= 2)
{
UpdateStatusLabel("Dead Zone Override - Strong Setup", clrLime);
return false; // Allow trade
}
// Light dead zone with no confirmations
if(dead_zone_score > 0)
{
UpdateStatusLabel("DEAD ZONE — LOW CONFIDENCE", clrOrange);
return true;
}
return false; // Clear conditions
}
//+------------------------------------------------------------------+
//| TRADE SETUPS
//+------------------------------------------------------------------+
bool CheckSetup1_StructuralBounce(bool is_buy, string &setup_label)
{
if(!Allow_Structural_Bounce) return false;
double current = (SymbolInfoDouble(_Symbol, SYMBOL_BID) + SymbolInfoDouble(_Symbol, SYMBOL_ASK)) / 2;
bool at_mfib = IsPriceAtMFIB032(current);
bool at_ema14 = IsPriceAtEMA14(current);
bool stoch_ok = IsStochOversold() || IsStochReset(is_buy);
if(at_mfib && (at_ema14 || IsPriceAtHigherMA(current)) && stoch_ok)
{
setup_label = "STRUCTURAL BOUNCE";
return true;
}
return false;
}
bool CheckSetup2_StructuralBreak(bool is_buy, string &setup_label)
{
if(!Allow_Structural_Break) return false;
double close_curr = iClose(_Symbol, PERIOD_CURRENT, 0);
double close_prev = iClose(_Symbol, PERIOD_CURRENT, 1);
bool broke_mfib = false;
bool broke_ema14 = false;
bool held = false;
if(is_buy)
{
broke_mfib = (close_prev < MFIB_032 && close_curr > MFIB_032);
broke_ema14 = (close_prev < MA_Current[1] && close_curr > MA_Current[1]);
held = (close_curr > MFIB_032);
}
else
{
broke_mfib = (close_prev > MFIB_032 && close_curr < MFIB_032);
broke_ema14 = (close_prev > MA_Current[1] && close_curr < MA_Current[1]);
held = (close_curr < MFIB_032);
}
bool stoch_ok = is_buy ? (Stoch_K_Current > 50) : (Stoch_K_Current < 50);
if((broke_mfib || broke_ema14) && held && stoch_ok)
{
setup_label = "STRUCTURAL BREAK & HOLD";
return true;
}
return false;
}
bool CheckSetup3_MagnetSnapback(bool is_buy, string &setup_label)
{
if(!Allow_Magnet_Snapback) return false;
double current = (SymbolInfoDouble(_Symbol, SYMBOL_BID) + SymbolInfoDouble(_Symbol, SYMBOL_ASK)) / 2;
double ema14 = MA_Current[1];
bool extended = is_buy ? (current < ema14 * 0.99) : (current > ema14 * 1.01);
bool stoch_extreme = is_buy ? IsStochOversold() : IsStochOverbought();
bool returning = IsPriceAtEMA14(current) && IsPriceAtMFIB032(current);
if(extended && stoch_extreme && returning)
{
setup_label = "MAGNET SNAPBACK ENTRY";
return true;
}
return false;
}
bool CheckSetup4_MFIBContinuation(bool is_buy, string &setup_label)
{
if(!Allow_MFIB_Continuation) return false;
bool mode_ok = is_buy ? MFIB_Bull_Mode : MFIB_Bear_Mode;
bool ema14_respected = IsPriceAtEMA14(iClose(_Symbol, PERIOD_CURRENT, 0));
bool micro_align = is_buy ? IsMicroBullAlign() : IsMicroBearAlign();
bool stoch_reset = IsStochReset(is_buy);
if(mode_ok && ema14_respected && micro_align && stoch_reset)
{
setup_label = "MFIB MODE CONTINUATION";
return true;
}
return false;
}
bool CheckSetup5_FailedBreak(bool is_buy, string &setup_label)
{
if(!Allow_Failed_Break) return false;
double close_curr = iClose(_Symbol, PERIOD_CURRENT, 0);
double close_prev = iClose(_Symbol, PERIOD_CURRENT, 1);
double close_old = iClose(_Symbol, PERIOD_CURRENT, 2);
bool attempted_break = false;
bool failed = false;
bool stoch_crossed = false;
if(is_buy)
{
// Failed bearish break
attempted_break = (close_old > MFIB_032 && close_prev < MFIB_032);
failed = (close_curr > MFIB_032);
stoch_crossed = (Stoch_K_Previous < 50 && Stoch_K_Current > 50);
}
else
{
// Failed bullish break
attempted_break = (close_old < MFIB_032 && close_prev > MFIB_032);
failed = (close_curr < MFIB_032);
stoch_crossed = (Stoch_K_Previous > 50 && Stoch_K_Current < 50);
}
if(attempted_break && failed && stoch_crossed)
{
setup_label = "FAILED STRUCTURE BREAK";
return true;
}
return false;
}
bool CheckSetup6_TripleConfluence(bool is_buy, string &setup_label)
{
if(!Allow_Triple_Confluence) return false;
double current = (SymbolInfoDouble(_Symbol, SYMBOL_BID) + SymbolInfoDouble(_Symbol, SYMBOL_ASK)) / 2;
bool at_mfib = IsPriceAtMFIB032(current);
bool at_ema14 = IsPriceAtEMA14(current);
bool stoch_extreme = is_buy ? (Stoch_K_Current <= 20) : (Stoch_K_Current >= 80);
// Check for rejection candle
double body_size = MathAbs(iClose(_Symbol, PERIOD_CURRENT, 1) - iOpen(_Symbol, PERIOD_CURRENT, 1));
double wick_size = is_buy ?
(iHigh(_Symbol, PERIOD_CURRENT, 1) - MathMax(iOpen(_Symbol, PERIOD_CURRENT, 1), iClose(_Symbol, PERIOD_CURRENT, 1))) :
(MathMin(iOpen(_Symbol, PERIOD_CURRENT, 1), iClose(_Symbol, PERIOD_CURRENT, 1)) - iLow(_Symbol, PERIOD_CURRENT, 1));
bool rejection_candle = (wick_size > body_size * 1.5);
if(at_mfib && at_ema14 && stoch_extreme && rejection_candle)
{
setup_label = "TRIPLE LEVEL REJECT";
return true;
}
return false;
}
//+------------------------------------------------------------------+
bool IsPriceAtHigherMA(double price)
{
double buffer = MA_Touch_Buffer * _Point;
// Check MA50, MA140, MA230, MA500
int higher_mas[4] = {3, 4, 5, 6};
for(int i=0; i<4; i++)
{
int idx = higher_mas[i];
if(MathAbs(price - MA_Current[idx]) <= buffer)
return true;
}
return false;
}
//+------------------------------------------------------------------+
void UpdateStatusLabel(string status, color clr)
{
ObjectDelete(0, "Label_Status");
ObjectCreate(0, "Label_Status", OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, "Label_Status", OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, "Label_Status", OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, "Label_Status", OBJPROP_YDISTANCE, 60);
ObjectSetString(0, "Label_Status", OBJPROP_TEXT, status);
ObjectSetInteger(0, "Label_Status", OBJPROP_COLOR, clr);
ObjectSetInteger(0, "Label_Status", OBJPROP_FONTSIZE, 11);
}
void UpdateMFIBModeLabel()
{
ObjectDelete(0, "Label_MFIB_Mode");
ObjectCreate(0, "Label_MFIB_Mode", OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, "Label_MFIB_Mode", OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, "Label_MFIB_Mode", OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, "Label_MFIB_Mode", OBJPROP_YDISTANCE, 30);
if(MFIB_Bull_Mode)
{
ObjectSetString(0, "Label_MFIB_Mode", OBJPROP_TEXT, "MFIB: BULL MODE ↑");
ObjectSetInteger(0, "Label_MFIB_Mode", OBJPROP_COLOR, clrLime);
}
else if(MFIB_Bear_Mode)
{
ObjectSetString(0, "Label_MFIB_Mode", OBJPROP_TEXT, "MFIB: BEAR MODE ↓");
ObjectSetInteger(0, "Label_MFIB_Mode", OBJPROP_COLOR, clrRed);
}
else
{
ObjectSetString(0, "Label_MFIB_Mode", OBJPROP_TEXT, "MFIB: TRANSITION");
ObjectSetInteger(0, "Label_MFIB_Mode", OBJPROP_COLOR, clrYellow);
}
ObjectSetInteger(0, "Label_MFIB_Mode", OBJPROP_FONTSIZE, 12);
}
//+------------------------------------------------------------------+
void DetermineTrendBias()
{
UpdateMAs();
Previous_Trend_Bullish = Current_Trend_Bullish;
Previous_Trend_Bearish = Current_Trend_Bearish;
int bullish_alignment = 0;
int bearish_alignment = 0;
for(int i=0; i<6; i++)
{
if(i < 5 && MA_Current[i] > MA_Current[i+1])
bullish_alignment++;
if(i < 5 && MA_Current[i] < MA_Current[i+1])
bearish_alignment++;
}
bool ma14_above_ma50 = MA_Current[1] > MA_Current[3];
bool ma14_below_ma50 = MA_Current[1] < MA_Current[3];
if(bullish_alignment >= 3 && ma14_above_ma50)
{
Current_Trend_Bullish = true;
Current_Trend_Bearish = false;
}
else if(bearish_alignment >= 3 && ma14_below_ma50)
{
Current_Trend_Bullish = false;
Current_Trend_Bearish = true;
}
}
bool TrendReversed()
{
if(Previous_Trend_Bullish && Current_Trend_Bearish)
{
Print("===== TREND REVERSAL: BULL → BEAR =====");
return true;
}
if(Previous_Trend_Bearish && Current_Trend_Bullish)
{
Print("===== TREND REVERSAL: BEAR → BULL =====");
return true;
}
return false;
}
void CloseOppositeTrades(bool close_buys)
{
int closed = 0;
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((close_buys && type == POSITION_TYPE_BUY) ||
(!close_buys && type == POSITION_TYPE_SELL))
{
Trade.PositionClose(ticket);
closed++;
}
}
if(closed > 0)
Print("Closed ", closed, " opposite trades on reversal");
}
//+------------------------------------------------------------------+
double FindNearestFibLevel(double price, bool find_below)
{
double levels[] = {MFIB_ATL, MFIB_0236, MFIB_032, MFIB_05, MFIB_0618, MFIB_0786, MFIB_ATH};
double nearest = 0;
double min_distance = 999999;
for(int i=0; i<ArraySize(levels); i++)
{
double level = levels[i];
double distance = MathAbs(price - level);
if(find_below && level < price && distance < min_distance)
{
nearest = level;
min_distance = distance;
}
else if(!find_below && level > price && distance < min_distance)
{
nearest = level;
min_distance = distance;
}
}
return nearest;
}
void CalculateDynamicSLTP(double entry, bool is_buy, double &sl, double &tp)
{
if(Use_Fib_Based_SLTP)
{
sl = FindNearestFibLevel(entry, is_buy);
// If no Fib level found or too close, use symbol-specific SL
if(sl == 0 || MathAbs(entry - sl) / _Point < 100)
sl = is_buy ? entry - Symbol_SL_Points * _Point : entry + Symbol_SL_Points * _Point;
double sl_distance = MathAbs(entry - sl);
tp = is_buy ? entry + (sl_distance * Symbol_RR_Ratio)
: entry - (sl_distance * Symbol_RR_Ratio);
// Adjust TP to nearest Fib if close
double nearest_tp_fib = FindNearestFibLevel(entry, !is_buy);
if(nearest_tp_fib != 0)
{
double calculated_tp_dist = MathAbs(tp - entry);
double fib_tp_dist = MathAbs(nearest_tp_fib - entry);
// Only snap to Fib if within 15% and Fib level is further than minimum
if(MathAbs(calculated_tp_dist - fib_tp_dist) / calculated_tp_dist < 0.15 &&
fib_tp_dist >= Symbol_TP_Points * _Point * 0.8)
tp = nearest_tp_fib;
}
// Ensure minimum TP based on symbol
double min_tp_distance = Symbol_TP_Points * _Point;
if(MathAbs(tp - entry) < min_tp_distance)
tp = is_buy ? entry + min_tp_distance : entry - min_tp_distance;
}
else
{
// Fallback: use symbol-specific values
sl = is_buy ? entry - Symbol_SL_Points * _Point : entry + Symbol_SL_Points * _Point;
tp = is_buy ? entry + Symbol_TP_Points * _Point : entry - Symbol_TP_Points * _Point;
}
}
double GetLotSize(int sl_points)
{
double risk = AccountInfoDouble(ACCOUNT_BALANCE) * Risk_Per_Trade / 100.0;
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double lot = risk / ((sl_points * _Point / tickSize) * tickValue);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
lot = MathMax(lot, minLot);
lot = MathMin(lot, maxLot);
lot = NormalizeDouble(lot / step, 0) * step;
return lot;
}
bool CheckLimits()
{
MqlDateTime dt;
TimeCurrent(dt);
dt.hour = 0; dt.min = 0; dt.sec = 0;
datetime today = StructToTime(dt);
if(today != LastDay)
{
DailyStart = AccountInfoDouble(ACCOUNT_BALANCE);
TodayTrades = 0;
LastDay = today;
}
if(TodayTrades >= Max_Trades_Per_Day) return false;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double pl = ((balance - DailyStart) / DailyStart) * 100.0;
if(pl <= -Max_Daily_Loss_Percent || pl >= Max_Daily_Profit_Percent)
return false;
return true;
}
void OpenTrade(bool buy, double price, string setup_type, string details)
{
double sl, tp;
CalculateDynamicSLTP(price, buy, sl, tp);
int sl_points = (int)(MathAbs(price - sl) / _Point);
double lot = GetLotSize(sl_points);
if(lot < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)) return;
string comment = setup_type + " | " + details;
bool result = buy ? Trade.Buy(lot, _Symbol, price, sl, tp, comment)
: Trade.Sell(lot, _Symbol, price, sl, tp, comment);
if(result)
{
TodayTrades++;
ulong ticket = Trade.ResultOrder();
int size = ArraySize(OpenPositions);
ArrayResize(OpenPositions, size+1);
OpenPositions[size].ticket = ticket;
OpenPositions[size].entry = price;
OpenPositions[size].sl_level = sl;
OpenPositions[size].tp_level = tp;
OpenPositions[size].original_lot = lot;
OpenPositions[size].is_buy = buy;
OpenPositions[size].be_set = false;
OpenPositions[size].partials_closed = 0;
OpenPositions[size].setup_type = setup_type;
Print("========== ", setup_type, " ", TodayTrades, " ==========");
Print(buy ? "BUY" : "SELL", " @ ", price);
Print("Details: ", details);
Print("===================================");
string arrow_name = "Arrow_" + IntegerToString(ticket);
ObjectCreate(0, arrow_name, OBJ_ARROW, 0, TimeCurrent(), price);
ObjectSetInteger(0, arrow_name, OBJPROP_COLOR, buy ? clrLime : clrRed);
ObjectSetInteger(0, arrow_name, OBJPROP_ARROWCODE, buy ? 233 : 234);
ObjectSetInteger(0, arrow_name, OBJPROP_WIDTH, 3);
}
}
//+------------------------------------------------------------------+
//| ADD RE-ENTRY OPPORTUNITY TO QUEUE
//+------------------------------------------------------------------+
void AddReEntryOpportunity(ulong ticket, bool was_buy, double exit_price, double entry_price, string reason)
{
if(!Enable_ReEntry) return;
// Check if this trade already in queue
for(int i=0; i<ArraySize(ReEntryQueue); i++)
{
if(ReEntryQueue[i].original_ticket == ticket)
return; // Already queued
}
int size = ArraySize(ReEntryQueue);
ArrayResize(ReEntryQueue, size + 1);
ReEntryQueue[size].original_ticket = ticket;
ReEntryQueue[size].was_buy = was_buy;
ReEntryQueue[size].exit_price = exit_price;
ReEntryQueue[size].original_entry = entry_price;
ReEntryQueue[size].exit_time = TimeCurrent();
ReEntryQueue[size].exit_reason = reason;
ReEntryQueue[size].re_entered = false;
ReEntryQueue[size].re_entry_attempts = 0;
Print("📌 RE-ENTRY QUEUED: ", ticket, " | ", (was_buy ? "BUY" : "SELL"), " | Reason: ", reason);
}
//+------------------------------------------------------------------+
//| CHECK FOR STRONG CONFIRMATION (Re-entry validation)
//+------------------------------------------------------------------+
bool HasStrongConfirmation(bool check_bullish)
{
double current = (SymbolInfoDouble(_Symbol, SYMBOL_BID) + SymbolInfoDouble(_Symbol, SYMBOL_ASK)) / 2;
int confirmations = 0;
// 1. MFIB Confirmation
if(check_bullish && MFIB_Bull_Mode && current > MFIB_032)
confirmations++;
else if(!check_bullish && MFIB_Bear_Mode && current < MFIB_032)
confirmations++;
// 2. Strong MA Alignment (7-14-21 perfect stack)
if(check_bullish && MA_Current[0] > MA_Current[1] + 20 * _Point &&
MA_Current[1] > MA_Current[2] + 20 * _Point)
confirmations++;
else if(!check_bullish && MA_Current[0] < MA_Current[1] - 20 * _Point &&
MA_Current[1] < MA_Current[2] - 20 * _Point)
confirmations++;
// 3. Stoch Confirmation
if(check_bullish && Stoch_K_Current < 70 && Stoch_K_Current > Stoch_K_Previous)
confirmations++;
else if(!check_bullish && Stoch_K_Current > 30 && Stoch_K_Current < Stoch_K_Previous)
confirmations++;
// 4. Price at Key MA (retest setup)
if(IsPriceAtEMA14(current) || IsPriceAtMFIB032(current))
confirmations++;
// 5. Momentum (strong move in direction)
double close_curr = iClose(_Symbol, PERIOD_CURRENT, 0);
double close_prev = iClose(_Symbol, PERIOD_CURRENT, 1);
double move = MathAbs(close_curr - close_prev) / _Point;
if(check_bullish && close_curr > close_prev && move > 50)
confirmations++;
else if(!check_bullish && close_curr < close_prev && move > 50)
confirmations++;
// Need at least 3 confirmations for re-entry
return (confirmations >= 3);
}
//+------------------------------------------------------------------+
//| PROCESS RE-ENTRY OPPORTUNITIES
//+------------------------------------------------------------------+
void ProcessReEntries()
{
if(!Enable_ReEntry) return;
if(ArraySize(ReEntryQueue) == 0) return;
for(int i=ArraySize(ReEntryQueue)-1; i>=0; i--)
{
// Skip if already re-entered
if(ReEntryQueue[i].re_entered) continue;
// Skip if max attempts reached
if(ReEntryQueue[i].re_entry_attempts >= ReEntry_Max_Attempts)
{
// Remove from queue
ArrayRemove(ReEntryQueue, i, 1);
continue;
}
// Check cooldown
if(TimeCurrent() - ReEntryQueue[i].exit_time < ReEntry_Cooldown)
continue;
// Check if it was SL or BE exit
bool was_sl_exit = (StringFind(ReEntryQueue[i].exit_reason, "SL") >= 0);
bool was_be_exit = (StringFind(ReEntryQueue[i].exit_reason, "BE") >= 0);
if(was_sl_exit && !ReEntry_After_SL) continue;
if(was_be_exit && !ReEntry_After_BE) continue;
bool is_buy = ReEntryQueue[i].was_buy;
// Check if setup is still valid
bool setup_valid = false;
string validation = "";
if(Require_Stronger_Signal)
{
// Need STRONG confirmation for re-entry
if(HasStrongConfirmation(is_buy))
{
setup_valid = true;
validation = "STRONG CONFIRMATION";
}
}
else
{
// Just need trend alignment
if(is_buy && (Current_Trend_Bullish || MFIB_Bull_Mode))
{
setup_valid = true;
validation = "TREND ALIGNED";
}
else if(!is_buy && (Current_Trend_Bearish || MFIB_Bear_Mode))
{
setup_valid = true;
validation = "TREND ALIGNED";
}
}
// Additional validation: Check if price has moved favorably since exit
double current = (SymbolInfoDouble(_Symbol, SYMBOL_BID) + SymbolInfoDouble(_Symbol, SYMBOL_ASK)) / 2;
double exit_price = ReEntryQueue[i].exit_price;
bool price_favorable = false;
if(is_buy && current > exit_price - 100 * _Point) // Not too far below exit
price_favorable = true;
else if(!is_buy && current < exit_price + 100 * _Point) // Not too far above exit
price_favorable = true;
if(setup_valid && price_favorable)
{
// Execute re-entry
double entry_price = is_buy ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
: SymbolInfoDouble(_Symbol, SYMBOL_BID);
string reason = "RE-ENTRY " + IntegerToString(ReEntryQueue[i].re_entry_attempts + 1) +
" | " + validation + " | Original: " +
IntegerToString(ReEntryQueue[i].original_ticket);
OpenTrade(is_buy, entry_price, "RE-ENTRY", reason);
ReEntryQueue[i].re_entry_attempts++;
ReEntryQueue[i].exit_time = TimeCurrent(); // Reset cooldown
Print("🔄 RE-ENTRY EXECUTED: ", ReEntryQueue[i].original_ticket,
" | Attempt ", ReEntryQueue[i].re_entry_attempts, "/", ReEntry_Max_Attempts);
// If max attempts reached, remove from queue
if(ReEntryQueue[i].re_entry_attempts >= ReEntry_Max_Attempts)
ArrayRemove(ReEntryQueue, i, 1);
}
else
{
// Check if opportunity has expired (>10 minutes old)
if(TimeCurrent() - ReEntryQueue[i].exit_time > 600)
{
Print("⏰ RE-ENTRY EXPIRED: ", ReEntryQueue[i].original_ticket,
" | Setup no longer valid");
ArrayRemove(ReEntryQueue, i, 1);
}
}
}
}
//+------------------------------------------------------------------+
void ManagePositions()
{
UpdateMAs();
// Check for closed positions and queue re-entries
for(int i=0; i<ArraySize(OpenPositions); i++)
{
ulong ticket = OpenPositions[i].ticket;
// Check if position still exists
if(!PositionSelectByTicket(ticket))
{
// Position was closed - determine why
bool was_sl = false;
bool was_be = false;
double exit_price = 0;
// Try to get exit info from history
if(HistorySelectByPosition(ticket))
{
int deals = HistoryDealsTotal();
for(int d=deals-1; d>=0; d--)
{
ulong deal_ticket = HistoryDealGetTicket(d);
if(HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID) == ticket)
{
exit_price = HistoryDealGetDouble(deal_ticket, DEAL_PRICE);
// Check if hit SL or BE
double entry = OpenPositions[i].entry;
double sl = OpenPositions[i].sl_level;
bool is_buy = OpenPositions[i].is_buy;
// Was it at SL?
if(MathAbs(exit_price - sl) < 50 * _Point)
{
// Check if SL was at BE
if(MathAbs(sl - entry) < 50 * _Point)
was_be = true;
else
was_sl = true;
}
break;
}
}
}
// Queue re-entry if appropriate
if(was_sl || was_be)
{
string reason = was_be ? "BE STOP" : "STOP LOSS";
AddReEntryOpportunity(ticket, OpenPositions[i].is_buy, exit_price,
OpenPositions[i].entry, reason);
}
// Remove from tracking
ArrayRemove(OpenPositions, i, 1);
i--;
continue;
}
}
// Manage existing positions
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
int idx = -1;
for(int j=0; j<ArraySize(OpenPositions); j++)
{
if(OpenPositions[j].ticket == ticket)
{
idx = j;
break;
}
}
if(idx == -1) continue;
double entry = OpenPositions[idx].entry;
double sl = PositionGetDouble(POSITION_SL);
bool is_buy = OpenPositions[idx].is_buy;
double current = is_buy ? SymbolInfoDouble(_Symbol, SYMBOL_BID)
: SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double profit_points = is_buy ? (current - entry) / _Point
: (entry - current) / _Point;
if(!OpenPositions[idx].be_set && profit_points >= Move_BE_At_Points)
{
if((is_buy && sl < entry) || (!is_buy && sl > entry))
{
Trade.PositionModify(ticket, entry, 0);
OpenPositions[idx].be_set = true;
Print("BE SET: ", ticket, " @ ", entry);
}
}
double lot = PositionGetDouble(POSITION_VOLUME);
if(IsPriceAtHigherMA(current))
{
if(OpenPositions[idx].partials_closed < 4)
{
double close_size = NormalizeDouble(OpenPositions[idx].original_lot * Partial_TP_Percent / 100.0, 2);
if(close_size > 0 && close_size <= lot)
{
Trade.PositionClosePartial(ticket, close_size);
OpenPositions[idx].partials_closed++;
Print("PARTIAL TP ", OpenPositions[idx].partials_closed, ": Closed ", Partial_TP_Percent, "%");
}
}
}
if(profit_points >= Trailing_SL_Points + 100)
{
double newSL = is_buy ? current - Trailing_SL_Points * _Point
: current + Trailing_SL_Points * _Point;
if((is_buy && newSL > sl + 50 * _Point) ||
(!is_buy && newSL < sl - 50 * _Point))
{
Trade.PositionModify(ticket, newSL, 0);
}
}
}
}
//+------------------------------------------------------------------+
void OnTick()
{
// Update MFIB every 30 minutes
if(TimeCurrent() - Last_MFIB_Calc >= 1800)
{
CalculateMFIB();
if(Show_MFIB_Levels) DrawMFIBLevels();
Last_MFIB_Calc = TimeCurrent();
}
if(TimeCurrent() - Last_Trend_Check >= 5)
{
DetermineTrendBias();
UpdateMFIBModeLabel();
if(TrendReversed())
{
if(Current_Trend_Bullish)
CloseOppositeTrades(false);
else if(Current_Trend_Bearish)
CloseOppositeTrades(true);
}
Last_Trend_Check = TimeCurrent();
}
ManagePositions();
// Process re-entry opportunities
ProcessReEntries();
if(!CheckLimits()) return;
// Check for dead zones
if(IsDeadZone()) return;
int buy_count = 0;
int sell_count = 0;
for(int i=0; i<PositionsTotal(); i++)
{
if(PositionGetTicket(i) == 0) continue;
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
buy_count++;
else
sell_count++;
}
}
int total_open = buy_count + sell_count;
if(total_open >= Max_Simultaneous_Trades) return;
// AGGRESSIVE FORCE ENTRY - Ensure we hit minimum 4 trades
bool force_entry = (total_open < Min_Active_Entries);
bool force_entry_urgent = (total_open < 2); // Super aggressive below 2 trades
UpdateMAs();
UpdateStochastic();
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double current = (bid + ask) / 2;
int ma14_crosses_bull = CountMA14Crosses(true);
int ma14_crosses_bear = CountMA14Crosses(false);
// Get labels for display
string mfib_label_bull = GetMFIBLabel(current, true);
string mfib_label_bear = GetMFIBLabel(current, false);
string ema14_label_bull = GetEMA14Label(current, true);
string ema14_label_bear = GetEMA14Label(current, false);
string stoch_label_bull = GetStochLabel(true);
string stoch_label_bear = GetStochLabel(false);
// MA RETEST DETECTION (KEY FOR MISSED OPPORTUNITIES!)
int retest_ma_idx = -1;
string retest_label_bull = "";
string retest_label_bear = "";
bool ma_retest_bull = DetectMARetest(true, retest_ma_idx, retest_label_bull);
bool ma_retest_bear = DetectMARetest(false, retest_ma_idx, retest_label_bear);
// MA REJECTION DETECTION
string reject_label_bull = "";
string reject_label_bear = "";
bool ma_reject_bull = DetectMAReject(true, reject_label_bull);
bool ma_reject_bear = DetectMAReject(false, reject_label_bear);
// Check MFIB interaction requirement (can be overridden by force entry or MA retest)
bool has_mfib_interaction = (mfib_label_bull != "" || mfib_label_bear != "");
if(Require_MFIB_Interaction && !has_mfib_interaction && !force_entry && !ma_retest_bull && !ma_retest_bear)
{
UpdateStatusLabel("No MFIB Interaction - Waiting", clrGray);
return;
}
string setup_label = "";
string details = "";
// BUY SETUPS
if(Current_Trend_Bullish || MFIB_Bull_Mode || force_entry)
{
bool buy_signal = false;
// PRIORITY 1: MA RETEST (Catches those circled opportunities!)
if(ma_retest_bull)
{
buy_signal = true;
setup_label = "MA RETEST";
details = retest_label_bull + " + " + stoch_label_bull;
}
// PRIORITY 2: MA REJECTION
else if(ma_reject_bull)
{
buy_signal = true;
setup_label = "MA REJECTION";
details = reject_label_bull + " + " + stoch_label_bull;
}
// Check all 6 standard setups
else if(CheckSetup1_StructuralBounce(true, setup_label))
{
buy_signal = true;
details = mfib_label_bull + " + " + ema14_label_bull + " + " + stoch_label_bull;
}
else if(CheckSetup2_StructuralBreak(true, setup_label))
{
buy_signal = true;
details = "Break & Hold + " + stoch_label_bull;
}
else if(CheckSetup3_MagnetSnapback(true, setup_label))
{
buy_signal = true;
details = ema14_label_bull + " + " + stoch_label_bull;
}
else if(CheckSetup4_MFIBContinuation(true, setup_label))
{
buy_signal = true;
details = "MFIB Bull Mode + Micro Align + " + stoch_label_bull;
}
else if(CheckSetup5_FailedBreak(true, setup_label))
{
buy_signal = true;
details = "Failed Bear Break + Stoch Cross";
}
else if(CheckSetup6_TripleConfluence(true, setup_label))
{
buy_signal = true;
details = mfib_label_bull + " + " + ema14_label_bull + " + Rejection";
}
// FORCE ENTRY LOGIC (More aggressive)
if(!buy_signal && force_entry_urgent)
{
// Super aggressive: just need any MA alignment
if(ma14_crosses_bull >= 1 || IsMicroBullAlign())
{
buy_signal = true;
setup_label = "FORCE ENTRY URGENT";
details = "Need " + IntegerToString(Min_Active_Entries) + " trades (" + IntegerToString(total_open) + " open)";
}
}
else if(!buy_signal && force_entry && ma14_crosses_bull >= Min_MA14_Crosses && buy_count < sell_count)
{
buy_signal = true;
setup_label = "FORCE ENTRY";
details = "Min trades " + IntegerToString(total_open) + "/" + IntegerToString(Min_Active_Entries);
}
if(buy_signal)
{
OpenTrade(true, ask, setup_label, details);
UpdateStatusLabel(setup_label + " LONG", clrLime);
}
}
// SELL SETUPS
if(Current_Trend_Bearish || MFIB_Bear_Mode || force_entry)
{
bool sell_signal = false;
// PRIORITY 1: MA RETEST (Catches those circled opportunities!)
if(ma_retest_bear)
{
sell_signal = true;
setup_label = "MA RETEST";
details = retest_label_bear + " + " + stoch_label_bear;
}
// PRIORITY 2: MA REJECTION
else if(ma_reject_bear)
{
sell_signal = true;
setup_label = "MA REJECTION";
details = reject_label_bear + " + " + stoch_label_bear;
}
// Check all 6 standard setups
else if(CheckSetup1_StructuralBounce(false, setup_label))
{
sell_signal = true;
details = mfib_label_bear + " + " + ema14_label_bear + " + " + stoch_label_bear;
}
else if(CheckSetup2_StructuralBreak(false, setup_label))
{
sell_signal = true;
details = "Break & Hold + " + stoch_label_bear;
}
else if(CheckSetup3_MagnetSnapback(false, setup_label))
{
sell_signal = true;
details = ema14_label_bear + " + " + stoch_label_bear;
}
else if(CheckSetup4_MFIBContinuation(false, setup_label))
{
sell_signal = true;
details = "MFIB Bear Mode + Micro Align + " + stoch_label_bear;
}
else if(CheckSetup5_FailedBreak(false, setup_label))
{
sell_signal = true;
details = "Failed Bull Break + Stoch Cross";
}
else if(CheckSetup6_TripleConfluence(false, setup_label))
{
sell_signal = true;
details = mfib_label_bear + " + " + ema14_label_bear + " + Rejection";
}
// FORCE ENTRY LOGIC (More aggressive)
if(!sell_signal && force_entry_urgent)
{
// Super aggressive: just need any MA alignment
if(ma14_crosses_bear >= 1 || IsMicroBearAlign())
{
sell_signal = true;
setup_label = "FORCE ENTRY URGENT";
details = "Need " + IntegerToString(Min_Active_Entries) + " trades (" + IntegerToString(total_open) + " open)";
}
}
else if(!sell_signal && force_entry && ma14_crosses_bear >= Min_MA14_Crosses && sell_count < buy_count)
{
sell_signal = true;
setup_label = "FORCE ENTRY";
details = "Min trades " + IntegerToString(total_open) + "/" + IntegerToString(Min_Active_Entries);
}
if(sell_signal)
{
OpenTrade(false, bid, setup_label, details);
UpdateStatusLabel(setup_label + " SHORT", clrRed);
}
}
}
//+------------------------------------------------------------------+