//+------------------------------------------------------------------+
//| SMC_AMD_IFVG_Session_EA.mq5 |
//| AMD + IFVG Strategy (HTF H4 / LTF M15) |
//| |
//| Accumulation -> Manipulation (sweep) -> Displacement -> |
//| IFVG -> Body-close Confirmation -> Entry |
//| + Trade Management : BE @1R, trail after 2R, partial TP |
//| + Session filter : London & New York only |
//| + News filter : pause X min before & after high-impact |
//| events (MT5 economic calendar) |
//| |
//| NOTE: heuristic SMC logic. Backtest & optimise before live. |
//+------------------------------------------------------------------+
#property copyright "Generated for educational use"
#property version "1.20"
#property strict
#include <Trade/[Link]>
CTrade trade;
//==================================================================
// ENUMS
//==================================================================
enum ENUM_NEWS_IMP { NEWS_LOW = 1, NEWS_MED = 2, NEWS_HIGH = 3 };
//==================================================================
// INPUTS
//==================================================================
input group "=== General / Money Management ==="
input double InpRiskPercent = 1.0; // Risk per trade (% of balance). 0 = fixed lot
input double InpFixedLot = 0.10; // Fixed lot (used only when Risk % = 0)
input long InpMagic = 990120; // Magic number
input int InpSlippage = 30; // Max deviation (points)
input int InpMaxOpenTrades = 1; // Max simultaneous positions (this EA/symbol)
input group "=== Timeframes ==="
input ENUM_TIMEFRAMES InpLTF = PERIOD_M15; // Trading timeframe (attach chart to this)
input ENUM_TIMEFRAMES InpHTF = PERIOD_H4; // Higher timeframe
input group "=== HTF Trend Filter (optional) ==="
input bool InpUseHtfTrend = true; // Only trade in HTF trend direction
input int InpHtfEmaFast = 50; // HTF fast EMA
input int InpHtfEmaSlow = 200; // HTF slow EMA
input bool InpRequireHtfClose = true; // Require HTF close beyond fast EMA
input bool InpRequireStructure = false; // Require HH/HL (buy) or LH/LL (sell)
input int InpStructurePivot = 2; // Pivot strength
input int InpStructureBars = 120; // HTF bars scanned for structure
input group "=== Phase: Accumulation ==="
input int InpAccMin = 5; // Min accumulation candles
input int InpAccMax = 20; // Max accumulation candles
input double InpAccMaxRangeATR = 1.5; // Range height <= this * ATR (low volatility)
input group "=== Phase: Manipulation (Liquidity Sweep) ==="
input int InpSweepLookback = 6; // Bars searched for the sweep
input double InpSweepMinATR = 0.10; // Sweep extends >= this * ATR beyond range
input group "=== Phase: Displacement ==="
input double InpDispBodyATR = 0.8; // Displacement body >= this * ATR
input double InpDispBodyRatio = 0.60; // Body / total-range ratio
input bool InpDispCloseBeyondPrev = true; // Close beyond prior candle extreme
input group "=== Phase: IFVG + Confirmation ==="
input bool InpRequireFullBody = true; // Whole body beyond IFVG (wick close invalid)
input int InpConfirmWindow = 4; // Bars after displacement for confirmation
input group "=== Phase: Entry Model ==="
input bool InpUseRetracement = true; // true = limit into IFVG; false = market now
input int InpPendingExpiryBars = 12; // Pending-order expiry (bars)
input int InpMaxSetupAgeBars = 6; // Act only on recently-confirmed setups
input group "=== Take Profit (R:R) ==="
input double InpMinRR = 3.0; // Minimum R:R (1:3)
input double InpPreferredRR = 5.0; // Preferred / fallback R:R (1:5)
input bool InpUseSwingTP = true; // Target next swing liquidity
input int InpSwingLookback = 60; // Lookback for liquidity / swing TP
input double InpSlBufferATR = 0.20;// SL buffer beyond sweep (* ATR)
input group "=== Trade Management ==="
input bool InpUseBreakeven = true; // Move SL to BE
input double InpBeAtR = 1.0; // Move to BE at this R multiple
input int InpBeLockPoints = 5; // Lock this many points beyond entry
input bool InpUseTrailing = true; // Trail SL
input double InpTrailStartR = 2.0; // Start trailing at this R multiple
input bool InpTrailUseATR = true;// true = ATR trail; false = R-distance trail
input double InpTrailAtrMult = 1.5; // ATR multiplier (ATR trail)
input double InpTrailRDist = 1.0; // Distance in R (R trail)
input bool InpUsePartialTP = true;// Take partial profit
input double InpPartialAtR = 2.0; // Partial close at this R multiple
input double InpPartialPct = 50.0;// % of position to close
input group "=== Session Filter (broker SERVER time!) ==="
input bool InpUseSessions = true; // Only trade inside sessions below
input bool InpSess1Enable = true; // London session
input int InpSess1StartHour = 10; // London start hour (server)
input int InpSess1EndHour = 19; // London end hour (server)
input bool InpSess2Enable = true;// New York session
input int InpSess2StartHour = 15; // NY start hour (server)
input int InpSess2EndHour = 24; // NY end hour (server)
input group "=== News Filter (MT5 Economic Calendar) ==="
input bool InpUseNewsFilter = true; // Pause around news
input int InpNewsBeforeMin = 15; // Minutes BEFORE event to pause
input int InpNewsAfterMin = 15; // Minutes AFTER event to pause
input ENUM_NEWS_IMP InpNewsMinImp = NEWS_HIGH; // Minimum importance to react to
input group "=== Engine ==="
input int InpAtrPeriod = 14; // ATR period
input int InpMaxScanBars = 150; // History scanned each new bar
//==================================================================
// GLOBALS
//==================================================================
int g_atrHandle = INVALID_HANDLE;
int g_emaFastH = INVALID_HANDLE;
int g_emaSlowH = INVALID_HANDLE;
datetime g_lastBarTime = 0;
datetime g_lastBuySetup = 0;
datetime g_lastSellSetup= 0;
bool g_newsWarned = false;
double O[], H[], L[], C[];
datetime T[];
int N = 0;
struct SmcSetup
bool valid;
int dir;
double ifvgTop, ifvgBottom;
double manipLevel;
datetime dispTime;
double entry, sl, tp;
};
struct PosState
ulong ticket;
int dir;
double entry;
double oneR;
bool movedBE;
bool partialDone;
bool trailing;
};
PosState g_pos[];
//+------------------------------------------------------------------+
int OnInit()
g_atrHandle = iATR(_Symbol, InpLTF, InpAtrPeriod);
g_emaFastH = iMA(_Symbol, InpHTF, InpHtfEmaFast, 0, MODE_EMA, PRICE_CLOSE);
g_emaSlowH = iMA(_Symbol, InpHTF, InpHtfEmaSlow, 0, MODE_EMA, PRICE_CLOSE);
if(g_atrHandle==INVALID_HANDLE || g_emaFastH==INVALID_HANDLE ||
g_emaSlowH==INVALID_HANDLE)
{ Print("Indicator handle creation failed."); return(INIT_FAILED); }
[Link](InpMagic);
[Link](InpSlippage);
[Link](_Symbol);
if(InpAccMin < 3 || InpAccMin > InpAccMax)
{ Print("Invalid accumulation bounds."); return(INIT_PARAMETERS_INCORRECT); }
if(_Period != InpLTF)
Print("WARNING: chart timeframe (", EnumToString(_Period),
") differs from InpLTF (", EnumToString(InpLTF),
"). Detection uses InpLTF data; attaching to M15 is recommended.");
Print("SMC_AMD_IFVG_Session_EA initialised on ", _Symbol);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
if(g_atrHandle!=INVALID_HANDLE) IndicatorRelease(g_atrHandle);
if(g_emaFastH!=INVALID_HANDLE) IndicatorRelease(g_emaFastH);
if(g_emaSlowH!=INVALID_HANDLE) IndicatorRelease(g_emaSlowH);
//+------------------------------------------------------------------+
void OnTick()
// Trade management always runs (sessions/news do not stop managing open trades)
ManagePositions();
// New setups only on a new closed LTF bar
datetime curBar = iTime(_Symbol, InpLTF, 0);
if(curBar == g_lastBarTime) return;
g_lastBarTime = curBar;
// Execution filters (apply to NEW entries only)
if(InpUseSessions && !InSession()) return;
if(IsNewsBlock()) return;
if(!LoadBuffers()) return;
double atr = CurrentATR();
if(atr <= 0) return;
if(InpUseHtfTrend)
int bias = HtfBias();
if(bias > 0) TryBuy(atr);
else if(bias < 0) TrySell(atr);
else
if(!TryBuy(atr)) TrySell(atr); // no HTF gate -> scan both
bool TryBuy(double atr)
SmcSetup s = FindBuySetup(atr);
if([Link] && [Link] != g_lastBuySetup && CountMyOrders() < InpMaxOpenTrades)
if(ExecuteSetup(s)) { g_lastBuySetup = [Link]; return true; }
return false;
bool TrySell(double atr)
SmcSetup s = FindSellSetup(atr);
if([Link] && [Link] != g_lastSellSetup && CountMyOrders() < InpMaxOpenTrades)
if(ExecuteSetup(s)) { g_lastSellSetup = [Link]; return true; }
return false;
//==================================================================
// SESSION FILTER (server time)
//==================================================================
bool HourInWindow(int h, int start, int end)
// end==24 means midnight; supports wrap (e.g., 22 -> 5)
if(start == end) return false;
if(start < end) return (h >= start && h < end);
return (h >= start || h < end); // wraps midnight
bool InSession()
MqlDateTime dt; TimeToStruct(TimeCurrent(), dt);
int h = [Link];
bool ok = false;
if(InpSess1Enable && HourInWindow(h, InpSess1StartHour, InpSess1EndHour)) ok = true;
if(InpSess2Enable && HourInWindow(h, InpSess2StartHour, InpSess2EndHour)) ok = true;
return ok;
//==================================================================
// NEWS FILTER (MT5 economic calendar)
//==================================================================
bool NewsInRange(datetime from, datetime to, datetime now, string currency)
MqlCalendarValue values[];
int n = CalendarValueHistory(values, from, to, NULL, currency);
if(n <= 0) return false;
for(int i = 0; i < n; i++)
MqlCalendarEvent ev;
if(!CalendarEventById(values[i].event_id, ev)) continue;
if((int)[Link] < (int)InpNewsMinImp) continue;
datetime et = values[i].time;
if(now >= et - InpNewsBeforeMin*60 && now <= et + InpNewsAfterMin*60)
return true;
return false;
bool IsNewsBlock()
if(!InpUseNewsFilter) return false;
datetime now = TimeCurrent();
datetime from = now - (InpNewsAfterMin + 2)*60;
datetime to = now + (InpNewsBeforeMin + 2)*60;
string cur1 = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_BASE);
string cur2 = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_PROFIT);
bool blocked = false;
if(StringLen(cur1) > 0) blocked = NewsInRange(from, to, now, cur1);
if(!blocked && StringLen(cur2) > 0 && cur2 != cur1)
blocked = NewsInRange(from, to, now, cur2);
// If the calendar returns nothing ever, warn once (tester/broker may not support it)
if(!blocked && !g_newsWarned)
MqlCalendarValue probe[];
if(CalendarValueHistory(probe, now-86400, now+86400, NULL, cur1) <= 0)
Print("NOTE: economic calendar returned no data for ", cur1,
". News filter may be unsupported on this broker/tester.");
g_newsWarned = true;
return blocked;
}
//==================================================================
// DATA
//==================================================================
bool LoadBuffers()
int want = MathMin(InpMaxScanBars + 60, 1000);
MqlRates r[];
ArraySetAsSeries(r, false);
int got = CopyRates(_Symbol, InpLTF, 0, want, r);
if(got < InpAccMax + InpSweepLookback + 10) return false;
N = got - 1;
ArrayResize(O,N); ArrayResize(H,N); ArrayResize(L,N);
ArrayResize(C,N); ArrayResize(T,N);
for(int i=0;i<N;i++){ O[i]=r[i].open; H[i]=r[i].high; L[i]=r[i].low; C[i]=r[i].close; T[i]=r[i].time; }
return true;
double CurrentATR()
double buf[];
if(CopyBuffer(g_atrHandle,0,0,2,buf)<2) return 0.0;
return buf[1];
}
//==================================================================
// HTF TREND (optional)
//==================================================================
int HtfBias()
double f[], s[];
if(CopyBuffer(g_emaFastH,0,0,2,f)<2) return 0;
if(CopyBuffer(g_emaSlowH,0,0,2,s)<2) return 0;
double fast=f[1], slow=s[1];
double htfClose=iClose(_Symbol, InpHTF, 1);
bool bull=(fast>slow), bear=(fast<slow);
if(InpRequireHtfClose){ bull=bull&&(htfClose>fast); bear=bear&&(htfClose<fast); }
if(InpRequireStructure){ int st=HtfStructure(); bull=bull&&(st>0); bear=bear&&(st<0); }
if(bull) return 1;
if(bear) return -1;
return 0;
int HtfStructure()
MqlRates r[];
ArraySetAsSeries(r,false);
int got = CopyRates(_Symbol, InpHTF, 0, InpStructureBars+2, r);
if(got < 4*InpStructurePivot+5) return 0;
int n = got-1;
double sh[]; double sl[];
int p = InpStructurePivot;
for(int i=p;i<n-p;i++)
bool isHigh=true, isLow=true;
for(int k=1;k<=p;k++)
if(r[i].high<=r[i-k].high || r[i].high<=r[i+k].high) isHigh=false;
if(r[i].low >=r[i-k].low || r[i].low >=r[i+k].low ) isLow=false;
if(isHigh){ int z=ArraySize(sh); ArrayResize(sh,z+1); sh[z]=r[i].high; }
if(isLow ){ int z=ArraySize(sl); ArrayResize(sl,z+1); sl[z]=r[i].low; }
int nh=ArraySize(sh), nl=ArraySize(sl);
if(nh<2||nl<2) return 0;
bool hh=sh[nh-1]>sh[nh-2], hl=sl[nl-1]>sl[nl-2];
bool lh=sh[nh-1]<sh[nh-2], ll=sl[nl-1]<sl[nl-2];
if(hh&&hl) return 1;
if(lh&&ll) return -1;
return 0;
}
//==================================================================
// RANGE HELPERS
//==================================================================
double HighestHigh(int from,int to){ double m=-DBL_MAX; for(int i=from;i<=to;i++) if(H[i]>m)m=H[i];
return m; }
double LowestLow (int from,int to){ double m= DBL_MAX; for(int i=from;i<=to;i++) if(L[i]<m)m=L[i];
return m; }
//==================================================================
// BUY SETUP
//==================================================================
SmcSetup FindBuySetup(double atr)
SmcSetup out; [Link]=false; [Link]=1;
int newest=N-1, pStart=newest-1, pEnd=InpAccMin+InpSweepLookback+2;
for(int p=pStart; p>=pEnd; p--)
double body=C[p]-O[p], range=H[p]-L[p];
if(C[p]<=O[p]) continue;
if(body<InpDispBodyATR*atr) continue;
if(range<=0||body/range<InpDispBodyRatio) continue;
if(InpDispCloseBeyondPrev && C[p]<=H[p-1]) continue;
if(L[p+1]<=H[p-1]) continue;
double gapBottom=H[p-1], gapTop=L[p+1];
int sweepStart=p-1-InpSweepLookback, sweepEnd=p-1;
if(sweepStart<0) continue;
double manipLow=LowestLow(sweepStart,sweepEnd);
int accEnd=sweepStart-1;
if(accEnd<InpAccMin-1) continue;
bool accFound=false; double rangeHigh=0,rangeLow=0;
for(int L1=InpAccMax; L1>=InpAccMin; L1--)
int accStart=accEnd-L1+1; if(accStart<0) continue;
double rh=HighestHigh(accStart,accEnd), rl=LowestLow(accStart,accEnd);
if((rh-rl)<=InpAccMaxRangeATR*atr){ rangeHigh=rh; rangeLow=rl; accFound=true; break; }
if(!accFound) continue;
if(manipLow > rangeLow - InpSweepMinATR*atr) continue;
int confirmBar=-1, cEnd=MathMin(p+InpConfirmWindow,newest);
for(int q=p+1;q<=cEnd;q++)
bool bull=(C[q]>O[q]), closeOK=(C[q]>gapTop);
bool fullOK=InpRequireFullBody?(MathMin(O[q],C[q])>gapTop):closeOK;
if(bull&&closeOK&&fullOK){ confirmBar=q; break; }
if(confirmBar<0) continue;
if(newest-confirmBar>InpMaxSetupAgeBars) continue;
if(C[newest]<=gapTop) continue;
double sl=manipLow-InpSlBufferATR*atr;
double entry=InpUseRetracement?gapTop:SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double risk=entry-sl; if(risk<=0) continue;
double tp=BuildTP(+1,entry,risk,atr);
if((tp-entry)/risk<InpMinRR) continue;
[Link]=true; [Link]=gapTop; [Link]=gapBottom;
[Link]=manipLow; [Link]=T[p]; [Link]=entry; [Link]=sl; [Link]=tp;
return out;
return out;
//==================================================================
// SELL SETUP
//==================================================================
SmcSetup FindSellSetup(double atr)
SmcSetup out; [Link]=false; [Link]=-1;
int newest=N-1, pStart=newest-1, pEnd=InpAccMin+InpSweepLookback+2;
for(int p=pStart; p>=pEnd; p--)
{
double body=O[p]-C[p], range=H[p]-L[p];
if(C[p]>=O[p]) continue;
if(body<InpDispBodyATR*atr) continue;
if(range<=0||body/range<InpDispBodyRatio) continue;
if(InpDispCloseBeyondPrev && C[p]>=L[p-1]) continue;
if(H[p+1]>=L[p-1]) continue;
double gapTop=L[p-1], gapBottom=H[p+1];
int sweepStart=p-1-InpSweepLookback, sweepEnd=p-1;
if(sweepStart<0) continue;
double manipHigh=HighestHigh(sweepStart,sweepEnd);
int accEnd=sweepStart-1;
if(accEnd<InpAccMin-1) continue;
bool accFound=false; double rangeHigh=0,rangeLow=0;
for(int L1=InpAccMax; L1>=InpAccMin; L1--)
int accStart=accEnd-L1+1; if(accStart<0) continue;
double rh=HighestHigh(accStart,accEnd), rl=LowestLow(accStart,accEnd);
if((rh-rl)<=InpAccMaxRangeATR*atr){ rangeHigh=rh; rangeLow=rl; accFound=true; break; }
if(!accFound) continue;
if(manipHigh < rangeHigh + InpSweepMinATR*atr) continue;
int confirmBar=-1, cEnd=MathMin(p+InpConfirmWindow,newest);
for(int q=p+1;q<=cEnd;q++)
bool bear=(C[q]<O[q]), closeOK=(C[q]<gapBottom);
bool fullOK=InpRequireFullBody?(MathMax(O[q],C[q])<gapBottom):closeOK;
if(bear&&closeOK&&fullOK){ confirmBar=q; break; }
if(confirmBar<0) continue;
if(newest-confirmBar>InpMaxSetupAgeBars) continue;
if(C[newest]>=gapBottom) continue;
double sl=manipHigh+InpSlBufferATR*atr;
double entry=InpUseRetracement?gapBottom:SymbolInfoDouble(_Symbol,SYMBOL_BID);
double risk=sl-entry; if(risk<=0) continue;
double tp=BuildTP(-1,entry,risk,atr);
if((entry-tp)/risk<InpMinRR) continue;
[Link]=true; [Link]=gapTop; [Link]=gapBottom;
[Link]=manipHigh; [Link]=T[p]; [Link]=entry; [Link]=sl; [Link]=tp;
return out;
return out;
}
//==================================================================
// TAKE PROFIT (1:3 min, 1:5 fallback)
//==================================================================
double BuildTP(int dir,double entry,double risk,double atr)
int newest=N-1, from=MathMax(0,newest-InpSwingLookback);
double rrFallback=(dir>0)?entry+InpPreferredRR*risk:entry-InpPreferredRR*risk;
if(!InpUseSwingTP) return rrFallback;
if(dir>0){ double sh=HighestHigh(from,newest); if(sh>entry&&(sh-entry)/risk>=InpMinRR) return sh; }
else { double slw=LowestLow(from,newest); if(slw<entry&&(entry-slw)/risk>=InpMinRR) return
slw; }
return rrFallback;
//==================================================================
// EXECUTION
//==================================================================
bool ExecuteSetup(const SmcSetup &s)
int dig=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
double entry=NormalizeDouble([Link],dig);
double sl=NormalizeDouble([Link],dig);
double tp=NormalizeDouble([Link],dig);
double lots=CalcLot(MathAbs(entry-sl));
if(lots<=0){ Print("Lot calc 0 — skip."); return false; }
string note="AMD_IFVG";
if(!InpUseRetracement)
if([Link]>0) return [Link](lots,_Symbol,0.0,sl,tp,note);
else return [Link](lots,_Symbol,0.0,sl,tp,note);
datetime expiry=TimeCurrent()+InpPendingExpiryBars*PeriodSeconds(InpLTF);
if([Link]>0)
double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
if(entry>=ask) return [Link](lots,_Symbol,0.0,sl,tp,note);
return [Link](lots,entry,_Symbol,sl,tp,ORDER_TIME_SPECIFIED,expiry,note);
else
double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
if(entry<=bid) return [Link](lots,_Symbol,0.0,sl,tp,note);
return [Link](lots,entry,_Symbol,sl,tp,ORDER_TIME_SPECIFIED,expiry,note);
//==================================================================
// POSITION SIZING (SL distance == Risk%)
//==================================================================
double CalcLot(double slPriceDistance)
double minLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double maxLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
if(InpRiskPercent<=0.0) return ClampLot(InpFixedLot,minLot,maxLot,step);
double tickVal=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
double tickSize=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
if(tickSize<=0||tickVal<=0||slPriceDistance<=0) return ClampLot(InpFixedLot,minLot,maxLot,step);
double riskMoney=AccountInfoDouble(ACCOUNT_BALANCE)*InpRiskPercent/100.0;
double lossPerLot=(slPriceDistance/tickSize)*tickVal;
if(lossPerLot<=0) return minLot;
return ClampLot(riskMoney/lossPerLot,minLot,maxLot,step);
double ClampLot(double lots,double minLot,double maxLot,double step)
if(step>0) lots=MathFloor(lots/step)*step;
lots=MathMax(minLot,MathMin(maxLot,lots));
return NormalizeDouble(lots,2);
}
//==================================================================
// TRADE MANAGEMENT
//==================================================================
int FindPosState(ulong ticket){ for(int i=0;i<ArraySize(g_pos);i++) if(g_pos[i].ticket==ticket) return i;
return -1; }
void RegisterPosition(ulong ticket)
if(!PositionSelectByTicket(ticket)) return;
int dir=(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)?1:-1;
double entry=PositionGetDouble(POSITION_PRICE_OPEN);
double psl=PositionGetDouble(POSITION_SL);
double oneR=(psl>0)?MathAbs(entry-psl):0.0;
if(oneR<=0) return;
int idx=ArraySize(g_pos); ArrayResize(g_pos,idx+1);
g_pos[idx].ticket=ticket; g_pos[idx].dir=dir; g_pos[idx].entry=entry;
g_pos[idx].oneR=oneR; g_pos[idx].movedBE=false; g_pos[idx].partialDone=false;
g_pos[idx].trailing=false;
void PurgeClosed()
for(int i=ArraySize(g_pos)-1;i>=0;i--)
if(!PositionSelectByTicket(g_pos[i].ticket))
{ int last=ArraySize(g_pos)-1; g_pos[i]=g_pos[last]; ArrayResize(g_pos,last); }
}
void ManagePositions()
for(int i=PositionsTotal()-1;i>=0;i--)
ulong tk=PositionGetTicket(i); if(tk==0) continue;
if(PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC)!=InpMagic) continue;
if(FindPosState(tk)<0) RegisterPosition(tk);
PurgeClosed();
if(ArraySize(g_pos)==0) return;
double atr=CurrentATR();
int dig=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
long stopLvl=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
double minDist=stopLvl*point;
for(int i=0;i<ArraySize(g_pos);i++)
ulong tk=g_pos[i].ticket;
if(!PositionSelectByTicket(tk)) continue;
int dir=g_pos[i].dir;
double entry=g_pos[i].entry, oneR=g_pos[i].oneR;
double curSL=PositionGetDouble(POSITION_SL);
double curTP=PositionGetDouble(POSITION_TP);
double vol=PositionGetDouble(POSITION_VOLUME);
double px=(dir>0)?
SymbolInfoDouble(_Symbol,SYMBOL_BID):SymbolInfoDouble(_Symbol,SYMBOL_ASK);
double rMult=((px-entry)*dir)/oneR;
// Partial TP
if(InpUsePartialTP && !g_pos[i].partialDone && rMult>=InpPartialAtR)
double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
double minLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
double closeVol=vol*InpPartialPct/100.0;
if(step>0) closeVol=MathFloor(closeVol/step)*step;
double remain=vol-closeVol;
if(closeVol>=minLot && (remain>=minLot || remain<=0))
{ if([Link](tk,closeVol)) g_pos[i].partialDone=true; }
else g_pos[i].partialDone=true;
// Break-even
if(InpUseBreakeven && !g_pos[i].movedBE && rMult>=InpBeAtR)
double be=NormalizeDouble(entry+dir*InpBeLockPoints*point,dig);
bool ok=(dir>0)?(be>curSL && (px-be)>=minDist):(be<curSL && (be-px)>=minDist);
if(curSL==0.0) ok=(dir>0)?(px-be)>=minDist:(be-px)>=minDist;
if(ok && [Link](tk,be,curTP)){ g_pos[i].movedBE=true; curSL=be; }
// Trailing
if(InpUseTrailing && rMult>=InpTrailStartR)
double dist=InpTrailUseATR?InpTrailAtrMult*atr:InpTrailRDist*oneR;
if(dist>0)
double newSL=NormalizeDouble((dir>0)?px-dist:px+dist,dig);
bool improves=(dir>0)?(newSL>curSL):(newSL<curSL||curSL==0.0);
bool farEnough=(dir>0)?(px-newSL)>=minDist:(newSL-px)>=minDist;
if(dir>0 && newSL<entry) improves=false;
if(dir<0 && newSL>entry) improves=false;
if(improves && farEnough) [Link](tk,newSL,curTP);
//==================================================================
// ORDER COUNT
//==================================================================
int CountMyOrders()
{
int cnt=0;
for(int i=PositionsTotal()-1;i>=0;i--)
ulong tk=PositionGetTicket(i); if(tk==0) continue;
if(PositionGetString(POSITION_SYMBOL)==_Symbol &&
PositionGetInteger(POSITION_MAGIC)==InpMagic) cnt++;
for(int i=OrdersTotal()-1;i>=0;i--)
ulong tk=OrderGetTicket(i); if(tk==0) continue;
if(OrderGetString(ORDER_SYMBOL)==_Symbol && OrderGetInteger(ORDER_MAGIC)==InpMagic)
cnt++;
return cnt;
//+------------------------------------------------------------------+