//+--------------------------+//
//| MY TRADE MANAGER MT4.mq4 |//
//+--------------------------+//
//#property icon      "avg_trader_101.ico"
#property copyright "avg_trader_101"

#property strict

#define Id MQLInfoString(MQL_PROGRAM_NAME)
#define major   1
#define minor   1
#include <stdlib.mqh>
#include <stderror.mqh>
#define gVar "TMMT4"
//--
#include <WinUser32.mqh>
#import "user32.dll"
 
int GetAncestor(int, int);
#define MT4_WMCMD_EXPERTS  33020 

#import

enum YesNo{No=0,Yes=1};
enum ENUM_SYMBOL_TRADE_INFO
  {
   AllOpenOrders = 0, //All Open Orders
   CurrentChartSymbol = 1 //Current Chart Symbol
  };
  
input string noteCloseManagement       = ">> TP/SL ============="; //Description
input ENUM_SYMBOL_TRADE_INFO InpSymbol = AllOpenOrders; //Chart Symbol Selection
input double InpSL                     = 20; //Initial SL
input int InpBE                        = 12; //Break Even (pips), if 0 BE not Used
input int InpBEplus                    = 2;  //BE +
input double InpTP1                    = 10; //Take Profit 1 (pips)
input double InpPercentPartialClose1   = 80; //Partial Close %
input double InpTP2                    = 20; //Take Profit 2 (pips)
input double InpPercentPartialClose2   = 50; //Partial Close %
input double InpTP3                    = 40; //Take Profit 3 (pips)
input double InpPercentPartialClose3   = 100; //Partial Close %

input string noteTimeManagement        = ">> Trading Time  ====="; //Description
input string InpStartTime              = "01:10:00"; //Start Time (HH:MM:SS)
input string InpEndTime                = "23:55:00"; //End Time (HH:MM:SS)

int Sleeptime = 1000;
int Slippage  = 3;//Slippage:

static int shift;
datetime timestart,timeend;
//----
int getDigit(string symbol){ return((int)MarketInfo(symbol, MODE_DIGITS)); }

double getPoin(string symbol){
   double poin;
   int digits = getDigit(symbol);
   
   poin = MarketInfo(symbol,MODE_POINT);
   if (digits==2 || digits==4) { poin = MarketInfo(symbol,MODE_POINT)*1.0;    }
   if (digits==3 || digits==5) { poin = MarketInfo(symbol,MODE_POINT)*10.0;   }
   if (digits==6)              { poin = MarketInfo(symbol,MODE_POINT)*100.0;  }
   if (digits==7)              { poin = MarketInfo(symbol,MODE_POINT)*1000.0; }
   
   return(poin);
}

double getPrec(string symbol)
{
   double prec;
   int digits = getDigit(symbol);
   
   prec=1;
   if (digits==2 || digits==4) { prec=1.0;    }
   if (digits==3 || digits==5) { prec=10.0;   }
   if (digits==6)              { prec=100.0;  }//1000 ?
   if (digits==7)              { prec=1000.0; }
return(prec);
}

int getSlippage(string symbol){
   int realslippage;
   int digits = getDigit(symbol);
   
   realslippage=Slippage;
   if (digits==2 || digits==4){ realslippage = Slippage*1;    }
   if (digits==3 || digits==5){ realslippage = Slippage*10;   }
   if (digits==6)             { realslippage = Slippage*100;  }
   if (digits==7)             { realslippage = Slippage*1000; }
return(realslippage);
}

