//+-------------------------------------------------------------------+
//|                                        Sacupay-MontanaEA1.0.mq4  |
//|                      Copyright © 2011, WildhorseEnterprises       |
//|                                        http://www.metaquotes.net  |
//|
#property copyright "Copyright © 2011, Wildhorse Enterprises"
#property link      ""

#import "kernel32.dll"
   int GetTimeZoneInformation(int& a0[]);
#import

#define BUY 1
#define SELL -1
#define FLAT 0
#define UP 1
#define DN -1
#define GOOD 1
#define PRICE 2
#define TAKE 3
#define STOP 4

extern bool    SignalOnly = false;
extern int     UseClosedCandle=1;
extern bool    ShowArrows=true,
               AlertOn=true,
               EmailOn=false;
extern string  mm = "Money Management settings - Percent Risk";
extern bool    UseMM = true;
extern double  Risk = 1.0,
               NoMMLots = 0.01;
extern bool    UseBasketProfit = false;
extern double  BasketProfit = 5;
extern bool    UseEquityPctClose = false;
extern double  EquityPct = 2.0;
extern string  t2 = "Sacupay-Montana settings";
extern int     period=100;
extern int     price=6;
extern string  t3 = "MA settings";
extern int     MAPeriod = 100,
               MAMethod = 0,
               MAPrice = 0;
extern string  g0 = "Misc settings";
extern bool    ReentryOnBounce = true,
               UseSRBreak = true,
               Martingale=false;
extern double  LotMultiplier=2.0;
extern int     MaxTrades = 10;
extern int     MaxSpread = 15,
               Slippage = 3;
extern bool    CloseOppositeTrades = true,
               CloseFridays = false;
extern int     CloseHour = 22;               
extern string  s1 = "SL Options";
extern bool    UseStdSL = false;
               //UseHiddenSL = false;
extern int     StopLoss = 50;
extern bool    UseSRStopLoss = true;
extern int     SLPipDiff = 1;
extern bool    AddSpread = true;
extern string  t1 = "TP Options";
extern bool    UseStdTP = false,
               //UseHiddenTP = false,
               UseScaleOutTP = false;
extern int     TakeProfit = 50;
extern double  CloseTPPercent = 50;
extern string  b1 = "BE Options";
extern bool    UseStdBE = false;
extern double  BreakEvenPips = 20;
extern int     LockInPips = 2;
extern bool    BE_AfterTP1 = false;
extern string  t0 = "Trail Stop settings";
extern bool    UseStdTS = false;
extern int     TrailStart = 40,
               TrailStop = 10;
extern bool    UseMATrail = true;               
extern int     StartMATrailPips = 40;
extern bool    UseSRTrailStop = false,
               UsePercentTS = false;
extern double  TSPercent = 30.0;
extern int     TSPercentStartPips = 20;
extern bool    UsePSARTrail = false;
extern double  PSAR_Step = 0.005,
               PSAR_Max = 0.05;
extern bool    MoveSL_TP = false;
extern int     TP_DistancePips = 10,
               MovePips = 10;
extern bool    UseCandleTrail = false;
extern int     TrailCandlesBack = 3,
               StartCTPips = 20;
extern bool    UseHourTrade1 = false;
extern int     FromHourTrade1 = 6,
               ToHourTrade1 = 18;
extern bool    UseHourTrade2 = false;
extern int     FromHourTrade2 = 6,
               ToHourTrade2 = 18;
extern color   ArrowsUpColor = Green,
               ArrowsDnColor = Red;
extern int     MagicID = 301729;
extern string  TradeComment = "SM_EA-1.0";
bool           BuySignal=false,
               SellSignal=false,
               BuySignal1=false,
               SellSignal1=false,
               BuyTradeExists,
               SellTradeExists;
int            StopRange,X,minutesUntilNextEvent=0,SignalCandle=0,Alerted=0,Trend=0;
static datetime LastBuyTime=0,LastSellTime=0,dtBarTime=0;
double         Pt,Res=0.0,Sup=0.0;
int            LotDecimal = 0;
double         LotStep,LotSize,LotTickValue,MinLot,MaxLot;

