//+------------------------------------------------------------------+
//|TPSLManager_V2.mq4                                        		 |
//|Programmed by ME                                                  |
//+------------------------------------------------------------------+
#property copyright "Masha Inc."

#include <stdlib.mqh>
#include <stderror.mqh>
#include <WinUser32.mqh> 

extern string  TP_SL_Settings          = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern bool    UseHiddenStopLoss       = true;
extern int     HiddenSL                = 172;
extern bool    UseEmergencyStopLoss    = false;
extern int     EmergencySL             = 300;
extern bool    UseHiddenTakeProfit     = true;
extern int     HiddenTP1               = 172;
extern string  Trailingstop_Settings   = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern bool    ProfitTrailing          = true;  
extern bool    UseHiddenTrailingStop   = true;
extern int     TrailingStop            = 75;    
extern int     TrailingStop2           = 20;
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                 = clrCrimson;
extern color   SLColor                 = clrCrimson;
extern color   BEColor                 = clrYellow;
extern color   TSColor                 = clrBlue;
extern color   TextColor               = clrSilver;
extern int     ShiftLabel              = 1;
extern bool    FullScreenLines         = true;
extern string  FSL                     = "If False, lines start at current bar";
extern string  Dyn_Exit_Settings       = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern string  DYN                     = "Dynamic Exit Settings";
extern bool    flagAtrTp               = true;
extern bool    flagAtrSl               = true;
extern bool    flagDynBeTs             = true;
extern double  atrSl                   = 2.1;
extern double  atrTp                   = 2.1;
extern double  atrTs                   = 0.7;
extern double  atrTs2                  = 0.2;
extern double  atrBe                   = 0.35;
extern string  Other_Settings          = "覧覧覧覧覧覧覧覧覧覧覧覧覧覧覧";
extern string  OS                      = "Other settings";
extern bool    DeleteOCO               = false;
extern string  OCO_Comment             = "Will delete remaining Pending orders";
extern int     tf                      = PERIOD_M15;
extern int     atrPeriod               = 480;

double HSL, HTP, HBE, HTS, BEPrice, ATR;
int    LineType;
color  LineColor;
bool   IsTrade;

//+------------------------------------------------------------------+
void init()
{
    if (FullScreenLines)
    {
        LineType = OBJ_HLINE;
    }
    else
    {
        LineType = OBJ_TREND;
    }
}

