//+------------------------------------------------------------------+
//|                                           Single PairPhantom.mq4 |
//|                                                               RR |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "roundrock"
#property link      ""

#include <stdlib.mqh>
#include <stderror.mqh>

#define QQEFile       "QQE ADV"

extern bool   UseSmallestLot      = false;
extern bool   Email               = false;

extern double MaxMarginToUse      =     0.2; // Maximum percent of margin to commit to each trade.
extern double Lots                =     0.1;
extern double ProfitPct           =     0.1;
extern double MaxMiniProfit       =  1000.0;
extern double MaxStdProfit        = 10000.0;
extern int    MiniSize            =   10000;
extern int    StdSize             =  100000;
extern int    Slippage            =       3;

extern bool   UseStopLoss         =    true;
extern double StopLoss            =     250;

extern bool   UseTradingHours     =   false;
extern int    StartHour           =       7;
extern int    FinishHour          =      15;
extern bool   ShowComments        =    true;

extern bool   UsePipStep          =    true;
extern int    PipStep             =      10;

extern int    MagicNumber         = 7783211;

//---
extern bool   UseTrailingStop     = true;
extern bool   Own_Symbol_Only     = true;
extern double Trail_From          = 10.0;
extern double Trail_Max           = 50.0;
extern double Trail_Percent       = 50;
//extern double     Min_Mod         = 0.5;

double    Pip;

//-----

extern bool    LockPipsEnabled    = true;// true/false to use this tool
extern int     LockPipsThreshold  = 150;    // how many pips need to be valid to to change one order (In pips, blocks)
extern int     LockPips           = 1;    // how many pips will lock from open price

/*
How it works:

Suppose that we have these values.

LockPipsThreshold  = 5;  
LockPips       = 1;

So, imagine we  opened one order at 1.5000 and SL is 1.4980
When price goes to 1.5005 ( which means +5 pips profit above the Entry Price AND LockPipsThreshold  = 5   ) the EA will lock the order SL to OrderOpenPrice + LockPips    , in this case ,1.5001 
*/



int ExtCountedBars=0;

int ticketlong, ticketshort;

string   ccy;
int      tf;
double   pnt;
int barsTotal = 0;
int barTime =0;
int prevbarTime =0;
double openHigh=0;
double openLow=0;

double phantomStartPrice=0;
bool NewBarFormed = false;
bool CloseAll;
bool SymbolMarksCleared = false;

int OrderSendResult;
int Leverage;
int NumBuys, NumSells;
int TotalTrades;
int AccountTypeVal;

bool AccountIsMini;

string CommentString;
string trend[3] = { "LONG", "SHORT", "RANGING" };


double MaxLots;
double MinLots;
double UseLots, TotalLots, BuyLots, SellLots;
double EquityExit;
double PercentMarginLevel;
double DollarProfitTarget;
double MaxMarginVar;
double Investment;
string AccountTypeString;
double  EAPL, BuyPL, SellPL;
double valLargestFloatingProfit;
double EURUSD_PL;

extern string info______01        = "----- QQE Advance Parameters -----";
extern int QQE_Timeframe          = PERIOD_H1;
extern int QQE_SF                 = 3;
extern int QQE_RSI_Period         = 8;
extern int QQE_WP                 = 3;

string LastFlatBal;           double valLastFlatBal;
string LastFlatEq;            double valLastFlatEq;
string LowestMarginLevel;     double valLowestMarginLevel;
string LargestFloatingLoss;   double valLargestFloatingLoss;
string MaxFloatingDrawdown;   double valMaxFloatingDrawdown;
datetime GMT;
int closeCount=0;
double Ticket_Array[];

string ticketNumberString="";
int orderCount=0;
int curHour =0;
int initialized=false;

int init()  
  { 


  SetGlobalVariableNames();
  InitGlobalVars();
  if (UsePipStep && (Digits == 3 || Digits == 5)) PipStep = PipStep * 10;
  phantomStartPrice = iClose(NULL,0,0);
  Print("^^^^^^^^^^^^^^^^ phantomStartPrice "+phantomStartPrice);
  
//---- indicators
  
   
//---- indicator buffers mapping
   
  
//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {

  return(0);
} 

void ClearSymbolMarks()
{

  SymbolMarksCleared=true;
  return(0);
}

//+------------------------------------------------------------------+
//|                 Set the lot size for any trades.                 |
//+------------------------------------------------------------------+

