//+---------------------------------------------------------------------------|
//|                                            PRD Trader v1.7_R.mq4          |
//|                                            by William R Garrison          |
//|                                                     10 June 2009          |
//|                                                                           |
//|                       Based on PRD Signal2 indicator by BigBawls          |
//|    which, in turn, is based on the trading system by Robert Hill          |
//|         which uses the past regression deviated indicator with a          |
//|                    three-order scale-out order management system          |
//|                                                                           |
//|  9 June 2009 - Added low and high range for TP targets                    |
//| 10 June 2009 - Adjust slippage for 5-digit pricing,                       |
//|                add RefreshRates() between orders                          |
//| 11 June 2009 - Add option to record channel values                        |
//| 11 June 2009 - Fix stop adjust for orders 2 and 3 when price is too close |
//| 11 June 2009 - Move signal logic into EA                                  |
//| 12 June 2009 - Add closeout for reversal signal                           |
//|                Add "No TP" and channel line SL option for third order     |
//| 12 June 2009 - Add PermitTpAdjustEveryTick                                |
//|                Add cutoff time on Fridays                                 |
//|                                                                           |
//| Changes by Robert                                                         |
//| 12 June 2009 - Added constants for easier readingof code                  |
//|                Modularized code for easier changes in future              |
//|                Added inputs for past regression deviated                  |
//|                Added MinStopLoss                                          |
//|                Fixed bug for Trade 1 closed when Trade2 is closed         |
//|                Fixed bug in trailing stop for trade 3                     |
//|                                                                           |
//| 13 June 2009 - Changed PRD indicator to be optimizable, named new         |
//|                indicator "past regression deviated Opt"                   |
//+---------------------------------------------------------------------------+
#property copyright "Copyright 2009, William Garrison and Robert Hill"

#include <stdlib.mqh>
#include <stderror.mqh>

// Trade signals
#define FLAT 0
#define LONG 1
#define SHORT 2

// Indicator buffers
#define MEAN_YELLOW 0
#define UPPER_LIME 1
#define LOWER_LIME 2
#define UPPER_ORANGE 3
#define LOWER_ORANGE 4
#define UPPER_RED 5
#define LOWER_RED 6

 int period=0;
/*default 0 means the channel will use the open time from "x" bars back on which ever time period 
the indicator is attached to.  one can change to 1,5,15,30,60...etc to "lock" the start time to a specific 
period, and then view the "locked" channels on a different time period...*/

extern int     LR.length=55;   // bars back regression begins
extern double  std.channel.1 = 0.809;        // 1st channel
extern double  std.channel.2 = 1.618;        // 2nd channel
extern double  std.channel.3 = 2.618;        // 3nd channel

extern double     lot = 0.1;
extern int        UseMM = true;
extern double     Risk = 3.0;
int        Shift = 1;
extern string     target_range_desc = "1 for low targets, 2 for high targets";
extern int        TargetRange = 2;
extern bool       DynamicTP = false;
extern bool       Order3OpenTP = true;
extern int        InitialStop = 150;
extern int        PipsLock = 10;
extern int        MinProfitForLock = 25;
extern bool       UseTrailingStop = false;
extern int        TrailingStop=30.0;
extern bool       UseChannelStop = true;
extern int        ChannelStopLinesBack = 2;
extern bool       EnterWithCCI=true;
extern int        CCIPeriod = 14;
extern int        CCIEntryLevel = 100;
extern int        TradeStartHour = 0;
extern int        TradeStopHour = 0;
extern int        FridayCutoffHour = 12;
extern bool       EmailAlert=false;
extern bool       RecordTicks = false;
extern bool       RecordChannel = false;
extern string     EAVersion = "PRD 1.7";
extern int        MagicNumber1 = 090608;
extern int        MagicNumber2 = 090609;
extern int        MagicNumber3 = 090610;

int               slippage = 3;
int               lotdigits = 0;
int               pip_adjust = 0;
double            minlot, maxlot, stops_level;
string            tick_file_name;
int               buyzone, sellzone;
double            BuyEntry, SellEntry;
int               BuySellTimeFrame;
datetime          last_tick = -1;
bool              order2mod = false;
bool              order3mod = false;
bool              new_bar = false;

   int ticket1 = -1;
   int ticket1type = -1;
   int ticket2 = -1;
   int ticket2type = -1;
   int ticket3 = -1;
   int ticket3type = -1;

double MeanYellow;
double High1Lime;
double Low1Lime;
double High2Orange;
double Low2Orange;
double High3Red;
double Low3Red;
   
int totalTries = 5; 
int retryDelay = 1000;
int OrderErr;

