//+------------------------------------------------------------------+
//|                                         WUKAR_WB_Trail_v1.3e.mq4 |
//| Orignals WUKAR.mq4 and Wheelbarrel Trailing_v1.2.mq4             |
//| are merged. Credit goes to the original authors                  |
//--------------------------------------------------------------------

#include <stdlib.mqh>
#include <stderror.mqh>
#include <WinUser32.mqh> 

extern double  RiskPercent             = 1.0;
extern double  AdditionalEquity        = 0;
extern string  TP_SL_Settings          = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern bool    UseHiddenStopLoss       = false;
extern int     HiddenSL                = 100;
extern bool    UseEmergencyStopLoss    = true;
extern int     EmergencySL             = 150;
extern bool    UseHiddenTakeProfit     = true;
extern double  TakeProfitMultiplier=2; //Use one or the other
extern int     HiddenTP1=50; //
extern string  Trailingstop_Settings   = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern bool    ProfitTrailing          = true;
extern bool    UseHiddenTrailingStop   = true;
extern bool    ATRTrail                = true;
extern int     ATRTF                   = 5;
extern int     TSPeriod                = 9;
extern int     BarsBack                = 10;
extern string  TSComment               = "If not using ATRTrail";
extern int     TrailingStop            = 35;
extern int     TrailingStep            = 1;
extern bool    UseSound                = false;
extern string  NameFileSound           = "cork_pop.wav";
extern string  Breakeven_Settings      = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern string  BE                      = "Break even settings";
extern bool    BreakEven               = false;
extern bool    UseHiddenBreakEven      = true;
extern int     BreakEvenPips           = 35;
extern string  Line_Settings           = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern string  LS                      = "Line settings";
extern bool    DrawLines               = true;
extern color   TPColor                 = Green;
extern color   SLColor                 = Red;
extern color   BEColor                 = Yellow;
extern color   TSColor                 = Magenta;
extern color   TextColor               = DimGray;
extern int     ShiftLabel              = 1;
extern bool    FullScreenLines         = true;
extern string  FSL                     = "If False, lines start at current bar";
extern string  Other_Settings          = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern string  OS                      = "Other settings";
extern double  Commission              = 7;
extern bool    DeleteOCO               = true;
extern string  OCO_Comment             = "Will delete remaining Pending orders";
extern int     MagicNumber             = 32769;

double HSL,HTP,HBE,HTS,BEPrice;
string ObjPref="WUKAR_";
int    LineType;
color  LineColor;
bool   IsTrade;
double BuyEntryPrice,SellEntryPrice,EntryPrice,Entry;
int    Mode;

double Lots;
double equity;
double StopLoss,StopLevel,TakeProfit;
double ReqMargin;
double TradeReq;
double EquityRisk;
double expiration;

string TicketNo;
bool   DeleteGV=false;
//+------------------------------------------------------------------+
void init()
  {
   StopLoss=0;
   BuyEntryPrice=10000;
   SellEntryPrice=-1;
   expiration=Time[0];

   if(FullScreenLines)
      LineType=OBJ_HLINE;
   else
      LineType=OBJ_TREND;
  }
