//+------------------------------------------------------------------+
//|                                                 DabsPro_0.1.mq5   |
//|        1.37 Fibonacci extension + pin-bar (hammer / shooting      |
//|        star) rejection strategy with full money management.       |
//|                                                                   |
//|  Designed for the 15-minute timeframe (PERIOD_M15). Detects a     |
//|  pin bar (small body, one dominant wick) whose wick tags the      |
//|  1.37 extension of the most recent swing leg, in the rejection    |
//|  direction, and trades it with risk-based position sizing,        |
//|  broker-aware ATR stops, R-multiple targets, break-even and       |
//|  ATR trailing.                                                    |
//|                                                                   |
//|  Money-management notes (validated against MQL5 best practice):   |
//|   - Lots solved from equity-at-risk and stop distance via         |
//|     tick value / tick size, then clamped to broker volume step.   |
//|   - OrderCalcMargin pre-trade check (avoids 'not enough money').  |
//|   - SL/TP honour SYMBOL_TRADE_STOPS_LEVEL & freeze level          |
//|     (avoids 'invalid stops').                                      |
//|   - Each position's INITIAL risk is cached so break-even and      |
//|     trailing trigger at correct R multiples even after the stop   |
//|     has already moved.                                            |
//|                                                                   |
//|  Strategy edge is modest (~53-59% conditioned win-rate in study); |
//|  disciplined risk control is what keeps it survivable.            |
//|  Educational. Backtest and demo before any live capital.          |
//+------------------------------------------------------------------+
#property copyright "DabsPro"
#property version   "0.10"
#property strict
#property description "1.37-fib / pin-bar rejection EA with baked-in money management. M15 timeframe."

#include <Trade/Trade.mqh>
#include <Trade/SymbolInfo.mqh>

//==================== INPUTS ========================================
input group "=== Strategy ==="
input ENUM_TIMEFRAMES InpTF            = PERIOD_CURRENT; // Signal timeframe (CURRENT = chart). Any TF supported; 15m has the strongest edge in study.
input double  InpFib                   = 1.37;        // Fibonacci extension level
input int     InpPivotK                = 3;           // Swing pivot half-window (bars)
input int     InpLookback              = 200;         // Bars scanned for swings
input double  InpBodyMaxFrac           = 0.30;        // Max body / range  (little candle)
input double  InpDomWickFrac           = 0.55;        // Min dominant wick / range (mostly wick)
input double  InpOppWickFrac           = 0.20;        // Max opposite wick / range
input double  InpTagTolPct             = 0.15;        // Wick-tag tolerance (% of price)

enum DirMode { BOTH=0, BULL_ONLY=1, BEAR_ONLY=2 };
input DirMode InpDirMode               = BOTH;        // Which patterns to trade

input group "=== Multi-timeframe trend filter ==="
input bool    InpUseTrendFilter        = false;       // Gate entries by a higher-timeframe trend
input ENUM_TIMEFRAMES InpTrendTF       = PERIOD_H1;   // Higher timeframe for the trend
input int     InpTrendEMA              = 50;          // EMA period on the higher timeframe
input bool    InpTrendStrict           = true;        // true: price & EMA-slope must agree; false: slope only

input group "=== Edge filters (from the study) ==="
input bool    InpUseSession            = true;        // Only trade the 'open' session window
input int     InpSessionStartHour      = 13;          // Session start hour (broker time)
input int     InpSessionEndHour        = 15;          // Session end hour (broker time, exclusive)
input bool    InpUseRelVolume          = true;        // Require elevated volume
input double  InpMinRelVolume          = 1.5;         // Min signal vol / median(20)
input bool    InpUseRSI                = false;       // Require RSI band
input int     InpRSIPeriod             = 14;          // RSI period
input double  InpRSIMin                = 35.0;        // RSI lower bound
input double  InpRSIMax                = 65.0;        // RSI upper bound