int GetEntry() {
   double sac=iCustom(NULL,0,"Sacupay - Montaña V2",Red,Green,false,period,price,2,SignalCandle);
   if (sac>0) {
      if (Trend==0) {
         Trend=1;
         return(FLAT);
         }
      else if (Trend<0) {
         Trend=1;
         return(BUY);
         }
      }
   else if (sac<0) {
      if (Trend==0) {
         Trend=-1;
         return(FLAT);
         }
      else if (Trend>0) {
         Trend=-1;
         return(SELL);
         }
      }
   return(FLAT);
}
int GetMAEntry() {
   double ma=iMA(NULL,0,MAPeriod,0,MAMethod,MAPrice,SignalCandle);
   if (Close[SignalCandle]>ma && Low[SignalCandle+1]<=ma) return(BUY);
   else if (Close[SignalCandle]<ma && High[SignalCandle+1]>=ma) return(SELL);
   return(FLAT);
}
bool IsTradeTime1() {
   if ((FromHourTrade1 < ToHourTrade1) && ((Hour() < FromHourTrade1) || (Hour() >= ToHourTrade1))) return (false);
   if (FromHourTrade1 > ToHourTrade1 && Hour() < FromHourTrade1 && Hour() >= ToHourTrade1) return (false);
   return (true);
}
bool IsTradeTime2() {
   if ((FromHourTrade2 < ToHourTrade2) && ((Hour() < FromHourTrade2) || (Hour() >= ToHourTrade2))) return (false);
   if (FromHourTrade2 > ToHourTrade2 && Hour() < FromHourTrade2 && Hour() >= ToHourTrade2) return (false);
   return (true);
}
double GetRes() {
   double result=0.0,fractal=0.0;
   for (int ct=1;ct<Bars;ct++) {
      fractal=iFractals(NULL,0,MODE_UPPER,ct);
      if (fractal>0.0) {
         result=fractal;
         break;
         }
      }
   result=MathMax(result,High[iHighest(NULL,0,MODE_HIGH,2,1)]);
   return(result);
}
double GetSup() {
   double result=0.0,fractal=0.0;
   for (int ct=1;ct<Bars;ct++) {
      fractal=iFractals(NULL,0,MODE_LOWER,ct);
      if (fractal>0.0) {
         result=fractal;
         break;
         }
      }
   result=MathMin(result,Low[iLowest(NULL,0,MODE_LOW,2,1)]);
   return(result);
}
double GetSL(int cmd, double Price) { 
   double myStop;
   if (cmd==BUY) {
      if (UseStdSL) {
         if (StopLoss==0) myStop=0.0;
         else myStop=Price-StopLoss*Pt;
         }
      else if (UseSRStopLoss) {
         if (Sup==0.0) myStop=0.0;
         else {
            myStop = Sup-SLPipDiff*Pt;
            if (AddSpread) myStop -= MarketInfo(Symbol(),MODE_SPREAD)*Point;
            }
         }
      else myStop=0.0;
      }
   else if (cmd==SELL) {
      if (UseStdSL) {
         if (StopLoss==0) myStop=0.0;
         else myStop=Price+StopLoss*Pt;
         }
      else if (UseSRStopLoss) {
         if (Res==0.0) myStop=0.0;
         else {
            myStop = Res+SLPipDiff*Pt;
            if (AddSpread) myStop += MarketInfo(Symbol(),MODE_SPREAD)*Point;
            }
         }
      else myStop=0.0;
      }
   return(myStop);
}
double GetTP(int cmd, double Price) {
   double myTake;
   if (cmd==BUY) {
      if (UseStdTP) myTake=Price+TakeProfit*Pt;
      else myTake=0.0;
      }
   else if (cmd==SELL) {
      if (UseStdTP) myTake=Price-TakeProfit*Pt;
      else myTake=0.0;
      }
   return(myTake);
}
double GetTP1(int cmd, double Price) {
   double myTake;
   if (cmd==BUY) {
      if (UseScaleOutTP) myTake=Price+TakeProfit*Pt;
      else myTake=0.0;
      }
   else if (cmd==SELL) {
      if (UseScaleOutTP) myTake=Price-TakeProfit*Pt;
      else myTake=0.0;
      }
   return(myTake);
}
void deinit() {
   Comment("");
   if (ShowArrows) {
      for (int i=ObjectsTotal()-1;i>=0;i--) {
         if (StringFind(ObjectName(i),"LukenEA")>-1) ObjectDelete(ObjectName(i));
         }
      }
}
int init() {
   if (Digits==5 || Digits==3) X=10;
   else X=1; 
   Pt = X*Point;
   StopRange = MarketInfo(Symbol(),MODE_STOPLEVEL)/X;
   if (UseClosedCandle==1) SignalCandle=1;
   LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   LotSize = MarketInfo(Symbol(), MODE_LOTSIZE);
   LotTickValue = MarketInfo(Symbol(), MODE_TICKVALUE)*X;
   MinLot = MarketInfo(Symbol(),MODE_MINLOT);
   MaxLot = MarketInfo(Symbol(),MODE_MAXLOT);
   if(LotStep==0.01) LotDecimal=2;
   else if(LotStep==0.1) LotDecimal=1;
   return;
} 
      