int init() {
   double foo = MarketInfo(Symbol(),MODE_LOTSTEP);
//   Print("lotstep ", foo);
   if (foo == 0.01) lotdigits = 2;
   else
      if (foo == 0.1) lotdigits = 1;
      else
         lotdigits = 0;

   if ((Digits == 3) || (Digits == 5))
      pip_adjust = 10;
   else
      pip_adjust = 1;
   
   stops_level = MarketInfo(Symbol(), MODE_STOPLEVEL) / pip_adjust;
   
   buyzone =-CCIEntryLevel;
   sellzone= CCIEntryLevel;
 
   Print("digits ", Digits, " lotdigits ", lotdigits, "buyzone ", buyzone, " sellzone ", sellzone);
   Print("pip_adjust ", pip_adjust, " InitialStop ", InitialStop*pip_adjust, " TrailingStop ", TrailingStop*pip_adjust,
         " slippage ", slippage*pip_adjust, " Stops Level ", stops_level*pip_adjust); 

   // range check for the TP target range selection
   if (TargetRange < 1) TargetRange = 1;
   if (TargetRange > 2) TargetRange = 2;

   // range check for channel trailing stop value
   if (ChannelStopLinesBack < 1) ChannelStopLinesBack = 1;
   if (ChannelStopLinesBack > 2) ChannelStopLinesBack = 2;

   new_bar = false;

   // If the tick file doesn't exist, write the column header
   tick_file_name = Symbol()+"_ticks.csv";
   if (RecordTicks) init_tick_file();

   }
   
void GetTicketInfo()
{
   int total = OrdersTotal();
    ticket1 = -1;
    ticket1type = -1;
    ticket2 = -1;
    ticket2type = -1;
    ticket3 = -1;
    ticket3type = -1;
    
   for(int cnt = 0; cnt < total; cnt++) 
   {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderType() <= OP_SELL && OrderSymbol() == Symbol())
      {
         if (OrderMagicNumber() == MagicNumber1)
         {
          ticket1 = OrderTicket();
          ticket1type = OrderType();
         }
         if (OrderMagicNumber() == MagicNumber2)
         {
          ticket2 = OrderTicket();
          ticket2type = OrderType();
         }
         if (OrderMagicNumber() == MagicNumber3)
         {
          ticket3 = OrderTicket();
          ticket3type = OrderType();
         }
      }
    }
}

bool HandleTicket1()
{
   double localtarget = 0;
   double localstop = 0;
   
   // what if the first target was so close to the open that ticket1 has no TP value?
   // go ahead and close ticket 1 whan ticket 2 closes
   if((ticket1 > 0) && (ticket2 < 0))
     {
      OrderSelect(ticket1, SELECT_BY_TICKET, MODE_TRADES);
      CloseOrder(ticket1, OrderLots(), OrderType());
      Print("Ticket 1 closed by ticket 2 closing");
      ticket1 = -1; // Bug fix
     }
     
   // adjust targets 
   if((DynamicTP > 0) && (ticket1 > 0) && (new_bar))
     {
      bool foo = OrderSelect(ticket1, SELECT_BY_TICKET, MODE_TRADES);
      if (!foo)
        {
         Print("Error during target1 adjust order select ", ErrorDescription(GetLastError())); 
         return(false); 
        }         
                 
      if (TargetRange == 1)
        {
         if (OrderType() == OP_BUY)
           {
            Low1Lime = GetPRD(LOWER_LIME, 0);
            localtarget = Low1Lime;
           }
         else
           {   // OrderType() == OP_SELL
            High1Lime = GetPRD(UPPER_LIME, 0);
            localtarget = High1Lime;
           }
        }
      else
        {   // targets in high range
         MeanYellow = GetPRD(MEAN_YELLOW, 0);
         localtarget = MeanYellow;
        }

      localtarget = NormalizeDouble(localtarget, Digits);
      if(((OrderType() == OP_BUY) && (OrderTakeProfit() < localtarget)) ||
         ((OrderType() == OP_SELL) && (OrderTakeProfit() > localtarget)))
        {
         if(!OrderModify(ticket1, OrderOpenPrice(), OrderStopLoss(), localtarget, 0, Blue)) 
           {
            Print("Error during ticket1 target adjust ", ErrorDescription(GetLastError())); 
            Print("TP1 buy/sell open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localtarget ", localtarget, " TP ", OrderTakeProfit());
           }
        }
     }   // end of ticket 1
     return(true);
}