input group "=== Money management ==="
input bool    InpUseRiskPercent        = true;        // Size by risk % (else fixed lots)
input double  InpRiskPercent           = 0.5;         // Risk per trade (% of equity)
input double  InpFixedLots             = 0.10;        // Fixed lot size (if risk % off)
input int     InpATRPeriod             = 14;          // ATR period
input double  InpATRmultSL             = 1.2;         // Stop = wick extreme +/- this*ATR
input double  InpRR                    = 2.0;         // Take-profit = RR * stop distance
input double  InpMaxRiskLots           = 5.0;         // Hard cap on lots
input bool    InpSkipIfBelowMinLot     = false;       // Skip trade if risk-lot < broker min (else use min)
input double  InpMaxSpreadPoints       = 50;          // Skip if spread above this (points)
input double  InpMarginBufferPct       = 20;          // Require this % free-margin headroom

input group "=== Trade management ==="
input int     InpMaxPositions          = 1;           // Max concurrent positions (this symbol+magic)
input bool    InpUseBreakEven          = true;        // Move SL to break-even
input double  InpBreakEvenR            = 1.0;         // ...after price travels this many R
input double  InpBreakEvenLockPts      = 5;           // Points locked beyond entry at BE
input bool    InpUseTrailing           = true;        // ATR trailing stop
input double  InpTrailATRmult          = 1.5;         // Trailing distance in ATR
input double  InpTrailStartR           = 1.0;         // Only start trailing after this many R
input bool    InpCloseOppositeSignal   = false;       // Close on opposite signal

input group "=== Misc ==="
input long    InpMagic                 = 137037;      // Magic number
input int     InpSlippage              = 20;          // Deviation (points)
input string  InpComment               = "DabsPro0.1";// Order comment

//==================== GLOBALS =======================================
CTrade            trade;
CSymbolInfo       sym;
ENUM_TIMEFRAMES   gTF;                     // resolved signal timeframe
int           hATR   = INVALID_HANDLE;
int           hRSI   = INVALID_HANDLE;
int           hTrend = INVALID_HANDLE;     // HTF EMA handle
datetime      lastBarTime = 0;

// initial-risk cache (so BE / trailing use the ORIGINAL R, not the moved SL)
ulong         gTicket[];
double        gInitRisk[];

//+------------------------------------------------------------------+
int OnInit()
  {
   if(!sym.Name(_Symbol))
     {
      Print("DabsPro: cannot select symbol ", _Symbol);
      return(INIT_FAILED);
     }
   trade.SetExpertMagicNumber(InpMagic);
   trade.SetDeviationInPoints(InpSlippage);
   trade.SetTypeFillingBySymbol(_Symbol);
   trade.SetMarginMode();
   trade.LogLevel(LOG_LEVEL_ERRORS);

   gTF = (InpTF == PERIOD_CURRENT) ? (ENUM_TIMEFRAMES)_Period : InpTF;

   hATR = iATR(_Symbol, gTF, InpATRPeriod);
   hRSI = iRSI(_Symbol, gTF, InpRSIPeriod, PRICE_CLOSE);
   if(hATR == INVALID_HANDLE || hRSI == INVALID_HANDLE)
     {
      Print("DabsPro: failed to create indicator handles");
      return(INIT_FAILED);
     }
   if(InpUseTrendFilter)
     {
      hTrend = iMA(_Symbol, InpTrendTF, InpTrendEMA, 0, MODE_EMA, PRICE_CLOSE);
      if(hTrend == INVALID_HANDLE)
        { Print("DabsPro: failed to create HTF trend handle"); return(INIT_FAILED); }
     }
   ArrayResize(gTicket, 0);
   ArrayResize(gInitRisk, 0);
   PrintFormat("DabsPro 0.1 initialised on %s %s  (risk %.2f%%, RR %.1f%s)",
               _Symbol, EnumToString(gTF), InpRiskPercent, InpRR,
               InpUseTrendFilter ? StringFormat(", HTF %s EMA%d",
                                   EnumToString(InpTrendTF), InpTrendEMA) : "");
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(hATR   != INVALID_HANDLE) IndicatorRelease(hATR);
   if(hRSI   != INVALID_HANDLE) IndicatorRelease(hRSI);
   if(hTrend != INVALID_HANDLE) IndicatorRelease(hTrend);
  }