int getNorm(string symbol){
   double step     = MarketInfo(symbol,MODE_LOTSTEP);
   int norm     = 0;
   if (step==1)    norm = 0;
   if (step==0.1)  norm = 1;
   if (step==0.01) norm = 2;
   return(norm);
}
//----
int init()
  {
//---
   EventSetTimer(1);
   if(!IsTradeAllowed())
   {
      Comment(" Trading Paused ",TimeToStr(TimeCurrent(),TIME_MINUTES));
      return(0);
   }
   
   if(!IsExpertEnabled() && !IsTesting()){
   Print("Please enable your autotrade!");
   Comment("Please enable your autotrade!");
   ExpertRemove();
   }
   
   Print("run "+Symbol());
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//---
   Comment("");
   EventKillTimer();
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
int start(){
   //-------------
   bool enableTrade = false;
   //--
   timestart   = StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + " " + InpStartTime);
   timeend     = StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + " " + InpEndTime);
   if(timestart>timeend)
     {
      if(TimeCurrent()<=StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + " " + "23:59")){
      timeend=timeend+PeriodSeconds(PERIOD_D1);
      } else
      if(TimeCurrent()>StrToTime(TimeToStr(TimeCurrent(), TIME_DATE) + " " + "00:00"))
        {
         timestart=timestart-PeriodSeconds(PERIOD_D1);
        }
     }
   
   if(TimeCurrent()>=timestart && TimeCurrent()<timeend) 
     {
      enableTrade = true;
     }
   
   int main = GetAncestor(WindowHandle(Symbol(), Period()), 2/*GA_ROOT*/);
      
   if(enableTrade==true)
     {
      if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)){
               PrintFormat("Auto Trading::::: Triggered -- Starting Time: ",TimeToStr(timestart,TIME_DATE|TIME_SECONDS));
               Print("Auto Trading::::: Starting AutoTrading for all terminal charts");      
               PostMessageA(main, WM_COMMAND,  MT4_WMCMD_EXPERTS, 0 );
            }
         
     } else
   if(enableTrade==false)
     {
      if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)){
               PrintFormat("Auto Trading::::: Triggered (local time)-- Stopping : ",TimeToStr(timeend,TIME_DATE|TIME_SECONDS));
               Print("Auto Trading::::: Stopping AutoTrading for all terminal charts");            
               PostMessageA(main, WM_COMMAND,  MT4_WMCMD_EXPERTS, 0 ) ;
            }
     }
   
   //---
   /*if(IsTesting() && enableTrade==true)
     {
      if(OrdersTotal()<=0)
        {
         double price=Bid;
         double stoploss=0;
         double takeprofit=0;
         int ticket=OrderSend(Symbol(),OP_SELL,1,price,3,stoploss,takeprofit,"",0,0,clrGreen);
        }
     }
   */
   //--- 
   TPSLmanagement();
   //---
 return(0);
}
//=============================================================================================
int OrderCount(string symbol) {
   int count = 0;
   for (int i = OrdersTotal() - 1; i >= 0; i--) {
      if (OrderSelect(i, SELECT_BY_POS))
         if (OrderSymbol()==symbol && OrderType()<=1){
          count++; 
         }
   }
   return (count);
}

int CheckValid(double openprice){
   int result=0;
   for(int i=0;i<OrdersHistoryTotal();i++){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
      if(InpSymbol==CurrentChartSymbol && OrderSymbol()!=Symbol()) continue;
      if(OrderType()==OP_BUY || OrderType()==OP_SELL){
         if(OrderCloseTime()>=TimeCurrent()-(7*PeriodSeconds(PERIOD_D1)))
           {
            if(OrderOpenPrice()==openprice)
              {
               result++;
              }
           }        
        }
      //--
     }
  //--
  return(result);
}

