//+------------------------------------------------------------------+ //| QuarterTheory_VIZION_FINAL_v5.1.mq5 | //| Directional Re-Entry Filters + MFIB/Stoch Reject Pullbacks | //| 150PT SL | 300PT TRAIL | 4000PT TP | RUNNERS PROTECTED | //+------------------------------------------------------------------+ #property copyright "QuarterTheory x VIZION - Final v5.1" #property version "5.10" #property strict #include CTrade Trade; //================ INPUT PARAMETERS ==================// input group "=== CORE SETTINGS ===" input int MagicNumber = 456789; input double Risk_Per_Trade = 1.2; input int Max_Trades_Per_Setup = 10; input int Max_Total_Trades = 100; input int Min_Runners_To_Keep = 4; input group "=== MARKET MODE SYSTEM ===" input bool Use_Market_Mode_Filter = true; input int Mode_Confirmation_Bars = 2; input double Chop_ATR_Threshold = 0.5; input double Range_Price_Threshold = 0.3; input group "=== REVERSAL CONFIRMATION ===" input bool Only_Close_On_Full_Reversal = true; // Protect runners from pullbacks input int Reversal_Confirmation_Bars = 3; // Bars needed for full reversal input group "=== MA SYSTEM ===" input int MA_1 = 7; input int MA_2 = 14; input int MA_3 = 21; input int MA_4 = 50; input int MA_5 = 140; input int MA_6 = 230; input int MA_7 = 500; input int MA_8 = 1000; input int MA_9 = 1100; input int MA_10 = 1300; input int MA_Touch_Buffer = 100; input group "=== STOCHASTIC ===" input int Stoch_K_Period = 5; input int Stoch_D_Period = 3; input int Stoch_Slowing = 3; input double Stoch_Extreme_High = 85.0; // Extreme overbought input double Stoch_Extreme_Low = 15.0; // Extreme oversold input double Stoch_High = 70.0; input double Stoch_Low = 30.0; input group "=== MFIB SYSTEM ===" input int MFIB_Lookback = 500; // (kept for future expansion) input group "=== FIBONACCI ===" input int Lookback_Bars = 200; input bool Show_Levels = true; input group "=== TIGHT SL + AGGRESSIVE TRAIL SYSTEM ===" input int Initial_SL_Points = 150; // Tight entry SL input int BreakEven_Points = 300; // Move to BE at 300 input int Trailing_Distance_Points = 300; // Trail by 300 input int TP_Points = 4000; // Final TP at 4000 input int Partial_TP_Points = 900; // First partial at 900 input double Partial_TP_Percent = 33.0; // Close 33% at partial //================ ENUMS ==================// enum MODE_FAMILY { FAMILY_TRENDING = 0, FAMILY_RANGING = 1, FAMILY_CHOP = 2, FAMILY_TRANSITIONAL = 3 }; enum TREND_BIAS { BIAS_NEUTRAL = 0, BIAS_BULL = 1, BIAS_BEAR = -1 }; enum TREND_STRENGTH { STRENGTH_WEAK = 0, STRENGTH_CONFIRMED = 1, STRENGTH_STRONG = 2 }; enum PRICE_STATE { STATE_CONTINUATION = 0, // Trend expansion / clean STATE_PULLBACK = 1, // Counter-move but structure intact STATE_DEEP_RETRACEMENT = 2, // Threatening structure / testing MA50+ STATE_REVERSAL_ATTEMPT = 3, // Structure break + failed reclaim attempt STATE_REVERSAL_CONFIRMED = 4, // New bias confirmed // Range states (mapped when FAMILY_RANGING) STATE_RANGE_MID_DRIFT = 10, STATE_RANGE_EDGE_TEST = 11, STATE_RANGE_REJECTION = 12, STATE_RANGE_BREAK_ATTEMPT = 13, STATE_RANGE_BREAK_CONFIRMED = 14, // Chop states (mapped when FAMILY_CHOP) STATE_CHOP_NOISE = 20, STATE_CHOP_VOL_SPIKE = 21, STATE_CHOP_SQUEEZE = 22, STATE_CHOP_FAKEOUT_LOOP = 23, STATE_UNKNOWN = 99 }; enum SETUP_TYPE { SETUP_MA14_CROSS = 1, SETUP_MA50_BOUNCE = 2, SETUP_MA140_BOUNCE = 3, SETUP_MA230_BOUNCE = 4, SETUP_MA500_TOUCH = 5, SETUP_FIB_BREAK = 6, SETUP_FIB_RECLAIM = 7, SETUP_FIB_REJECT = 8, SETUP_MAGNET_WALK = 9, SETUP_STAIRCASE_ADV = 10, SETUP_CTRL_PULLBACK = 11, SETUP_TF_RESET = 12, SETUP_MFIB_LADDER = 13, SETUP_MFIB_PRESS = 14, SETUP_MEAN_REV = 15, SETUP_RANGE_ENGINE = 16 }; //================ GLOBALS ==================// int Stoch_Handle, ATR_Handle, ADX_Handle; double Stoch_K_Current = 0, Stoch_K_Previous = 0, Stoch_K_Prev2 = 0; double Stoch_D_Current = 0; double Current_ATR = 0; double Current_ADX = 0; double PriceLevels[7]; int MA_Handles[10]; double MA_Current[10]; double MA_Previous[10]; double MA_Prev2[10]; double MFIB_High, MFIB_Low; double MFIB_Level_236, MFIB_Level_382, MFIB_Level_050; double MFIB_Level_618, MFIB_Level_786; MODE_FAMILY Current_Family = FAMILY_TRANSITIONAL; TREND_BIAS Current_Bias = BIAS_NEUTRAL; TREND_STRENGTH Current_Strength = STRENGTH_WEAK; PRICE_STATE Current_State = STATE_UNKNOWN; MODE_FAMILY Prev_Family = FAMILY_TRANSITIONAL; TREND_BIAS Prev_Bias = BIAS_NEUTRAL; TREND_STRENGTH Prev_Strength = STRENGTH_WEAK; int Mode_Confirmation_Count = 0; int Reversal_Confirm_Counter = 0; // Warning flags bool MA7_Cross_14_Warning = false; bool MA7_Cross_21_Warning = false; bool MA50_Break_Warning = false; bool Fib_Reject_Warning = false; // Classic fib reject bool MFIB_Reject_Warning = false; // MFIB level reject (new) bool MA_Reject_Warning = false; bool Stoch_Extreme_Warning = false; bool Stoch_Reject_Warning = false; // K/D reject at any level (new) bool Pullback_Warning = false; bool Retracement_Warning = false; struct Position { ulong ticket; double entry; double original_lot; bool is_buy; bool partial_tp_hit; bool be_set; bool trailing_active; bool is_runner; SETUP_TYPE setup_type; string setup_name; MODE_FAMILY entry_family; TREND_BIAS entry_bias; TREND_STRENGTH entry_strength; double distance_from_current; }; Position OpenPositions[]; int TodayTrades = 0; int BuyTrades = 0; int SellTrades = 0; int ClosedByReversal = 0; int SetupCount[17]; datetime LastEntryTime[17]; //================ HELPERS ==================// double MidPrice() { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); return (bid + ask) / 2.0; } bool NearLevel(const double price, const double level, const double tolPoints) { return (MathAbs(price - level) <= tolPoints * _Point); } bool StochCrossUp() { // K crosses above D on current bar vs previous bar (approx using K prev and current D current) return (Stoch_K_Previous < Stoch_D_Current && Stoch_K_Current >= Stoch_D_Current); } bool StochCrossDown() { return (Stoch_K_Previous > Stoch_D_Current && Stoch_K_Current <= Stoch_D_Current); } bool IsBullBias() { return (Current_Bias == BIAS_BULL); } bool IsBearBias() { return (Current_Bias == BIAS_BEAR); } // Reclaim / reject MA50 logic for re-enabling trend-direction entries bool Bull_MA50_Reclaimed() { // MA7 reclaims above MA50 bool reclaimed = (MA_Previous[0] <= MA_Previous[3]) && (MA_Current[0] > MA_Current[3]); // or price rejects MA50 and closes above with stoch turning up double low0 = iLow(_Symbol, PERIOD_CURRENT, 0); double close0 = iClose(_Symbol, PERIOD_CURRENT, 0); bool rejected = (low0 <= MA_Current[3] && close0 > MA_Current[3] && (StochCrossUp() || Stoch_K_Current > 50)); return (reclaimed || rejected); } bool Bear_MA50_Reclaimed() { bool reclaimed = (MA_Previous[0] >= MA_Previous[3]) && (MA_Current[0] < MA_Current[3]); double high0 = iHigh(_Symbol, PERIOD_CURRENT, 0); double close0 = iClose(_Symbol, PERIOD_CURRENT, 0); bool rejected = (high0 >= MA_Current[3] && close0 < MA_Current[3] && (StochCrossDown() || Stoch_K_Current < 50)); return (reclaimed || rejected); } //+------------------------------------------------------------------+ int OnInit() { Print("========================================"); Print("FINAL SYSTEM v5.1"); Print("Direction Filters: Trend entries paused during pullback/retracement"); Print("Pullback defs expanded: MA cross OR MFIB reject OR Stoch reject"); Print("========================================"); Trade.SetExpertMagicNumber(MagicNumber); Trade.SetDeviationInPoints(50); Trade.SetTypeFilling(ORDER_FILLING_FOK); Stoch_Handle = iStochastic(_Symbol, PERIOD_CURRENT, Stoch_K_Period, Stoch_D_Period, Stoch_Slowing, MODE_SMA, STO_LOWHIGH); ATR_Handle = iATR(_Symbol, PERIOD_CURRENT, 14); ADX_Handle = iADX(_Symbol, PERIOD_CURRENT, 14); 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); ArrayInitialize(SetupCount, 0); ArrayInitialize(LastEntryTime, 0); CalculateLevels(); if(Show_Levels) DrawLevels(); 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); if(ATR_Handle != INVALID_HANDLE) IndicatorRelease(ATR_Handle); if(ADX_Handle != INVALID_HANDLE) IndicatorRelease(ADX_Handle); ObjectsDeleteAll(0, "Level_"); ObjectsDeleteAll(0, "ModeLabel"); ObjectsDeleteAll(0, "StateLabel"); ObjectsDeleteAll(0, "WarningLabel"); Print("Final: B:", BuyTrades, " | S:", SellTrades, " | Reversed:", ClosedByReversal); } //+------------------------------------------------------------------+ void CalculateLevels() { double high = iHigh(_Symbol, PERIOD_CURRENT, 0); double low = iLow(_Symbol, PERIOD_CURRENT, 0); for(int i=1; i<=Lookback_Bars; i++) { double h = iHigh(_Symbol, PERIOD_CURRENT, i); double l = iLow(_Symbol, PERIOD_CURRENT, i); if(h > high) high = h; if(l < low) low = l; } double range = high - low; PriceLevels[0] = low; PriceLevels[1] = low + range * 0.236; PriceLevels[2] = low + range * 0.382; PriceLevels[3] = low + range * 0.5; PriceLevels[4] = low + range * 0.618; PriceLevels[5] = low + range * 0.786; PriceLevels[6] = high; MFIB_High = high; MFIB_Low = low; MFIB_Level_236 = low + range * 0.236; MFIB_Level_382 = low + range * 0.382; MFIB_Level_050 = low + range * 0.5; MFIB_Level_618 = low + range * 0.618; MFIB_Level_786 = low + range * 0.786; } void DrawLevels() { ObjectsDeleteAll(0, "Level_"); color level_colors[7] = {clrRed, clrOrange, clrYellow, clrLime, clrCyan, clrBlue, clrMagenta}; for(int i=0; i<7; i++) { string name = "Level_" + IntegerToString(i); ObjectCreate(0, name, OBJ_HLINE, 0, 0, PriceLevels[i]); ObjectSetInteger(0, name, OBJPROP_COLOR, level_colors[i]); ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, name, OBJPROP_WIDTH, 2); } } //+------------------------------------------------------------------+ void UpdateIndicators() { for(int i=0; i<10; i++) { double curr[1], prev[1], prev2[1]; if(CopyBuffer(MA_Handles[i], 0, 0, 1, curr) > 0) MA_Current[i] = curr[0]; if(CopyBuffer(MA_Handles[i], 0, 1, 1, prev) > 0) MA_Previous[i] = prev[0]; if(CopyBuffer(MA_Handles[i], 0, 2, 1, prev2) > 0) MA_Prev2[i] = prev2[0]; } double k_curr[1], k_prev[1], k_prev2[1], d_curr[1]; if(CopyBuffer(Stoch_Handle, MAIN_LINE, 0, 1, k_curr) > 0) Stoch_K_Current = k_curr[0]; if(CopyBuffer(Stoch_Handle, MAIN_LINE, 1, 1, k_prev) > 0) Stoch_K_Previous = k_prev[0]; if(CopyBuffer(Stoch_Handle, MAIN_LINE, 2, 1, k_prev2) > 0) Stoch_K_Prev2 = k_prev2[0]; if(CopyBuffer(Stoch_Handle, SIGNAL_LINE, 0, 1, d_curr) > 0) Stoch_D_Current = d_curr[0]; double atr[1], adx[1]; if(CopyBuffer(ATR_Handle, 0, 0, 1, atr) > 0) Current_ATR = atr[0]; if(CopyBuffer(ADX_Handle, 0, 0, 1, adx) > 0) Current_ADX = adx[0]; } //+------------------------------------------------------------------+ void DetectWarnings() { double current = MidPrice(); double bufferPts = (double)MA_Touch_Buffer; // Reset warnings MA7_Cross_14_Warning = false; MA7_Cross_21_Warning = false; MA50_Break_Warning = false; Fib_Reject_Warning = false; MFIB_Reject_Warning = false; MA_Reject_Warning = false; Stoch_Extreme_Warning = false; Stoch_Reject_Warning = false; Pullback_Warning = false; Retracement_Warning = false; // 1) STOCH extremes if(Stoch_K_Current <= Stoch_Extreme_Low || Stoch_K_Current >= Stoch_Extreme_High) Stoch_Extreme_Warning = true; // 2) STOCH reject at ANY meaningful band (your request) // - overbought reject: K crosses down while above 50 (stronger if above 70) // - oversold reject: K crosses up while below 50 (stronger if below 30) bool stoch_reject_down = (StochCrossDown() && Stoch_K_Current > 50); bool stoch_reject_up = (StochCrossUp() && Stoch_K_Current < 50); if(stoch_reject_down || stoch_reject_up) Stoch_Reject_Warning = true; // 3) MA7 x MA14 cross (early structure stress) bool ma7_crossed_14_down = (MA_Previous[0] > MA_Previous[1]) && (MA_Current[0] <= MA_Current[1]); bool ma7_crossed_14_up = (MA_Previous[0] < MA_Previous[1]) && (MA_Current[0] >= MA_Current[1]); if(ma7_crossed_14_down || ma7_crossed_14_up) { MA7_Cross_14_Warning = true; Retracement_Warning = true; } // 4) MA7 x MA21 cross (deeper) bool ma7_crossed_21_down = (MA_Previous[0] > MA_Previous[2]) && (MA_Current[0] <= MA_Current[2]); bool ma7_crossed_21_up = (MA_Previous[0] < MA_Previous[2]) && (MA_Current[0] >= MA_Current[2]); if(ma7_crossed_21_down || ma7_crossed_21_up) { MA7_Cross_21_Warning = true; Retracement_Warning = true; } // 5) MA50 break warning (reversal pressure) bool ma7_broke_50_down = (MA_Previous[0] > MA_Previous[3]) && (MA_Current[0] <= MA_Current[3]); bool ma7_broke_50_up = (MA_Previous[0] < MA_Previous[3]) && (MA_Current[0] >= MA_Current[3]); if(ma7_broke_50_down || ma7_broke_50_up) MA50_Break_Warning = true; // 6) Classic fib reject if at fib + stoch extreme OR stoch reject bool at_fib = false; for(int i=1; i<6; i++) { if(NearLevel(current, PriceLevels[i], bufferPts)) { at_fib = true; break; } } if(at_fib && (Stoch_Extreme_Warning || Stoch_Reject_Warning)) { Fib_Reject_Warning = true; Pullback_Warning = true; } // 7) MFIB reject (new): if at MFIB + stoch extreme OR stoch reject bool at_mfib = NearLevel(current, MFIB_Level_236, bufferPts) || NearLevel(current, MFIB_Level_382, bufferPts) || NearLevel(current, MFIB_Level_050, bufferPts) || NearLevel(current, MFIB_Level_618, bufferPts) || NearLevel(current, MFIB_Level_786, bufferPts); if(at_mfib && (Stoch_Extreme_Warning || Stoch_Reject_Warning)) { MFIB_Reject_Warning = true; Pullback_Warning = true; } // 8) MA reject with stoch signal bool at_ma50 = NearLevel(current, MA_Current[3], bufferPts); bool at_ma140 = NearLevel(current, MA_Current[4], bufferPts); bool at_ma230 = NearLevel(current, MA_Current[5], bufferPts); if((at_ma50 || at_ma140 || at_ma230) && (Stoch_Extreme_Warning || Stoch_Reject_Warning)) { MA_Reject_Warning = true; Pullback_Warning = true; } } //+------------------------------------------------------------------+ // Family/Bias/Strength detection (keeps your old logic but outputs // clearer labels: Trending/Ranging/Chop + Weak/Confirmed/Strong + Bull/Bear) void DetectFamilyBiasStrength(MODE_FAMILY &family, TREND_BIAS &bias, TREND_STRENGTH &strength) { double current = MidPrice(); bool mas_aligned_bull = (MA_Current[0] > MA_Current[1]) && (MA_Current[1] > MA_Current[2]) && (MA_Current[2] > MA_Current[3]); bool mas_aligned_bear = (MA_Current[0] < MA_Current[1]) && (MA_Current[1] < MA_Current[2]) && (MA_Current[2] < MA_Current[3]); // quick chop/range tests double recent_high = iHigh(_Symbol, PERIOD_CURRENT, 0); double recent_low = iLow(_Symbol, PERIOD_CURRENT, 0); for(int i=1; i<20; i++) { recent_high = MathMax(recent_high, iHigh(_Symbol, PERIOD_CURRENT, i)); recent_low = MathMin(recent_low, iLow(_Symbol, PERIOD_CURRENT, i)); } double range_size = (recent_high - recent_low) / current; bool is_ranging = (range_size < Range_Price_Threshold); bool ma_clustered = false; if(Current_ATR > 0.0) ma_clustered = ((MathAbs(MA_Current[0] - MA_Current[3]) / Current_ATR) < Chop_ATR_Threshold); bool is_choppy = (ma_clustered || Current_ADX < 15); // Decide bias first if trend exists if(mas_aligned_bull) bias = BIAS_BULL; else if(mas_aligned_bear) bias = BIAS_BEAR; else { // softer bias using MA7 vs MA50 if not fully aligned if(MA_Current[0] > MA_Current[3]) bias = BIAS_BULL; else if(MA_Current[0] < MA_Current[3]) bias = BIAS_BEAR; else bias = BIAS_NEUTRAL; } // Decide family if(is_choppy && !(mas_aligned_bull || mas_aligned_bear)) family = FAMILY_CHOP; else if(is_ranging && !(mas_aligned_bull || mas_aligned_bear)) family = FAMILY_RANGING; else if(bias != BIAS_NEUTRAL) family = FAMILY_TRENDING; else family = FAMILY_TRANSITIONAL; // Decide strength (only meaningful in trending; still shown) if(Current_ADX > 25 && (mas_aligned_bull || mas_aligned_bear)) strength = STRENGTH_STRONG; else if(Current_ADX > 18 && (mas_aligned_bull || mas_aligned_bear)) strength = STRENGTH_CONFIRMED; else strength = STRENGTH_WEAK; } //+------------------------------------------------------------------+ // State logic: expanded pullback defs = MA stress OR MFIB reject OR Stoch reject. // Direction rule you requested: // - In bull trend pullback/retracement: ONLY SELL entries until MA50 reclaim/reject-up. // - In bear trend pullback/retracement: ONLY BUY entries until MA50 reclaim/reject-down. PRICE_STATE DetermineStateFromContext() { // If not trending, map to range/chop sub-states if(Current_Family == FAMILY_RANGING) { double current = MidPrice(); double bufferPts = (double)MA_Touch_Buffer; bool near_low = NearLevel(current, PriceLevels[1], bufferPts) || NearLevel(current, PriceLevels[0], bufferPts); bool near_high = NearLevel(current, PriceLevels[5], bufferPts) || NearLevel(current, PriceLevels[6], bufferPts); if(near_low || near_high) return STATE_RANGE_EDGE_TEST; // mid drift default if(Stoch_Reject_Warning || Stoch_Extreme_Warning) return STATE_RANGE_REJECTION; // break attempt / confirmed using close beyond outer levels double close0 = iClose(_Symbol, PERIOD_CURRENT, 0); if(close0 > PriceLevels[6] || close0 < PriceLevels[0]) return STATE_RANGE_BREAK_CONFIRMED; if(NearLevel(current, PriceLevels[6], bufferPts) || NearLevel(current, PriceLevels[0], bufferPts)) return STATE_RANGE_BREAK_ATTEMPT; return STATE_RANGE_MID_DRIFT; } if(Current_Family == FAMILY_CHOP) { // simple chop phase mapping using ATR/ADX + stoch flips if(Current_ADX < 12 && !Stoch_Reject_Warning) return STATE_CHOP_NOISE; if(Current_ATR > 0 && (MathAbs(iClose(_Symbol, PERIOD_CURRENT, 0) - iOpen(_Symbol, PERIOD_CURRENT, 0)) / Current_ATR) > 1.2) return STATE_CHOP_VOL_SPIKE; if(Current_ADX < 15 && Current_ATR > 0 && (MathAbs(MA_Current[0] - MA_Current[3]) / Current_ATR) < 0.25) return STATE_CHOP_SQUEEZE; if(Stoch_Reject_Warning) return STATE_CHOP_FAKEOUT_LOOP; return STATE_CHOP_NOISE; } // Trending / Transitional: use your structure ideas but cleaner naming bool ma7_above_14 = (MA_Current[0] > MA_Current[1]); bool ma7_above_21 = (MA_Current[0] > MA_Current[2]); bool ma7_above_50 = (MA_Current[0] > MA_Current[3]); bool ma14_above_50 = (MA_Current[1] > MA_Current[3]); bool ma21_above_50 = (MA_Current[2] > MA_Current[3]); bool ma7_below_14 = (MA_Current[0] < MA_Current[1]); bool ma7_below_21 = (MA_Current[0] < MA_Current[2]); bool ma7_below_50 = (MA_Current[0] < MA_Current[3]); bool ma14_below_50 = (MA_Current[1] < MA_Current[3]); bool ma21_below_50 = (MA_Current[2] < MA_Current[3]); bool pullbackSignal = (Pullback_Warning || MFIB_Reject_Warning || Fib_Reject_Warning || Stoch_Reject_Warning); bool retraceSignal = (MA7_Cross_14_Warning || MA7_Cross_21_Warning); if(IsBullBias()) { // confirmed reversal is when structure fully flips below 50s if(ma7_below_50 && !ma14_above_50 && !ma21_above_50) return STATE_REVERSAL_CONFIRMED; // reversal attempt: MA50 pressure/break warning + failed reclaim vibe if(MA50_Break_Warning && (retraceSignal || Stoch_Extreme_Warning || Stoch_Reject_Warning)) return STATE_REVERSAL_ATTEMPT; // deep retracement = MA7 not above 14/21 or testing MA50 and you have pullback signals if((!ma7_above_14 || !ma7_above_21 || !ma7_above_50) && (pullbackSignal || retraceSignal)) return STATE_DEEP_RETRACEMENT; // pullback = structure mostly intact (14/21 above 50) and we have *any* reject signal if(ma14_above_50 && ma21_above_50 && pullbackSignal) return STATE_PULLBACK; return STATE_CONTINUATION; } if(IsBearBias()) { if(ma7_above_50 && !ma14_below_50 && !ma21_below_50) return STATE_REVERSAL_CONFIRMED; if(MA50_Break_Warning && (retraceSignal || Stoch_Extreme_Warning || Stoch_Reject_Warning)) return STATE_REVERSAL_ATTEMPT; if((!ma7_below_14 || !ma7_below_21 || !ma7_below_50) && (pullbackSignal || retraceSignal)) return STATE_DEEP_RETRACEMENT; if(ma14_below_50 && ma21_below_50 && pullbackSignal) return STATE_PULLBACK; return STATE_CONTINUATION; } return STATE_UNKNOWN; } //+------------------------------------------------------------------+ void UpdateModeAndState() { // detect new family/bias/strength MODE_FAMILY detected_family; TREND_BIAS detected_bias; TREND_STRENGTH detected_strength; DetectFamilyBiasStrength(detected_family, detected_bias, detected_strength); // set state using current detected context MODE_FAMILY tmpFamily = detected_family; TREND_BIAS tmpBias = detected_bias; TREND_STRENGTH tmpStrength = detected_strength; // temporarily apply to compute state consistently Current_Family = tmpFamily; Current_Bias = tmpBias; Current_Strength = tmpStrength; PRICE_STATE detected_state = DetermineStateFromContext(); // Confirmation logic (avoid flapping) bool changed = (detected_family != Prev_Family) || (detected_bias != Prev_Bias) || (detected_strength != Prev_Strength); if(changed) { // quick flip if reversal confirmed int required = Mode_Confirmation_Bars; if(detected_state == STATE_REVERSAL_CONFIRMED) required = 1; if(detected_family == Prev_Family && detected_bias == Prev_Bias && detected_strength == Prev_Strength) { Mode_Confirmation_Count++; if(Mode_Confirmation_Count >= required) { Prev_Family = Current_Family; Prev_Bias = Current_Bias; Prev_Strength = Current_Strength; Current_Family = detected_family; Current_Bias = detected_bias; Current_Strength = detected_strength; Current_State = detected_state; Mode_Confirmation_Count = 0; Reversal_Confirm_Counter = 0; // Close on confirmed reversal only if(Current_State == STATE_REVERSAL_CONFIRMED) CloseOnFullReversal(); } } else { Prev_Family = detected_family; Prev_Bias = detected_bias; Prev_Strength = detected_strength; Mode_Confirmation_Count = 1; } } else { Mode_Confirmation_Count = 0; Current_Family = detected_family; Current_Bias = detected_bias; Current_Strength = detected_strength; Current_State = detected_state; } UpdateLabels(); } //+------------------------------------------------------------------+ string FamilyToText(MODE_FAMILY f) { switch(f) { case FAMILY_TRENDING: return "Trending"; case FAMILY_RANGING: return "Ranging"; case FAMILY_CHOP: return "Chop"; case FAMILY_TRANSITIONAL: return "Transitional"; } return "Unknown"; } string BiasToText(TREND_BIAS b) { if(b == BIAS_BULL) return "Bull"; if(b == BIAS_BEAR) return "Bear"; return "Neutral"; } string StrengthToText(TREND_STRENGTH s) { switch(s) { case STRENGTH_WEAK: return "Weak"; case STRENGTH_CONFIRMED: return "Confirmed"; case STRENGTH_STRONG: return "Strong"; } return "Weak"; } string StateToText(PRICE_STATE s) { switch(s) { case STATE_CONTINUATION: return "Continuation"; case STATE_PULLBACK: return "Pullback"; case STATE_DEEP_RETRACEMENT: return "Deep Retracement"; case STATE_REVERSAL_ATTEMPT: return "Reversal Attempt"; case STATE_REVERSAL_CONFIRMED: return "Reversal Confirmed"; case STATE_RANGE_MID_DRIFT: return "Range: Mid Drift"; case STATE_RANGE_EDGE_TEST: return "Range: Edge Test"; case STATE_RANGE_REJECTION: return "Range: Rejection"; case STATE_RANGE_BREAK_ATTEMPT: return "Range: Break Attempt"; case STATE_RANGE_BREAK_CONFIRMED: return "Range: Break Confirmed"; case STATE_CHOP_NOISE: return "Chop: Noise"; case STATE_CHOP_VOL_SPIKE: return "Chop: Vol Spike"; case STATE_CHOP_SQUEEZE: return "Chop: Squeeze"; case STATE_CHOP_FAKEOUT_LOOP: return "Chop: Fakeout Loop"; default: return "Unknown"; } } //+------------------------------------------------------------------+ void UpdateLabels() { // MODE LABEL (top-left) ObjectDelete(0, "ModeLabel"); ObjectCreate(0, "ModeLabel", OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, "ModeLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, "ModeLabel", OBJPROP_XDISTANCE, 10); ObjectSetInteger(0, "ModeLabel", OBJPROP_YDISTANCE, 20); string mode_text = "MODE: " + FamilyToText(Current_Family); if(Current_Family == FAMILY_TRENDING) mode_text += " | " + StrengthToText(Current_Strength) + " " + BiasToText(Current_Bias); color mode_color = clrYellow; if(Current_Family == FAMILY_TRENDING) { if(Current_Bias == BIAS_BULL) mode_color = (Current_Strength == STRENGTH_STRONG ? clrLime : (Current_Strength == STRENGTH_CONFIRMED ? clrGreenYellow : clrGreen)); if(Current_Bias == BIAS_BEAR) mode_color = (Current_Strength == STRENGTH_STRONG ? clrRed : (Current_Strength == STRENGTH_CONFIRMED ? clrOrangeRed : clrOrange)); } else if(Current_Family == FAMILY_RANGING) mode_color = clrAqua; else if(Current_Family == FAMILY_CHOP) mode_color = clrViolet; ObjectSetString(0, "ModeLabel", OBJPROP_TEXT, mode_text); ObjectSetInteger(0, "ModeLabel", OBJPROP_COLOR, mode_color); ObjectSetInteger(0, "ModeLabel", OBJPROP_FONTSIZE, 12); // STATE LABEL ObjectDelete(0, "StateLabel"); ObjectCreate(0, "StateLabel", OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, "StateLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, "StateLabel", OBJPROP_XDISTANCE, 10); ObjectSetInteger(0, "StateLabel", OBJPROP_YDISTANCE, 40); string state_text = "STATE: " + StateToText(Current_State); // add action guidance (buys-only/sells-only) for your key trend pullback logic if(Current_Family == FAMILY_TRENDING && (Current_State == STATE_PULLBACK || Current_State == STATE_DEEP_RETRACEMENT)) { if(IsBullBias() && !Bull_MA50_Reclaimed()) state_text += " | ACTION: SELLS-ONLY (until MA50 reclaim/reject-up)"; else if(IsBearBias() && !Bear_MA50_Reclaimed()) state_text += " | ACTION: BUYS-ONLY (until MA50 reclaim/reject-down)"; else state_text += " | ACTION: TREND-OK"; } color state_color = clrWhite; if(Current_State == STATE_CONTINUATION) state_color = clrLime; else if(Current_State == STATE_PULLBACK) state_color = clrYellow; else if(Current_State == STATE_DEEP_RETRACEMENT) state_color = clrOrange; else if(Current_State == STATE_REVERSAL_ATTEMPT) state_color = clrOrangeRed; else if(Current_State == STATE_REVERSAL_CONFIRMED) state_color = clrRed; else if(Current_Family == FAMILY_RANGING) state_color = clrAqua; else if(Current_Family == FAMILY_CHOP) state_color = clrViolet; ObjectSetString(0, "StateLabel", OBJPROP_TEXT, state_text); ObjectSetInteger(0, "StateLabel", OBJPROP_COLOR, state_color); ObjectSetInteger(0, "StateLabel", OBJPROP_FONTSIZE, 11); // WARNING LABEL bool anyWarn = (Stoch_Extreme_Warning || Stoch_Reject_Warning || MA7_Cross_14_Warning || MA7_Cross_21_Warning || MA50_Break_Warning || Fib_Reject_Warning || MFIB_Reject_Warning || MA_Reject_Warning); if(anyWarn) { ObjectDelete(0, "WarningLabel"); ObjectCreate(0, "WarningLabel", OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, "WarningLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, "WarningLabel", OBJPROP_XDISTANCE, 10); ObjectSetInteger(0, "WarningLabel", OBJPROP_YDISTANCE, 60); string warn_text = "WARN: "; if(Stoch_Extreme_Warning) warn_text += "STOCH-EXT | "; if(Stoch_Reject_Warning) warn_text += "STOCH-REJECT | "; if(MA7_Cross_14_Warning) warn_text += "MA7x14 | "; if(MA7_Cross_21_Warning) warn_text += "MA7x21 | "; if(MA50_Break_Warning) warn_text += "MA50-BREAK | "; if(Fib_Reject_Warning) warn_text += "FIB-REJECT | "; if(MFIB_Reject_Warning) warn_text += "MFIB-REJECT | "; if(MA_Reject_Warning) warn_text += "MA-REJECT"; ObjectSetString(0, "WarningLabel", OBJPROP_TEXT, warn_text); ObjectSetInteger(0, "WarningLabel", OBJPROP_COLOR, clrRed); ObjectSetInteger(0, "WarningLabel", OBJPROP_FONTSIZE, 10); } else { ObjectDelete(0, "WarningLabel"); } } //+------------------------------------------------------------------+ void MarkRunners() { double current = MidPrice(); for(int i=0; i OpenPositions[i].distance_from_current) { Position temp = OpenPositions[i]; OpenPositions[i] = OpenPositions[j]; OpenPositions[j] = temp; } } } for(int i=0; i=0; i--) { if(PositionGetTicket(i) == 0) continue; if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue; if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue; ulong ticket = PositionGetTicket(i); bool is_buy = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY); int idx = -1; for(int j=0; j= 0 && OpenPositions[idx].is_runner) { Print("🏃 RUNNER PROTECTED: ", OpenPositions[idx].setup_name, " | Dist: ", (int)OpenPositions[idx].distance_from_current); continue; } bool should_close = false; if(is_buy && IsBearBias()) should_close = true; if(!is_buy && IsBullBias()) should_close = true; if(should_close) { if(Trade.PositionClose(ticket)) { ClosedByReversal++; Print("✂ REVERSAL CLOSE: ", is_buy ? "BUY" : "SELL"); } } } } //+------------------------------------------------------------------+ // Direction filter core: // - Strong/confirmed/weak trend: allow trend direction in continuation. // - During pullback/deep retracement: ONLY countertrend until MA50 reclaim/reject. // - Range/chop: allow both but keep range-engine preference via your setup logic. bool IsDirectionAllowed(bool is_buy) { if(!Use_Market_Mode_Filter) return true; // Trending family directional rules if(Current_Family == FAMILY_TRENDING) { // Reversal confirmed: trade ONLY new bias direction if(Current_State == STATE_REVERSAL_CONFIRMED) { if(IsBullBias() && !is_buy) return false; if(IsBearBias() && is_buy) return false; return true; } // Pullback / deep retracement: countertrend-only until MA50 reclaim/reject if(Current_State == STATE_PULLBACK || Current_State == STATE_DEEP_RETRACEMENT) { if(IsBullBias()) { if(!Bull_MA50_Reclaimed()) return (!is_buy); // SELLS ONLY // once reclaimed/rejected-up, allow trend direction again return is_buy; } if(IsBearBias()) { if(!Bear_MA50_Reclaimed()) return (is_buy); // BUYS ONLY return (!is_buy); } } // Continuation: trend direction only (aggressive) if(Current_State == STATE_CONTINUATION) { if(IsBullBias() && !is_buy) return false; if(IsBearBias() && is_buy) return false; return true; } // Reversal attempt: still allow both, but you can tighten here later return true; } // Ranging / Chop / Transitional: allow both (your setup blocks decide) return true; } //+------------------------------------------------------------------+ int CountSetupTrades(SETUP_TYPE setup) { int count = 0; for(int i=0; i= Max_Trades_Per_Setup) return; if(PositionsTotal() >= Max_Total_Trades) return; datetime now = TimeCurrent(); if(now - LastEntryTime[setup_type] < 1) return; LastEntryTime[setup_type] = now; double lot = GetLotSize(); if(lot < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)) return; double sl = buy ? price - Initial_SL_Points * _Point : price + Initial_SL_Points * _Point; double tp = buy ? price + TP_Points * _Point : price - TP_Points * _Point; string comment = setup_name + "|" + FamilyToText(Current_Family) + "|" + BiasToText(Current_Bias) + "|" + StrengthToText(Current_Strength) + "|" + StateToText(Current_State); bool result = false; if(buy) result = Trade.Buy(lot, _Symbol, 0, sl, tp, comment); else result = Trade.Sell(lot, _Symbol, 0, sl, tp, comment); if(result) { TodayTrades++; if(buy) BuyTrades++; else SellTrades++; SetupCount[setup_type]++; ulong ticket = Trade.ResultOrder(); int size = ArraySize(OpenPositions); ArrayResize(OpenPositions, size+1); OpenPositions[size].ticket = ticket; OpenPositions[size].entry = price; OpenPositions[size].original_lot = lot; OpenPositions[size].is_buy = buy; OpenPositions[size].partial_tp_hit = false; OpenPositions[size].be_set = false; OpenPositions[size].trailing_active = false; OpenPositions[size].is_runner = false; OpenPositions[size].setup_type = setup_type; OpenPositions[size].setup_name = setup_name; OpenPositions[size].entry_family = Current_Family; OpenPositions[size].entry_bias = Current_Bias; OpenPositions[size].entry_strength = Current_Strength; OpenPositions[size].distance_from_current = 0; Print("✓ ", setup_name, " ", buy ? "BUY" : "SELL", " | ", BiasToText(Current_Bias), " | ", StateToText(Current_State)); } } //+------------------------------------------------------------------+ void ManagePositions() { 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= Partial_TP_Points) { double current_lot = PositionGetDouble(POSITION_VOLUME); double close_size = NormalizeDouble(OpenPositions[idx].original_lot * Partial_TP_Percent / 100.0, 2); if(close_size > 0 && close_size <= current_lot) { if(Trade.PositionClosePartial(ticket, close_size)) OpenPositions[idx].partial_tp_hit = true; } } // Break Even if(!OpenPositions[idx].be_set && profit_points >= BreakEven_Points) { if((is_buy && current_sl < entry) || (!is_buy && current_sl > entry)) { if(Trade.PositionModify(ticket, entry, current_tp)) OpenPositions[idx].be_set = true; } } // Trailing if(profit_points >= BreakEven_Points + 100) { OpenPositions[idx].trailing_active = true; double newSL = 0; bool should_modify = false; if(is_buy) { newSL = current - Trailing_Distance_Points * _Point; if(newSL > current_sl + 30 * _Point) should_modify = true; } else { newSL = current + Trailing_Distance_Points * _Point; if(newSL < current_sl - 30 * _Point) should_modify = true; } if(should_modify) Trade.PositionModify(ticket, newSL, current_tp); } } } //+------------------------------------------------------------------+ void OnTick() { UpdateIndicators(); DetectWarnings(); // periodic level refresh static int tick_count = 0; tick_count++; if(tick_count >= 100) { CalculateLevels(); tick_count = 0; } // update mode/state/labels UpdateModeAndState(); // manage open trades ManagePositions(); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double current = (bid + ask) / 2.0; double previous = iClose(_Symbol, PERIOD_CURRENT, 1); double buffer = MA_Touch_Buffer * _Point; //================================================================= // SETUPS (unchanged core triggers) — now filtered mainly by direction //================================================================= // 1) Pullback/Deep Retracement behavior (your new rule: opposite entries only) if(Current_Family == FAMILY_TRENDING && (Current_State == STATE_PULLBACK || Current_State == STATE_DEEP_RETRACEMENT)) { bool bull = IsBullBias(); bool bear = IsBearBias(); // while bull pullback: SELLS ONLY until MA50 reclaim/reject-up // while bear pullback: BUYS ONLY until MA50 reclaim/reject-down bool allowTrendAgain = (bull && Bull_MA50_Reclaimed()) || (bear && Bear_MA50_Reclaimed()); // Countertrend mean-reversion entries if(!allowTrendAgain) { // Stoch-based reversion (any reject OR extremes) if(Stoch_Extreme_Warning || Stoch_Reject_Warning) { if(bull) { // bull pullback => open sells (countertrend) if(Stoch_K_Current >= Stoch_Low) // keep it aggressive; you can tighten later OpenTrade(false, bid, "PB-COUNTER-SELL", SETUP_MEAN_REV); } if(bear) { // bear pullback => open buys (countertrend) if(Stoch_K_Current <= Stoch_High) OpenTrade(true, ask, "PB-COUNTER-BUY", SETUP_MEAN_REV); } } // Fib/MFIB reject confirmations (new) if(Fib_Reject_Warning || MFIB_Reject_Warning) { if(bull) OpenTrade(false, bid, (MFIB_Reject_Warning ? "MFIB-REJECT-SELL" : "FIB-REJECT-SELL"), SETUP_FIB_REJECT); if(bear) OpenTrade(true, ask, (MFIB_Reject_Warning ? "MFIB-REJECT-BUY" : "FIB-REJECT-BUY"), SETUP_FIB_REJECT); } // MA reject at key levels with stoch reject/extreme if(MA_Reject_Warning) { if(bull) OpenTrade(false, bid, "MA-REJECT-SELL", SETUP_CTRL_PULLBACK); if(bear) OpenTrade(true, ask, "MA-REJECT-BUY", SETUP_CTRL_PULLBACK); } } else { // MA50 reclaimed/rejected back in favor => allow trend direction entries again immediately if(bull) OpenTrade(true, ask, "MA50-RECLAIM-BUY", SETUP_MA50_BOUNCE); if(bear) OpenTrade(false, bid, "MA50-RECLAIM-SELL", SETUP_MA50_BOUNCE); } } // 2) Normal trend continuation setups if(Current_Family == FAMILY_TRENDING && Current_State == STATE_CONTINUATION) { // MA14 CROSS (kept) int ma14_crosses = 0; for(int i=0; i<10; i++) if(i != 1 && MA_Current[1] > MA_Current[i]) ma14_crosses++; if(ma14_crosses >= 2) OpenTrade(true, ask, "MA14-CROSS↑", SETUP_MA14_CROSS); ma14_crosses = 0; for(int i=0; i<10; i++) if(i != 1 && MA_Current[1] < MA_Current[i]) ma14_crosses++; if(ma14_crosses >= 2) OpenTrade(false, bid, "MA14-CROSS↓", SETUP_MA14_CROSS); // MA BOUNCES (kept) if(MathAbs(current - MA_Current[3]) <= buffer) { OpenTrade(true, ask, "MA50-BOUNCE↑", SETUP_MA50_BOUNCE); OpenTrade(false, bid, "MA50-BOUNCE↓", SETUP_MA50_BOUNCE); } if(MathAbs(current - MA_Current[4]) <= buffer) { OpenTrade(true, ask, "MA140-BOUNCE↑", SETUP_MA140_BOUNCE); OpenTrade(false, bid, "MA140-BOUNCE↓", SETUP_MA140_BOUNCE); } // FIB BREAKS (kept) for(int i=1; i<6; i++) { if(MathAbs(current - PriceLevels[i]) <= buffer) { if(previous < PriceLevels[i]) OpenTrade(true, ask, "FIB-BREAK↑", SETUP_FIB_BREAK); if(previous > PriceLevels[i]) OpenTrade(false, bid, "FIB-BREAK↓", SETUP_FIB_BREAK); } } // MAGNET WALK (kept) bool hugging = (Current_ATR > 0.0) ? (MathAbs(current - MA_Current[2]) / Current_ATR < 0.7) : false; if(hugging && MA_Current[0] > MA_Current[3]) OpenTrade(true, ask, "MAGNET-WALK↑", SETUP_MAGNET_WALK); if(hugging && MA_Current[0] < MA_Current[3]) OpenTrade(false, bid, "MAGNET-WALK↓", SETUP_MAGNET_WALK); } // 3) Range setups (kept, plus your new “don’t lose money” guard by family) if(Current_Family == FAMILY_RANGING) { if(MathAbs(current - PriceLevels[1]) < buffer && Stoch_K_Current < 35) OpenTrade(true, ask, "RANGE-BUY", SETUP_RANGE_ENGINE); if(MathAbs(current - PriceLevels[5]) < buffer && Stoch_K_Current > 65) OpenTrade(false, bid, "RANGE-SELL", SETUP_RANGE_ENGINE); // Optional extra: MFIB reject inside range edges = higher confidence if(MFIB_Reject_Warning) { if(Stoch_Reject_Warning || Stoch_Extreme_Warning) { // if near lower half -> buy; upper half -> sell if(current <= MFIB_Level_050) OpenTrade(true, ask, "RANGE-MFIB-BUY", SETUP_RANGE_ENGINE); if(current >= MFIB_Level_050) OpenTrade(false, bid, "RANGE-MFIB-SELL", SETUP_RANGE_ENGINE); } } } // 4) Chop handling (light-touch; your direction filter won’t block) if(Current_Family == FAMILY_CHOP) { // In chop: lean mean reversion + rejects if(Stoch_Extreme_Warning || Stoch_Reject_Warning || Fib_Reject_Warning || MFIB_Reject_Warning) { if(Stoch_K_Current <= Stoch_Low) OpenTrade(true, ask, "CHOP-REV-BUY", SETUP_MEAN_REV); if(Stoch_K_Current >= Stoch_High) OpenTrade(false, bid, "CHOP-REV-SELL", SETUP_MEAN_REV); } } } //+------------------------------------------------------------------+