//+------------------------------------------------------------------+
void OnTick()
  {
   sym.RefreshRates();
   ManageOpenPositions();          // manage every tick

   // act once per new closed bar
   datetime t[2];
   if(CopyTime(_Symbol, gTF, 0, 2, t) < 2) return;
   if(t[0] == lastBarTime) return;
   lastBarTime = t[0];

   CheckForSignal();
  }

//+------------------------------------------------------------------+
//| Detect pin bar at the last CLOSED bar (shift 1) and trade it     |
//+------------------------------------------------------------------+
void CheckForSignal()
  {
   if(PositionsForThisEA() >= InpMaxPositions) return;

   int need = InpLookback + InpPivotK + 5;
   MqlRates r[];
   ArraySetAsSeries(r, true);
   if(CopyRates(_Symbol, gTF, 0, need, r) < need) return;

   int sig = 1;                    // last closed bar
   double o = r[sig].open, h = r[sig].high, l = r[sig].low, c = r[sig].close;
   double rng = h - l;
   if(rng <= 0) return;
   double body  = MathAbs(c - o);
   double upper = h - MathMax(o, c);
   double lower = MathMin(o, c) - l;
   double dom   = MathMax(upper, lower);
   double opp   = MathMin(upper, lower);

   bool isPin = (body <= InpBodyMaxFrac * rng) &&
                (dom  >= InpDomWickFrac * rng) &&
                (opp  <= InpOppWickFrac * rng);
   if(!isPin) return;

   bool bull = (lower >= upper);   // hammer
   bool bear = (upper >  lower);   // shooting star
   if(InpDirMode == BULL_ONLY && !bull) return;
   if(InpDirMode == BEAR_ONLY && !bear) return;

   double upLevel, dnLevel; bool haveUp, haveDn;
   GetFibLevels(r, sig, haveUp, upLevel, haveDn, dnLevel);

   double tol     = InpTagTolPct / 100.0 * c;
   double bodyTop = MathMax(o, c), bodyBot = MathMin(o, c);

   bool buySignal = false, sellSignal = false;

   if(bear && haveUp)                 // upside 1.37 rejected by shooting star -> SELL
      if(bodyTop - tol <= upLevel && upLevel <= h + tol) sellSignal = true;
   if(!sellSignal && bull && haveDn)  // downside 1.37 rejected by hammer -> BUY
      if(l - tol <= dnLevel && dnLevel <= bodyBot + tol) buySignal = true;

   if(!buySignal && !sellSignal) return;

   // ---- confirmation filters ----
   if(!PassSessionFilter(r[sig].time))        return;
   if(!PassVolumeFilter(r, sig))              return;
   if(!PassRSIFilter())                       return;
   if(!PassTrendFilter(buySignal))            return;
   if(SpreadPoints() > InpMaxSpreadPoints)    return;

   if(InpCloseOppositeSignal)
      CloseOpposite(buySignal ? POSITION_TYPE_BUY : POSITION_TYPE_SELL);
   if(PositionsForThisEA() >= InpMaxPositions) return;

   double atr = GetATR();
   if(atr <= 0) return;

   if(buySignal)  OpenTrade(true,  l, atr);
   else           OpenTrade(false, h, atr);
  }