void TPSLmanagement(){
   double breakeven_;
   bool modstatus;
   
   if(OrdersTotal()>0){
   for(int cnt=OrdersTotal();cnt>=0;cnt--){
     if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)) continue;
     if(InpSymbol==CurrentChartSymbol && OrderSymbol()!=Symbol()) continue;
	     
	     breakeven_=InpBE*getPoin(OrderSymbol());
	     double stoplevel=MarketInfo(OrderSymbol(),MODE_STOPLEVEL)*MarketInfo(OrderSymbol(),MODE_POINT);
	     if(breakeven_ < stoplevel)breakeven_=stoplevel;
	     int ticket = OrderTicket();
	     //---
	     RefreshRates();
	     //initial SL
	     if(InpSL>0)
	       {
	        double SL = 0;
	        if(OrderType()==OP_BUY)  { SL = OrderOpenPrice()-InpSL*getPoin(OrderSymbol()); } 
	        if(OrderType()==OP_SELL) { SL = OrderOpenPrice()+InpSL*getPoin(OrderSymbol()); }
	           
	           if(OrderStopLoss()==0)
	             {
	              GlobalVariableSet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#1",OrderLots());
	              modstatus=OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0,clrNONE);
	             }
	       }
	     //---
	     //BE
	     if(InpBE>0)
	       {
	        if(OrderType()==OP_SELL){
	  	     if(OrderStopLoss()>OrderOpenPrice()-InpBEplus*getPoin(OrderSymbol())){
	  	         if(OrderClosePrice()<OrderOpenPrice()-breakeven_)
	  	         modstatus=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-InpBEplus*getPoin(OrderSymbol()),OrderTakeProfit(),0,clrNONE);
	  	      }
	  	      }
	       
	        if(OrderType()==OP_BUY){
	  	     if(OrderStopLoss()<OrderOpenPrice()+InpBEplus*getPoin(OrderSymbol())){
	  	         if(OrderClosePrice()>OrderOpenPrice()+breakeven_)
	  	         modstatus=OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+InpBEplus*getPoin(OrderSymbol()),OrderTakeProfit(),0,clrNONE);
	  	      }
	  	      }
	       }
	     ///---
	     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)){
	     if(InpTP1>0 && GlobalVariableGet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#1")!=0)
	       {
	        double lot = NormalizeDouble(GlobalVariableGet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#1"),getNorm(OrderSymbol()));
	        if(OrderType()==OP_SELL)
	          {
	           if(OrderClosePrice()<=OrderOpenPrice()-InpTP1*getPoin(OrderSymbol()) && OrderLots()==lot)
	             {
	              GlobalVariableDel(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#1");
	              GlobalVariableSet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#2",OrderLots()-LotManagement(InpPercentPartialClose1*0.01*OrderLots(),OrderSymbol()));
	              if(!OrderClose(ticket,LotManagement(InpPercentPartialClose1*0.01*OrderLots(),OrderSymbol()),MarketInfo(OrderSymbol(),MODE_ASK),getSlippage(OrderSymbol()),clrNONE)){
	              Print("Close Error", GetLastError());
	              }
	             }
	          }
	        if(OrderType()==OP_BUY)
	          {
	           if(OrderClosePrice()>=OrderOpenPrice()+InpTP1*getPoin(OrderSymbol()) && OrderLots()==lot)
	             {
	              GlobalVariableDel(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#1");
	              GlobalVariableSet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#2",OrderLots()-LotManagement(InpPercentPartialClose1*0.01*OrderLots(),OrderSymbol()));
	              if(!OrderClose(ticket,LotManagement(InpPercentPartialClose1*0.01*OrderLots(),OrderSymbol()),MarketInfo(OrderSymbol(),MODE_BID),getSlippage(OrderSymbol()),clrNONE)){
	              Print("Close Error", GetLastError());
	              }
	             }
	          }
	       }
	     //---
	     if(InpTP2>0 && GlobalVariableGet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#2")!=0)
	       {
	        double lot = NormalizeDouble(GlobalVariableGet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#2"),getNorm(OrderSymbol()));
	        
	        if(OrderType()==OP_SELL)
	          {
	           if(OrderClosePrice()<=OrderOpenPrice()-InpTP2*getPoin(OrderSymbol()) && OrderLots()==lot)
	             {
	              GlobalVariableDel(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#2");
	              GlobalVariableSet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#3",OrderLots()-LotManagement(InpPercentPartialClose2*0.01*OrderLots(),OrderSymbol()));
	              
	              if(!OrderClose(ticket,LotManagement(InpPercentPartialClose2*0.01*OrderLots(),OrderSymbol()),MarketInfo(OrderSymbol(),MODE_ASK),getSlippage(OrderSymbol()),clrNONE)){
	              Print("Close Error", GetLastError());
	              }
	             }
	          }
	        if(OrderType()==OP_BUY)
	          {
	           if(OrderClosePrice()>=OrderOpenPrice()+InpTP2*getPoin(OrderSymbol()) && OrderLots()==lot)
	             {
	              GlobalVariableDel(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#2");
	              GlobalVariableSet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#3",OrderLots()-LotManagement(InpPercentPartialClose2*0.01*OrderLots(),OrderSymbol()));
	              
	              if(!OrderClose(ticket,LotManagement(InpPercentPartialClose2*0.01*OrderLots(),OrderSymbol()),MarketInfo(OrderSymbol(),MODE_BID),getSlippage(OrderSymbol()),clrNONE)){
	              Print("Close Error", GetLastError());
	              }
	             }
	          }
	       }
	     //---
	     if(InpTP3>0 && GlobalVariableGet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#3")!=0)
	       {
	        double lot = NormalizeDouble(GlobalVariableGet(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#3"),getNorm(OrderSymbol()));
	        
	        if(OrderType()==OP_SELL)
	          {
	           if(OrderClosePrice()<=OrderOpenPrice()-InpTP3*getPoin(OrderSymbol()) && OrderLots()==lot)
	             {
	              GlobalVariableDel(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#3");
	              
	              if(!OrderClose(ticket,LotManagement(InpPercentPartialClose3*0.01*OrderLots(),OrderSymbol()),MarketInfo(OrderSymbol(),MODE_ASK),getSlippage(OrderSymbol()),clrNONE)){
	              Print("Close Error", GetLastError());
	              }
	             }
	          }
	        if(OrderType()==OP_BUY)
	          {
	           if(OrderClosePrice()>=OrderOpenPrice()+InpTP3*getPoin(OrderSymbol()) && OrderLots()==lot)
	             {
	              GlobalVariableDel(gVar+OrderSymbol()+DoubleToStr(OrderOpenPrice(),getDigit(OrderSymbol()))+"#3");
	              
	              if(!OrderClose(ticket,LotManagement(InpPercentPartialClose3*0.01*OrderLots(),OrderSymbol()),MarketInfo(OrderSymbol(),MODE_BID),getSlippage(OrderSymbol()),clrNONE)){
	              Print("Close Error", GetLastError());
	              }
	             }
	          }
	       }
	     }
	     //--- 
   }
   } 
}

// Lots Management
double LotManagement(double mylots,string symbol)
{
   double lots = mylots;
   if(lots<MarketInfo(symbol,MODE_MINLOT))lots=MarketInfo(Symbol(),MODE_MINLOT);
   if(lots>MarketInfo(symbol,MODE_MAXLOT))lots=MarketInfo(Symbol(),MODE_MAXLOT);
   return(NormalizeDouble(lots,getNorm(symbol)));
}