bool HandleTicket2()
{
   double localtarget = 0;
   double localstop = 0;

                
   if(ticket2 > 0)
     {
      bool foo = OrderSelect(ticket2, SELECT_BY_TICKET, MODE_TRADES);
      if (!foo)
        {
         Print("Error during target2 adjust order select ", ErrorDescription(GetLastError())); 
         return(false); 
        }         
           
      if (OrderType() == OP_BUY)
        {
         // bring stop to breakeven if first order closed
         if ((ticket1 < 0) && (!order2mod))
           {
             if (Bid>=OrderOpenPrice()+MinProfitForLock*Point*pip_adjust)
             {
               localstop = OrderOpenPrice()+PipsLock*Point*pip_adjust;
               localstop = NormalizeDouble(localstop, Digits);
               if(!OrderModify(ticket2, OrderOpenPrice(), localstop, OrderTakeProfit(), 0, Blue)) 
                 {
                    Print("Error during ticket2 stop adjust ", ErrorDescription(GetLastError())); 
                    Print("TS2 BE buy open ", OrderOpenPrice(), " BS ", OrderStopLoss(), " localstop ", localstop, " TP ", OrderTakeProfit());
                 }
                 else
                   order2mod = true;
             }
           }
           
         if ((DynamicTP > 0) && (new_bar))
           {
            if (TargetRange == 1)
              {   // low range targets
               MeanYellow = GetPRD(MEAN_YELLOW, 0);
               localtarget = MeanYellow;
              }
            else
              {   // high range targets
               High1Lime = GetPRD(UPPER_LIME, 0);
               localtarget = High1Lime;
              }
            localtarget = NormalizeDouble(localtarget, Digits);
            if(OrderTakeProfit() != localtarget)
              {
               if(!OrderModify(ticket2, OrderOpenPrice(), OrderStopLoss(), localtarget, 0, Blue)) 
                 {
                  Print("Error during ticket2 target adjust ", ErrorDescription(GetLastError())); 
                  Print("TP2 buy open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localtarget ", localtarget, " TP ", OrderTakeProfit());
                 }
              }
           }   //end of adjust TP
        }   // end of OP_BUY
      else
        {      // OrderType() == OP_SELL
         // bring stop to breakeven if first order closed
         if ((ticket1 < 0) && (!order2mod))
           {
             if (Ask<=OrderOpenPrice()-MinProfitForLock*Point*pip_adjust)
              {
                localstop = OrderOpenPrice()-PipsLock*Point*pip_adjust;
                localstop = NormalizeDouble(localstop, Digits);
                
                if(!OrderModify(ticket2, OrderOpenPrice(), localstop, OrderTakeProfit(), 0, Red)) 
                {
                    Print("Error during ticket2 stop adjust ", ErrorDescription(GetLastError())); 
                    Print("TS2 BE sell open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localstop ", localstop, " TP ", OrderTakeProfit());
                }
                else
                   order2mod = true;
              }
           }
                 
         if ((DynamicTP > 0) && (new_bar))
           {
            if (TargetRange == 1)
              {
               MeanYellow = GetPRD(MEAN_YELLOW, 0);
               localtarget = MeanYellow;
              }
            else
              {
               Low1Lime = GetPRD(LOWER_LIME, 0);
               localtarget = Low1Lime;
              }
            localtarget = NormalizeDouble(localtarget, Digits);
            if(OrderTakeProfit() != localtarget)
              {
               if(!OrderModify(ticket2, OrderOpenPrice(), OrderStopLoss(), localtarget, 0, Red)) 
                 {
                  Print("Error during ticket2 target adjust ", ErrorDescription(GetLastError())); 
                  Print("TP2 sell open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localtarget ", localtarget, " TP ", OrderTakeProfit());
                 }
              }
           }   // end of adjust TP
        }   // end of OP_SELL
     }   // end of ticket 2
     return(true);
}