//+------------------------------------------------------------------+
//| Build & send an order with full risk control                     |
//+------------------------------------------------------------------+
void OpenTrade(bool isBuy, double wickExtreme, double atr)
  {
   sym.RefreshRates();
   double entry = isBuy ? sym.Ask() : sym.Bid();
   double rawSL = isBuy ? MathMin(wickExtreme, entry) - InpATRmultSL * atr
                        : MathMax(wickExtreme, entry) + InpATRmultSL * atr;

   double sl = BrokerizeStop(entry, rawSL, isBuy);     // honour stops level
   double slDist = MathAbs(entry - sl);
   if(slDist <= 0) return;

   double tp = isBuy ? entry + InpRR * slDist : entry - InpRR * slDist;
   tp = BrokerizeTP(entry, tp, isBuy);

   double lots = CalcLots(slDist);
   if(lots <= 0) { Print("DabsPro: lot size resolves to 0 -> skip"); return; }

   ENUM_ORDER_TYPE ot = isBuy ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   if(!HasEnoughMargin(ot, lots, entry))
     {
      PrintFormat("DabsPro: insufficient free-margin headroom for %.2f lots -> skip", lots);
      return;
     }

   entry = NormalizeDouble(entry, _Digits);
   sl    = NormalizeDouble(sl, _Digits);
   tp    = NormalizeDouble(tp, _Digits);

   bool ok = isBuy ? trade.Buy(lots, _Symbol, entry, sl, tp, InpComment)
                   : trade.Sell(lots, _Symbol, entry, sl, tp, InpComment);
   if(!ok || (trade.ResultRetcode() != TRADE_RETCODE_DONE &&
              trade.ResultRetcode() != TRADE_RETCODE_PLACED))
      PrintFormat("DabsPro: order failed retcode=%d (%s)",
                  trade.ResultRetcode(), trade.ResultRetcodeDescription());
   else
      PrintFormat("DabsPro: %s %.2f lots @ %.5f  SL %.5f  TP %.5f  (risk %.1f pts)",
                  isBuy?"BUY":"SELL", lots, entry, sl, tp, slDist/_Point);
  }

//+------------------------------------------------------------------+
//| 1.37 extension of the most recent up-leg and down-leg            |
//+------------------------------------------------------------------+
void GetFibLevels(const MqlRates &r[], int sig,
                  bool &haveUp, double &upLevel,
                  bool &haveDn, double &dnLevel)
  {
   haveUp = haveDn = false; upLevel = dnLevel = 0;
   int K = InpPivotK;

   int    pivType[];  double pivPrice[];  int n = 0;
   ArrayResize(pivType, InpLookback); ArrayResize(pivPrice, InpLookback);

   // pivots, scanned newest -> oldest (shift grows with age)
   for(int i = sig + K; i <= InpLookback && i + K < ArraySize(r); i++)
     {
      bool isHigh = true, isLow = true;
      for(int j = 1; j <= K; j++)
        {
         if(r[i].high < r[i-j].high || r[i].high < r[i+j].high) isHigh = false;
         if(r[i].low  > r[i-j].low  || r[i].low  > r[i+j].low ) isLow  = false;
        }
      if(isHigh)      { pivType[n]=+1; pivPrice[n]=r[i].high; n++; }
      else if(isLow)  { pivType[n]=-1; pivPrice[n]=r[i].low;  n++; }
     }
   for(int a = 0; a < n - 1; a++)
     {
      int newer = a, older = a + 1;          // newer has smaller shift
      if(!haveUp && pivType[older]==-1 && pivType[newer]==+1)
        { upLevel = pivPrice[older] + InpFib*(pivPrice[newer]-pivPrice[older]); haveUp=true; }
      if(!haveDn && pivType[older]==+1 && pivType[newer]==-1)
        { dnLevel = pivPrice[older] - InpFib*(pivPrice[older]-pivPrice[newer]); haveDn=true; }
      if(haveUp && haveDn) break;
     }
  }

//+------------------------------------------------------------------+
//| Filters                                                          |
//+------------------------------------------------------------------+
bool PassSessionFilter(datetime barTime)
  {
   if(!InpUseSession) return true;
   MqlDateTime dt; TimeToStruct(barTime, dt);
   return (dt.hour >= InpSessionStartHour && dt.hour < InpSessionEndHour);
  }

bool PassVolumeFilter(const MqlRates &r[], int sig)
  {
   if(!InpUseRelVolume) return true;
   int m = 20;
   if(sig + 1 + m >= ArraySize(r)) return true;
   double vols[]; ArrayResize(vols, m);
   for(int i = 0; i < m; i++) vols[i] = (double)r[sig + 1 + i].tick_volume;
   ArraySort(vols);
   double med = (vols[m/2 - 1] + vols[m/2]) / 2.0;
   if(med <= 0) return true;
   return ((double)r[sig].tick_volume / med >= InpMinRelVolume);
  }