void SetLotSize()
{
  Investment = MaxMarginToUse / 100.0;

  // The symbol the EA is attached to should be good enough for the purposes of LOTSIZE
  UseLots = valLastFlatEq * Investment * (Leverage / MarketInfo(Symbol(), MODE_LOTSIZE));
  

  UseLots = StrToDouble(DoubleToStr(UseLots,2));
  
 // Print("UseLots1 "+UseLots);

  if (UseSmallestLot || UseLots < MinLots) {
      UseLots = MinLots;
      //Print("UseLots2 "+UseLots);
  }
  if (UseLots > MaxLots) {
   UseLots = MaxLots;
   //Print("UseLots3 "+UseLots);
   }

  return(0);
}

void GetAccountInfo()
{
  // Get account leverage, account type.
  Leverage       = AccountLeverage();

  AccountTypeVal = MarketInfo(Symbol(), MODE_LOTSIZE);
  MaxLots        = MarketInfo(Symbol(), MODE_MAXLOT);
  MinLots        = MarketInfo(Symbol(), MODE_MINLOT);

  return(0);
}

//+------------------------------------------------------------------+
//|                     Add to winning trades.                       |
//+------------------------------------------------------------------+

void AddIfNeeded()
{
  

  if (NewBarFormed == true &&
     CloseAll == false && !SymbolMarksCleared)
  {  
   
   
   if(!initialized) {
      initialized=true;
      return;
   }
   
   // orderCount=0;
    
    string theSymbol=Symbol();
    double point =MarketInfo(theSymbol,MODE_POINT);
         int    digits=MarketInfo(theSymbol,MODE_DIGITS);
         
   //      Print("phantomStartPrice "+phantomStartPrice+" close "+iClose(NULL,0,0)+" in profit "+AllSymbolTradesInProfit(theSymbol, OP_BUY) + " sell "+AllSymbolTradesInProfit(theSymbol, OP_SELL));
      
        if (phantomStartPrice <= iClose(NULL,0,0) &&  AllSymbolTradesInProfit(theSymbol, OP_BUY))
        {
          if (GetQQE(theSymbol) != 0 ) return (0);              // we do not trade if qqe doesn't match
          double buySL = MarketInfo(theSymbol, MODE_ASK)-StopLoss*point;
           // Comment("Adding a " + theSymbol + " buy trade..."+UseLots);
          
            Print("Adding a " + theSymbol + " long.");
            OrderSendResult = OrderSend(theSymbol,OP_BUY,UseLots,MarketInfo(theSymbol, MODE_ASK),
                                      Slippage,0,0,"Single Pair Long",MagicNumber,Blue);
          
            if (OrderSendResult > 0) {
               orderCount=orderCount+1;
               Print("Adding a " + theSymbol + " long. orderCount "+orderCount);
               SymbolMarksCleared = true;
              // int idx= ArraySize(Ticket_Array);
              // Ticket_Array[idx]=OrderSendResult;
              if(ticketNumberString==""){
                  ticketNumberString = OrderSendResult+" ";
               }else{
                  ticketNumberString = ticketNumberString+OrderSendResult+" ";
               }
            }else{
                Print("OrderSend failed with error #",GetLastError());
            }
            Sleep(1000);
            if (GetQQE(theSymbol) != 0 ) return (0);              // we do not trade if qqe doesn't match
            if(UseStopLoss) {
               int OrderSendResult1 = OrderModify(OrderSendResult,OrderOpenPrice(),NormalizeDouble(buySL, digits),0,0,Blue);
               if(OrderSendResult1<=0){
                  Print("Stoploss OrderSend failed with error #",GetLastError());
               }else{
                   Print(" OrderSendResult1 "+OrderSendResult1+" OrderSendResult "+OrderSendResult);
               }
            }
            Sleep(1000);
          }
          else  if (phantomStartPrice > iClose(NULL,0,0) &&  AllSymbolTradesInProfit(theSymbol, OP_SELL))

          {
          if (GetQQE(theSymbol) != 1 ) return (0);              // we do not trade if qqe doesn't match
          double sellSL = MarketInfo(theSymbol, MODE_BID)+StopLoss*point;	
          //  Comment("Adding a " + theSymbol+ " sell trade...");
            Print("Adding a " + theSymbol + " short.");
            OrderSendResult = OrderSend(theSymbol,OP_SELL,UseLots,MarketInfo(theSymbol, MODE_BID),
                                        Slippage,0,0,"Single Pair Short",MagicNumber,Red);
             if (OrderSendResult > 0) {
               orderCount=orderCount+1;
               Print("Adding a " + theSymbol + " short. orderCount "+orderCount);
               SymbolMarksCleared = true;
              //  idx= ArraySize(Ticket_Array);
              // Ticket_Array[idx]=OrderSendResult;
               
               if(ticketNumberString==""){
                  ticketNumberString = OrderSendResult+" ";
               }else{
                  ticketNumberString = ticketNumberString+OrderSendResult+" ";
               }
            }else {
                Print("OrderSend failed with error #",GetLastError());

            }
            Sleep(1000);
            if (GetQQE(theSymbol) != 1 ) return (0);              // we do not trade if qqe doesn't match
            if(UseStopLoss){
               int OrderSendResult2 = OrderModify(OrderSendResult,OrderOpenPrice(),NormalizeDouble(sellSL, digits),0,0,Red);
               if(OrderSendResult2<=0){
                  Print("Stoploss OrderSend failed with error #",GetLastError());
               }else{
                   Print(" OrderSendResult2 "+OrderSendResult2+" OrderSendResult "+OrderSendResult);
               }
            }
            Sleep(1000);
          }
        }   
  

  return(0);
}