bool HandleTicket3()
{
   double localtarget = 0;
   double localstop = 0;

          
   if(ticket3 > 0)
     {
      bool foo = OrderSelect(ticket3, SELECT_BY_TICKET, MODE_TRADES);
      if (!foo)
        {
         Print("Error during target3 adjust order select ", ErrorDescription(GetLastError())); 
         return(false); 
        }         
              
      if (OrderType() == OP_BUY)
        {
         // special for the last ticket, bring stop to breakeven
         if ((ticket1 < 0) && (!order3mod))
           {
              if ((Bid>=OrderOpenPrice()+MinProfitForLock*Point*pip_adjust) &&
                  (OrderStopLoss() < OrderOpenPrice()+PipsLock*Point*pip_adjust))
               {
                 localstop = OrderOpenPrice()+PipsLock*Point*pip_adjust;
                 localstop = NormalizeDouble(localstop, Digits);
                 
                 if(!OrderModify(ticket3, OrderOpenPrice(), localstop, OrderTakeProfit(), 0, Blue)) 
                 {
                    Print("Error during ticket3 target adjust ", ErrorDescription(GetLastError())); 
                    Print("TS3 BE buy open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localstop ", localstop, " TP ", OrderTakeProfit());
                 }
                 else
                   order3mod = true;
               }
           }
                        
         if((DynamicTP > 0) && (!Order3OpenTP) && (new_bar))
           {
            if (TargetRange == 1)
              {
               High1Lime = GetPRD(UPPER_LIME,0);
               localtarget = High1Lime;
              }
            else
              {
               High2Orange = GetPRD(UPPER_ORANGE,0);
               localtarget = High2Orange;
              }
            localtarget = NormalizeDouble(localtarget,Digits);
            if(OrderTakeProfit() != localtarget)
              {
               if(!OrderModify(ticket3, OrderOpenPrice(), OrderStopLoss(), localtarget, 0, Blue)) 
                 {
                  Print("Error during ticket3 target adjust ", ErrorDescription(GetLastError())); 
                  Print("TP3 buy open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localtarget ", localtarget, " TP ", OrderTakeProfit());
                 }
              }
           }
                               
         if (((UseTrailingStop == 1) || (UseChannelStop) || (Order3OpenTP)) && (new_bar))
           {
            localstop = 9999;
            if (UseChannelStop)
              {
               High3Red = GetPRD(UPPER_RED,0);
               High2Orange = GetPRD(UPPER_ORANGE,0);
               High1Lime = GetPRD(UPPER_LIME,0);
               MeanYellow = GetPRD(MEAN_YELLOW,0);
               Low1Lime = GetPRD(LOWER_LIME, 0);
               if (OrderClosePrice() > High3Red)
                {
                  if (ChannelStopLinesBack == 2)
                    localstop = High1Lime;
                  else
                    localstop = High2Orange;
                }
               else if (OrderClosePrice() > High2Orange)
                {
                  if (ChannelStopLinesBack == 2)
                    localstop = MeanYellow;
                  else
                    localstop = High1Lime;
                }
               else if (OrderClosePrice() > High1Lime)
                {
                  if (ChannelStopLinesBack == 2)
                    localstop = Low1Lime;
                  else
                     localstop = MeanYellow;
                }
              }               
            if (UseTrailingStop == 1) localstop = Bid-TrailingStop*Point*pip_adjust;
            
            localstop = NormalizeDouble(localstop, Digits);
                          
            if((localstop > OrderStopLoss()+(5*Point*pip_adjust)) &&
               (Bid > localstop+stops_level*pip_adjust))
              {
               if(!OrderModify(ticket3, OrderOpenPrice(), localstop, OrderTakeProfit(), 0, Red)) 
                 {
                  Print("Error during ticket3 trailing stop ", ErrorDescription(GetLastError())); 
                  Print("TS3 Buy open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localstop ", localstop, 
                        " TP ", OrderTakeProfit(), " Channel ", UseChannelStop, " Bid ", Bid);
                 }
              }
           }   // end of trailing stop
                  
        }   // end of OP_BUY
      else
        {      // OrderType() == OP_SELL
         // special for the last ticket, bring stop to breakeven
         if ((ticket1 < 0) && (!order3mod))
           {
             if ((Ask<=OrderOpenPrice()-MinProfitForLock*Point*pip_adjust) &&
                  (OrderStopLoss() > OrderOpenPrice()-PipsLock*Point*pip_adjust))
              {

                 localstop = OrderOpenPrice()-PipsLock*Point*pip_adjust;
                 localstop = NormalizeDouble(localstop, Digits);
                 
                 if(!OrderModify(ticket3, OrderOpenPrice(), localstop, OrderTakeProfit(), 0, Red)) 
                   {
                    Print("Error during ticket3 target adjust ", ErrorDescription(GetLastError())); 
                    Print("TS3 BE sell open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localstop ", localstop, " TP ", OrderTakeProfit());
                   }
                   else
                     order3mod = true;
               }
           }
                 
         if((DynamicTP > 0) && (!Order3OpenTP) && (new_bar))
           {
            if (TargetRange == 1)
              {
               Low1Lime = GetPRD(LOWER_LIME,0);
               localtarget = Low1Lime;
              }
            else
              {
               Low2Orange = GetPRD(LOWER_ORANGE,0);
               localtarget = Low2Orange;
              }
              localtarget = NormalizeDouble(localtarget, Digits);
              
            if(OrderTakeProfit() != localtarget )
              {
               if(!OrderModify(ticket3, OrderOpenPrice(), OrderStopLoss(), localtarget, 0, Red)) 
                 {
                  Print("Error during ticket3 target adjust ", ErrorDescription(GetLastError())); 
                  Print("TP3 buy open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localtarget ", localtarget, " TP ", OrderTakeProfit());
                 }
              }
           }
              
         if (((UseTrailingStop == 1) || (UseChannelStop) || (Order3OpenTP)) && (new_bar))
           {
            localstop = 0;
            if (UseChannelStop)
              {
               High1Lime = GetPRD(UPPER_LIME, 0);
               MeanYellow = GetPRD(MEAN_YELLOW,0);
               Low1Lime = GetPRD(LOWER_LIME,0);
               Low2Orange = GetPRD(LOWER_ORANGE,0);
               Low3Red = GetPRD(LOWER_RED,0);
               if (OrderClosePrice() < Low3Red)
                {
                  if (ChannelStopLinesBack == 2)
                    localstop = Low1Lime;
                  else
                    localstop = Low2Orange;
                }
               else if (OrderClosePrice() < Low2Orange)
                {
                  if (ChannelStopLinesBack == 2)
                    localstop = MeanYellow;
                  else
                    localstop = Low1Lime;
                }
               else if (OrderClosePrice() > Low1Lime)
                {
                  if (ChannelStopLinesBack == 2)
                    localstop = High1Lime;
                  else
                    localstop = MeanYellow;
                }
              }               
              if (UseTrailingStop == 1) localstop = Ask+TrailingStop*Point*pip_adjust;
              
              localstop = NormalizeDouble(localstop, Digits);
              
            if((localstop < OrderStopLoss()-(5*Point*pip_adjust)) &&
               (Ask < localstop-stops_level*pip_adjust))
              {
               if(!OrderModify(ticket3, OrderOpenPrice(), localstop, OrderTakeProfit(), 0, Red)) 
                 {
                  Print("Error during trailing stop ", ErrorDescription(GetLastError())); 
                  Print("TS3 sell open ", OrderOpenPrice(), " SL ", OrderStopLoss(), " localstop ", localstop, 
                        " TP ", OrderTakeProfit(), " Channel ", UseChannelStop, " Ask ", Ask);
                 }
              }
           }   // end of trailing stop
            
        }   // end of OP_SELL
     }   //end of ticket3
     
     return(true);
}   
   