bool PassRSIFilter()
  {
   if(!InpUseRSI) return true;
   double v[1];
   if(CopyBuffer(hRSI, 0, 1, 1, v) < 1) return false;
   return (v[0] >= InpRSIMin && v[0] <= InpRSIMax);
  }

double SpreadPoints()
  { return (sym.Ask() - sym.Bid()) / _Point; }

// Higher-timeframe trend gate: longs only with an up-trend, shorts with a down-trend.
bool PassTrendFilter(bool isBuy)
  {
   if(!InpUseTrendFilter || hTrend == INVALID_HANDLE) return true;
   double e[2];
   if(CopyBuffer(hTrend, 0, 1, 2, e) < 2) return false;   // e[1]=newer, e[0]=older
   double slope = e[1] - e[0];
   double px    = sym.Bid();
   bool up   = InpTrendStrict ? (slope > 0 && px > e[1]) : (slope > 0);
   bool down = InpTrendStrict ? (slope < 0 && px < e[1]) : (slope < 0);
   return isBuy ? up : down;
  }

//+------------------------------------------------------------------+
//| Broker-aware stop placement                                      |
//+------------------------------------------------------------------+
int MinStopPoints()
  {
   int sl = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
   int fz = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL);
   int m  = MathMax(sl, fz);
   return (m > 0 ? m : 10);        // sensible fallback when broker reports 0
  }

// push SL out so it is at least the broker minimum distance from price
double BrokerizeStop(double price, double sl, bool isBuy)
  {
   double minDist = (MinStopPoints() + 1) * _Point;
   if(isBuy)  sl = MathMin(sl, price - minDist);
   else       sl = MathMax(sl, price + minDist);
   return sl;
  }
double BrokerizeTP(double price, double tp, bool isBuy)
  {
   double minDist = (MinStopPoints() + 1) * _Point;
   if(isBuy)  tp = MathMax(tp, price + minDist);
   else       tp = MathMin(tp, price - minDist);
   return tp;
  }

//+------------------------------------------------------------------+
//| Money management                                                 |
//+------------------------------------------------------------------+
double CalcLots(double slDistPrice)
  {
   if(!InpUseRiskPercent)
      return(NormalizeLots(InpFixedLots));

   double capital  = MathMin(AccountInfoDouble(ACCOUNT_EQUITY),
                             AccountInfoDouble(ACCOUNT_BALANCE));
   double riskMoney= capital * InpRiskPercent / 100.0;

   double tickVal  = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tickSize <= 0 || tickVal <= 0) return(0);

   double tickCount  = slDistPrice / tickSize;        // verified MQL5 formula
   double lossPerLot = tickCount * tickVal;
   if(lossPerLot <= 0) return(0);

   double lots = riskMoney / lossPerLot;
   return(NormalizeLots(lots));
  }

double NormalizeLots(double lots)
  {
   double minL = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxL = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   lots = MathMin(lots, InpMaxRiskLots);
   if(step > 0) lots = MathFloor(lots / step) * step;

   if(lots < minL)
     {
      if(InpSkipIfBelowMinLot) return(0);     // respect risk cap strictly
      lots = minL;                            // otherwise trade the minimum
     }
   lots = MathMin(lots, maxL);
   return(NormalizeDouble(lots, 2));
  }

bool HasEnoughMargin(ENUM_ORDER_TYPE type, double lots, double price)
  {
   double margin = 0.0;
   if(!OrderCalcMargin(type, _Symbol, lots, price, margin))
      return(true);                            // can't compute -> don't block
   double freeM = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   return(margin * (1.0 + InpMarginBufferPct/100.0) <= freeM);
  }

double GetATR()
  {
   double v[1];
   if(CopyBuffer(hATR, 0, 1, 1, v) < 1) return(0);
   return(v[0]);
  }