//+------------------------------------------------------------------+
void deinit()
{
//   DeleteAllLines();
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
void start() 
{
    datetime tickTime_M15;    
    bool result = false;
    int totalorders, PendingOrder;
    
    IsTrade = false;
    PendingOrder = 0;    
    totalorders = OrdersTotal();
    
    for (int k = totalorders - 1; k >= 0; k--)
    {
        result = OrderSelect(k, SELECT_BY_POS);
        
        if (flagAtrTp || flagAtrSl || flagDynBeTs)
        {            
            ATR = iATR(OrderSymbol(), tf, atrPeriod, 0);
        }
        
        if (OrderType() > OP_SELL && OrderSymbol() == Symbol())
        {
            PendingOrder = OrderTicket();
        }
      
        if (OrderType() <= OP_SELL && OrderSymbol() == Symbol())
        {
            IsTrade = True;
            
            TrailingPositions();
         
            if (UseHiddenStopLoss)
            {
                HiddenStopLoss();
            }
         
            if (UseHiddenTakeProfit)
            {
                HiddenTakeProfit();
            }  
         
            if (UseEmergencyStopLoss)
            {
                EmergencyStopLoss();
            }                   
        }
      
        if (IsTrade && DeleteOCO && PendingOrder > 0)
        {
            OrderDelete(PendingOrder);
        }
    }
    
    if (!IsTrade)
    {
        DeleteAllLines();
        HSL = 0;
        HTP = 0;
        HBE = 0;
        HTS = 0;
        BEPrice = 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 and 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, NewStop, Ts, Ts2, Be, spread;
    string curSymbol;
            
    RefreshRates();
    curSymbol = OrderSymbol();
    pp = MarketInfo(curSymbol, MODE_POINT);
    spread = MarketInfo(curSymbol, MODE_SPREAD);
    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 (flagDynBeTs)
    {            
        Ts = NormalizeDouble((atrTs * ATR) / pp, 0);
        Ts2 = NormalizeDouble((atrTs2 * ATR) / pp, 0);
        Be = NormalizeDouble((atrBe * ATR) / pp, 0);                               
    }
    else
    {
        Ts = TrailingStop;
        Ts2 = TrailingStop2;
        Be = BreakEvenPips;            
    }
    
    if (OrderType() == OP_BUY)
    {
        pBid = MarketInfo(curSymbol, MODE_BID);
        
        if ((HBE != 0.0 && pBid <= HBE) || (HTS != 0.0 && pBid <= HTS))
        {
            OrderClose(OrderTicket(), OrderLots(), pBid, 3, Red);
            return;
        }   
      
        if (BreakEven == true && HBE == 0.0 && BEPrice == 0.0 && pBid > OrderOpenPrice() + Be * pp)
        {
            BEPrice = OrderOpenPrice() + spread * pp;
        }

        if (ProfitTrailing == true && pBid - OrderOpenPrice() >= (Ts * pp))
        {
            NewStop = pBid - (Ts2 * pp);
        }
    }
   
    if (OrderType() == OP_SELL) 
    {
        pAsk = MarketInfo(curSymbol, MODE_ASK);
        if ((HBE != 0.0 && pAsk >= HBE) || (HTS != 0.0 && pAsk >= HTS))
        {
            OrderClose(OrderTicket(), OrderLots(), pAsk, 3, Red);
            return;
        }   
      
        if (BreakEven == true && HBE == 0.0 && BEPrice == 0.0 && pAsk < OrderOpenPrice() - Be * pp)
        {
            BEPrice = OrderOpenPrice() - spread * pp;
        }
         
        if (ProfitTrailing == true && OrderOpenPrice() - pAsk >= (Ts * pp))
        {
            NewStop = pAsk + (Ts2 * 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("TradeManager 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; 
    int err;
    
    fm = OrderModify(OrderTicket(), OrderOpenPrice(), ldStopLoss, OrderTakeProfit(), 0, CLR_NONE);
   
    if (fm && UseSound) 
    {
        PlaySound(NameFileSound);
    }
    
    if (!fm)
    {
        err = GetLastError();
        Print("TradeManager trailing error (",err,")");
        return false;
    }
    
   return true;
}
//+------------------------------------------------------------------+
void HiddenTakeProfit()
{ 
    bool result = false;  
    int err;
    double pp, spread;
    string curSymbol;
    
    curSymbol = OrderSymbol();    
    pp = MarketInfo(curSymbol, MODE_POINT);
    spread = MarketInfo(curSymbol, MODE_SPREAD);
    
    if (curSymbol == Symbol()) 
    {
        if (OrderType() == OP_BUY)
        {
            if (flagAtrTp)
            {
                HTP = OrderOpenPrice() + ((atrTp * ATR) + (spread * pp));
            }
            else
            {
                HTP = OrderOpenPrice() + ((HiddenTP1 + spread) * pp);
            }
            
            if (Bid >= HTP)
            {
                result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 3, clrGreen);
                
                if (result == true)
                {                                                                            
                    Print("-----------------------------------------");       
                    Print("Take Profit for: ", Symbol(), " closed BUY @ ", HTP);
                    Print("Date/Time: ", TimeToStr(TimeCurrent()));
                }
                else
                {
                    err = GetLastError();
                    Print("Close position error: (", err, "), ", ErrorDescription(err), " - Pair: ", curSymbol); 
                }
            }
        }
      
        if (OrderType() == OP_SELL)
        {  
            if (flagAtrTp)
            {
                HTP = OrderOpenPrice() - ((atrTp * ATR) + (spread * pp));
            }
            else
            {
                HTP = OrderOpenPrice() - ((HiddenTP1 + spread) * pp);
            }
            
            if (Ask <= HTP)
            {
                result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_ASK), 3, clrGreen);  
                
                if (result == true)
                {                                                                            
                    Print("-----------------------------------------");       
                    Print("Take Profit for: ", Symbol(), " closed SELL @ ", HTP);
                    Print("Date/Time: ", TimeToStr(TimeCurrent()));
                }
                else
                {
                    err = GetLastError();
                    Print("Close position error: (", err, "), ", ErrorDescription(err), " - Pair: ", curSymbol); 
                }
            }
        }
      
        if (DrawLines)
        {
             LineColor = TPColor;
             DrawLine("HiddenTP label", "HTP", "HTP line", LineType, LineColor, HTP);
        }
    }
   
    return;
}
//+-------------------------------------------------------------------------------------------+
void HiddenStopLoss()
{ 
    bool result = false;
    int err;
    double pp, spread;
    string curSymbol;
    
    curSymbol = OrderSymbol();
    pp = MarketInfo(curSymbol, MODE_POINT);
    spread = MarketInfo(curSymbol, MODE_SPREAD);
    
    if (curSymbol == Symbol()) 
    {
        if(OrderType() == OP_BUY)  
        {
            if (flagAtrSl)
            {
                HSL = OrderOpenPrice() - ((atrSl * ATR) + (spread * pp));
            }
            else
            {
                HSL = OrderOpenPrice() - ((HiddenSL + spread) * pp);
            }            
            
            if (HSL >= Bid)
            {
                result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), 3, clrRed);
                
                if (result == true)
                {                                                                            
                    Print("-----------------------------------------");       
                    Print("Stop Loss for: ", Symbol(), " closed BUY @ ", HSL);
                    Print("Date/Time: ", TimeToStr(TimeCurrent()));
                }
                else
                {
                    err = GetLastError();
                    Print("Close position error: (", err, "), ", ErrorDescription(err), " - Pair: ", curSymbol); 
                }
            }
        }

        if (OrderType() == OP_SELL)
        {
            if (flagAtrSl)
            {
                HSL = OrderOpenPrice() + ((atrSl * ATR) + (spread * pp));
            }
            else
            {
                HSL = OrderOpenPrice() + ((HiddenSL + spread) * pp);
            }
        
            if (HSL <= Ask)
            {
                result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_ASK), 3, clrRed);    
                
                if (result == true)
                {                                                                            
                    Print("-----------------------------------------");       
                    Print("Stop Loss for: ", Symbol(), " closed SELL @ ", HSL);
                    Print("Date/Time: ", TimeToStr(TimeCurrent()));
                }
                else
                {
                    err = GetLastError();
                    Print("Close position error: (", err, "), ", ErrorDescription(err), " - Pair: ", curSymbol); 
                }
            }
        }
      
        if (DrawLines)
        {
            LineColor = SLColor;
            DrawLine("HiddenSL label", "HSL", "HSL line", LineType, LineColor, HSL);
        }
    }
    
    return;
}

//+-------------------------------------------------------------------------------------------+
void EmergencyStopLoss()
{
   int totalorders = OrdersTotal();

    for(int k = totalorders - 1; k >= 0; k--)
    {
        OrderSelect(k, SELECT_BY_POS, MODE_TRADES);
        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 Sell  
    }
     
    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;
}