int start() {
   double locallots = 0;
   double localstop = 0;
   double localtarget = 0;
   bool OK;
   

   if (RecordTicks) Write_Tick_To_File();

   // there are function that only happen at the start of a bar
   if (Time[0] == last_tick) 
      new_bar = false;
   else
      new_bar = true;

   
   // determine what orders are still open
   
   GetTicketInfo();
   
   OK = HandleTicket1();
   if (!OK) return(0);
   OK = HandleTicket2();
   if (!OK) return(0);
   OK = HandleTicket3();
   if (!OK) return(0);
           
   // open orders only at the start of a bar
   if (Time[0] == last_tick) return(0);

   last_tick = Time[0];

   BuyEntry  = BuySignal();
   SellEntry = SellSignal();
   
   if (RecordChannel)
     {
      Print("New Bar ", TimeToStr(last_tick, TIME_MINUTES), " Buy Signal ", BuyEntry, " Sell Signal ", SellEntry);
      High3Red = GetPRD(UPPER_RED,0);
      High2Orange = GetPRD(UPPER_ORANGE,0);
      High1Lime = GetPRD(UPPER_LIME,0);
      MeanYellow = GetPRD(MEAN_YELLOW,0);
      Low1Lime = GetPRD(LOWER_LIME,0);
      Low2Orange = GetPRD(LOWER_ORANGE,0);
      Low3Red = GetPRD(LOWER_RED,0);
      Print("Channels ", High3Red, " ", High2Orange, " ", High1Lime, " ", MeanYellow, " ", Low1Lime, " ", Low2Orange, " ", Low3Red);
     }

   // if any order is open, Check for reversal signal
   if (CheckForReversal(ticket1, ticket1type)) ticket1 = -1;
   if (CheckForReversal(ticket2, ticket2type)) ticket2 = -1;
   if (CheckForReversal(ticket3, ticket3type)) ticket3 = -1;
   
   // if there is no open order, we can open one here
   if ((ticket1 < 0) && (ticket2 < 0) && (ticket3 < 0))
     {
      int Signal = GetSignal();
      // check hours that trade is not disqualified
      if(((TradeStartHour < TradeStopHour) && ((Hour() < TradeStartHour) || (Hour() >= TradeStopHour))) ||
         ((TradeStartHour > TradeStopHour) &&  (Hour() < TradeStartHour) && (Hour() >= TradeStopHour)))
        {
         Signal = FLAT;
        }  
                       
      // Check that we don't open new orders late on Fridays
      if((Day() == 5) && (FridayCutoffHour > 0) && (Hour() >= FridayCutoffHour))
        {
         Signal = FLAT;
        }
          
      if (Signal == FLAT) return(0);
      
      locallots = LotsOptimized();
      if (Signal == LONG) 
        { 
         if (!IsTradeAllowed()) Print("Buy order at ", Ask);
         else
           {
            //   establish indicator values
            Low3Red = GetPRD(LOWER_RED, 0);
            Low1Lime = GetPRD(LOWER_LIME,0);
            MeanYellow = GetPRD(MEAN_YELLOW,0);
            High1Lime = GetPRD(UPPER_LIME,0);
            High2Orange = GetPRD(UPPER_ORANGE,0);
//            High3Red = GetPRD(UPPER_RED,0);
                    
//            localstop = Low3Red;
//            if (localstop < Bid - InitialStop*Point*pip_adjust)
             localstop = Bid - InitialStop*Point*pip_adjust;
            localstop = NormalizeDouble(localstop,Digits);

            // First third of order
            if (TargetRange == 1)
                  localtarget = Low1Lime;
            else
                  localtarget = MeanYellow;
            localtarget = NormalizeDouble(localtarget,Digits);
                  
	         ticket1 = OpenBuyOrder("BE1 ", locallots, localstop, localtarget, MagicNumber1);
                     
            // Second third of order
            if (TargetRange == 1)
                  localtarget = MeanYellow;
            else
                  localtarget = High1Lime;
            localtarget = NormalizeDouble(localtarget,Digits);
            
	         ticket2 = OpenBuyOrder("BE2 ", locallots, localstop, localtarget, MagicNumber2);
                    
            // Last third of order
            if (TargetRange == 1)
                  localtarget = High1Lime;
            else
                  localtarget = High2Orange;
            if (Order3OpenTP) localtarget = 0;
            localtarget = NormalizeDouble(localtarget,Digits);
            
	         ticket3 = OpenBuyOrder("BE3 ", locallots, localstop, localtarget, MagicNumber3);
            order2mod = false;
            order3mod = false;
           }
        }   // end of buy entry
            
      if (Signal == SHORT) 
        { 
         if (!IsTradeAllowed()) Print("Sell order at ", Bid);
         else
           {
            //   establish indicator values
            High3Red = GetPRD(UPPER_RED,0);
            High1Lime = GetPRD(UPPER_LIME,0);
            MeanYellow = GetPRD(MEAN_YELLOW,0);
            Low1Lime = GetPRD(LOWER_LIME,0);
            Low2Orange = GetPRD(LOWER_ORANGE,0);
//            Low3Red = GetPRD(LOWER_RED,0);
                    
//            localstop = High3Red;
//            if (localstop < Ask + InitialStop*Point*pip_adjust)
             localstop = Ask + InitialStop*Point*pip_adjust;
            localstop = NormalizeDouble(localstop,Digits);

            // First third of order
            if (TargetRange == 1)
                  localtarget = High1Lime;
            else
                  localtarget = MeanYellow;
            localtarget = NormalizeDouble(localtarget,Digits);
	         ticket1 = OpenSellOrder("SE1 ", locallots, localstop, localtarget, MagicNumber1);
                    
            // Second third of order
            if (TargetRange == 1)
                  localtarget = MeanYellow;
            else
                  localtarget = Low1Lime;
            localtarget = NormalizeDouble(localtarget,Digits);
	         ticket2 = OpenSellOrder("SE2 ", locallots, localstop, localtarget, MagicNumber2);
                   
            // Last third of order
            if (TargetRange == 1)
                  localtarget = Low1Lime;
            else
                  localtarget = Low2Orange;
            if (Order3OpenTP) localtarget = 0;
            localtarget = NormalizeDouble(localtarget,Digits);
	         ticket3 = OpenSellOrder("SE3 ", locallots, localstop, localtarget, MagicNumber3);

            order2mod = false;
            order3mod = false;
           }
        }
               
      return(0);
     }      // end of open new orders
     
//----
   return(0);
  }