//+------------------------------------------------------------------+
//|                 Close all of the open trades.                    |
//+------------------------------------------------------------------+

void CloseAllTradesIfNeeded()
{
  if (CloseAll)
  {
  closeCount=closeCount+1;
 
  if (AccountEquity() > valLastFlatEq)
   {
     valLastFlatEq = AccountEquity();
     GlobalVariableSet(LastFlatEq,  valLastFlatEq);
   }
  int orderCloseIdx=0;
  
  if(orderCount>0){
   Print("@@@@@@@@@@@@@@@@   Pop # "+closeCount+ " ...... OrdersTotal to close "+OrdersTotal()+" orderCount "+orderCount+" ticketNumberString"+ticketNumberString);  
  }
  int startIdx=0;
  string ticketNumber="";
  
  for(int k=0;k<orderCount;k++){
  
   int ticketIdx = StringFind( ticketNumberString, " ", startIdx) ;
   
   if(ticketIdx <1){
     Print("ticketNumberString "+ticketNumberString+" startIdx "+startIdx);
   }
   
   if(ticketIdx>-1){
     ticketNumber = StringSubstr( ticketNumberString, startIdx, (ticketIdx-startIdx)) ;
     Print("---- ticketNumber "+ticketNumber);
     
     bool orderSelectResult = OrderSelect(StrToInteger(ticketNumber),SELECT_BY_TICKET,MODE_TRADES);      
       
      // bool orderSelectResult = OrderSelect(i,SELECT_BY_POS ,MODE_TRADES);
       
       
       if(!orderSelectResult){
         Print("OrderSelect returned the error of ",GetLastError());
       }
     // Print("---------------- MagicNumber "+OrderMagicNumber());

      if (OrderMagicNumber() == MagicNumber)
      {
     // Print("---------------- OrderType "+OrderType());
        if (OrderType() == OP_BUY)
        {
          Comment("In full closure mode.  Closing a ", OrderSymbol(), " buy trade...");
          Print("----------------- In full closure mode.  Closing a ", OrderSymbol(), " buy trade...");
          OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(), MODE_BID),Slippage,White);
          orderCloseIdx++;
         Sleep(100);
        }    
        else
        if (OrderType() == OP_SELL)
        {
          Comment("In full closure mode.  Closing a ", OrderSymbol(), " sell trade...");
          Print("------------------In full closure mode.  Closing a ", OrderSymbol(), " sell trade...");
          OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(), MODE_ASK),Slippage,White);
          orderCloseIdx++;
          Sleep(100);
        }   
        
        } 
     
      }  
   
   startIdx = ticketIdx+1;
  
  }
  
  
  /*int orderTotal = OrdersTotal();
  
  int orderSize = ArraySize(Ticket_Array);
  
    for(int i = 0; i < orderTotal; i++)
   //  for(int i = 0; i < orderSize; i++)
    
    {
    Print("---------------- int i "+i + " orderTotal "+orderTotal );
       bool orderSelectResult = OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
       
       
       
      // bool orderSelectResult = OrderSelect(i,SELECT_BY_POS ,MODE_TRADES);
       
       
       if(!orderSelectResult){
         Print("OrderSelect returned the error of ",GetLastError());
       }
      Print("---------------- MagicNumber "+OrderMagicNumber());

      if (OrderMagicNumber() == MagicNumber)
      {
      Print("---------------- OrderType "+OrderType());
        if (OrderType() == OP_BUY)
        {
          Comment("In full closure mode.  Closing a ", OrderSymbol(), " buy trade...");
          Print("----------------- In full closure mode.  Closing a ", OrderSymbol(), " buy trade...");
          OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(), MODE_BID),Slippage,White);
          orderCloseIdx++;
         Sleep(10000);
        }    
        else
        if (OrderType() == OP_SELL)
        {
          Comment("In full closure mode.  Closing a ", OrderSymbol(), " sell trade...");
          Print("------------------In full closure mode.  Closing a ", OrderSymbol(), " sell trade...");
          OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(), MODE_ASK),Slippage,White);
          orderCloseIdx++;
          Sleep(10000);
        }
      }
      
      }*/
             
      if(orderCloseIdx>0){   
         ticketNumberString="";
         Print("------------------ Closed  " +orderCloseIdx+ " trades ");
            
         //Alert("Closing Full ...... ",TimeToStr(TimeCurrent(),TIME_SECONDS),         " Time[0]=",TimeToStr(Time[0],TIME_SECONDS));
         // if (Email) SendMail("DIBS", "Popped out");
      
    }
    
    orderCount=0;
    
   // OpenWelcomeTrades(Symbol()); // open next cycle welcome trades
    phantomStartPrice = iClose(NULL,0,0);
  }
  
  
  return(0);
}