//+------------------------------------------------------------------+
//| Initial-risk cache (per ticket)                                  |
//+------------------------------------------------------------------+
double InitRiskFor(ulong ticket, double curOpen, double curSL)
  {
   for(int i = 0; i < ArraySize(gTicket); i++)
      if(gTicket[i] == ticket) return(gInitRisk[i]);

   double risk = MathAbs(curOpen - curSL);    // first time we see it
   int n = ArraySize(gTicket);
   ArrayResize(gTicket, n+1); ArrayResize(gInitRisk, n+1);
   gTicket[n] = ticket; gInitRisk[n] = risk;
   return(risk);
  }
void ForgetClosedTickets()
  {
   for(int i = ArraySize(gTicket)-1; i >= 0; i--)
      if(!PositionSelectByTicket(gTicket[i]))
        {
         int last = ArraySize(gTicket)-1;
         gTicket[i]=gTicket[last]; gInitRisk[i]=gInitRisk[last];
         ArrayResize(gTicket, last); ArrayResize(gInitRisk, last);
        }
  }

//+------------------------------------------------------------------+
//| Position management: break-even + ATR trailing                   |
//+------------------------------------------------------------------+
void ManageOpenPositions()
  {
   ForgetClosedTickets();
   double atr = GetATR();
   double minDist = (MinStopPoints() + 1) * _Point;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0 || !PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol)  continue;
      if(PositionGetInteger(POSITION_MAGIC) != InpMagic)  continue;

      long   type = PositionGetInteger(POSITION_TYPE);
      double open = PositionGetDouble(POSITION_PRICE_OPEN);
      double sl   = PositionGetDouble(POSITION_SL);
      double tp   = PositionGetDouble(POSITION_TP);
      double bid  = sym.Bid(), ask = sym.Ask();
      double R    = InitRiskFor(ticket, open, (sl!=0.0?sl:open));
      if(R <= 0) continue;

      double newSL = sl;

      if(type == POSITION_TYPE_BUY)
        {
         if(InpUseBreakEven && bid - open >= InpBreakEvenR * R)
            newSL = MathMax(newSL, open + InpBreakEvenLockPts * _Point);
         if(InpUseTrailing && atr > 0 && bid - open >= InpTrailStartR * R)
            newSL = MathMax(newSL, bid - InpTrailATRmult * atr);
         newSL = MathMin(newSL, bid - minDist);          // keep broker-legal
         if(newSL > sl + _Point/2.0)
            ModifySL(ticket, newSL, tp);
        }
      else if(type == POSITION_TYPE_SELL)
        {
         double cand = sl;
         if(InpUseBreakEven && open - ask >= InpBreakEvenR * R)
            cand = (cand==0.0? open - InpBreakEvenLockPts*_Point
                             : MathMin(cand, open - InpBreakEvenLockPts*_Point));
         if(InpUseTrailing && atr > 0 && open - ask >= InpTrailStartR * R)
            cand = (cand==0.0? ask + InpTrailATRmult*atr
                             : MathMin(cand, ask + InpTrailATRmult*atr));
         if(cand > 0) cand = MathMax(cand, ask + minDist); // broker-legal
         if(cand > 0 && (sl == 0.0 || cand < sl - _Point/2.0))
            ModifySL(ticket, cand, tp);
        }
     }
  }

void ModifySL(ulong ticket, double newSL, double tp)
  {
   newSL = NormalizeDouble(newSL, _Digits);
   if(!trade.PositionModify(ticket, newSL, NormalizeDouble(tp,_Digits)))
      if(trade.ResultRetcode() != TRADE_RETCODE_DONE)
         PrintFormat("DabsPro: modify #%I64u failed retcode=%d (%s)",
                     ticket, trade.ResultRetcode(), trade.ResultRetcodeDescription());
  }

//+------------------------------------------------------------------+
//| Helpers                                                          |
//+------------------------------------------------------------------+
int PositionsForThisEA()
  {
   int cnt = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0 || !PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
         PositionGetInteger(POSITION_MAGIC) == InpMagic) cnt++;
     }
   return(cnt);
  }

void CloseOpposite(ENUM_POSITION_TYPE wantType)
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0 || !PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol)  continue;
      if(PositionGetInteger(POSITION_MAGIC) != InpMagic)  continue;
      if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != wantType)
         trade.PositionClose(ticket);
     }
  }
//+------------------------------------------------------------------+