//+------------------------------------------------------------------+
//| OpenBuyOrder                                                     |
//| If Stop Loss or TakeProfit are used the values are calculated    |
//| for each trade                                                   |
//+------------------------------------------------------------------+
int OpenBuyOrder(string msg, double mLots, double StopLoss, double TakeProfit, int MagicNumber)
{
   int err,ticket;
   double TPprice,STprice;
   
   RefreshRates();
   ticket=OrderSend(Symbol(),OP_BUY,mLots,Ask,slippage*pip_adjust,0,0,EAVersion,MagicNumber,0,Green); 
   if (ticket > 0)
   {
    if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) 
     {
         if (StopLoss != 0 || TakeProfit != 0)
	      {
            TPprice = 0;
            if (TakeProfit > 0)
            {
              TPprice = TakeProfit;
		        TPprice = ValidTakeProfit(OP_BUY,Ask, TPprice);
		      }
            STprice = 0;
            if (StopLoss > 0)
            {
              STprice = StopLoss;
		        STprice = ValidStopLoss(OP_BUY,Bid, STprice);
		      }   
            
 // Normalize stoploss / takeprofit to the proper # of digits.
            if (Digits > 0) 
            {
              STprice = NormalizeDouble( STprice, Digits);
              TPprice = NormalizeDouble( TPprice, Digits); 
            }
		      ModifyOrder(ticket, OrderOpenPrice(), STprice, TPprice, LightGreen);
		   }
         Print(msg, "buy open ", OrderOpenPrice(), " BS ", STprice, " TP ", TPprice);
         if (MagicNumber == MagicNumber3 && EmailAlert)
             SendMail(EAVersion+"Buy", "Buy orders open on "+Symbol()+" at price "+DoubleToStr(OrderOpenPrice(),Digits));
     }
   }
   else
   {
      err = GetLastError();
      if(err==0)
      { 
         return(ticket);
      }
      else
      {
         if(err==4 || err==137 ||err==146 || err==136) //Busy errors
         {
            Sleep(5000);
         }
         else //normal error
         {
           Print(msg, "Error opening BUY order [" + EAVersion + "]: (" + err + ") " + ErrorDescription(err)); 
         }  
      }
   }
   
   return(ticket);
}