//+------------------------------------------------------------------+
void deinit()
  {
//   DeleteAllLines();
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
void start()
  {
   if(DeleteGV)
      if(getOpenOrders()==0) // if no open orders in current TF
        {
         GlobalVariablesDeleteAll(Symbol()+Period());
         DeleteGV=false;
        }

   IsTrade=false;
   bool PlaceTrade=false;
   bool result=false;
   int PendingOrder= 0;
   int totalorders = OrdersTotal();
   for(int i=totalorders-1; i>=0; i--)
     {
      result=OrderSelect(i,SELECT_BY_POS);
      if(OrderType()>OP_SELL && OrderSymbol()==Symbol())
         PendingOrder=OrderTicket();

      if(OrderType()<=OP_SELL && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
        {
         IsTrade=True;
         DeleteGV=true;
         TicketNo= OrderTicket();

         if(ProfitTrailing)
            TrailingPositions();

         if(UseHiddenStopLoss)
            HiddenStopLoss();
         if(UseHiddenTakeProfit)
            HiddenTakeProfit();
         if(UseEmergencyStopLoss)
            EmergencyStopLoss();
        }

      if(IsTrade && DeleteOCO && PendingOrder>0)
         OrderDelete(PendingOrder);

      if(ObjectFind("EJS_PL")==0 && IsTrade)
         ObjectDelete("EJS_PL");
     }
   if(!IsTrade)
     {
      DeleteAllLines();
      HSL = 0;
      HTP = 0;
      HBE = 0;
      HTS = 0;
      BEPrice=0;
      EntryPrice=0;

      if(ObjectFind("EJS_PL")==0)
        {
         if(Time[0]>expiration)
           {
            ObjectDelete("EJS_PL");
            BuyEntryPrice=10000;
            SellEntryPrice=-1;
           }

         EntryPrice=ObjectGet("EJS_PL",OBJPROP_PRICE1);

         if(StopLoss==0)
           {
            if(EntryPrice>Close[0])
              {
               BuyEntryPrice=EntryPrice;
               if(ATRTrail)
                  StopLoss=NormalizeDouble(EntryPrice-(Low[1]-iATR(Symbol(),ATRTF,TSPeriod,1)),Digits)/Point;
               else
                  StopLoss=HiddenSL;
              }
            else
              {
               SellEntryPrice=EntryPrice;
               if(ATRTrail)
                  StopLoss=NormalizeDouble((High[1]+iATR(Symbol(),ATRTF,TSPeriod,1)-EntryPrice),Digits)/Point;
               else
                  StopLoss=HiddenSL;
              }
           }

         //Print("StopLoss=",StopLoss);
         expiration=iTime(Symbol(),PERIOD_H1,0)+3599;
         if(Close[0]>=BuyEntryPrice)
           {
            Entry= Ask;
            Mode = OP_BUY;
            PlaceTrade=true;
           }

         if(Close[0]<=SellEntryPrice)
           {
            Entry= Bid;
            Mode = OP_SELL;
            PlaceTrade=true;
           }

         if(PlaceTrade)
           {
            double Risk=RiskPercent/100;

            equity=AccountBalance()+AdditionalEquity;

            int min_size_digits;

            //check account type (micro / mini / normal)
            if(MarketInfo(Symbol(),MODE_LOTSTEP)==0.001)
               min_size_digits=3;
            if(MarketInfo(Symbol(),MODE_LOTSTEP)==0.01)
               min_size_digits=2;
            if(MarketInfo(Symbol(),MODE_LOTSTEP)==0.05)
               min_size_digits=2;
            if(MarketInfo(Symbol(),MODE_LOTSTEP)==0.1)
               min_size_digits=1;
            if(MarketInfo(Symbol(),MODE_LOTSTEP)==1)
               min_size_digits=0;

            Lots=NormalizeDouble(equity*Risk/StopLoss/(MarketInfo(Symbol(),MODE_TICKVALUE)),2);
            if(Lots<MarketInfo(Symbol(),MODE_MINLOT))
               Lots=MarketInfo(Symbol(),MODE_MINLOT);
            if(Lots>MarketInfo(Symbol(),MODE_MAXLOT))
               Lots=MarketInfo(Symbol(),MODE_MAXLOT);
            Lots=NormalizeDouble(Lots,min_size_digits);
            if(MarketInfo(Symbol(),MODE_LOTSTEP)==0.05)
              {
               int templots=Lots*100;
               double remainder=templots%5;
               templots=templots-remainder;
               Lots = templots;
               Lots/=100;
              }

            //Check free margin
            ReqMargin=MarketInfo(Symbol(),MODE_MARGINREQUIRED)*Lots;
            EquityRisk=StopLoss*MarketInfo(Symbol(),MODE_TICKVALUE)*Lots;
            TradeReq=ReqMargin+EquityRisk;
            while(TradeReq>AccountFreeMargin())
              {
               Lots=Lots-MarketInfo(Symbol(),MODE_LOTSTEP);
               if(Lots<MarketInfo(Symbol(),MODE_MINLOT))
                 {
                  Print("Insufficient Funds to trade. Free Margin = ",AccountFreeMargin());
                  return(-1);
                 }// end if(Lots < MarketInfo(Symbol(), MODE_MINLOT))
               ReqMargin=MarketInfo(Symbol(),MODE_MARGINREQUIRED)*Lots;
               EquityRisk=StopLoss*MarketInfo(Symbol(),MODE_TICKVALUE)*Lots;
               TradeReq=ReqMargin+EquityRisk;
              }// end while(TradeReq > AccountFreeMargin() )

            //Print("Lots= ",Lots);

            if(Lots>0)
              {
               int ticket=OrderSend(Symbol(),Mode,Lots,Entry,3,0,0,"",MagicNumber,NULL,Red);
               if(ticket>0)
                 {
                  ObjectDelete("EJS_PL");
                  StopLoss=0;
                  BuyEntryPrice=10000;
                  SellEntryPrice=-1;
                 }
              }// end if(Lots > 0)          
           }
        }
      else
         expiration=Time[0];
     }

//   Comment("\n\n\n\n\n\n\n\nIsTrade = ",IsTrade,"\nHBE=",HBE,"\nHTS=",HTS);

   return;

/* Do not uncomment the below. It does not do anything useful except to
  open orders, so as to test, trail stop, tp aand stop loss of the two EAs 
  merged. Its a work around to test the EA is working in the tester. thats all */

// OpenPosition();    
  }
//+------------------------------------------------------------------+
void TrailingPositions()
  {
   double pBid,pAsk,pp;

   RefreshRates();
   pp=MarketInfo(OrderSymbol(),MODE_POINT);
   double NewStop=0;

   if(ObjectFind("HBE line")==0 && HBE==0)
      HBE=ObjectGetDouble(0,"HBE line",OBJPROP_PRICE,0);
   if(ObjectFind("HTS line")==0 && HTS==0)
      HTS=ObjectGetDouble(0,"HTS line",OBJPROP_PRICE,0);

   if(OrderType()==OP_BUY)
     {
      pBid=MarketInfo(OrderSymbol(),MODE_BID);
      if((HBE!=0.0 && pBid<=HBE) || (HTS!=0.0 && pBid<=HTS))
        {
         OrderClose(OrderTicket(),OrderLots(),pBid,5,Red);
         return;
        }

      if(BreakEven==true
         && HBE==0.0
         && BEPrice==0.0
         && pBid>OrderOpenPrice()+BreakEvenPips*pp)
         BEPrice=OrderOpenPrice()+Commission*pp;

      if(ATRTrail)
        {
         NewStop=NormalizeDouble(Low[1]-iATR(Symbol(),ATRTF,TSPeriod,1),Digits);
        }
      else
      if(pBid-OrderOpenPrice()>=(TrailingStop+TrailingStep) *pp)
                                NewStop=pBid-TrailingStop*pp;
     }

   if(OrderType()==OP_SELL)
     {
      pAsk=MarketInfo(OrderSymbol(),MODE_ASK);
      if((HBE!=0.0 && pAsk>=HBE) || (HTS!=0.0 && pAsk>=HTS))
        {
         OrderClose(OrderTicket(),OrderLots(),pAsk,5,Red);
         return;
        }

      if(BreakEven==true
         && HBE==0.0
         && BEPrice==0.0
         && pAsk<OrderOpenPrice()-BreakEvenPips*pp
         )
         BEPrice=OrderOpenPrice()-Commission*pp;

      if(ATRTrail)
        {
         NewStop=NormalizeDouble(High[1]+iATR(Symbol(),ATRTF,TSPeriod,1),Digits);
        }
      else
      if(OrderOpenPrice()-pAsk>=(TrailingStop+TrailingStep)*pp)
                                NewStop=pAsk+TrailingStop*pp;
     }

   if(BEPrice!=0)
     {
      if(UseHiddenBreakEven)
        {
         if(HBE == 0)
            HBE = BEPrice;
         if(DrawLines)
           {
            LineColor=BEColor;
            DrawLine("HiddenBE label","HBE","HBE line",LineType,LineColor,HBE);
           }
        }
      else
      if(ModifyStopLoss(BEPrice))
        {
         Print("WUKAR_WB Modified Stop Loss");
         BEPrice=0;
        }

     }

   if(NewStop!=0)
     {
      if(UseHiddenTrailingStop)
        {
         if((OrderType()==OP_BUY && HTS<NewStop) || (OrderType()==OP_SELL && HTS>NewStop) || HTS==0)
            HTS=NewStop;
         if(DrawLines)
           {
            LineColor=TSColor;
            DrawLine("HiddenTS label","HTS","HTS line",LineType,LineColor,HTS);
           }
        }
      else
      if((OrderType()==OP_BUY && OrderStopLoss()<NewStop) || (OrderType()==OP_SELL && OrderStopLoss()>NewStop))
      if(ModifyStopLoss(NewStop))
         Print("WUKAR_WB Modified Stop Loss");
     }

   if(ObjectFind(0,"HTS line")==0 && ObjectFind(0,"HBE line")==0)
     {
      ObjectDelete(0,"HBE line");
      ObjectDelete(0,"HiddenBE label");
     }

   return;
  }
//+------------------------------------------------------------------+
bool ModifyStopLoss(double ldStopLoss)
  {
   bool fm;
   fm=OrderModify(OrderTicket(),OrderOpenPrice(),ldStopLoss,OrderTakeProfit(),0,CLR_NONE);
   if(fm && UseSound)
      PlaySound(NameFileSound);
   if(!fm)
     {
      int err;
      err=GetLastError();
      Print("Wheelbarrel trailing error (",err,")");
      return false;
     }
   return true;
  }
//+------------------------------------------------------------------+
void HiddenTakeProfit()
  {
   bool result=false;
   if(OrderSymbol()==Symbol())
     {
      if(OrderType()==OP_BUY)
        {
         if(UseHiddenTakeProfit)
           {
            if(!checkVariable("TakeProfit",TicketNo))
              {
               StopLevel=NormalizeDouble(Low[1]-iATR(Symbol(),ATRTF,TSPeriod,1),Digits);
               if(TakeProfitMultiplier>0)
                  HTP=OrderOpenPrice()+MathAbs(OrderOpenPrice()-StopLevel)*TakeProfitMultiplier;
               else
                  HTP=OrderOpenPrice()+(HiddenTP1+Commission)*Point;
               setVariable("TakeProfit",TicketNo,HTP);
              }// end if 
            else
               HTP=getVariable("TakeProfit",TicketNo);
            if(Bid>=HTP)
               result=OrderClose(OrderTicket(),OrderLots(),MarketInfo(Symbol(),MODE_BID),5,Red);
           }
        }

      if(OrderType()==OP_SELL)
        {
         if(UseHiddenTakeProfit)
           {
            if(!checkVariable("TakeProfit",TicketNo))
              {
               StopLevel=NormalizeDouble(High[1]+iATR(Symbol(),ATRTF,TSPeriod,1),Digits);
               if(TakeProfitMultiplier>0)
                  HTP=OrderOpenPrice()-MathAbs(OrderOpenPrice()-StopLevel)*TakeProfitMultiplier;
               else
                  HTP=OrderOpenPrice()-(HiddenTP1+Commission)*Point;
               setVariable("TakeProfit",TicketNo,HTP);
              }// end if 
            else
               HTP=getVariable("TakeProfit",TicketNo);
            if(Ask<=HTP)
               result=OrderClose(OrderTicket(),OrderLots(),MarketInfo(Symbol(),MODE_ASK),5,Red);
           }
        }

      if(DrawLines)
        {
         LineColor=TPColor;
         if(UseHiddenTakeProfit)
           {
            DrawLine("HiddenTP label","HTP","HTP line",LineType,LineColor,HTP);
           }
        }
     }
   return;
  }
//+-------------------------------------------------------------------------------------------+
void HiddenStopLoss()
  {
   bool result=false;
   if(OrderSymbol()==Symbol())
     {
      if(OrderType()==OP_BUY)
        {
         HSL=OrderOpenPrice()-HiddenSL*Point;
         if(HSL>=Bid)
            result=OrderClose(OrderTicket(),OrderLots(),MarketInfo(Symbol(),MODE_BID),5,Red);
        }

      if(OrderType()==OP_SELL)
        {
         HSL=OrderOpenPrice()+HiddenSL*Point;
         if(HSL<=Ask)
            result=OrderClose(OrderTicket(),OrderLots(),MarketInfo(Symbol(),MODE_ASK),5,Red);
        }

      if(DrawLines)
        {
         LineColor=SLColor;
         DrawLine("HiddenSL label","HSL","HSL line",LineType,LineColor,HSL);
        }
     }
   return;
  }
//+-------------------------------------------------------------------------------------------+
void EmergencyStopLoss()
  {
   bool result=false;

   if(OrderSymbol()==Symbol())
     {
      if(OrderType()==OP_BUY && OrderStopLoss()==0.0)
         result=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-EmergencySL*Point,OrderTakeProfit(),0,clrNONE);
      if(OrderType()==OP_SELL && OrderStopLoss()==0.0)
         result=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+EmergencySL*Point,OrderTakeProfit(),0,clrNONE);
     }
   return;
  }
