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

1001 lines
77 KiB
MQL5

//+------------------------------------------------------------------+
//| VIZION_MASTER_MFIB_Engine_FIXED_v9_12.mq5 |
//| COMBINED: v9.11 Institutional engine + v2.01 “takes trades” flow |
//| FIXED: no nested functions, no duplicate vars, correct ordering |
//| KEEP: all setups + aggressive re-entry + ALWAYS 4-entry batching |
//| KEEP: RR>=1:8 via MFIB level-walk TP |
//| ADD: MFIB close-near interaction (stops “no trades” issue) |
//| ADD: safer no-trade filter (doesn't choke strong setups) |
//| NOTE: No max trades/day, no daily caps |
//+------------------------------------------------------------------+
#property strict
#property version "9.12"
#include <Trade/Trade.mqh>
CTrade trade;
//============================== INPUTS ==============================
input ENUM_TIMEFRAMES InpTF = PERIOD_CURRENT;
// MFIB (ONLY level engine)
input int InpMFIB_LookbackBars = 2500; // ATH/ATL scan window
input double InpTolPoints = 140; // touch tolerance (points) (was too tight -> “no trades”)
input int InpFlipWindowBars = 18; // whipsaw detection window
input int InpFalseBreakBars = 2; // false break check bars
// Risk & execution
input double InpRR_Min = 8.0; // minimum RR 1:8
input double InpSL_BufferPoints = 80; // SL buffer beyond MFIB/EMA14
input double InpRiskPct = 0.60; // base entry risk (balance %)
input double InpAddRiskPct = 0.30; // add-on risk
input int InpMaxAddsPerTrend = 8; // cap per trend (still aggressive)
input int InpMinEntryGapPoints = 25; // spacing between entries (AGGRESSIVE)
input long InpMagic = 8081400;
input int InpSlippagePoints = 30;
// Always 4 entries per clean setup
input bool InpAlwaysFourPerSetup = true;
input int InpEntriesPerSetup = 4; // forced batch size
input double InpEntryBatchStepPoints = 35; // spacing inside batch (points)
// Heartbeat recency
input int InpHeartbeatLookback = 24; // 7↔50 fresh window
input int InpEarlyFlipLookback = 18; // 7↔(14&21) fresh window
// Continuation detection
input int InpContinuBarWindow = 12; // bars to evaluate staircase
input int InpContinuMinMFIBBreaks = 2; // MFIB breaks within window
input int InpContinuMin7Crosses = 2; // EMA7 crosses vs others within window
// Stochastic (timing)
input int InpStochK = 14;
input int InpStochD = 3;
input int InpStochSlowing = 3;
input ENUM_MA_METHOD InpStochMethod = MODE_SMA;
input ENUM_STO_PRICE InpStochPriceField = STO_LOWHIGH;
// UI panel
input bool InpShowPanel = true;
input int InpCorner = 0;
input int InpX = 10;
input int InpY = 14;
input int InpFontSize = 12;
input int InpPanelW = 820;
input int InpPanelH = 520;
//============================== GLOBALS ==============================
string PFX="VIZ_MASTER_";
string PANEL_BG="VIZ_MASTER_PANEL_BG";
// EMA handles
int hE7=-1,hE14=-1,hE21=-1,hE50=-1,hE140=-1,hE230=-1,hE500=-1,hE1400=-1;
int hStoch=-1;
// MFIB ratios (include extensions to help reach RR>=8)
double g_ratios[] = {0.0,0.32,0.382,0.5,0.618,0.705,0.786,1.0,1.272,1.618,2.0,2.618};
double g_bullLevels[160]; int g_bullCount=0;
double g_bearLevels[160]; int g_bearCount=0;
double g_mfib032_low=EMPTY_VALUE;
double g_mfib032_high=EMPTY_VALUE;
double g_ath=EMPTY_VALUE, g_atl=EMPTY_VALUE;
// entry tracking
double g_lastLongEntry=0.0;
double g_lastShortEntry=0.0;
//============================== HELPERS ==============================
double AbsD(double v){ return (v<0?-v:v); }
bool ObjExists(const string name){ return (ObjectFind(0,name) >= 0); }
double GetBuf(const int handle,const int bufferIndex,const int shift)
{
double a[];
if(CopyBuffer(handle,bufferIndex,shift,1,a)!=1) return EMPTY_VALUE;
return a[0];
}
bool TouchedWithin(const double hi,const double lo,const double lvl,const double tolPrice)
{ return (hi >= (lvl - tolPrice) && lo <= (lvl + tolPrice)); }
bool CrossUp(const double prevA,const double prevB,const double curA,const double curB)
{ return (prevA<=prevB && curA>curB); }
bool CrossDown(const double prevA,const double prevB,const double curA,const double curB)
{ return (prevA>=prevB && curA<curB); }
int BarsSinceCross(const int hA,const int hB,const bool wantUp,const int maxLook)
{
for(int i=1;i<=maxLook;i++)
{
double ap=GetBuf(hA,0,i);
double bp=GetBuf(hB,0,i);
double ac=GetBuf(hA,0,i-1);
double bc=GetBuf(hB,0,i-1);
if(ap==EMPTY_VALUE||bp==EMPTY_VALUE||ac==EMPTY_VALUE||bc==EMPTY_VALUE) continue;
if(wantUp && CrossUp(ap,bp,ac,bc)) return i;
if(!wantUp && CrossDown(ap,bp,ac,bc)) return i;
}
return 9999;
}
//============================== UI ==================================
void PutPanelBG()
{
if(!InpShowPanel) return;
if(!ObjExists(PANEL_BG))
{
ObjectCreate(0,PANEL_BG,OBJ_RECTANGLE_LABEL,0,0,0);
ObjectSetInteger(0,PANEL_BG,OBJPROP_CORNER,InpCorner);
ObjectSetInteger(0,PANEL_BG,OBJPROP_XDISTANCE,InpX-6);
ObjectSetInteger(0,PANEL_BG,OBJPROP_YDISTANCE,InpY-6);
ObjectSetInteger(0,PANEL_BG,OBJPROP_BGCOLOR,(long)clrBlack);
ObjectSetInteger(0,PANEL_BG,OBJPROP_COLOR,(long)clrDimGray);
ObjectSetInteger(0,PANEL_BG,OBJPROP_BACK,true);
ObjectSetInteger(0,PANEL_BG,OBJPROP_XSIZE,InpPanelW);
ObjectSetInteger(0,PANEL_BG,OBJPROP_YSIZE,InpPanelH);
ObjectSetInteger(0,PANEL_BG,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,PANEL_BG,OBJPROP_HIDDEN,true);
}
}
void PutLabel(const string shortName,const string text,const int x,const int y,const color col)
{
if(!InpShowPanel) return;
string obj = PFX + "LBL_" + shortName;
if(!ObjExists(obj))
{
ObjectCreate(0,obj,OBJ_LABEL,0,0,0);
ObjectSetInteger(0,obj,OBJPROP_CORNER,InpCorner);
ObjectSetInteger(0,obj,OBJPROP_XDISTANCE,x);
ObjectSetInteger(0,obj,OBJPROP_YDISTANCE,y);
ObjectSetInteger(0,obj,OBJPROP_FONTSIZE,InpFontSize);
ObjectSetString (0,obj,OBJPROP_FONT,"Consolas");
ObjectSetInteger(0,obj,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,obj,OBJPROP_HIDDEN,true);
}
ObjectSetString (0,obj,OBJPROP_TEXT,text);
ObjectSetInteger(0,obj,OBJPROP_COLOR,(long)col);
}
void PutHLine(const string shortName,const double price,const color col,const ENUM_LINE_STYLE style=STYLE_DOT)
{
string obj = PFX + "HL_" + shortName;
if(!ObjExists(obj))
{
ObjectCreate(0,obj,OBJ_HLINE,0,0,price);
ObjectSetInteger(0,obj,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,obj,OBJPROP_HIDDEN,true);
}
ObjectSetDouble (0,obj,OBJPROP_PRICE,price);
ObjectSetInteger(0,obj,OBJPROP_COLOR,(long)col);
ObjectSetInteger(0,obj,OBJPROP_STYLE,style);
ObjectSetInteger(0,obj,OBJPROP_WIDTH,1);
}
void CleanupObjects()
{
int total=ObjectsTotal(0);
for(int i=total-1;i>=0;i--)
{
string nm=ObjectName(0,i);
if(StringFind(nm,PFX)==0) ObjectDelete(0,nm);
}
ObjectDelete(0,PANEL_BG);
}
//============================== MFIB ================================
bool BuildMFIB()
{
int barsAvail = Bars(_Symbol,InpTF);
if(barsAvail < 600) return false;
int scanBars = InpMFIB_LookbackBars;
if(scanBars<=0 || scanBars>barsAvail) scanBars=barsAvail;
int hiIdx = iHighest(_Symbol,InpTF,MODE_HIGH,scanBars,0);
int loIdx = iLowest (_Symbol,InpTF,MODE_LOW ,scanBars,0);
if(hiIdx<0 || loIdx<0) return false;
g_ath = iHigh(_Symbol,InpTF,hiIdx);
g_atl = iLow (_Symbol,InpTF,loIdx);
double range = g_ath - g_atl;
if(range<=0) return false;
// dual 0.32 stack anchors
g_mfib032_low = g_atl + range*0.32;
g_mfib032_high = g_ath - range*0.32;
// Bull fib: ATL -> ATH
g_bullCount=0;
for(int i=0;i<ArraySize(g_ratios) && g_bullCount<(int)ArraySize(g_bullLevels);i++)
g_bullLevels[g_bullCount++] = g_atl + range*g_ratios[i];
// Bear fib: ATH -> ATL
g_bearCount=0;
for(int j=0;j<ArraySize(g_ratios) && g_bearCount<(int)ArraySize(g_bearLevels);j++)
g_bearLevels[g_bearCount++] = g_ath - range*g_ratios[j];
return true;
}
bool MFIB_TouchedAny(const double hi,const double lo,const double tolPrice)
{
if(TouchedWithin(hi,lo,g_mfib032_low,tolPrice)) return true;
if(TouchedWithin(hi,lo,g_mfib032_high,tolPrice)) return true;
for(int i=0;i<g_bullCount;i++)
if(TouchedWithin(hi,lo,g_bullLevels[i],tolPrice)) return true;
for(int j=0;j<g_bearCount;j++)
if(TouchedWithin(hi,lo,g_bearLevels[j],tolPrice)) return true;
return false;
}
// NEW: “close near any level” so you don’t miss trades by 0.01–0.80 on gold
bool CloseNearAnyMFIB(const double close,const double tolPrice)
{
if(g_mfib032_low!=EMPTY_VALUE && AbsD(close-g_mfib032_low)<=tolPrice) return true;
if(g_mfib032_high!=EMPTY_VALUE && AbsD(close-g_mfib032_high)<=tolPrice) return true;
for(int i=0;i<g_bullCount;i++) if(AbsD(close-g_bullLevels[i])<=tolPrice) return true;
for(int j=0;j<g_bearCount;j++) if(AbsD(close-g_bearLevels[j])<=tolPrice) return true;
return false;
}
// FIXED: arrays passed by reference in MQL5
double NextUp(const double price,const double &levels[],const int count)
{
double best=EMPTY_VALUE;
for(int i=0;i<count;i++)
if(levels[i]>price && (best==EMPTY_VALUE || levels[i]<best)) best=levels[i];
return best;
}
double NextDown(const double price,const double &levels[],const int count)
{
double best=EMPTY_VALUE;
for(int i=0;i<count;i++)
if(levels[i]<price && (best==EMPTY_VALUE || levels[i]>best)) best=levels[i];
return best;
}
double ClosestLevel(const double price,const double &levels[],const int count)
{
if(count<=0) return EMPTY_VALUE;
double best=levels[0];
double bd=AbsD(price-best);
for(int i=1;i<count;i++)
{
double d=AbsD(price-levels[i]);
if(d<bd){ bd=d; best=levels[i]; }
}
return best;
}
// MFIB reject/reclaim helper
bool Reclaim(const double prevClose,const double curClose,const double lvl,const double tol)
{ return (prevClose < (lvl - tol) && curClose > (lvl + tol)); }
bool Reject(const double prevClose,const double curClose,const double lvl,const double tol)
{ return (prevClose > (lvl + tol) && curClose < (lvl - tol)); }
bool MFIB_Whipsaw032(const double lvl,const double tol)
{
int flips=0;
for(int i=1;i<=InpFlipWindowBars;i++)
{
double c1=iClose(_Symbol,InpTF,i);
double c0=iClose(_Symbol,InpTF,i-1);
if((c1 < (lvl-tol) && c0 > (lvl+tol)) || (c1 > (lvl+tol) && c0 < (lvl-tol)))
flips++;
if(flips>=2) return true;
}
return false;
}
bool MFIB_FalseBreak032(const double lvl,const double tol,const bool brokeUp)
{
double c0=iClose(_Symbol,InpTF,0);
for(int i=1;i<=InpFalseBreakBars;i++)
{
double c=iClose(_Symbol,InpTF,i);
if(brokeUp)
{ if(c > (lvl+tol) && c0 < (lvl-tol)) return true; }
else
{ if(c < (lvl-tol) && c0 > (lvl+tol)) return true; }
}
return false;
}
int CountMFIBBreaks(const bool bull,const int windowBars,const double tolPrice)
{
const int cnt = bull ? g_bullCount : g_bearCount;
if(cnt<3) return 0;
int breaks=0;
for(int i=windowBars;i>=1;i--)
{
double cPrev=iClose(_Symbol,InpTF,i);
double cCur =iClose(_Symbol,InpTF,i-1);
for(int k=1;k<cnt-1;k++)
{
double L = bull ? g_bullLevels[k] : g_bearLevels[k];
if(bull)
{
if(cPrev < (L - tolPrice) && cCur > (L + tolPrice)) { breaks++; break; }
}
else
{
if(cPrev > (L + tolPrice) && cCur < (L - tolPrice)) { breaks++; break; }
}
}
}
return breaks;
}
//============================== EMA INTERACTION ======================
void EMA_Interaction(const double hi,const double lo,const double prevClose,const double curClose,
const double ema,const double tol,
bool &touch,bool &reclaim,bool &reject)
{
touch = TouchedWithin(hi,lo,ema,tol);
reclaim = (prevClose < (ema - tol) && curClose > (ema + tol));
reject = (prevClose > (ema + tol) && curClose < (ema - tol));
}
int Count7CrossesWithin(const int windowBars)
{
int crosses=0;
for(int i=windowBars;i>=1;i--)
{
double e7p = GetBuf(hE7,0,i);
double e7c = GetBuf(hE7,0,i-1);
if(e7p==EMPTY_VALUE||e7c==EMPTY_VALUE) continue;
double e14p = GetBuf(hE14,0,i), e14c = GetBuf(hE14,0,i-1);
double e21p = GetBuf(hE21,0,i), e21c = GetBuf(hE21,0,i-1);
double e50p = GetBuf(hE50,0,i), e50c = GetBuf(hE50,0,i-1);
double e140p= GetBuf(hE140,0,i), e140c= GetBuf(hE140,0,i-1);
double e230p= GetBuf(hE230,0,i), e230c= GetBuf(hE230,0,i-1);
if(CrossUp(e7p,e14p,e7c,e14c) || CrossDown(e7p,e14p,e7c,e14c)) crosses++;
if(CrossUp(e7p,e21p,e7c,e21c) || CrossDown(e7p,e21p,e7c,e21c)) crosses++;
if(CrossUp(e7p,e50p,e7c,e50c) || CrossDown(e7p,e50p,e7c,e50c)) crosses++;
if(CrossUp(e7p,e140p,e7c,e140c)|| CrossDown(e7p,e140p,e7c,e140c)) crosses++;
if(CrossUp(e7p,e230p,e7c,e230c)|| CrossDown(e7p,e230p,e7c,e230c)) crosses++;
}
return crosses;
}
//============================== STOCH (TIMING ONLY) ==================
void StochFlags(double &k0,double &d0,
bool &osHold,bool &obReject,
bool &bullReset,bool &bearReset,
bool &hold50,bool &fail50,
bool &bullX,bool &bearX)
{
double k1=GetBuf(hStoch,0,1);
double d1=GetBuf(hStoch,1,1);
osHold = (k0<=20.0);
obReject = (k0>=80.0);
bullX = (k1<d1 && k0>d0);
bearX = (k1>d1 && k0<d0);
bullReset = (k1>80.0 && k0>=40.0 && k0<=55.0 && k0>k1);
bearReset = (k1<20.0 && k0>=45.0 && k0<=60.0 && k0<k1);
hold50 = (k0>=50.0 && k0<=60.0 && k0>k1);
fail50 = (k0<=50.0 && k0>=40.0 && k0<k1);
}
//============================== POSITIONS ============================
int CountMyPositions(const ENUM_POSITION_TYPE type)
{
int n=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if((long)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)!=type) continue;
n++;
}
return n;
}
double LastEntryPriceMy(const ENUM_POSITION_TYPE type)
{
double last=0.0;
datetime lt=0;
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if((long)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)!=type) continue;
datetime ot=(datetime)PositionGetInteger(POSITION_TIME);
if(ot>lt){ lt=ot; last=PositionGetDouble(POSITION_PRICE_OPEN); }
}
return last;
}
bool HasMinGap(const ENUM_POSITION_TYPE type,const double entry)
{
double last=(type==POSITION_TYPE_BUY?g_lastLongEntry:g_lastShortEntry);
if(last<=0.0) last=LastEntryPriceMy(type);
if(last<=0.0) return true;
return (AbsD(entry-last) >= (InpMinEntryGapPoints*_Point));
}
void CloseOpposing(const ENUM_POSITION_TYPE typeToClose)
{
for(int i=PositionsTotal()-1;i>=0;i--)
{
ulong ticket=PositionGetTicket(i);
if(ticket==0) continue;
if(!PositionSelectByTicket(ticket)) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if((long)PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)!=typeToClose) continue;
trade.PositionClose(ticket);
}
}
//============================== LOTS (RISK) ==========================
double CalcLotsByRisk(const double entry,const double sl,const double riskPct)
{
double bal=AccountInfoDouble(ACCOUNT_BALANCE);
double riskMoney=bal*(riskPct/100.0);
double tickValue=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
double tickSize =SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
if(tickValue<=0 || tickSize<=0) return 0.0;
double dist=AbsD(entry-sl);
if(dist < (2*_Point)) return 0.0;
double valuePerPointPerLot=(tickValue/tickSize)*_Point;
if(valuePerPointPerLot<=0) return 0.0;
double riskPerLot=(dist/_Point)*valuePerPointPerLot;
if(riskPerLot<=0) return 0.0;
double lots=riskMoney/riskPerLot;
double minLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double maxLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
double step =SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
lots=MathMax(minLot,MathMin(maxLot,lots));
lots=MathFloor(lots/step)*step;
return NormalizeDouble(lots,2);
}
//============================== SL/TP (MFIB LEVELS) ==================
bool ProjectSLTP(const bool isLong,
const double entry,
const double ema14,
const double slBufPrice,
double &sl,double &tp,double &rr)
{
sl=EMPTY_VALUE; tp=EMPTY_VALUE; rr=0.0;
double nearFib = isLong ? ClosestLevel(entry,g_bullLevels,g_bullCount)
: ClosestLevel(entry,g_bearLevels,g_bearCount);
if(nearFib==EMPTY_VALUE) return false;
if(isLong) sl = MathMin(ema14,nearFib) - slBufPrice;
else sl = MathMax(ema14,nearFib) + slBufPrice;
double risk=AbsD(entry-sl);
if(risk < (2*_Point)) return false;
if(isLong)
{
double cand=NextUp(entry,g_bullLevels,g_bullCount);
while(cand!=EMPTY_VALUE)
{
rr=AbsD(cand-entry)/risk;
if(rr>=InpRR_Min){ tp=cand; return true; }
cand=NextUp(cand+_Point,g_bullLevels,g_bullCount);
}
}
else
{
double cand=NextDown(entry,g_bearLevels,g_bearCount);
while(cand!=EMPTY_VALUE)
{
rr=AbsD(entry-cand)/risk;
if(rr>=InpRR_Min){ tp=cand; return true; }
cand=NextDown(cand-_Point,g_bearLevels,g_bearCount);
}
}
return false;
}
//============================== SEND ORDERS ==========================
bool SendBuy(const double lots,const double sl,const double tp)
{
trade.SetExpertMagicNumber(InpMagic);
trade.SetDeviationInPoints(InpSlippagePoints);
return trade.Buy(lots,_Symbol,0.0,sl,tp,"VIZ_MASTER");
}
bool SendSell(const double lots,const double sl,const double tp)
{
trade.SetExpertMagicNumber(InpMagic);
trade.SetDeviationInPoints(InpSlippagePoints);
return trade.Sell(lots,_Symbol,0.0,sl,tp,"VIZ_MASTER");
}
//============================== INIT/DEINIT ==========================
int OnInit()
{
ENUM_TIMEFRAMES tf=InpTF;
hE7 = iMA(_Symbol,tf,7,0,MODE_EMA,PRICE_CLOSE);
hE14 = iMA(_Symbol,tf,14,0,MODE_EMA,PRICE_CLOSE);
hE21 = iMA(_Symbol,tf,21,0,MODE_EMA,PRICE_CLOSE);
hE50 = iMA(_Symbol,tf,50,0,MODE_EMA,PRICE_CLOSE);
hE140 = iMA(_Symbol,tf,140,0,MODE_EMA,PRICE_CLOSE);
hE230 = iMA(_Symbol,tf,230,0,MODE_EMA,PRICE_CLOSE);
hE500 = iMA(_Symbol,tf,500,0,MODE_EMA,PRICE_CLOSE);
hE1400 = iMA(_Symbol,tf,1400,0,MODE_EMA,PRICE_CLOSE);
hStoch = iStochastic(_Symbol,tf,InpStochK,InpStochD,InpStochSlowing,InpStochMethod,InpStochPriceField);
if(hE7<0||hE14<0||hE21<0||hE50<0||hE140<0||hE230<0||hE500<0||hE1400<0||hStoch<0)
return INIT_FAILED;
trade.SetExpertMagicNumber(InpMagic);
PutPanelBG();
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
CleanupObjects();
}
//============================== ONTICK ===============================
void OnTick()
{
PutPanelBG();
if(!BuildMFIB()) return;
const double tolPrice=InpTolPoints*_Point;
const double slBufPrice=InpSL_BufferPoints*_Point;
const double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
const double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
// Candle
double c0=iClose(_Symbol,InpTF,0);
double c1=iClose(_Symbol,InpTF,1);
double h0=iHigh (_Symbol,InpTF,0);
double l0=iLow (_Symbol,InpTF,0);
// EMA values
double e7 =GetBuf(hE7,0,0), e7_1=GetBuf(hE7,0,1);
double e14 =GetBuf(hE14,0,0), e14_1=GetBuf(hE14,0,1);
double e21 =GetBuf(hE21,0,0), e21_1=GetBuf(hE21,0,1);
double e50 =GetBuf(hE50,0,0), e50_1=GetBuf(hE50,0,1);
double e140 =GetBuf(hE140,0,0);
double e230 =GetBuf(hE230,0,0);
double e500 =GetBuf(hE500,0,0);
double e1400 =GetBuf(hE1400,0,0);
if(e7==EMPTY_VALUE||e14==EMPTY_VALUE||e21==EMPTY_VALUE||e50==EMPTY_VALUE||e500==EMPTY_VALUE||e1400==EMPTY_VALUE) return;
// Stoch flags
double k0=GetBuf(hStoch,0,0);
double d0=GetBuf(hStoch,1,0);
bool st_os,st_ob,st_bullReset,st_bearReset,st_50hold,st_50fail,st_bullX,st_bearX;
StochFlags(k0,d0,st_os,st_ob,st_bullReset,st_bearReset,st_50hold,st_50fail,st_bullX,st_bearX);
// MFIB interaction (FIXED)
bool mfibInteraction = MFIB_TouchedAny(h0,l0,tolPrice) || CloseNearAnyMFIB(c0,tolPrice);
// MFIB MODE via dual 0.32 anchors
string mfibMode="TRANSITION";
if(c0 > (g_mfib032_high + tolPrice)) mfibMode="BULL";
else if(c0 < (g_mfib032_low - tolPrice)) mfibMode="BEAR";
bool mfibWhipsaw = MFIB_Whipsaw032(g_mfib032_high,tolPrice) || MFIB_Whipsaw032(g_mfib032_low,tolPrice);
bool mfibFalseBreak = MFIB_FalseBreak032(g_mfib032_high,tolPrice,true) || MFIB_FalseBreak032(g_mfib032_high,tolPrice,false)
|| MFIB_FalseBreak032(g_mfib032_low ,tolPrice,true) || MFIB_FalseBreak032(g_mfib032_low ,tolPrice,false);
// MFIB 0.32 interaction (dual)
bool mfib032Support = TouchedWithin(h0,l0,g_mfib032_high,tolPrice) && (c0>g_mfib032_high);
bool mfib032Resist = TouchedWithin(h0,l0,g_mfib032_low ,tolPrice) && (c0<g_mfib032_low);
bool mfib032Reclaim = Reclaim(c1,c0,g_mfib032_high,tolPrice) || Reclaim(c1,c0,g_mfib032_low,tolPrice);
bool mfib032Reject = Reject (c1,c0,g_mfib032_high,tolPrice) || Reject (c1,c0,g_mfib032_low,tolPrice);
bool mfibModeFlip = (mfib032Reclaim || mfib032Reject);
// EMA interactions
bool ema14Touch,ema14Reclaim,ema14Reject;
bool ema21Touch,ema21Reclaim,ema21Reject;
bool ema50Touch,ema50Reclaim,ema50Reject;
bool ema140Touch,ema140Reclaim,ema140Reject;
bool ema230Touch,ema230Reclaim,ema230Reject;
bool ema500Touch,ema500Reclaim,ema500Reject;
bool ema1400Touch,ema1400Reclaim,ema1400Reject;
EMA_Interaction(h0,l0,c1,c0,e14 ,tolPrice,ema14Touch,ema14Reclaim,ema14Reject);
EMA_Interaction(h0,l0,c1,c0,e21 ,tolPrice,ema21Touch,ema21Reclaim,ema21Reject);
EMA_Interaction(h0,l0,c1,c0,e50 ,tolPrice,ema50Touch,ema50Reclaim,ema50Reject);
EMA_Interaction(h0,l0,c1,c0,e140,tolPrice,ema140Touch,ema140Reclaim,ema140Reject);
EMA_Interaction(h0,l0,c1,c0,e230,tolPrice,ema230Touch,ema230Reclaim,ema230Reject);
EMA_Interaction(h0,l0,c1,c0,e500,tolPrice,ema500Touch,ema500Reclaim,ema500Reject);
EMA_Interaction(h0,l0,c1,c0,e1400,tolPrice,ema1400Touch,ema1400Reclaim,ema1400Reject);
//================= INSTITUTIONAL STACK LABELS ==================
bool MICRO_BULL_ALIGN = (e7>e14 && e14>e21);
bool MICRO_BEAR_ALIGN = (e7<e14 && e14<e21);
bool INTRADAY_BULL_CONTROL = (e21>e50);
bool INTRADAY_BEAR_CONTROL = (e21<e50);
bool SESSION_BULL_FLOW = (c0>e140 && c0>e230);
bool SESSION_BEAR_FLOW = (c0<e140 && c0<e230);
bool MACRO_BULL_BIAS = (c0>e500);
bool MACRO_BEAR_BIAS = (c0<e500);
bool GRAVITY_RESPECT = (c0>e1400);
bool GRAVITY_CAP = (c0<e1400);
bool FULL_BULL_DOM = (e7>e14 && e14>e21 && e21>e50 && e50>e140 && e140>e230 && e230>e500 && e500>e1400);
bool FULL_BEAR_DOM = (e7<e14 && e14<e21 && e21<e50 && e50<e140 && e140<e230 && e230<e500 && e500<e1400);
// "money zones" labels (interaction > crosses)
bool EMA21_MAGNET = ema21Touch;
bool EMA50_BATTLE = ema50Touch;
bool EMA140_PIVOT = ema140Touch;
bool EMA230_MEANREV = ema230Touch;
bool EMA500_WALL = ema500Touch;
bool EMA1400_GRAV = ema1400Touch;
// EMA14 magnet continuation labels
bool EMA14_MAGNET_HOLD = ema14Touch && ((c0>e14 && c1>e14) || (c0<e14 && c1<e14));
bool EMA14_MAGNET_RECLAIM = ema14Reclaim;
bool EMA14_MAGNET_REJECT = ema14Reject;
//================= STOCH + MA CONFIRMATIONS ==================
bool PULSE_CONFIRM_LONG = st_os && (MICRO_BULL_ALIGN || INTRADAY_BULL_CONTROL);
bool PULSE_FADE_SHORT = st_ob && (MICRO_BEAR_ALIGN || INTRADAY_BEAR_CONTROL);
bool RESET_ENTRY_LONG = st_bullReset && (ema21Touch || ema50Touch);
bool RESET_SHORT = st_bearReset && (ema21Touch || ema50Touch);
bool DEEP_STRUCTURE_BUY = (ema140Touch || ema230Touch) && st_os;
bool DEEP_STRUCTURE_SELL = (ema140Touch || ema230Touch) && st_ob;
bool GRAVITY_RECLAIM_L = ema1400Reclaim && st_bullX;
bool GRAVITY_REJECT_S = ema1400Reject && st_bearX;
//================= HEARTBEAT LOGIC ==================
// Early flip: 7 crosses 14 and 21
bool earlyUpNow = CrossUp(e7_1,e14_1,e7,e14) && CrossUp(e7_1,e21_1,e7,e21);
bool earlyDnNow = CrossDown(e7_1,e14_1,e7,e14) && CrossDown(e7_1,e21_1,e7,e21);
int earlyUpBars = MathMin(BarsSinceCross(hE7,hE14,true ,InpEarlyFlipLookback),
BarsSinceCross(hE7,hE21,true ,InpEarlyFlipLookback));
int earlyDnBars = MathMin(BarsSinceCross(hE7,hE14,false,InpEarlyFlipLookback),
BarsSinceCross(hE7,hE21,false,InpEarlyFlipLookback));
bool earlyBullFresh = earlyUpNow || (earlyUpBars<=InpEarlyFlipLookback && e7>e14 && e7>e21);
bool earlyBearFresh = earlyDnNow || (earlyDnBars<=InpEarlyFlipLookback && e7<e14 && e7<e21);
// Heartbeat confirm: 7 crosses 50 (main confirmation)
bool hbUpNow = CrossUp(e7_1,e50_1,e7,e50);
bool hbDnNow = CrossDown(e7_1,e50_1,e7,e50);
int hbUpBars = BarsSinceCross(hE7,hE50,true ,InpHeartbeatLookback);
int hbDnBars = BarsSinceCross(hE7,hE50,false,InpHeartbeatLookback);
bool hbBullFresh = hbUpNow || (hbUpBars<=InpHeartbeatLookback && e7>e50);
bool hbBearFresh = hbDnNow || (hbDnBars<=InpHeartbeatLookback && e7<e50);
bool trendIntactBull = (e7>e50) || hbBullFresh;
bool trendIntactBear = (e7<e50) || hbBearFresh;
//================= CORE SETUPS ==================
// PULLBACK (trend intact + touch EMA14/MFIB032 + Stoch reset/50 confirm)
bool PULLBACK_LONG =
trendIntactBull &&
(ema14Touch || mfib032Support || mfib032Reclaim) &&
(st_bullReset || (k0>=50.0 && k0<=60.0));
bool PULLBACK_SHORT =
trendIntactBear &&
(ema14Touch || mfib032Resist || mfib032Reject) &&
(st_bearReset || (k0<=50.0 && k0>=40.0));
// RETRACE (deeper move to 140/230 with Stoch extreme then turn)
bool RETRACE_LONG =
(ema140Touch || ema230Touch) &&
(st_os || (k0<=30.0)) &&
(st_bullX || st_bullReset);
bool RETRACE_SHORT =
(ema140Touch || ema230Touch) &&
(st_ob || (k0>=70.0)) &&
(st_bearX || st_bearReset);
// REVERSAL (MFIB mode + EMA14 + Stoch cross + micro align + heartbeat)
bool REVERSAL_LONG =
(mfibMode=="BULL" || mfibModeFlip) &&
(ema14Reclaim || ema14Touch) &&
(st_bullX || st_bullReset) &&
MICRO_BULL_ALIGN &&
(hbUpNow || hbBullFresh);
bool REVERSAL_SHORT =
(mfibMode=="BEAR" || mfibModeFlip) &&
(ema14Reject || ema14Touch) &&
(st_bearX || st_bearReset) &&
MICRO_BEAR_ALIGN &&
(hbDnNow || hbBearFresh);
// CONFIRMED RETRACEMENT (trend change + MFIB reject/reclaim)
bool RETRACE_CONFIRMED_LONG =
earlyBullFresh && (mfibModeFlip || mfib032Reclaim) && (st_bullX || st_bullReset);
bool RETRACE_CONFIRMED_SHORT =
earlyBearFresh && (mfibModeFlip || mfib032Reject) && (st_bearX || st_bearReset);
// BREAK/HOLD
bool BREAK_HOLD_LONG =
mfib032Reclaim &&
(c0>e14 && c0>e50) &&
(k0>50.0) &&
(st_bullX || (k0>=50.0 && k0<=60.0)) &&
(hbUpNow || hbBullFresh);
bool BREAK_HOLD_SHORT =
mfib032Reject &&
(c0<e14 && c0<e50) &&
(k0<50.0) &&
(st_bearX || (k0<=50.0 && k0>=40.0)) &&
(hbDnNow || hbBearFresh);
// TREND CONTINUATION (continuous 7 crosses + continuous MFIB breaks + EMA14 magnet)
int mfibBreaksBull = CountMFIBBreaks(true, InpContinuBarWindow, tolPrice);
int mfibBreaksBear = CountMFIBBreaks(false, InpContinuBarWindow, tolPrice);
int sevenCrosses = Count7CrossesWithin(InpContinuBarWindow);
bool TREND_CONT_LONG =
trendIntactBull &&
EMA14_MAGNET_HOLD &&
(mfibBreaksBull >= InpContinuMinMFIBBreaks) &&
(sevenCrosses >= InpContinuMin7Crosses) &&
(k0>55.0);
bool TREND_CONT_SHORT =
trendIntactBear &&
EMA14_MAGNET_HOLD &&
(mfibBreaksBear >= InpContinuMinMFIBBreaks) &&
(sevenCrosses >= InpContinuMin7Crosses) &&
(k0<45.0);
//================= EXTRA INSTITUTIONAL SETUPS ==================
bool GOLDEN_STRUCTURE_HOLD_L = (ema50Touch || ema140Touch) && mfibInteraction &&
(AbsD(c0-ClosestLevel(c0,g_bullLevels,g_bullCount)) <= (tolPrice*2.0));
bool GOLDEN_STRUCTURE_REJ_S = (ema50Touch || ema140Touch) && mfibInteraction &&
(AbsD(c0-ClosestLevel(c0,g_bearLevels,g_bearCount)) <= (tolPrice*2.0));
bool DEEP_LIQUIDITY_BUY = ema230Touch && st_os;
bool LIQUIDITY_TRAP_SHORT = ema230Touch && st_ob;
bool GRAVITY_BREAK_RUN_L = ema1400Reclaim && (MICRO_BULL_ALIGN || INTRADAY_BULL_CONTROL) && (st_bullX || st_bullReset);
bool GRAVITY_REJECT_RUN_S = ema1400Reject && (MICRO_BEAR_ALIGN || INTRADAY_BEAR_CONTROL) && (st_bearX || st_bearReset);
bool INSTITUTIONAL_REVERSION_L = MACRO_BULL_BIAS && st_os && (AbsD(c0-e500) > AbsD(e500-e230));
bool INSTITUTIONAL_REVERSION_S = MACRO_BEAR_BIAS && st_ob && (AbsD(c0-e500) > AbsD(e500-e230));
//================= STRONG CONFIRMATION + DEAD-ZONE OVERRIDE ==================
bool strongLong =
(REVERSAL_LONG || BREAK_HOLD_LONG || RETRACE_CONFIRMED_LONG || GRAVITY_BREAK_RUN_L || TREND_CONT_LONG) &&
(mfibModeFlip || mfib032Reclaim || mfib032Support || mfibInteraction) &&
(hbUpNow || hbBullFresh) &&
(st_bullX || st_bullReset || st_50hold) &&
(MACRO_BULL_BIAS || SESSION_BULL_FLOW);
bool strongShort =
(REVERSAL_SHORT || BREAK_HOLD_SHORT || RETRACE_CONFIRMED_SHORT || GRAVITY_REJECT_RUN_S || TREND_CONT_SHORT) &&
(mfibModeFlip || mfib032Reject || mfib032Resist || mfibInteraction) &&
(hbDnNow || hbBearFresh) &&
(st_bearX || st_bearReset || st_50fail) &&
(MACRO_BEAR_BIAS || SESSION_BEAR_FLOW);
bool DeadZoneOverride = (mfibInteraction && (strongLong || strongShort));
//================= FILTERS (SAFER — WON'T KILL ALL TRADES) ==================
bool MA_Chop = (!MICRO_BULL_ALIGN && !MICRO_BEAR_ALIGN) && (AbsD(e7-e50) < (40*_Point));
bool DeadStoch = (k0>=40.0 && k0<=60.0);
// Only block if BOTH: whipsaw+chop OR deadstoch+touch14 AND not strong
bool NO_TRADE = ((mfibWhipsaw && MA_Chop) || (DeadStoch && ema14Touch && !mfibModeFlip)) && !(strongLong || strongShort);
// HARD gate behavior you wanted:
// - MFIB interaction is required unless strong override is active
if(!DeadZoneOverride)
{
if(!mfibInteraction) return;
if(NO_TRADE) return;
}
else
{
if(mfibFalseBreak) return;
}
//================= CONFIRMED TREND CHANGE: CLOSE OPPOSING ==================
bool CONF_TRENDCHANGE_UP =
earlyBullFresh && (hbUpNow || hbBullFresh) && (e7>e50) &&
mfibModeFlip && (st_bullX || st_bullReset || st_50hold);
bool CONF_TRENDCHANGE_DOWN =
earlyBearFresh && (hbDnNow || hbBearFresh) && (e7<e50) &&
mfibModeFlip && (st_bearX || st_bearReset || st_50fail);
if(CONF_TRENDCHANGE_UP) CloseOpposing(POSITION_TYPE_SELL);
if(CONF_TRENDCHANGE_DOWN) CloseOpposing(POSITION_TYPE_BUY);
//================= DECIDE TRADE INTENT ==================
bool wantLong =
strongLong ||
REVERSAL_LONG || BREAK_HOLD_LONG || PULLBACK_LONG || RETRACE_LONG || TREND_CONT_LONG ||
RETRACE_CONFIRMED_LONG || CONF_TRENDCHANGE_UP ||
PULSE_CONFIRM_LONG || RESET_ENTRY_LONG || DEEP_STRUCTURE_BUY || GRAVITY_RECLAIM_L ||
GOLDEN_STRUCTURE_HOLD_L || DEEP_LIQUIDITY_BUY || GRAVITY_BREAK_RUN_L || INSTITUTIONAL_REVERSION_L;
bool wantShort =
strongShort ||
REVERSAL_SHORT || BREAK_HOLD_SHORT || PULLBACK_SHORT || RETRACE_SHORT || TREND_CONT_SHORT ||
RETRACE_CONFIRMED_SHORT || CONF_TRENDCHANGE_DOWN ||
PULSE_FADE_SHORT || RESET_SHORT || DEEP_STRUCTURE_SELL || GRAVITY_REJECT_S ||
GOLDEN_STRUCTURE_REJ_S || LIQUIDITY_TRAP_SHORT || GRAVITY_REJECT_RUN_S || INSTITUTIONAL_REVERSION_S;
if(wantLong && wantShort)
{
if(CONF_TRENDCHANGE_UP) wantShort=false;
else if(CONF_TRENDCHANGE_DOWN) wantLong=false;
else { wantLong=false; wantShort=false; }
}
//================= AGGRESSIVE RE-ENTRY CONTROL ==================
int buys = CountMyPositions(POSITION_TYPE_BUY);
int sells= CountMyPositions(POSITION_TYPE_SELL);
bool canAddLong = (buys < (1 + InpMaxAddsPerTrend));
bool canAddShort = (sells < (1 + InpMaxAddsPerTrend));
// clean setup => force batch 4
bool cleanLong = (strongLong || TREND_CONT_LONG || PULLBACK_LONG || BREAK_HOLD_LONG || GRAVITY_BREAK_RUN_L || REVERSAL_LONG);
bool cleanShort = (strongShort|| TREND_CONT_SHORT|| PULLBACK_SHORT|| BREAK_HOLD_SHORT|| GRAVITY_REJECT_RUN_S || REVERSAL_SHORT);
int batchLong = (InpAlwaysFourPerSetup && cleanLong) ? InpEntriesPerSetup : 1;
int batchShort = (InpAlwaysFourPerSetup && cleanShort) ? InpEntriesPerSetup : 1;
//================= EXECUTE ENTRIES (BATCH) ==================
if(wantLong && canAddLong)
{
for(int n=0;n<batchLong;n++)
{
if(!canAddLong) break;
double entry = ask + (n*InpEntryBatchStepPoints*_Point);
if(!HasMinGap(POSITION_TYPE_BUY,entry) && n==0) break;
double sl,tp,rr;
if(!ProjectSLTP(true,entry,e14,slBufPrice,sl,tp,rr)) break;
double riskPct = (buys==0 ? InpRiskPct : InpAddRiskPct);
if(strongLong || TREND_CONT_LONG) riskPct = MathMin(riskPct*1.45, InpRiskPct);
double lots = CalcLotsByRisk(entry,sl,riskPct);
if(lots<=0.0) break;
if(SendBuy(lots,sl,tp))
{
g_lastLongEntry=entry;
buys++;
canAddLong = (buys < (1 + InpMaxAddsPerTrend));
}
else break;
}
}
if(wantShort && canAddShort)
{
for(int n=0;n<batchShort;n++)
{
if(!canAddShort) break;
double entry = bid - (n*InpEntryBatchStepPoints*_Point);
if(!HasMinGap(POSITION_TYPE_SELL,entry) && n==0) break;
double sl,tp,rr;
if(!ProjectSLTP(false,entry,e14,slBufPrice,sl,tp,rr)) break;
double riskPct = (sells==0 ? InpRiskPct : InpAddRiskPct);
if(strongShort || TREND_CONT_SHORT) riskPct = MathMin(riskPct*1.45, InpRiskPct);
double lots = CalcLotsByRisk(entry,sl,riskPct);
if(lots<=0.0) break;
if(SendSell(lots,sl,tp))
{
g_lastShortEntry=entry;
sells++;
canAddShort = (sells < (1 + InpMaxAddsPerTrend));
}
else break;
}
}
//================= PANEL ==================
if(InpShowPanel)
{
PutHLine("MFIB032_LOW", g_mfib032_low, clrSilver, STYLE_DOT);
PutHLine("MFIB032_HIGH", g_mfib032_high, clrSilver, STYLE_DOT);
int x=InpX,y=InpY,dy=InpFontSize+4;
PutLabel("HDR",
"VIZ MASTER | MFIB LEVEL ENGINE | Institutional Stack + EMA14 Magnet | Aggressive 4-batch | RR>=1:8",
x,y,clrSilver); y+=dy;
PutLabel("STACK",
StringFormat("MICRO:%s INTRADAY:%s SESSION:%s MACRO:%s GRAV:%s FULL:%s",
MICRO_BULL_ALIGN?"BULL":(MICRO_BEAR_ALIGN?"BEAR":"-"),
INTRADAY_BULL_CONTROL?"BULL":(INTRADAY_BEAR_CONTROL?"BEAR":"-"),
SESSION_BULL_FLOW?"BULL":(SESSION_BEAR_FLOW?"BEAR":"-"),
MACRO_BULL_BIAS?"BULL":(MACRO_BEAR_BIAS?"BEAR":"-"),
GRAVITY_RESPECT?"RESPECT":(GRAVITY_CAP?"CAP":"-"),
FULL_BULL_DOM?"BULL":(FULL_BEAR_DOM?"BEAR":"-")),
x,y,(FULL_BULL_DOM||FULL_BEAR_DOM)?clrGold:clrGray); y+=dy;
PutLabel("MZ",
StringFormat("Money Zones: EMA21=%d EMA50=%d EMA140=%d EMA230=%d EMA500=%d EMA1400=%d | MFIBInteract=%d",
EMA21_MAGNET,EMA50_BATTLE,EMA140_PIVOT,EMA230_MEANREV,EMA500_WALL,EMA1400_GRAV,(int)mfibInteraction),
x,y,clrGray); y+=dy;
PutLabel("MAGNET14",
StringFormat("EMA14 MAGNET: HOLD=%d RECLAIM=%d REJECT=%d | TrendCont L=%d S=%d",
EMA14_MAGNET_HOLD,EMA14_MAGNET_RECLAIM,EMA14_MAGNET_REJECT,TREND_CONT_LONG,TREND_CONT_SHORT),
x,y,(EMA14_MAGNET_HOLD?clrLime:clrSilver)); y+=dy;
PutLabel("TREND",
StringFormat("Heartbeat(7/50): UPnow=%d DNnow=%d | CONF_UP=%d CONF_DN=%d | Strong L=%d S=%d",
hbUpNow,hbDnNow,CONF_TRENDCHANGE_UP,CONF_TRENDCHANGE_DOWN,strongLong,strongShort),
x,y,(CONF_TRENDCHANGE_UP||CONF_TRENDCHANGE_DOWN)?clrGold:clrGray); y+=dy;
PutLabel("SET",
StringFormat("Core: REV L=%d S=%d | PULL L=%d S=%d | RETR L=%d S=%d | BREAK L=%d S=%d",
REVERSAL_LONG,REVERSAL_SHORT,PULLBACK_LONG,PULLBACK_SHORT,RETRACE_LONG,RETRACE_SHORT,BREAK_HOLD_LONG,BREAK_HOLD_SHORT),
x,y,clrSilver); y+=dy;
PutLabel("INST",
StringFormat("Inst: GOLDEN L=%d S=%d | LIQ L=%d S=%d | GRAV_RUN L=%d S=%d | INST_REV L=%d S=%d",
GOLDEN_STRUCTURE_HOLD_L,GOLDEN_STRUCTURE_REJ_S,DEEP_LIQUIDITY_BUY,LIQUIDITY_TRAP_SHORT,GRAVITY_BREAK_RUN_L,GRAVITY_REJECT_RUN_S,INSTITUTIONAL_REVERSION_L,INSTITUTIONAL_REVERSION_S),
x,y,(GRAVITY_BREAK_RUN_L||GRAVITY_REJECT_RUN_S)?clrGold:clrGray);
}
}