//+------------------------------------------------------------------+
//| OpenSellOrder                                                    |
//| If Stop Loss or TakeProfit are used the values are calculated    |
//| for each trade                                                   |
//+------------------------------------------------------------------+
int OpenSellOrder(string msg, double mLots, double StopLoss, double TakeProfit, int MagicNumber)
{
   int err, ticket;
   double TPprice,STprice;
   
   RefreshRates();
   ticket=OrderSend(Symbol(),OP_SELL,mLots,Bid,slippage*pip_adjust,0,0,EAVersion,MagicNumber,0,Red); 
   if (ticket > 0)
   {
     if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) 
     {
         if (StopLoss != 0 || TakeProfit != 0)
	      {
            TPprice = 0;
            if (TakeProfit > 0)
            {
              TPprice=TakeProfit;
		        TPprice = ValidTakeProfit(OP_SELL,Bid, TPprice); 
            }
            STprice = 0;
            if (StopLoss > 0)
            {
              STprice = StopLoss;
		        STprice = ValidStopLoss(OP_SELL,Ask, STprice); 
		      }
 // Normalize stoploss / takeprofit to the proper # of digits.
            if (Digits > 0) 
            {
               STprice = NormalizeDouble( STprice, Digits);
               TPprice = NormalizeDouble( TPprice, Digits); 
            }
		      ModifyOrder(ticket, OrderOpenPrice(), STprice, TPprice, LightGreen);
		   }
         Print(msg, "sell open ", OrderOpenPrice(), " BS ", STprice, " TP ", TPprice);
         if (MagicNumber == MagicNumber3 && EmailAlert)
             SendMail(EAVersion+"Sell", "Sell orders open on "+Symbol()+" at price "+DoubleToStr(OrderOpenPrice(),Digits));
     }
   }
   else
   {
      err = GetLastError();
      if(err==0)
      { 
         return(ticket);
      }
      else
      {
        if(err==4 || err==137 ||err==146 || err==136) //Busy errors
        {
           Sleep(5000);
        }
        else //normal error
        {
           Print("Error opening Sell order [" + EAVersion + "]: (" + err + ") " + ErrorDescription(err));
        }
      } 
   }
   
   return(ticket);
}

int CloseOrder(int ticket,double numLots,int cmd)
{
	bool exit_loop = false, result;
   int cnt, err, digits;
   double myPrice;
   
   if (cmd == OP_BUY) myPrice = MarketInfo(Symbol( ), MODE_BID);
   if (cmd == OP_SELL) myPrice = MarketInfo(Symbol( ), MODE_ASK);
   digits = MarketInfo(Symbol( ), MODE_DIGITS) ;
   if (digits > 0)  myPrice = NormalizeDouble( myPrice, digits);
      
    cnt = 0;
    while (!exit_loop)
    {
		if (IsTradeAllowed()) 
		{
       result = OrderClose(ticket,numLots,myPrice,slippage*pip_adjust,Violet);
		 err = GetLastError();
      }
        else cnt++;
		if (result == true) 
			exit_loop = true;

         err=GetLastError();
		switch (err) 
		{
			case ERR_NO_ERROR:
				exit_loop = true;
				break;
			case ERR_SERVER_BUSY:
			case ERR_NO_CONNECTION:
			case ERR_INVALID_PRICE:
			case ERR_OFF_QUOTES:
			case ERR_BROKER_BUSY:
			case ERR_TRADE_CONTEXT_BUSY: 
			case ERR_TRADE_TIMEOUT:		// for modify this is a retryable error, I hope. 
				cnt++; 	// a retryable error
				break;
			case ERR_PRICE_CHANGED:
			case ERR_REQUOTE:
				RefreshRates();
				continue; 	// we can apparently retry immediately according to MT docs.
			default:
				// an apparently serious, unretryable error.
				exit_loop = true;
				break; 
		}  // end switch 

		if (cnt > totalTries) 
			exit_loop = true; 
			
		if (!exit_loop) 
		{
         Sleep(retryDelay);
			RefreshRates(); 
		}
	}  
	// we have now exited from loop. 
	if ((result == true) || (err == ERR_NO_ERROR)) 
	{
		OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES); 
		return(true); // SUCCESS! 
	}
	 
   Print(" Error closing order : (", err , ") " + ErrorDescription(err));
   return(false);

}


int ModifyOrder(int ord_ticket,double op, double price,double tp, color mColor)
{
    int CloseCnt, err;
    
    CloseCnt=0;
    while (CloseCnt < 3)
    {
       if (OrderModify(ord_ticket,op,price,tp,0,mColor))
       {
         CloseCnt = 3;
       }
       else
       {
          err=GetLastError();
          Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err));
         if (err>0) CloseCnt++;
       }
    }
}

double ValidStopLoss(int type, double price, double SL)
{

   double newSL, temp;
   
   temp = stops_level*Point*pip_adjust;
   newSL = SL;
   if (type == OP_BUY)
   {
		 if((price - SL) < temp) newSL = price - temp;
   }
   if (type == OP_SELL)
   {
       if((SL-price) < temp)  newSL = price + temp;  
   }
   newSL = NormalizeDouble(newSL,Digits);   

   return(newSL);   
}

double ValidTakeProfit(int type, double price, double TP)
{

   double newTP, temp;
   
   temp = stops_level*Point*pip_adjust;
   newTP = TP;
   if (type == OP_BUY)
   {
		 if((TP - price) < temp) newTP = price + temp;
   }
   if (type == OP_SELL)
   {
       if((price - TP) < temp)  newTP = price - temp;  
   }
   newTP = NormalizeDouble(newTP,Digits);   

   return(newTP);   
}


//+------------------------------------------------------------------+
//| Money Management                                                 |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double oLots;
   
//---- select lot size
   if(UseMM == 1)
      oLots=NormalizeDouble(AccountFreeMargin()*Risk/100/MarketInfo(Symbol(),MODE_MARGINREQUIRED),lotdigits);
   else
      oLots = lot;