//+-------------------------------------------------------------------------------------------+
void OpenPosition()
  {
   int ans=0;
   if(Open[0]>Close[0])
     {
      ans=OrderSend(Symbol(),OP_BUY,0.01,Ask,25,0,0,NULL,10,Blue); //Opening Buy        
     }
   else
     {
      ans=OrderSend(Symbol(),OP_SELL,0.01,Bid,25,0,0,NULL,10,Blue); //Opening Buy  
     }
   if(ans<0)
     {
      Print("Error when opening a order #",GetLastError());
      Sleep(10000);
      return;
     }
  }
//+-------------------------------------------------------------------------------------------+
//| Subroutine to draw pivot lines and labels                                |                                                                                  |
//+-------------------------------------------------------------------------------------------+
void DrawLine(string LineLabel,string LineText,string TMLine,int LnType,color LnColor,double LinePrice)
  {
   if(ObjectFind(LineLabel)!=0)
     {
      ObjectCreate(LineLabel,OBJ_TEXT,0,Time[0]+Period()*60*ShiftLabel,LinePrice);
      ObjectSetText(LineLabel,LineText,8,"Arial",EMPTY);
     }
   else
     {
      ObjectMove(LineLabel,0,Time[0]+Period()*60*ShiftLabel,LinePrice);
      ObjectSetText(LineLabel,LineText,8,"Arial",EMPTY);
     }

   if(ObjectFind(TMLine)!=0)
     {
      ObjectCreate(TMLine,LnType,0,Time[1],LinePrice,Time[0],LinePrice);
      ObjectSet(TMLine,OBJPROP_STYLE,STYLE_DASHDOTDOT);
      ObjectSet(TMLine,OBJPROP_COLOR,LnColor);
      //         ObjectSet(TMLine, OBJPROP_RAY, true);
     }
   else
     {
      ObjectMove(TMLine,0,Time[1],LinePrice);
      ObjectMove(TMLine,1,Time[0],LinePrice);
     }
  }