int start(){
   Res=GetRes();
   Sup=GetSup();
   int Cmd=0,MACmd=0;
   if (UseClosedCandle==0 || dtBarTime!=Time[0]) {
      dtBarTime=Time[0];
      Cmd=GetEntry();
      MACmd=GetMAEntry();
      }
   if ((Cmd==BUY || (ReentryOnBounce && Trend>0 && LastBuyTime!=0 && MACmd==BUY)) && LastBuyTime!=Time[0]) {
      BuySignal=true;
      SellSignal=false;
      }
   else if ((Cmd==SELL || (ReentryOnBounce && Trend<0 && LastSellTime!=0 && MACmd==SELL)) && LastSellTime!=Time[0]) {
      SellSignal=true;
      BuySignal=false;
      }
   if (MACmd==BUY && LastBuyTime!=Time[0]) {
      BuySignal1=true;
      SellSignal1=false;
      }
   else if (MACmd==SELL && LastSellTime!=Time[0]) {
      SellSignal1=true;
      BuySignal1=false;
      }
   BuyTradeExists = false;
   SellTradeExists = false;
   int num=0;
   double lots=0,buytp1,selltp1,Profit=0.0;
   bool Closed1=false;
   RefreshRates();
   for (int l = OrdersTotal()-1; l>=0; l--) {
      OrderSelect(l, SELECT_BY_POS,MODE_TRADES);
      if (OrderSymbol() == Symbol()  && OrderMagicNumber()>=MagicID && OrderMagicNumber()<MagicID+10000) {
         lots=(OrderMagicNumber()-MagicID)/100.0;
         if (lots>OrderLots()) Closed1=true;
         if (OrderType() == OP_BUY) {
            if (UseScaleOutTP && !Closed1) {
               buytp1=GetTP1(BUY,OrderOpenPrice());
               if (Bid>=buytp1 && buytp1>0.0) {
                  if (BE_AfterTP1) GoToBE(l);
                  CloseBuy(l,1);
                  }
               }
            //if (UseHiddenTP && Bid>=OrderOpenPrice()+TakeProfit*Pt && TakeProfit>0) {CloseBuy(l);continue;}
            //if (UseHiddenSL && Bid<=OrderOpenPrice()-StopLoss*Pt && StopLoss>0) {CloseBuy(l);continue;}
            if (UseStdTS) UpdateTrail(l);
            if (UseCandleTrail && (Bid-OrderOpenPrice()>=StartCTPips*Pt)) UpdateCandleTrail(l);
            if (UsePSARTrail && !(UseScaleOutTP && !Closed1)) UpdatePSARTrail(l);
            if (UseSRTrailStop) UpdateSRTrailStop(l,Sup);
            if (UsePercentTS) UpdatePctTS(l);
            if (UseMATrail && (Bid-OrderOpenPrice()>=StartMATrailPips*Pt)) UpdateMATrail(l);
            if (UseStdBE) GoToBE(l);
            if (MoveSL_TP) MoveSLTP(l);
            Profit+=OrderProfit();
            BuyTradeExists = true;
            //BuySignal = false;
            num++;
            }
         else if (OrderType() == OP_SELL) {
            if (UseScaleOutTP && !Closed1) {
               selltp1=GetTP1(SELL,OrderOpenPrice());
               if (Ask<=selltp1) {
                  if (BE_AfterTP1) GoToBE(l);
                  CloseSell(l,1);
                  }
               }
            //if (UseHiddenTP && Ask<=OrderOpenPrice()-TakeProfit*Pt && TakeProfit>0) {CloseSell(l);continue;}
            //if (UseHiddenSL && Ask>=OrderOpenPrice()+StopLoss*Pt && StopLoss>0) {CloseSell(l);continue;}
            if (UseStdTS) UpdateTrail(l);
            if (UseCandleTrail && (OrderOpenPrice()-Ask>=StartCTPips*Pt)) UpdateCandleTrail(l);
            if (UsePSARTrail && !(UseScaleOutTP && !Closed1)) UpdatePSARTrail(l);
            if (UseSRTrailStop) UpdateSRTrailStop(l,Res);
            if (UsePercentTS) UpdatePctTS(l);
            if (UseMATrail && (OrderOpenPrice()-Ask>=StartMATrailPips*Pt)) UpdateMATrail(l);
            if (UseStdBE) GoToBE(l);
            if (MoveSL_TP) MoveSLTP(l);
            Profit+=OrderProfit();
            SellTradeExists = true;
            //SellSignal=false;
            num++;
            }
         }
      }
   double HistoryProfit=0.0;
   for (l=0;l<OrdersHistoryTotal();l++) {
      if (!OrderSelect(l, SELECT_BY_POS,MODE_HISTORY)) continue;
      if (OrderSymbol()==Symbol()  && OrderMagicNumber()>=MagicID && OrderMagicNumber()<MagicID+10000) 
         HistoryProfit+=OrderProfit();
      }
   if ((UseBasketProfit && Profit>=BasketProfit && BasketProfit>0) || (UseEquityPctClose && Profit/AccountEquity()>=EquityPct/100) || (CloseFridays && DayOfWeek()==5 && Hour()>=CloseHour)) {
      CloseAll();
      return;
      }
   double currentSpread = MarketInfo(Symbol(),MODE_SPREAD)/X;
   if (currentSpread>MaxSpread) {
      Comment("Current spread ",NormalizeDouble(currentSpread,1),"exceeds maximal allowed spread ",MaxSpread);
      ClearSignals();
      return;
      }
   if ((UseHourTrade1 && !IsTradeTime1()) || (UseHourTrade2 && !IsTradeTime2())) {
      Comment("Outside trading time");
      ClearSignals();
      return;
      }
   Comment("Spread       : ",currentSpread,"\n",
           "Profit         : ",Profit,"\n",
           "Hist Profit   : ",HistoryProfit
           );
   if (BuySignal && BuySignal1 && (!UseSRBreak || Bid>Res) && (num<MaxTrades || (CloseOppositeTrades && SellTradeExists)) && LastBuyTime!=Time[0]) {
      if (ShowArrows && Alerted<BUY) DrawArrow(ArrowsUpColor,233,false);
      if (!SignalOnly) BuyNow();
      else if (AlertOn && Alerted<BUY) DoAlert(BUY);
      Alerted=BUY;
      }
   else if (SellSignal && SellSignal1 && (!UseSRBreak || Bid<Sup) && (num<MaxTrades || (CloseOppositeTrades && BuyTradeExists)) && LastSellTime!=Time[0]) {
      if (ShowArrows && Alerted>SELL) DrawArrow(ArrowsDnColor,234,true);
      if (!SignalOnly) SellNow();
      else if (AlertOn && Alerted>SELL) DoAlert(SELL);
      Alerted=SELL;
      }
   return;
}
bool CloseAll() {
   int ct;
   bool err;
   for (int cnt=OrdersTotal()-1; cnt>=0 ; cnt--) {
      if (!OrderSelect(cnt, SELECT_BY_POS,MODE_TRADES)) continue;
      if (OrderSymbol() == Symbol()  && OrderMagicNumber()>=MagicID && OrderMagicNumber()<MagicID+10000) {
         ct=0;
         err=false;
         while (!err && ct<50) {
            RefreshRates();
            if (OrderType()==OP_BUY) 
               err = OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(OrderClosePrice(),Digits), Slippage, Blue);
            else if (OrderType()==OP_SELL)
               err = OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(OrderClosePrice(),Digits), Slippage, Red);
            else if (OrderType()>1) err=OrderDelete(OrderTicket());
            ct++;
            }
         if (!err) {
            Print("Close unsuccessful - ticket #",OrderTicket()," - error ",GetLastError());
            //return(false);
            }
         }
      }
   return(true);
}
 