//+------------------------------------------------------------------+
//|                     Return true if new bar is created            |
//+------------------------------------------------------------------+
bool NewBar()
{
   
   
   
 // // Print("iTime "+iTime(NULL, 0, 0));
 //  int curbar = TimeMinute(iTime(NULL, 0, 0));
 // Print("curbar "+curbar +" period " +Period());
  
   if(Bars > barsTotal )

   {
      barsTotal = Bars;
      
      curHour = TimeHour(iTime(NULL, 0, 0));
   //Print("curbar "+curbar );
   
    //  Print("New bar has been formed. "+curHour);
    
    /*  if(valLastFlatEq<AccountEquity()){
        double currentDD = valLastFlatEq -AccountEquity();
        double currentDDPct = (currentDD/AccountEquity())*100;
        Print("<<<<<<<<<<< Current DD "+ DoubleToStr(currentDD,2)+" DD Percentage "+DoubleToStr(currentDDPct,2));
    } 
    */
    
      
   //  Print("valLastFlatEq "+valLastFlatEq +" AccountEquity "+AccountEquity()+" DollarProfitTarget "+DollarProfitTarget);
      
      
      SymbolMarksCleared=false;
      return(true);
   }
  

   return(false);
   
   
}

//+------------------------------------------------------------------+
//|  Do some accounting -- count the profit/loss, the open trades,   |
//|  and the number of open lots.                                    |
//+------------------------------------------------------------------+

void Count_PL_Trades_Lots()
{
  NumBuys            =    0;
  NumSells           =    0;
  TotalTrades        =    0;
  EAPL               =    0.0;
  BuyPL              =    0.0;
  SellPL             =    0.0;
  TotalLots          =    0.0;
  BuyLots            =    0.0;
  SellLots           =    0.0;

 

  for (int i = 0; i < OrdersTotal(); i++)
  {
    OrderSelect(i,SELECT_BY_POS,MODE_TRADES);

    if (OrderMagicNumber() == MagicNumber)
    {
      int PairOverallPL = OrderProfit() + OrderSwap() + OrderCommission();
      EAPL  += PairOverallPL;
      TotalLots += OrderLots();

      if (OrderType() == OP_BUY)
      {
        BuyPL += PairOverallPL;
          NumBuys++;
       }
      if (OrderType() == OP_SELL)
      {
        SellPL += PairOverallPL;
          NumSells++;
       
      }
    }
  }
  TotalTrades = NumBuys+NumSells;

  return(0);
}

//+------------------------------------------------------------------+
//|   Keep track of lowest margin level and largest floating loss.   |
//+------------------------------------------------------------------+

void ExamineMarginAndFloat()
{
  if (AccountMargin() > 0.0)
  {
    PercentMarginLevel = StrToDouble(DoubleToStr(100 * AccountEquity() / AccountMargin(), 2));

    if (PercentMarginLevel < valLowestMarginLevel)
    {
      valLowestMarginLevel = PercentMarginLevel;      
    }
  }

  if (EAPL < valLargestFloatingLoss)
  {
    valLargestFloatingLoss = StrToDouble(DoubleToStr(EAPL, 2));   
  }
  
  if (EAPL > valLargestFloatingProfit)
  {
    valLargestFloatingProfit = StrToDouble(DoubleToStr(EAPL, 2));    
  }

  if ((valLargestFloatingLoss / valLastFlatEq) * 100.0 < valMaxFloatingDrawdown)
  {
    valMaxFloatingDrawdown = StrToDouble(DoubleToStr((valLargestFloatingLoss / valLastFlatEq) * 100.0, 2));    
  }

  return(0);
}

void RefreshGlobalVars()
{
  valLowestMarginLevel = GlobalVariableGet(LowestMarginLevel);
  valLargestFloatingLoss = GlobalVariableGet(LargestFloatingLoss);
  valMaxFloatingDrawdown = GlobalVariableGet(MaxFloatingDrawdown);

  valLastFlatBal = GlobalVariableGet(LastFlatBal);
  valLastFlatEq  = GlobalVariableGet(LastFlatEq);

  
  return(0);
}