//+------------------------------------------------------------------+
void DeleteAllLines()
  {
   ObjectDelete(0,"HiddenSL label");
   ObjectDelete(0,"HSL line");
   ObjectDelete(0,"HiddenTP label");
   ObjectDelete(0,"HTP line");
   ObjectDelete(0,"HiddenBE label");
   ObjectDelete(0,"HBE line");
   ObjectDelete(0,"HiddenTS label");
   ObjectDelete(0,"HTS line");
   return;
  }
//+------------------------------------------------------------------+
//-----------------------------------------------------
int getOpenOrders()
  {
   int CurrentPairOrders=0;
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)
         continue;

      if(OrderSymbol()!=Symbol())
         continue;

      if(OrderSymbol()==Symbol())// && OrderMagicNumber() == MagicNumber)
         CurrentPairOrders++;
     }// end for (int i = 0; i < OrdersTotal(); i++)
   return(CurrentPairOrders);
  }// end int getOpenOrders()
//---------------------------------------------------------------
void setVariable(string name,string TicketNo,double value)
  {
   GlobalVariableSet(getFullName(name,TicketNo),value);
  }
//---------------------------------------------------------------
double getVariable(string name,string TicketNo)
  {
   return(GlobalVariableGet(getFullName(name, TicketNo)));
  }
//---------------------------------------------------------------
bool checkVariable(string name,string TicketNo)
  {
   return(GlobalVariableCheck(getFullName(name, TicketNo)));
  }
//---------------------------------------------------------------
string getFullName(string name,string TicketNo)
  {
//   return(WindowExpertName() + Symbol() + Period() + name);
   return(Symbol() + Period() + name + TicketNo);
  }
//+------------------------------------------------------------------+