bool CloseBuy(int ticket, int cmd=0) {
   int ct;
   bool err;
   double Lots;
   if (ticket<0) {
      for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
         if (!OrderSelect(cnt, SELECT_BY_POS,MODE_TRADES)) continue;
         if (OrderSymbol() == Symbol()  && OrderMagicNumber()>=MagicID && OrderMagicNumber()<MagicID+10000 && OrderType() == OP_BUY) {
            ct=0;
            err=false;
            Print("Closing buys");
            while (!err && ct<50) {
               RefreshRates();
               err = OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(OrderClosePrice(),Digits), Slippage, Blue);
               ct++;
               }
            if (!err) {
               Alert("Close buy unsuccessful - ",GetLastError());
               return(false);
               }
            }
         }
      }
   else {
      if (OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) {
         ct=0;
         err=false;
         if (cmd==1) {
            Lots=OrderLots()*CloseTPPercent/100.0;
            if (OrderLots()-Lots<MinLot) Lots=MathMax(OrderLots()-MinLot,MinLot);
            }
         else Lots=OrderLots();
         while (!err && ct<50) {
            RefreshRates();
            err = OrderClose(OrderTicket(), NormalizeDouble(Lots,LotDecimal), NormalizeDouble(OrderClosePrice(),Digits), Slippage, Blue);
            ct++;
            }     
         if (!err) {
            Alert("Close buy unsuccessful - ",GetLastError());
            return(false);
            }
         }
      }
   return(true);
}
bool CloseSell(int ticket, int cmd=0) {
   int ct;
   bool err;
   double Lots;
   if (ticket<0) {
      for (int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
         if (!OrderSelect(cnt, SELECT_BY_POS,MODE_TRADES)) continue;
         if (OrderSymbol() == Symbol()  && OrderMagicNumber()>=MagicID && OrderMagicNumber()<MagicID+10000 && OrderType() == OP_SELL) {
            ct=0;
            err=false;
            while (!err && ct<50) {
               RefreshRates();
               err = OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(OrderClosePrice(),Digits), Slippage, Red);
               ct++;
               }
            if (!err) {
               Alert("Close sell unsuccessful - ",GetLastError());
               return(false);
               }
            }
         }
      }
   else {
      if (OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) {
         ct=0;
         err=false;
         if (cmd==1) {
            Lots=OrderLots()*CloseTPPercent/100.0;
            if (OrderLots()-Lots<MinLot) Lots=MathMax(OrderLots()-MinLot,MinLot);
            }
         else Lots=OrderLots();
         while (!err && ct<50) {
            RefreshRates();
            err = OrderClose(OrderTicket(), NormalizeDouble(Lots,LotDecimal), NormalizeDouble(OrderClosePrice(),Digits), Slippage, Red);
            ct++;
            }     
         if (!err) {
            Alert("Close sell unsuccessful - ",GetLastError());
            return(false);
            }
         }
      }
   return(true);
}   
bool BuyNow() {
   int err;
   if (CloseOppositeTrades) CloseSell(-1);
   if ((UseHourTrade1 && !IsTradeTime1()) || (UseHourTrade2 && !IsTradeTime2())) return(false);
   RefreshRates();
   double lots=0;
   bool CLoss=CheckLoss(lots);
   int Op=OP_BUY,Exp=0;
   double Price=NormalizeDouble(Ask,Digits);
   double myStop = GetSL(BUY,Price);
   double myTake = GetTP(BUY,Price);
   if (Martingale && CLoss) double myLots=lots*LotMultiplier;
   else myLots = GetLots(Price,myStop);
   if (Bid>myTake && myTake!=0.0) {
      Print("Buy: Too far already...Bid: ",Bid," myStop: ",myStop," myTake: ",myTake);
      return(false);
      }
   while (!IsTradeAllowed()) Sleep(5000);
   RefreshRates();
   int Chk = 0;
   while (Chk!=GOOD) {
      Chk = IsBuyValid(myStop,myTake);
      if (Chk==TAKE) myTake += Pt;
      else if (Chk==STOP) myStop -= Pt;
      }
   string TC=TradeComment + " Buy";
   err = OrderSend(Symbol(),Op,myLots,Price,Slippage,0,0,TC,MagicID+myLots*100,Exp,Blue);
   if (err<0) {
      Print ("Buy unsuccessful - ",err);
      return(false);
      }
   else if (OrderSelect(err,SELECT_BY_TICKET,MODE_TRADES)) {
      LastBuyTime=Time[0];
      ClearSignals();
      if (OrderType() != Op) {
         Alert("Warning: Broker reversed trade #",err,"!!!!!");
         if (Op<2) OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(OrderClosePrice(),Digits),Slippage,Blue);
         else OrderDelete(OrderTicket());
         return(false);
         }
      if (myStop==0 && myTake==0) return(true);
      bool result=false;
      int ct=0;
      while (!result && ct<50) {
         ct++;
         Sleep(3000);
         result=OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(myStop,Digits),NormalizeDouble(myTake,Digits),0,CLR_NONE);
         }   
      if (!result) Alert("Error modifying buy order: ",GetLastError());
      }
   return(true);
}
bool SellNow() {
   int err;
   if (CloseOppositeTrades) CloseBuy(-1);
   if ((UseHourTrade1 && !IsTradeTime1()) || (UseHourTrade2 && !IsTradeTime2())) return(false);
   RefreshRates();
   double lots=0;
   bool CLoss=CheckLoss(lots);
   int Op=OP_SELL,Exp=0;
   double Price=NormalizeDouble(Bid,Digits);
   double myStop = GetSL(SELL,Price);
   double myTake = GetTP(SELL,Price);
   if (Martingale && CLoss) double myLots=lots*LotMultiplier;
   else myLots = GetLots(Price,myStop);
   if (Ask<myTake && myTake!=0.0) {
      Print("Sell: Too far already...Ask: ",Ask," myStop: ",myStop," myTake: ",myTake);
      return(false);
      }
   while (!IsTradeAllowed()) Sleep(5000);
   RefreshRates();
   int Chk=0;
   while (Chk!=GOOD) {
      Chk = IsSellValid(myStop,myTake);
      if (Chk==TAKE) myTake -= Pt;
      else if (Chk==STOP) myStop += Pt;
      }
   string TC=TradeComment + " Sell";
   err = OrderSend(Symbol(),Op,myLots,Price,Slippage,0,0,TC,MagicID+myLots*100,Exp,Red);
   if (err<0) Print ("Sell unsuccessful - ",err);
   else if (OrderSelect(err,SELECT_BY_TICKET,MODE_TRADES)) {
      LastSellTime=Time[0];
      ClearSignals();
      if (OrderType() != Op) {
         Alert("Warning: Broker reversed trade #",err,"!!!!!");
         if (Op<2) OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(OrderClosePrice(),Digits),Slippage,Red);
         else OrderDelete(OrderTicket());
         return(false);
         }
      if (myStop==0 && myTake==0) return(true);
      bool result=false;
      int ct=0;
      while(!result && ct<50) {
         ct++;
         Sleep(3000);
         result=OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(myStop,Digits),NormalizeDouble(myTake,Digits),0,CLR_NONE);
         }
      if (!result) Alert("Error modifying buy order: ",GetLastError());
      }
   return(true);
}