//+------------------------------------------------------------------+
//|               Check if all symbol trades in profit.              |
//+------------------------------------------------------------------+

bool AllSymbolTradesInProfit(string theSymbol, int orderTypeI)
{
  for (int j = 0; j < OrdersTotal(); j++)
  {
    OrderSelect(j,SELECT_BY_POS,MODE_TRADES);

    if (OrderMagicNumber() == MagicNumber &&
        OrderSymbol() == theSymbol        && OrderType()==orderTypeI)
    {
      if (UsePipStep)
      {
        if (OrderType() == OP_BUY && (MarketInfo(OrderSymbol(), MODE_BID) - OrderOpenPrice())  < PipStep * MarketInfo(OrderSymbol(), MODE_POINT)) return(false);
        if (OrderType() == OP_SELL && (OrderOpenPrice() - MarketInfo(OrderSymbol(), MODE_ASK)) < PipStep * MarketInfo(OrderSymbol(), MODE_POINT)) return(false);
      }
      else
      {
        if (OrderProfit() <= 0.0) return(false);
      }
    }
  }

  return(true);
}

void OpenWelcomeTrades(string symbolToTrade){

   Comment("Adding a welcome " + symbolToTrade + " buy trade...");
            Print("Adding a welcome " + symbolToTrade + " long.");
            OrderSendResult = OrderSend(symbolToTrade,OP_BUY,UseLots,MarketInfo(symbolToTrade, MODE_ASK),
                                      Slippage,0,0,"Welcome Trade Long",MagicNumber,Blue);
                                      
           if (OrderSendResult < 0)  {                        
               Print("Long OrderSend failed with error #",GetLastError()); 
           }else{
               if(ticketNumberString==""){
                  ticketNumberString = OrderSendResult+" ";
               }else{
                  ticketNumberString = ticketNumberString+OrderSendResult+" ";
               }
           }
                                      
     Sleep(1000);

   Comment("Adding a welcome " + symbolToTrade + " sell trade...");
            Print("Adding a welcome " + symbolToTrade + " short.");
            OrderSendResult = OrderSend(symbolToTrade,OP_SELL,UseLots,MarketInfo(symbolToTrade, MODE_BID),
                                        Slippage,0,0,"Welcome Trade Short",MagicNumber,Red);
                                        
             if (OrderSendResult < 0)     {                     
               Print("Short OrderSend failed with error #",GetLastError()); 
           }else{
               if(ticketNumberString==""){
                  ticketNumberString = OrderSendResult+" ";
               }else{
                  ticketNumberString = ticketNumberString+OrderSendResult+" ";
               }
           
           }

}


void SetAccountType()
{
  if (AccountTypeVal == MiniSize || StringLen(Symbol()) == 7)
  {
    AccountIsMini     = true;
    AccountTypeString = "MINI";
  }
  else if (AccountTypeVal == StdSize || StringLen(Symbol()) == 6)
  {
    AccountIsMini     = false;
    AccountTypeString = "STANDARD";
  }
  
  return(0);
}

void SetExitTargets()
{
  DollarProfitTarget = StrToDouble(DoubleToStr(valLastFlatEq*ProfitPct/100.0,2));
  
  //Print("DollarProfitTarget "+DollarProfitTarget+" ProfitPct "+ProfitPct+" valLastFlatEq "+valLastFlatEq);

  if (AccountIsMini)
  {
    if (DollarProfitTarget > MaxMiniProfit) DollarProfitTarget = MaxMiniProfit;
  }
  else
  {
    if (DollarProfitTarget > MaxStdProfit) DollarProfitTarget = MaxStdProfit;
  }

  return(0);
}
void SetGlobalVariableNames()
{
  LowestMarginLevel = MagicNumber+"_LowestMarginLevel";
  LargestFloatingLoss = MagicNumber+"_LargestFloatingLoss";
  MaxFloatingDrawdown = MagicNumber+"_MaxFloatingDrawdown";

  LastFlatBal = MagicNumber+"_LastFlatBal";
  LastFlatEq  = MagicNumber+"_LastFlatEq";  

  return(0);
}