//   Print("Margin ", AccountFreeMargin(), " Risk/100 ", Risk/100, " reqd ", MarketInfo(Symbol(),MODE_MARGINREQUIRED), " digits ", lotdigits);
//---- return lot size
   minlot = MarketInfo(Symbol(),MODE_MINLOT);
   maxlot = MarketInfo(Symbol(),MODE_MAXLOT);
   
//   Print("oLots ", oLots, " minlot ", minlot, " maxlot ", maxlot);
   if (oLots > maxlot) oLots = maxlot;
   if (oLots < minlot) oLots = minlot;
   return(oLots);
}

void init_tick_file()
  {
   int fhandle = 0;
   int fcount;
   int r;

   fhandle = FileOpen(tick_file_name, FILE_CSV|FILE_READ, ",");
//   Print("tick file init open ", fhandle);
   if (fhandle < 1)
     {
      // tick file does not exist - write header
      Print ("Tick file does not exist - write header");
      fhandle = FileOpen(tick_file_name, FILE_CSV|FILE_WRITE, ",");

      fcount = FileWrite(fhandle, "Date/Time", "Bid", "Ask", "Spread", "Buy entry", "Sell entry");
      if (fcount < 0)
        {
         Print("Error during tick header write ", GetLastError());
         return;
        }
      FileClose(fhandle);
      Print("Tick file header written for ", Symbol()); 
     }
  }

void Write_Tick_To_File()
  {
   int fhandle;
   int fcount;
   string currentTime;
   
   fhandle = FileOpen(tick_file_name, FILE_CSV|FILE_READ|FILE_WRITE, ",");
   if (fhandle == -1)
     {
      Print("Tick file cannot be opened");
      return;
     }
   fcount = FileSeek(fhandle, 0, SEEK_END);
   if (fcount < 0)
     {
      Print("Error during seek end of tick file ", GetLastError());
     }

   currentTime = TimeToStr(TimeCurrent(), TIME_SECONDS);     
   fcount = FileWrite(fhandle, currentTime, 
                      NormalizeDouble(Bid, Digits), 
                      NormalizeDouble(Ask, Digits), 
                      (Ask/Point)-(Bid/Point),
                      BuyEntry,
                      SellEntry);

   if (fcount < 0)
     {
      Print("Error during tick write ", GetLastError());
     }
      
   FileClose(fhandle);
  }

//    ----------------------------------------------------------------------
//    The signal check functions look for Bar-2 and Bar-1 to have crossed
//    the orange line.  
//    ----------------------------------------------------------------------
int BuySignal()
  {
   double Low2Orange = GetPRD(LOWER_ORANGE,Shift);
   double Low2Orange2 = GetPRD(LOWER_ORANGE,Shift+1);
  
   if ((Close[Shift]>Low2Orange) && (Close[Shift+1]<Low2Orange2))
     {
      if (EnterWithCCI)
        {
         double cci=iCCI(NULL,0,CCIPeriod,PRICE_TYPICAL,Shift);
         if (cci > buyzone) 
            return(1);
         else
            return(0);         
        }
      return(1);
     }
   return(0);
  }

int SellSignal()
  {
   double High2Orange = GetPRD(UPPER_ORANGE,Shift);
   double High2Orange2 = GetPRD(UPPER_ORANGE,Shift+1);
  
   if ((Close[Shift]<High2Orange) && (Close[Shift+1]>High2Orange2))
     {
      if (EnterWithCCI)
        {
         double cci=iCCI(NULL,0,CCIPeriod,PRICE_TYPICAL,Shift);
         if (cci < sellzone) 
            return(1);
         else
            return(0);         
        }
      return(1);
     }
   return(0);
  }


int GetSignal()
{

   int isBuy, isSell;

   isBuy = BuySignal();
   if (isBuy > 0) return(LONG);
   
   isSell = SellSignal();
   if (isSell > 0) return (SHORT);
   return(FLAT);
}

double GetPRD(int buffer, int pos)
{

  double buffer_val;
  
  buffer_val = iCustom(NULL, 0, "Past Regression Deviated Opt", period, LR.length,std.channel.1, std.channel.2,std.channel.3, buffer, pos);
  return(buffer_val);
}

//    ----------------------------------------------------------------------
//    CheckForReversal will close an order if a opposite signal appears
//    returns true if order is now closed, false if no action taken
//    ----------------------------------------------------------------------
bool CheckForReversal(int l_ticket, int l_type)
  {
   if (l_ticket < 0) return(true);
   if (((l_type == OP_BUY) && (SellEntry > 0)) ||
       ((l_type == OP_SELL) && (BuyEntry > 0)))
     {
      if (!OrderSelect(l_ticket, SELECT_BY_TICKET, MODE_TRADES))
        {
         Print("Error during reversal ticket ", l_ticket, " select ", ErrorDescription(GetLastError())); 
         return(false); 
        }         

      if (!OrderClose(l_ticket, OrderLots(), OrderClosePrice(), 3*pip_adjust, 0))
        {
         Print("Error during reversal ticket ", l_ticket, " close ", ErrorDescription(GetLastError())); 
         return(false); 
        }
      return(true);         
     }
   return(false);
  }
     