double GetLots(double Price, double Stop) {
   double LotsToRisk,Lots;
   if (!UseMM) return(NoMMLots);
   int StopLossInPips = MathAbs(Price-Stop)/Pt;
   if (StopLossInPips==0) StopLossInPips = 100;
   LotsToRisk = ((AccountFreeMargin()*Risk)/100)/StopLossInPips;
   Lots = StrToDouble(DoubleToStr(LotsToRisk/LotTickValue,LotDecimal));
   Lots=MathMin(MathMax(Lots,MinLot),MaxLot);
   return(Lots);    
}
void UpdateTrail (int ticket) {
   RefreshRates();
   double NewStop;
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   if (OrderType() == OP_BUY) {
      if (TrailStop>0&&NormalizeDouble(Ask-TrailStart*Pt,Digits)>NormalizeDouble(OrderOpenPrice(),Digits)) {                 
         if(NormalizeDouble(OrderStopLoss(),Digits)<NormalizeDouble(Bid-TrailStop*Pt,Digits)||(OrderStopLoss()==0)) {
            NewStop = Bid-TrailStop*Pt;
            if (NormalizeDouble(OrderStopLoss(),Digits)<NormalizeDouble(NewStop,Digits)&& NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(NewStop,Digits)) {
               err=OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Blue);
               if (!err) Print ("Error modifying order on TrailStop: ",GetLastError());
               }
            }
         }
      }
   else if (OrderType() == OP_SELL) {
      if (TrailStop>0&&NormalizeDouble(Bid+TrailStart*Pt,Digits)<NormalizeDouble(OrderOpenPrice(),Digits)) {                 
         if (NormalizeDouble(OrderStopLoss(),Digits)>NormalizeDouble(Ask+TrailStop*Pt,Digits)||(OrderStopLoss()==0)) {
            NewStop = Ask+TrailStop*Pt;
            if (NormalizeDouble(OrderStopLoss(),Digits) > NormalizeDouble(NewStop,Digits) && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(NewStop,Digits)) {
               err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Red);
               if (!err) Print ("Error modifying order on TrailStop: ",GetLastError());
               }
            }
         }
      }
   return;
}
void UpdateSRTrailStop (int ticket, double newStop) {
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   if (OrderType() == OP_BUY) {
      newStop -= SLPipDiff*Pt;
      if (AddSpread) newStop -= MarketInfo(Symbol(),MODE_SPREAD)*Point;
      if (NormalizeDouble(OrderStopLoss(),Digits)<NormalizeDouble(newStop,Digits) && NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(newStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(newStop,Digits),OrderTakeProfit(),0,Blue);
         if (!err) Print ("Error modifying order on SRTrail: ",GetLastError());
         }
      }
   else if (OrderType() == OP_SELL) {
      newStop += SLPipDiff*Pt;
      if (AddSpread) newStop += MarketInfo(Symbol(),MODE_SPREAD)*Point;
      if ((NormalizeDouble(OrderStopLoss(),Digits)>NormalizeDouble(newStop,Digits) || OrderStopLoss()==0.0) && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(newStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(newStop,Digits),OrderTakeProfit(),0,Red);
         if (!err) Print ("Error modifying order on SRTrail: ",GetLastError());
         }
      }
   return;
}
void UpdatePctTS (int ticket) {
   RefreshRates();
   double NewStop,MaxPrice;
   int TradeTime;
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   TradeTime=iBarShift(NULL,0,OrderOpenTime(),true);
   if (OrderType() == OP_BUY) {
      MaxPrice=High[iHighest(NULL,0,MODE_HIGH,TradeTime,0)];
      NewStop = MaxPrice-(MaxPrice-OrderOpenPrice())*TSPercent/100;
      if (TSPercentStartPips>0&&NormalizeDouble(Ask-TSPercentStartPips*Pt,Digits)>NormalizeDouble(OrderOpenPrice(),Digits)) {                 
         if(NormalizeDouble(OrderStopLoss(),Digits)<NormalizeDouble(NewStop,Digits) && NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(NewStop,Digits)) {
            err=OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Blue);
            if (!err) Print ("Error modifying order on TrailStop: ",GetLastError());
            }
         }
      }
   else if (OrderType() == OP_SELL) {
      MaxPrice=Low[iLowest(NULL,0,MODE_LOW,TradeTime,0)];
      NewStop = MaxPrice+(OrderOpenPrice()-MaxPrice)*TSPercent/100;
      if (TSPercentStartPips>0&&NormalizeDouble(Bid+TSPercentStartPips*Pt,Digits)<NormalizeDouble(OrderOpenPrice(),Digits)) {                 
         if ((NormalizeDouble(OrderStopLoss(),Digits)>NormalizeDouble(NewStop,Digits) || OrderStopLoss()==0.0) && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(NewStop,Digits)) {
            err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Red);
            if (!err) Print ("Error modifying order on TrailStop: ",GetLastError());
            }
         }
      }
   return;
}