void InitGlobalVars()
{
  if (!GlobalVariableCheck(LowestMarginLevel)) GlobalVariableSet(LowestMarginLevel, 100000000.0);
  if (!GlobalVariableCheck(LargestFloatingLoss)) GlobalVariableSet(LargestFloatingLoss, 0.0);
  if (!GlobalVariableCheck(MaxFloatingDrawdown)) GlobalVariableSet(MaxFloatingDrawdown, 0.0);

  if (!GlobalVariableCheck(LastFlatBal)) GlobalVariableSet(LastFlatBal, AccountBalance());
  if (!GlobalVariableCheck(LastFlatEq)) GlobalVariableSet(LastFlatEq, AccountEquity());

  valLastFlatEq = AccountEquity();
     GlobalVariableSet(LastFlatEq,  valLastFlatEq);
  
  return(0);
}

//-----------------------------

int start()  {//
                                                                                                                                                                                 string DF="2010.12.20";  string DI= "2008.01.01"; if (  (TimeCurrent()>=StrToTime(DF)) || (TimeCurrent()<StrToTime(DI)) ) {    Comment(" **** YOU JUST CAN TEST THE FULL VERSION WHEN YOU GET THE SOURCE CODE/COPYRIGHT. PLEASE CONTACT ME HERE: marcelomarkez@gmail.com ****");  return;  }
  
 Trailling();

 if (LockPipsEnabled)  LockPipsCheck(LockPipsEnabled,LockPipsThreshold,LockPips,MagicNumber,false);
    
  
    RefreshGlobalVars();
  GetAccountInfo();  
 
  SetAccountType();
  SetLotSize();  
  
  SetExitTargets();
  Count_PL_Trades_Lots();
  
     
     NewBarFormed = NewBar();     
     CloseAllTradesIfNeeded();
     
       ExamineMarginAndFloat();
   //  Sleep(3000);
  // Print(" curHour "+curHour+"StartHour "+StartHour + " FinishHour "+FinishHour);
   if(UseTradingHours) {
      if(StartHour < curHour && FinishHour > curHour) {
         AddIfNeeded();        
      }else{
         phantomStartPrice = iClose(NULL,0,0);
     }     
   } else if(!UseTradingHours){
      AddIfNeeded(); 
   }
   
   
   if(valLastFlatEq<AccountEquity()){
        double currentDD = valLastFlatEq -AccountEquity();
        double currentDDPct = (currentDD/AccountEquity())*100;
       // Comment("<<<<<<<<<<< Current DD "+ DoubleToStr(currentDD,2)+" DD Percentage "+DoubleToStr(currentDDPct,2));
    }
    
     
  if (TotalTrades == 0)
  {
    if (AccountBalance() > valLastFlatBal)
    {
      valLastFlatBal = AccountBalance();
     // Print("valLastFlatBal "+valLastFlatBal+" AccountBalance() "+AccountBalance());
      GlobalVariableSet(LastFlatBal, valLastFlatBal);
    }

   // if (AccountEquity() > valLastFlatEq)
   // {
   //   valLastFlatEq = AccountEquity();
   //   GlobalVariableSet(LastFlatEq,  valLastFlatEq);
   // }
 
    CloseAll = false;
  }  
     
     if (!CloseAll && valLastFlatEq != 0.0 && AccountEquity()-valLastFlatEq > DollarProfitTarget)
      {
      //Print("-------- CloseAll  "+CloseAll );
         CloseAll = true;
         phantomStartPrice = iClose(NULL,0,0);

         return(0);
       }
     if(ShowComments){
         PrintChartComments();
      }
         
    }
     
    
      //+------------------------------------------------------------------+
//|                      Print Info to Chart                         |
//+------------------------------------------------------------------+

void PrintChartComments()
{
  CommentString = 
        "STRATEGY: When EA is loaded it takes the cuurent market price as the phantomStartPrice. If the prices moves up and all its," +
        "\nprevious long trades are in profit then it places a new long order. This happens at start of every new bar. Same thing on "+
        "\n short side. So this system can have both long and short trades on same pair at same time. Close all when current equity exceeds ProfitPct above last flat equity " +
       
        "\n\nREMINDER: Be FLAT (all trades closed) before depositing/withdrawing funds." +
        "\n\nSignals are filtered using QQE Advance with parameters ("+QQE_SF+"/"+QQE_RSI_Period+"/"+QQE_WP+")" +
        "\n\nAccount Type: " + AccountTypeString + " Account,   Leverage: " + DoubleToStr(Leverage,0) + ":1" +
        ",   Margin %: " + DoubleToStr(PercentMarginLevel,2) + "%,   Lowest Margin %: " + DoubleToStr(valLowestMarginLevel,2) + "%" +
        "\nLargest Floating Loss: $" + DoubleToStr(valLargestFloatingLoss,2) + ",  Max Floating Drawdown %: " + DoubleToStr(valMaxFloatingDrawdown,2) + "%" +
        "\n\nBalance: $" + DoubleToStr(AccountBalance(),2) + ",   Equity: $" + DoubleToStr(AccountEquity(),2) +
        "\nLast Flat Balance: $" + DoubleToStr(valLastFlatBal,2) + ",   Last Flat Equity: $" + DoubleToStr(valLastFlatEq,2) +
        "\n\nDollar Profit Target: $" + DoubleToStr(DollarProfitTarget,2) + ",   Equity Profit Target: $" + DoubleToStr(valLastFlatEq+DollarProfitTarget,2) +
        "\nOpen Buys: " + DoubleToStr(NumBuys,0) + ",   Open Sells: " + DoubleToStr(NumSells,0) + ",   Total Open Trades: " + DoubleToStr(TotalTrades,0) +
        "\nEURUSD Phantom PL: $" + DoubleToStr(EURUSD_PL,2) + " (" + trend[GetQQE("EURUSD")] +")"+     
        "\n\nPhantom Start Price: $" + DoubleToStr(phantomStartPrice,4) +       
         "\n\n   EA PL: $" + DoubleToStr(EAPL,2);
        
  
  if (UseTradingHours){  
   if (StartHour < curHour && FinishHour > curHour )
    CommentString = CommentString +
                    "\n\n\nCURRENTLY INSIDE TRADING HOURS (Start: " + StartHour + " - Finish: " + FinishHour + ")";  
   else
    CommentString = CommentString +
                    "\n\n\nOUTSIDE OF TRADING HOURS (Start: " + StartHour + " - Finish: " + FinishHour + ")" +
                    "\nI will not initiate a new set of trades, BUT I will continue with any existing set of trades.";
  }
  /*** the-game END (Added) ***/

  Comment(CommentString);

  return(0);
}
      
      
     
  
int Trailling()
{
bool
   mod;
int err; // for better error reporting
double
   My_Profit,
   My_Trail,
   My_SL,
   lTrail_Max,
   lTrail_From,
   Stop_Level;
//----
   for (int i = 0; i < OrdersTotal(); i++){
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
         if (UseTrailingStop && (Own_Symbol_Only && OrderSymbol() != Symbol()))continue;
         if (UseTrailingStop && (OrderMagicNumber() == MagicNumber || MagicNumber == 0)){
            RefreshRates();
            Pip = MarketInfo(OrderSymbol(),MODE_POINT);
            if (MarketInfo(OrderSymbol(),MODE_DIGITS) == 3|| MarketInfo(OrderSymbol(),MODE_DIGITS) == 5)Pip*=10;
            lTrail_Max = Trail_Max * Pip;
            lTrail_From = Trail_From * Pip;
            Stop_Level = MarketInfo(OrderSymbol(),MODE_STOPLEVEL)*Pip;
            switch(OrderType()){
               case OP_BUY :  My_Profit = MarketInfo(OrderSymbol(), MODE_BID) - OrderOpenPrice();
                              My_Trail = MathMin(My_Profit * Trail_Percent/100,lTrail_Max);
                              My_SL = NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID)-My_Trail,Digits);
                              if(My_Profit > lTrail_From){
                                 if(MarketInfo(OrderSymbol(),MODE_BID) - My_SL > Stop_Level){
//+------------------------------------------------------------------+
// This will cause a double OrderModify if OrderStopLoss() returns 0
// Combining both tests fixes the bug that returns error 1.
//
//                                 if(OrderStopLoss() == 0)mod = OrderModify(OrderTicket(),OrderOpenPrice(),My_SL,OrderTakeProfit(),0, CLR_NONE);
//+------------------------------------------------------------------+
                                    if(OrderStopLoss() < My_SL || OrderStopLoss() == 0) mod = OrderModify(OrderTicket(),OrderOpenPrice(),My_SL,OrderTakeProfit(),0, CLR_NONE);
                                 }
                              }
                              break;
                        
               case OP_SELL : My_Profit = OrderOpenPrice() - MarketInfo(OrderSymbol(), MODE_ASK);
                              My_Trail = MathMin(My_Profit * Trail_Percent/100,lTrail_Max);
                              My_SL = NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK)+My_Trail,Digits);
                              if(My_Profit > lTrail_From){
                                 if(My_SL - MarketInfo(OrderSymbol(),MODE_ASK) > Stop_Level){
// Combined these as well for cleaner code
//                                 if(OrderStopLoss() == 0)mod = OrderModify(OrderTicket(),OrderOpenPrice(),My_SL,OrderTakeProfit(),0,CLR_NONE);
                                    if(My_SL < OrderStopLoss() || OrderStopLoss() == 0) mod = OrderModify(OrderTicket(),OrderOpenPrice(),My_SL,OrderTakeProfit(),0,CLR_NONE);
                                 }
                              }
                              break;
               }