void UpdateCandleTrail (int ticket) {
   double NewStop;
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   if (OrderType() == OP_BUY) {
      NewStop = Low[iLowest(Symbol(),0,MODE_LOW,TrailCandlesBack,0)]-SLPipDiff*Pt;
      if (NormalizeDouble(Bid,Digits)<=NormalizeDouble(NewStop,Digits)) {
         CloseBuy(ticket);
         return;
         }
      if (NormalizeDouble(OrderStopLoss(),Digits) < NormalizeDouble(NewStop,Digits) && NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Blue);
         if (!err) Print ("Error modifying order on candletrail: ",GetLastError());
         }
      }
   else if (OrderType() == OP_SELL) {
      NewStop = High[iHighest(Symbol(),0,MODE_HIGH,TrailCandlesBack,0)]+SLPipDiff*Pt;
      if (NormalizeDouble(Ask,Digits)>=NormalizeDouble(NewStop,Digits)) {
         CloseSell(ticket);
         return;
         }
      if ((NormalizeDouble(OrderStopLoss(),Digits) > NormalizeDouble(NewStop,Digits) || OrderStopLoss()==0.0) && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Red);
         if (!err) Print ("Error modifying order on candletrail: ",GetLastError());
         }
      }
   return;
}
void UpdatePSARTrail (int ticket) {
   double NewStop=iSAR(NULL,0,PSAR_Step,PSAR_Max,0);
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   if (OrderType() == OP_BUY) {
      NewStop -= SLPipDiff*Pt;
      if (AddSpread) NewStop -= MarketInfo(Symbol(),MODE_SPREAD)*Point;
      if (NormalizeDouble(OrderStopLoss(),Digits) < NormalizeDouble(NewStop,Digits) && NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Blue);
         if (!err) Print ("Error modifying order on candletrail: ",GetLastError());
         }
      }
   else if (OrderType() == OP_SELL) {
      NewStop += SLPipDiff*Pt;
      if (AddSpread) NewStop += MarketInfo(Symbol(),MODE_SPREAD)*Point;
      if ((NormalizeDouble(OrderStopLoss(),Digits) > NormalizeDouble(NewStop,Digits) || OrderStopLoss()==0.0) && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Red);
         if (!err) Print ("Error modifying order on candletrail: ",GetLastError());
         }
      }
   return;
}
void UpdateMATrail (int ticket) {
   double NewStop=iMA(NULL,0,MAPeriod,0,MAMethod,MAPrice,0);
   double ma=iMA(NULL,0,MAPeriod,0,MAMethod,MAPrice,1);
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   if (OrderType() == OP_BUY) {
      if (NewStop<ma) return;
      NewStop -= SLPipDiff*Pt;
      if (AddSpread) NewStop -= MarketInfo(Symbol(),MODE_SPREAD)*Point;
      if (NormalizeDouble(OrderStopLoss(),Digits) < NormalizeDouble(NewStop,Digits) && NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Blue);
         if (!err) Print ("Error modifying order on candletrail: ",GetLastError());
         }
      }
   else if (OrderType() == OP_SELL) {
      if (NewStop>ma) return;
      NewStop += SLPipDiff*Pt;
      if (AddSpread) NewStop += MarketInfo(Symbol(),MODE_SPREAD)*Point;
      if ((NormalizeDouble(OrderStopLoss(),Digits) > NormalizeDouble(NewStop,Digits) || OrderStopLoss()==0.0) && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Red);
         if (!err) Print ("Error modifying order on candletrail: ",GetLastError());
         }
      }
   return;
}
void GoToBE(int ticket) {
   double NewStop;
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   if (OrderType() == OP_BUY) {
      NewStop = OrderOpenPrice()+ LockInPips*Pt;
      if (Bid-OrderOpenPrice()>=BreakEvenPips*Pt&&NormalizeDouble(OrderStopLoss(),Digits)<NormalizeDouble(NewStop,Digits)
         && NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Blue);
         if (!err) Print ("Error modifying order on BE: ",GetLastError());
         }
      }
   else if (OrderType() == OP_SELL) {
      NewStop = OrderOpenPrice()- LockInPips*Pt;
      if (OrderOpenPrice()-Ask>=BreakEvenPips*Pt && (NormalizeDouble(OrderStopLoss(),Digits)>NormalizeDouble(NewStop,Digits) || OrderStopLoss()==0.0)
          && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(NewStop,Digits)) {
         err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),OrderTakeProfit(),0,Red);
         if (!err) Print ("Error modifying order on BE: ",GetLastError());
         }
      }
   return;
}
void MoveSLTP(int ticket) {
   double NewStop,NewTake;
   bool err;
   if (!OrderSelect(ticket, SELECT_BY_POS,MODE_TRADES)) return;
   if (OrderType() == OP_BUY) {
      if (OrderTakeProfit()-Bid<=TP_DistancePips*Pt && OrderStopLoss()>0.0 && OrderTakeProfit()>0.0) {
         NewStop = OrderStopLoss()+MovePips*Pt;
         NewTake = OrderTakeProfit()+MovePips*Pt;
         if (NormalizeDouble(OrderStopLoss(),Digits)<NormalizeDouble(NewStop,Digits) && NormalizeDouble(Bid-StopRange*Pt,Digits)>NormalizeDouble(NewStop,Digits)) {
            err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),NormalizeDouble(NewTake,Digits),0,Blue);
            if (!err) Print ("Error modifying order on MoveSL_TP: ",GetLastError());
            }
         }
      }
   else if (OrderType() == OP_SELL) {
      if (Ask-OrderTakeProfit()<=TP_DistancePips*Pt && OrderStopLoss()>0.0 && OrderTakeProfit()>0.0) {
         NewStop = OrderStopLoss()-MovePips*Pt;
         NewTake = OrderTakeProfit()-MovePips*Pt;
         if ((NormalizeDouble(OrderStopLoss(),Digits)>NormalizeDouble(NewStop,Digits) || OrderStopLoss()==0.0) && NormalizeDouble(Ask+StopRange*Pt,Digits)<NormalizeDouble(NewStop,Digits)) {
            err = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(NewStop,Digits),NormalizeDouble(NewTake,Digits),0,Red);
            if (!err) Print ("Error modifying order on MoveSL_TP: ",GetLastError());
            }
         }
      }
   return;
}
void DrawArrow(color theColor,int theCode,bool up) {
   string name = "TDIEA:"+Time[0];
   double gap  = 3.0*iATR(NULL,0,20,0)/4.0;   
   ObjectCreate(name,OBJ_ARROW,0,Time[0],0);
      ObjectSet(name,OBJPROP_ARROWCODE,theCode);
      ObjectSet(name,OBJPROP_COLOR,theColor);
      if (up)
            ObjectSet(name,OBJPROP_PRICE1,High[0]+gap);
      else  ObjectSet(name,OBJPROP_PRICE1,Low[0] -gap);
}
void DoAlert(int cmd) {
   if (cmd>0) {
      if (AlertOn) Alert("TDIEA Buy Alert! "+Symbol()+" ["+Period()+"m]");
      if (EmailOn) SendMail("TDIEA Buy Alert!",Symbol()+" ["+Period()+"m] - Buy entry price "+NormalizeDouble(Ask,Digits));
      }
   else if (cmd<0) {
      if (AlertOn) Alert("TDIEA Sell Alert! "+Symbol()+" ["+Period()+"m]");
      if (EmailOn) SendMail("TDIEA Sell Alert!",Symbol()+" ["+Period()+"m] - Sell entry price "+NormalizeDouble(Bid,Digits));
      }
   return;
}
int IsBuyValid(double Stop, double Take) {
   if (Ask+StopRange*Pt>Take&&Take!=0) return (TAKE);
   if (Bid-StopRange*Pt<Stop) return(STOP);
   return(GOOD);
}

int IsSellValid(double Stop, double Take) {
   if (Bid-StopRange*Pt<Take) return(TAKE);
   if (Ask+StopRange*Pt>Stop&&Stop!=0) return(STOP);
   return(GOOD);   
}
void ClearSignals() {
   BuySignal=false;
   SellSignal=false;
   BuySignal1=false;
   SellSignal1=false;
   return;
}
bool CheckLoss(double& lot) {
   bool result=false;
   lot = 0.0;
   for (int l=OrdersHistoryTotal()-1;l>=0;l--) {
      if (!OrderSelect(l, SELECT_BY_POS,MODE_HISTORY)) continue;
      if (OrderSymbol()==Symbol()  && OrderMagicNumber()>=MagicID && OrderMagicNumber()<MagicID+10000) {
         if (OrderType()>1) continue;
         if (OrderProfit()<0) {
            result=true;
            lot=OrderLots();
            }
         break;
         }
      }
   return(result);
}