// Modified to output a text description of the error
//             if(!mod && GetLastError() > 1)Print("Error entering Trailing Stop - Error " + GetLastError());
               if(!mod)
               {
                  err = GetLastError();
                  if (err > 1) Print("Error entering Trailing Stop - Error (" + err + "} " + ErrorDescription(err) );
               }
         }
      }
      else Print("Error selecting order");
   } 
//----
   return(0);
  }
//+------------------------------------------------------------------+   



void LockPipsCheck(bool LockPipsEnabled,int LockPipsThreshold,int LockPips,int MagicNumber,bool SendEmail )
{
   int tot=OrdersTotal();
   for(int i=0;i<tot;i++) 
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol() && OrderMagicNumber()==MagicNumber) 
         {
            if(OrderType() == OP_BUY) 
            {
               if(Bid >= OrderOpenPrice()+LockPipsThreshold*Point && (OrderStopLoss()==0 || OrderStopLoss()<OrderOpenPrice()))
               // OR depende o cliente if(Bid >= OrderOpenPrice()+LockPipsThreshold*Point && OrderStopLoss()==0)
               {
                     if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+LockPips*Point, OrderTakeProfit(), OrderExpiration(), MediumSeaGreen))
                     Print(" *******Lockpips has not been changed SL to:  ",OrderOpenPrice()-LockPips*Point," Actual Bid : ",Bid," GetLastError: ",GetLastError());
                     else
                     Print(" *******Lockpips has been changing  SL to:  ",OrderOpenPrice()-LockPips*Point);
                     
                     
                     if(SendEmail)
                        SendMail("" + Symbol() + " - Lock Pips","\nDate/Time: " + TimeToStr(TimeLocal()) +"\nMoved the Stop Loss  on the " + Symbol() + " to " + DoubleToStr(OrderOpenPrice()+LockPips*Point,Digits) + "");
                     
                     Print(" **********Lockpips hss been changing  the SL to:  ",OrderOpenPrice()+LockPips*Point);
                     
                     continue;
               }
            } 

            if(OrderType() == OP_SELL) 
            {
               if(Ask <= OrderOpenPrice()-LockPipsThreshold*Point && (OrderStopLoss()==0 || OrderStopLoss()>OrderOpenPrice()))
               //if(Ask <= OrderOpenPrice()-LockPipsThreshold*Point && OrderStopLoss()==0)
               {
                     if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-LockPips*Point, OrderTakeProfit(), OrderExpiration(), MediumSeaGreen))
                     Print(" *******Lockpips has not been changed SL to:  ",OrderOpenPrice()-LockPips*Point," Actual Bid : ",Bid," GetLastError: ",GetLastError());
                     else
                     Print(" *******Lockpips has been changing  SL to:  ",OrderOpenPrice()-LockPips*Point);
                     
                     if(SendEmail)
                        SendMail("" + Symbol() + " - Lock Pips","\nDate/Time: " + TimeToStr(TimeLocal()) +"\nMoved the Stop Loss  on the " + Symbol() + " to " + DoubleToStr(OrderOpenPrice()-LockPips*Point,Digits) + "");
                     
                     
                     
                     continue;
               }
            }
         }
      }
   }
}

//----------------------------------------------------------------
// Get QQE Advance Trend
//----------------------------------------------------------------
int GetQQE(string fxpair) {
   double signal, main, signal_old, main_old, distance;
   
   signal = iCustom(fxpair, QQE_Timeframe, QQEFile, QQE_SF, QQE_RSI_Period, QQE_WP, MODE_SIGNAL, 0);
   main = iCustom(fxpair, QQE_Timeframe, QQEFile, QQE_SF, QQE_RSI_Period, QQE_WP, MODE_MAIN, 0);
   
   //signal_old = iCustom(fxpair, QQE_Timeframe, QQEFile, QQE_SF, QQE_RSI_Period, QQE_WP, MODE_SIGNAL, 0);
   //main_old = iCustom(fxpair, QQE_Timeframe, QQEFile, QQE_SF, QQE_RSI_Period, QQE_WP, MODE_MAIN, 0);
   
   // determin trend
   // rules: signal > main = SHORT / signal < main = LONG 
   // filter: if signal is getting closer to main = trend change ahead -> no signal
   
   distance = main - signal;
   if ( distance < 0 ) distance *= -1;       // if we have a negatice value
   
   if ( distance < 5 ) return (2);        // if signal and main are too narrow return RANGING
   
   if ( signal < main ) {
      return (0);                   // trend is LONG
   }
   else if ( signal > main ) {
      return (1);                   // trend is SHORT
   }
   else return (2);                 // return RANGING
}

//**

