//+------------------------------------------------------------------+
//|                 Murrey Maths auto-trading EA by SteveHopwood.mq4 |
//|                                  Copyright © 2010, Steve Hopwood |
//|                              http://www.hopwood3.freeserve.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"
#define  upperhedgeline "Upper hedge line"
#define  lowerhedgeline "Lower hedge line"


//I have taken the code that displays the MM lines directly from this indicator.
//My grateful appreciation to the authour of the indi.
//+------------------------------------------------------------------+
//|                                           Murrey_Math_Line_X.mq4 |
//|                         Copyright © 2004, Vladislav Goshkov (VG).|
//|                                                      4vg@mail.ru |
//|                                 code change by Alex.Piech.FinGeR |
//+------------------------------------------------------------------+

//Alert("G");
//int x = 1;
//while (x == 1) Sleep(100);


/*
void LookForTradingOpportunities()
void DrawLines()
void GetCurrentMMlPosition()
bool DoesTradeExist(double lot)
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
void CountOpenTrades()
void TradeDirectionBySwap()
bool ShouldWinningPositionClose()
void LookForPendingDeletion()
void DeletePendingTrades()
void CloseAllTrades()

----Deal with losing trades
void HasMarketPassedExtreme()
bool HedgePosition()
void LookForFailedHedging()

*/

extern string  gi="----General inputs----";
extern double  Lot1=0.01;
extern double  Lot2=0.02;
extern double  Lot3=0.06;
extern double  Lot4=0.12;
extern int     BufferPips=10;
extern bool    TradeLong=true;
extern bool    TradeShort=true;
extern bool    DeleteUnwantedPendings=true;
extern bool    UseIndividualTradeStopLoss=false;
bool    CriminalIsECN=false;//Remove as an extern to leave the option open for using it - you never know
extern int     MagicNumber=0;
extern string  TradeComment="";
int     TakeProfit=0;//Remove as an extern to leave the option open for using it - you never know
extern string  tp="----Take Basket Profits----";
extern bool TakeProfitBasket = false; // If the basket hits the defined profit level then close all trades for this pair
extern int TakeProfitPercentage = 0; // Zero means do not use this.
                                     //Close basket based on percentage of accountbalance, e.g. TakeProfitPercentage = 2, closes at 2% of account
extern int TakeProfitDollar = 15; // Zero means do not use this.
                                 // Close basket based on hard dollar value, e.g. TakeProfitDollar = 15, closes at $15 profit
extern string  bf="----Trading balance filters----";
extern bool    UseZeljko=true;
extern bool    OnlyTradeCurrencyTwice=true;

extern string  lto="----Death trade options----";
extern bool    CloseLosingBasket=false;
extern string  hed="Hedging";
extern bool    UseHedging=false;
extern double  HedgeLotMultiplier=2;
extern bool    CloseHedgeOnReturnToGrid=false;

extern string  amc="----Available Margin checks----";
extern string  sco="Scoobs";
extern bool    UseScoobsMarginCheck=false;
extern string  fk="ForexKiwi";
extern bool    UseForexKiwi=true;
extern int     FkMinimumMarginPercent=1100;

extern string  pts="----Swap filter----";
//extern bool    TradePositiveSwapOnly=true;
extern bool    CadPairsPositiveOnly=true;
extern bool    AudPairsPositiveOnly=true;
extern bool    NzdPairsPositiveOnly=true;

extern string  mm="----Murray Mathis inputs----";
extern int     P = 64;//MM indi
extern int     MMPeriod = 0;//MM indi
extern int     StepBack = 0;//MM indi
extern double  TargetAsPercentofOctave=70;

///////////////////////////////////////////////////////////////////////////////////////////
//Indi variables
extern color  mml_clr_m_2_8 = Yellow;       // [-2]/8
extern color  mml_clr_m_1_8 = Purple;       // [-1]/8
extern color  mml_clr_0_8   = DeepSkyBlue;        //  [0]/8
extern color  mml_clr_1_8   = DarkOrange;      //  [1]/8
extern color  mml_clr_2_8   = Red;         //  [2]/8
extern color  mml_clr_3_8   = Green;       //  [3]/8
extern color  mml_clr_4_8   = Blue;        //  [4]/8
extern color  mml_clr_5_8   = Green;       //  [5]/8
extern color  mml_clr_6_8   = Red;         //  [6]/8
extern color  mml_clr_7_8   = DarkOrange;      //  [7]/8
extern color  mml_clr_8_8   = DeepSkyBlue;        //  [8]/8
extern color  mml_clr_p_1_8 = Purple;       // [+1]/8
extern color  mml_clr_p_2_8 = Yellow;       // [+2]/8

extern int    mml_wdth_m_2_8 = 2;        // [-2]/8
extern int    mml_wdth_m_1_8 = 1;       // [-1]/8
extern int    mml_wdth_0_8   = 1;        //  [0]/8
extern int    mml_wdth_1_8   = 1;      //  [1]/8
extern int    mml_wdth_2_8   = 1;         //  [2]/8
extern int    mml_wdth_3_8   = 1;       //  [3]/8
extern int    mml_wdth_4_8   = 1;        //  [4]/8
extern int    mml_wdth_5_8   = 1;       //  [5]/8
extern int    mml_wdth_6_8   = 1;         //  [6]/8
extern int    mml_wdth_7_8   = 1;      //  [7]/8
extern int    mml_wdth_8_8   = 1;        //  [8]/8
extern int    mml_wdth_p_1_8 = 1;       // [+1]/8
extern int    mml_wdth_p_2_8 = 2;       // [+2]/8

extern color  MarkColor   = Blue;
extern int    MarkNumber  = 217;


double  dmml = 0,
        dvtl = 0,
        sum  = 0,
        v1 = 0,
        v2 = 0,
        mn = 0,
        mx = 0,
        x1 = 0,
        x2 = 0,
        x3 = 0,
        x4 = 0,
        x5 = 0,
        x6 = 0,
        y1 = 0,
        y2 = 0,
        y3 = 0,
        y4 = 0,
        y5 = 0,
        y6 = 0,
        octave = 0,
        fractal = 0,
        range   = 0,
        finalH  = 0,
        finalL  = 0,
        mml[13];

string  ln_txt[13],        
        buff_str = "";
        
int     
        bn_v1   = 0,
        bn_v2   = 0,
        OctLinesCnt = 13,
        mml_thk = 8,
        mml_clr[13],
        mml_wdth[13],
        mml_shft = 50,
        nTime = 0,
        CurPeriod = 0,
        nDigits = 0,
        i = 0;
int NewPeriod=0;
///////////////////////////////////////////////////////////////////////////////////////////

double         BandHigh, BandLow;//Hi-lo of the market's MM band
double         OctaveSize = 195;
int            Band;//Band the market is within
int            OpenTrades;
double         BasketUpl;//For hedging
bool           ForceTradeClosure, ForcePendingTradeDeletion;

//Trade ticket numbers etc
int            TradeTicketNo[5];//Will use 1 to 4
int            TicketNo;//Temp store for successful order-send ticket number
bool           BuyPending, SellPending;//Set to true if pendings are in place
double         LargestLot;

//Hedging
bool           BuyOpen, SellOpen;
bool           HedgingInProgress;
double         OpenLots;
int            FilledBuys, FilledSells;
//mm lines
//Store mm +2/8 and -2/8 to check for a redraw
double OldHigh, OldLow;


//Matt's O-R stuff
int 	         O_R_Setting_max_retries 	= 1000;
double 	      O_R_Setting_sleep_time 		= 4.0; /* seconds */
double 	      O_R_Setting_sleep_max 		= 15.0; /* seconds */

// ============================================================================================
// * Line 8/8 и 0/8 (Ultimate Support and Ultimate Resistance).
// * Those lines are the most strong concerning Support and esistance.
// ============================================================================================
//* Line 7/8  (Weak, Place to Stop and Reverse).
//* This line is weak. If suddenly the price was going too fast and too far and stops around this line 
//* it means the price will reverse down very soon. If the price did not stop near this line this price 
//* will continue the movement to the line 8/8.
// ============================================================================================
//* Line 1/8  (Weak, Place to Stop and Reverse).
//* This line is weak. If suddenly the price was going too fast and too far and stops around this line 
//* it means the price will reverse up very soon. If the price did not stop near this line this price
//* will continue the movement down to the line 0/8.
// ============================================================================================
//* Line 2/8 and 6/8 (Pivot, Reverse)
//* Those two lines yield the line 4/8 only to the strength to reverse the price movement.
// ============================================================================================
//* Line 5/8 (Top of Trading Range)
//* The price is spending the about 40% of the time on the movement between the lines 5/8 and 3/8. 
//* If the price is moving near line 5/8 and stopping near the line during the 10 - 12 days so it means 
//* that it is necessary to sell in this "bonus zone" (some people are doing like this) but if the price is keeping the tendency to stay above 
//* 5/8 line, so it means that the price will be above. But if the price is droping below 5/8 line it means that the price will continue 
//* falling to the next level of resistance.
// ============================================================================================
//* Line 3/8 (Bottom of Trading Range).
//* If the price is below this line and in uptrend it means that it will be very difficult for the price to break this level. 
//* If the price broke this line during the uptrend and staying above during the 10 12 days it means that the price will be above this line 
//* during the 40% of its time moving between this line and 5/8 line.
// ============================================================================================
//* Line 4/8 (Major Support/Resistance Line).
//* It is the major line concerning support and resistance. This leve is the better for the new sell or buy. 
//* It is the strong level of support of the price is above 4/8. It is the fine resistance line if the price is below this 4/8 line. 
//* сопротивления.
// ============================================================================================


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{

   double multiplier;
   if(Digits == 2 || Digits == 4) multiplier = 1;
   if(Digits == 3 || Digits == 5) multiplier = 10;
   if(Digits == 6) multiplier = 100;   
   if(Digits == 7) multiplier = 1000;   

   OctaveSize*= multiplier;
   BufferPips*= multiplier;
   TakeProfit*= multiplier;
   
//---- indicators
   if(MMPeriod>0)
      NewPeriod   = P*MathCeil(MMPeriod/Period());
   else NewPeriod = P;
   
   
   ln_txt[0]  = "Extreme Overshoot  -2/8";// "Extreme overshoot [-2/8]";// [-2/8]
   ln_txt[1]  = "Overshoot  -1/8";// "Overshoot [-1/8]";// [-1/8]
   ln_txt[2]  = "Ultimate Support - Extremely Oversold  0/8";// "Ultimate Support - Extremely Oversold [0/8]";// [0/8]
   ln_txt[3]  = "Weak, Place to Stop and Reverse  1/8";// "Weak, Place to Stop and Reverse - [1/8]";// [1/8]
   ln_txt[4]  = "Strong, Pivot, Reverse  2/8";// "Strong, Pivot, Reverse [2/8]";// [2/8]
   ln_txt[5]  = "Bottom of Trading Range  3/8";// "Bottom of Trading Range - [3/8], if 10-12 bars then 40% Time. BUY Premium Zone";//[3/8]
   ln_txt[6]  = "Major Support/Resistance Pivotal Point  4/8";// "Major Support/Resistance Pivotal Point [4/8]- Best New BUY or SELL level";// [4/8]
   ln_txt[7]  = "Top of Trading Range  5/8";// "Top of Trading Range - [5/8], if 10-12 bars then 40% Time. SELL Premium Zone";//[5/8]
   ln_txt[8]  = "Strong, Pivot, Reverse  6/8";// "Strong, Pivot, Reverse [6/8]";// [6/8]
   ln_txt[9]  = "Weak, Place to Stop and Reverse  7/8";// "Weak, Place to Stop and Reverse - [7/8]";// [7/8]
   ln_txt[10] = "Ultimate Resistance - Extremely Overbought  8/8";// "Ultimate Resistance - Extremely Overbought [8/8]";// [8/8]
   ln_txt[11] = "Overshoot  +1/8";// "Overshoot [+1/8]";// [+1/8]
   ln_txt[12] = "Extreme Overshoot  +2/8";// "Extreme Overshoot [+2/8]";// [+2/8]

   //mml_shft = 3;
   mml_thk  = 3;

   // Начальная установка цветов уровней октав и толщины линий
   mml_clr[0]  = mml_clr_m_2_8;   mml_wdth[0] = mml_wdth_m_2_8; // [-2]/8
   mml_clr[1]  = mml_clr_m_1_8;   mml_wdth[1] = mml_wdth_m_1_8; // [-1]/8
   mml_clr[2]  = mml_clr_0_8;     mml_wdth[2] = mml_wdth_0_8;   //  [0]/8
   mml_clr[3]  = mml_clr_1_8;     mml_wdth[3] = mml_wdth_1_8;   //  [1]/8
   mml_clr[4]  = mml_clr_2_8;     mml_wdth[4] = mml_wdth_2_8;   //  [2]/8
   mml_clr[5]  = mml_clr_3_8;     mml_wdth[5] = mml_wdth_3_8;   //  [3]/8
   mml_clr[6]  = mml_clr_4_8;     mml_wdth[6] = mml_wdth_4_8;   //  [4]/8
   mml_clr[7]  = mml_clr_5_8;     mml_wdth[7] = mml_wdth_5_8;   //  [5]/8
   mml_clr[8]  = mml_clr_6_8;     mml_wdth[8] = mml_wdth_6_8;   //  [6]/8
   mml_clr[9]  = mml_clr_7_8;     mml_wdth[9] = mml_wdth_7_8;   //  [7]/8
   mml_clr[10] = mml_clr_8_8;     mml_wdth[10]= mml_wdth_8_8;   //  [8]/8
   mml_clr[11] = mml_clr_p_1_8;   mml_wdth[11]= mml_wdth_p_1_8; // [+1]/8
   mml_clr[12] = mml_clr_p_2_8;   mml_wdth[12]= mml_wdth_p_2_8; // [+2]/8
   
   //Store mm +2/8 and -2/8 to check for a redraw
   OldHigh = ObjectGet("mml12", OBJPROP_PRICE1);
   OldLow = ObjectGet("mml0", OBJPROP_PRICE1);

   if (TradeComment == "") TradeComment = " ";
   //start();
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment(" ");   
   return;//Don't want the lines deleted
   for(i=0;i<OctLinesCnt;i++) 
   {
       buff_str = "mml"+i;
       ObjectDelete(buff_str);
       buff_str = "mml"+i+".5";
       ObjectDelete(buff_str);
       buff_str = "mml_txt"+i;
       ObjectDelete(buff_str);
       buff_str = "MML_LatestCulcBar";
       ObjectDelete(buff_str);
   }//for(i=0;i<OctLinesCnt;i++) 
   
//----
   return(0);
}

void DrawLines()
{   
   
   
   //Store mm +2/8 and -2/8 to check for a redraw
   OldHigh = ObjectGet("mml12", OBJPROP_PRICE1);
   OldLow = ObjectGet("mml0", OBJPROP_PRICE1);
   //Do not redraw the lines if market has moved outside hi-lo yellow
   //if ((Bid > OldHigh && OldHigh > 0) || (Bid < OldLow && OldLow > 0) && OpenTrades > 0) return;
   //
   // Don't redraw if trades are Open - Sandovich
   if (UseIndividualTradeStopLoss) if (LargestLot >= Lot4 || LargestLot >= Lot3 || LargestLot >= Lot2 || LargestLot >= Lot1) return;
   // Don't redraw if Lot4 open
   if (LargestLot >= Lot4) return;

   if( (nTime != Time[0]) || (CurPeriod != Period()) ) 
   {
   
     //price
      bn_v1 = Lowest(NULL,0,MODE_LOW,NewPeriod+StepBack,StepBack);
      bn_v2 = Highest(NULL,0,MODE_HIGH,NewPeriod+StepBack,StepBack);

      v1 = Low[bn_v1];
      v2 = High[bn_v2];

   //determine fractal.....
      if( v2<=250000 && v2>25000 )
      fractal=100000;
      else
        if( v2<=25000 && v2>2500 )
        fractal=10000;
        else
          if( v2<=2500 && v2>250 )
          fractal=1000;
          else
            if( v2<=250 && v2>25 )
            fractal=100;
            else
              if( v2<=25 && v2>12.5 )
              fractal=12.5;
              else
                if( v2<=12.5 && v2>6.25)
                fractal=12.5;
                else
                  if( v2<=6.25 && v2>3.125 )
                  fractal=6.25;
                  else
                    if( v2<=3.125 && v2>1.5625 )
                    fractal=3.125;
                    else
                      if( v2<=1.5625 && v2>0.390625 )
                      fractal=1.5625;
                      else
                        if( v2<=0.390625 && v2>0)
                        fractal=0.1953125;
      
      range=(v2-v1);
      sum=MathFloor(MathLog(fractal/range)/MathLog(2));
      octave=fractal*(MathPow(0.5,sum));
      mn=MathFloor(v1/octave)*octave;
      if( (mn+octave)>v2 )
      mx=mn+octave; 
      else
        mx=mn+(2*octave);


   // calculating xx
   //x2
       if( (v1>=(3*(mx-mn)/16+mn)) && (v2<=(9*(mx-mn)/16+mn)) )
       x2=mn+(mx-mn)/2; 
       else x2=0;
   //x1
       if( (v1>=(mn-(mx-mn)/8))&& (v2<=(5*(mx-mn)/8+mn)) && (x2==0) )
       x1=mn+(mx-mn)/2; 
       else x1=0;

   //x4
       if( (v1>=(mn+7*(mx-mn)/16))&& (v2<=(13*(mx-mn)/16+mn)) )
       x4=mn+3*(mx-mn)/4; 
       else x4=0;

   //x5
       if( (v1>=(mn+3*(mx-mn)/8))&& (v2<=(9*(mx-mn)/8+mn))&& (x4==0) )
       x5=mx; 
       else  x5=0;

   //x3
       if( (v1>=(mn+(mx-mn)/8))&& (v2<=(7*(mx-mn)/8+mn))&& (x1==0) && (x2==0) && (x4==0) && (x5==0) )
       x3=mn+3*(mx-mn)/4; 
       else x3=0;

   //x6
       if( (x1+x2+x3+x4+x5) ==0 )
       x6=mx; 
       else x6=0;

        finalH = x1+x2+x3+x4+x5+x6;
   // calculating yy
   //y1
       if( x1>0 )
       y1=mn; 
       else y1=0;

   //y2
       if( x2>0 )
       y2=mn+(mx-mn)/4; 
       else y2=0;

   //y3
       if( x3>0 )
       y3=mn+(mx-mn)/4; 
       else y3=0;

   //y4
       if( x4>0 )
       y4=mn+(mx-mn)/2; 
       else y4=0;

   //y5
       if( x5>0 )
       y5=mn+(mx-mn)/2; 
       else y5=0;

   //y6
       if( (finalH>0) && ((y1+y2+y3+y4+y5)==0) )
       y6=mn; 
       else y6=0;

       finalL = y1+y2+y3+y4+y5+y6;

       for( i=0; i<OctLinesCnt; i++) {
            mml[i] = 0;
            }
         
      dmml = (finalH-finalL)/8;

      mml[0] =(finalL-dmml*2); //-2/8
      for( i=1; i<OctLinesCnt; i++) {
           mml[i] = mml[i-1] + dmml;
           }
      for( i=0; i<OctLinesCnt; i++ )
      {
           //Draw the line
           buff_str = "mml"+i;
           if(ObjectFind(buff_str) == -1) 
           {
               ObjectCreate(buff_str, OBJ_HLINE , 0,Time[0], mml[i]);
               ObjectSet(buff_str, OBJPROP_STYLE, STYLE_SOLID);
               ObjectSet(buff_str, OBJPROP_COLOR, mml_clr[i]);
               ObjectSet(buff_str, OBJPROP_WIDTH, mml_wdth[i]);
               ObjectMove(buff_str, 0, Time[0],  mml[i]);
           }//if(ObjectFind(buff_str) == -1) 
           else 
           {
               ObjectMove(buff_str, 0, Time[0],  mml[i]);
           }//else
             
           //Draw the label
           buff_str = "mml_txt"+i;
           if(ObjectFind(buff_str) == -1) 
           {
               ObjectCreate(buff_str, OBJ_TEXT, 0, Time[mml_shft], mml_shft);
               ObjectSetText(buff_str, ln_txt[i], 10, "Arial", mml_clr[i]);
               ObjectMove(buff_str, 0, Time[mml_shft],  mml[i]);
           }//if(ObjectFind(buff_str) == -1) 
           else 
           {
               ObjectMove(buff_str, 0, Time[mml_shft],  mml[i]);
           }//else
        
            //Draw the half-way point line        
            if (i > 4 && i < 9) continue;
            buff_str = "mml"+i + ".5";
            double tp = 0;
            if(ObjectFind(buff_str) == -1) 
            {
                tp = mml[i + 1] - mml[i];
                tp = NormalizeDouble((tp * TargetAsPercentofOctave) / 100, Digits);
                if (i < 5) ObjectCreate(buff_str, OBJ_HLINE, 0,Time[0], NormalizeDouble(mml[i - 1] + tp, Digits));
                if (i > 5) ObjectCreate(buff_str, OBJ_HLINE, 0,Time[0], NormalizeDouble(mml[i] - tp, Digits));
                ObjectSet(buff_str, OBJPROP_STYLE, STYLE_DOT);
                //ObjectSet(buff_str, OBJPROP_COLOR, mml_clr[i]);
                if (i < 5) ObjectSet(buff_str, OBJPROP_COLOR, mml_clr[i - 1]);
                if (i > 5) ObjectSet(buff_str, OBJPROP_COLOR, mml_clr[i]);
                ObjectSet(buff_str, OBJPROP_WIDTH, 1);
                
            }//if(ObjectFind(buff_str) == -1) 
            else 
            {
                tp = mml[i + 1] - mml[i];
                tp = NormalizeDouble((tp * TargetAsPercentofOctave) / 100, Digits);
                if (i < 5) ObjectMove(buff_str, 0, Time[0],  NormalizeDouble(mml[i - 1] + tp, Digits));
                if (i > 5) ObjectMove(buff_str, 0, Time[0],  NormalizeDouble(mml[i] - tp, Digits));
                
            }//else
     
       } // for( i=1; i<=OctLinesCnt; i++ ){

      nTime    = Time[0];
      CurPeriod= Period();
   
      string buff_str = "MML_LatestCulcBar";
      if(ObjectFind(buff_str) == -1) {
         ObjectCreate(buff_str, OBJ_ARROW,0, Time[StepBack], Low[StepBack]-2*Point );
         ObjectSet(buff_str, OBJPROP_ARROWCODE, MarkNumber);
         ObjectSet(buff_str, OBJPROP_COLOR, MarkColor);
         }
      else {
         ObjectMove(buff_str, 0, Time[StepBack], Low[StepBack]-2*Point );
         }

   }//if( (nTime != Time[0]) || (CurPeriod != Period()) ) 

   //Draw hedge lines
   ObjectDelete(upperhedgeline);
   ObjectCreate(upperhedgeline, OBJ_HLINE , 0,Time[0], NormalizeDouble((mml[OctLinesCnt - 1] + dmml), Digits));
   ObjectSet(upperhedgeline, OBJPROP_STYLE, STYLE_DOT);
   ObjectSet(upperhedgeline, OBJPROP_COLOR, Red);
   ObjectSet(upperhedgeline, OBJPROP_WIDTH, 0);

   ObjectDelete(lowerhedgeline);
   ObjectCreate(lowerhedgeline, OBJ_HLINE , 0,Time[0], NormalizeDouble((mml[0] - dmml), Digits));
   ObjectSet(lowerhedgeline, OBJPROP_STYLE, STYLE_DOT);
   ObjectSet(lowerhedgeline, OBJPROP_COLOR, Red);
   ObjectSet(lowerhedgeline, OBJPROP_WIDTH, 0);


   //Check to see if a redraw has occurred
   double high = ObjectGet("mml12", OBJPROP_PRICE1);
   double low = ObjectGet("mml0", OBJPROP_PRICE1);
   
   if ((OldHigh != high || OldLow != low) && OpenTrades > 0)
   {
      DeletePendingTrades();
   }//if (OldHigh != high || OldLow != low)
   
   

}//End void DrawLines()



void GetCurrentMMlPosition()
{

   //Defaults for in case the market is outside MM
   BandHigh = NormalizeDouble(mml[12] + (OctaveSize * Point), Digits);
   BandLow = NormalizeDouble(mml[0] - (OctaveSize * Point), Digits);
   
   Band = 0;
   
   //Calculates the hi-lo of the current band
   RefreshRates();
   for (int cc = 0; cc <= ArraySize(mml); cc++)
   {  
      if (Bid >= mml[cc] && Bid <= mml[cc + 1] )
      {
         BandHigh = mml[cc + 1];
         BandLow = mml[cc];
         Band++;
         break;
      }//if (Bid >= mml[cc] && Bid <= mml[cc + 1] )
      Band++;
   }//for (int cc = 0; cc <= ArraySize(mml); cc++)
   

}//void GetCurrentMMlPosition()

bool DoesTradeExist(double lot)
{
   //-1 is passed as the lot size to force a general find-any
   
   if (OrdersTotal() == 0) return(false);
   
   for (int cc = 0; cc <= OrdersTotal() - 1; cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderCloseTime() > 0) continue;
      //-1 is passed as the lot size to force a general find-any   
      if (OrderSymbol() == Symbol() && (OrderLots() == lot || lot == -1)) return(true);   
   }//for (int cc = 0; cc <= OrdersTotal() - 1; cc++)
   
   return(false);
   
}//bool DoesTradeExist(double lot)


void DeletePendingTrades()
{
   ForcePendingTradeDeletion = false;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderSymbol() != Symbol() ) continue;
      //if (OrderType() != OP_BUYLIMIT && OrderType() != OP_SELLLIMIT) continue;
      int tn = OrderTicket();
      while(IsTradeContextBusy()) Sleep(100);
      if ((OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT) && OrderCloseTime() == 0) 
      {
         bool result = OrderDelete(tn);      
         if (result) cc++;
         if (!result) ForcePendingTradeDeletion = true;//Force a retry at the next tick
      }//if (OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT) 
      
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

}//End void DeletePendingTrades()



void LookForTradingOpportunities()
{
   
   if (Band > 4 && Band < 9) return;
   double take, stop, price, lotsize;
   int type;
   bool SendTrade = false;
   double target;
   //double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
   
   //Only trade a currency twice
   if (OnlyTradeCurrencyTwice && OpenTrades == 0)
   {
      if (!IsThisPairTradable() ) return;
   }//if (OnlyTradeCurrencyTwice)

   
   //Long opportunities
   //Balance filter
   if (Band < 5 && (UseZeljko && !BalancedPair(OP_BUY) && FilledBuys == 0) ) return;
        
   
   target = ObjectGet("mml4.5", OBJPROP_PRICE1);
   //The first band needs a buffer to prevent pendings being placed then deleted in rapid succession, as the market 
   //ticks into the band, then straight out again
   target = NormalizeDouble(target - (BufferPips * Point), Digits);
   if (Band == 4 && Bid <= target && TradeLong)
   {
      if (!DoesTradeExist(Lot1) )
      {
         take = NormalizeDouble(mml[3] + (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) stop = NormalizeDouble(mml[2], Digits); // Paul addition for Sandovich
         type = OP_BUYLIMIT;
         price = NormalizeDouble(mml[3], Digits);
         SendTrade = true;
         lotsize = Lot1;         
      }//if (!DoesTradeExist(Lot1) )
      
   }//if (Band == 3 && Bid < mml[3] + (BufferPips * Point))
   
     
   target = ObjectGet("mml3.5", OBJPROP_PRICE1);
   if (Band == 3 && Bid >= target && TradeLong)
   {
      if (!DoesTradeExist(Lot2) )
      {
         take = NormalizeDouble(mml[2] + (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) stop = NormalizeDouble(mml[1], Digits); // Paul addition for Sandovich
         type = OP_BUYLIMIT;
         price = NormalizeDouble(mml[2], Digits);
         SendTrade = true;
         lotsize = Lot2;
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 3 && Bid < mml[3] + (BufferPips * Point))
   
   target = ObjectGet("mml2.5", OBJPROP_PRICE1);
   if (Band == 2 && Bid >= target && TradeLong)
   {
      if (!DoesTradeExist(Lot3) )
      {
         take = NormalizeDouble(mml[1] + (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) stop = NormalizeDouble(mml[0], Digits); // Paul addition for Sandovich
         type = OP_BUYLIMIT;
         price = NormalizeDouble(mml[1], Digits);
         SendTrade = true;
         lotsize = Lot3;
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 3 && Bid < mml[3] + (BufferPips * Point))
      
   target = ObjectGet("mml1.5", OBJPROP_PRICE1);
   if (Band == 1 && Bid >= target && TradeLong)
   {
      if (!DoesTradeExist(Lot4) )
      {
         take = NormalizeDouble(mml[0] + (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) 
         {            
            stop = NormalizeDouble(ObjectGet(lowerhedgeline, OBJPROP_PRICE1), Digits); // Paul addition for Sandovich
         }//if (UseIndividualTradeStopLoss) 
         
         type = OP_BUYLIMIT;
         price = NormalizeDouble(mml[0], Digits);
         SendTrade = true;
         lotsize = Lot4;
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 1 && Bid >= target && TradeLong)
   

   //Short opportunities
   //Balance filter
   if (Band > 8 && (UseZeljko && !BalancedPair(OP_SELL) && FilledSells == 0) ) return;
   target = ObjectGet("mml9.5", OBJPROP_PRICE1);
   //The first band needs a buffer to prevent pendings being placed then deleted in rapid succession, as the market 
   //ticks into the band, then straight out again
   target = NormalizeDouble(target + (BufferPips * Point), Digits);
   if (Band == 9 && Bid >= target && TradeShort)
   {
      if (!DoesTradeExist(Lot1) )
      {
         take = NormalizeDouble(mml[9] - (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) stop = NormalizeDouble(mml[10], Digits); // Paul addition for Sandovich
         type = OP_SELLLIMIT;
         price = NormalizeDouble(mml[9], Digits);
         SendTrade = true;
         lotsize = Lot1;
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 3 && Bid < mml[3] + (BufferPips * Point))
   
   target = ObjectGet("mml10.5", OBJPROP_PRICE1);
   if (Band == 10 && Bid <= target && TradeShort)
   {
      if (!DoesTradeExist(Lot2) )
      {
         take = NormalizeDouble(mml[10] - (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) stop = NormalizeDouble(mml[11], Digits); // Paul addition for Sandovich
         type = OP_SELLLIMIT;
         price = NormalizeDouble(mml[10], Digits);
         SendTrade = true;
         lotsize = Lot2;
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 3 && Bid < mml[3] + (BufferPips * Point))
   
   target = ObjectGet("mml11.5", OBJPROP_PRICE1);
   if (Band == 11 && Bid <= target && TradeShort)
   {
      if (!DoesTradeExist(Lot3) )
      {
         take = NormalizeDouble(mml[11] - (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) stop = NormalizeDouble(mml[12], Digits); // Paul addition for Sandovich
         type = OP_SELLLIMIT;
         price = NormalizeDouble(mml[11], Digits);
         SendTrade = true;
         lotsize = Lot3;
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 3 && Bid < mml[3] + (BufferPips * Point))
   
   target = ObjectGet("mml12.5", OBJPROP_PRICE1);
   if (Band == 12 && Bid <= target && TradeShort)
   {
      if (!DoesTradeExist(Lot4) )
      {
         take = NormalizeDouble(mml[12] - (TakeProfit * Point), Digits);
         if (UseIndividualTradeStopLoss) 
         {            
            stop = NormalizeDouble(ObjectGet(upperhedgeline, OBJPROP_PRICE1), Digits); // Paul addition for Sandovich            
         }//if (UseIndividualTradeStopLoss) 
         type = OP_SELLLIMIT;
         price = NormalizeDouble(mml[12], Digits);
         SendTrade = true;
         lotsize = Lot4;
      }//if (!DoesTradeExist(Lot4) )
   }//if (Band == 12 && Bid <= target && TradeShort)
   
   if (SendTrade)
   {
      //Neutralise the tp if necessary   
      bool result = SendSingleTrade(type, TradeComment, lotsize, price, stop, 0);
      // else result = SendSingleTrade(type, TradeComment, lotsize, price, 0, take);      
      //Alert("Band: ", Band, " Lot: ", lotsize, " Price: ", price, " mml ", mml[Band]);
      //int x = 1;
      //while (x == 1) Sleep(100);
      if (result) 
      {
         ForceTradeClosure = false;//Thrashing around a bit here
         OrderSelect(TicketNo, SELECT_BY_TICKET);
         if (type == OP_BUYLIMIT)
         {
            if (OrderLots() == Lot1) TradeTicketNo[1] = TicketNo;
            if (OrderLots() == Lot2) TradeTicketNo[2] = TicketNo;
            if (OrderLots() == Lot3) TradeTicketNo[3] = TicketNo;
            if (OrderLots() == Lot4) TradeTicketNo[4] = TicketNo;         
         }//if (type == OP_BUYLIMIT)
         
         if (type == OP_SELLLIMIT)
         {
            if (OrderLots() == Lot1) TradeTicketNo[1] = TicketNo;
            if (OrderLots() == Lot2) TradeTicketNo[2] = TicketNo;
            if (OrderLots() == Lot3) TradeTicketNo[3] = TicketNo;            
            if (OrderLots() == Lot4) TradeTicketNo[4] = TicketNo;         
         }//if (type == OP_SELLLIMIT)
         
         
      }//if (result) 
      
   }//if (SendTrade)
   
   
}//LookForTradingOpportunities()

bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
{
   

   int slippage = 10;
   int err;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
   color col = Red;
   if (type == OP_BUY || type == OP_BUYLIMIT) col = Green;
   
   int expiry = 0;
   //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60);

   if (!CriminalIsECN) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, col);
   

   
   /*
   //Is a 2 stage criminal
   if (CriminalIsECN)
   {
      bool result;
      int err;
      ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, col);
      if (ticket > 0)
      {
	     
	     if (take > 0 && stop > 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)			  
        }//if (take > 0 && stop > 0)
      
	     if (take != 0 && stop == 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)			  
        }//if (take == 0 && stop != 0)

        if (take == 0 && stop != 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)			  
        }//if (take == 0 && stop != 0)

      }//if (ticket > 0)
        
      
      
   }//if (CriminalIsECN)
   */
   
   //Error trapping for both
   if (ticket < 0)
   {
      string stype;
      if (type == OP_BUY) stype = "OP_BUY";
      if (type == OP_SELL) stype = "OP_SELL";
      if (type == OP_BUYLIMIT) stype = "OP_BUYLIMIT";
      if (type == OP_SELLLIMIT) stype = "OP_SELLLIMIT";
      if (type == OP_BUYSTOP) stype = "OP_BUYSTOP";
      if (type == OP_SELLSTOP) stype = "OP_SELLSTOP";
      err=GetLastError();
      Alert(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err) );
      Print(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (ticket < 0)  
   
   
   TicketNo = ticket;
   //Make sure the trade has appeared in the platform's history to avoid duplicate trades
   O_R_CheckForHistory(ticket); 
   
   
   //Got this far, so trade send succeeded
   return(true);
   
}//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)

//=============================================================================
//                           O_R_CheckForHistory()
//
//  This function is to work around a very annoying and dangerous bug in MT4:
//      immediately after you send a trade, the trade may NOT show up in the
//      order history, even though it exists according to ticket number.
//      As a result, EA's which count history to check for trade entries
//      may give many multiple entries, possibly blowing your account!
//
//  This function will take a ticket number and loop until
//  it is seen in the history.
//
//  RETURN VALUE:
//     TRUE if successful, FALSE otherwise
//
//
//  FEATURES:
//     * Re-trying under some error conditions, sleeping a random
//       time defined by an exponential probability distribution.
//
//     * Displays various error messages on the log for debugging.
//
//  ORIGINAL AUTHOR AND DATE:
//     Matt Kennel, 2010
//
//=============================================================================
bool O_R_CheckForHistory(int ticket)
{
   //My thanks to Matt for this code. He also has the undying gratitude of all users of my trading robots
   
   int lastTicket = OrderTicket();

   int cnt = 0;
   int err = GetLastError(); // so we clear the global variable.
   err = 0;
   bool exit_loop = false;
   bool success=false;

   while (!exit_loop) {
      /* loop through open trades */
      int total=OrdersTotal();
      for(int c = 0; c < total; c++) {
         if(OrderSelect(c,SELECT_BY_POS,MODE_TRADES) == true) {
            if (OrderTicket() == ticket) {
               success = true;
               exit_loop = true;
            }
         }
      }
      if (cnt > 3) {
         /* look through history too, as order may have opened and closed immediately */
         total=OrdersHistoryTotal();
         for(c = 0; c < total; c++) {
            if(OrderSelect(c,SELECT_BY_POS,MODE_HISTORY) == true) {
               if (OrderTicket() == ticket) {
                  success = true;
                  exit_loop = true;
               }
            }
         }
      }

      cnt = cnt+1;
      if (cnt > O_R_Setting_max_retries) {
         exit_loop = true;
      }
      if (!(success || exit_loop)) {
         Print("Did not find #"+ticket+" in history, sleeping, then doing retry #"+cnt);
         O_R_Sleep(O_R_Setting_sleep_time, O_R_Setting_sleep_max);
      }
   }
   // Select back the prior ticket num in case caller was using it.
   if (lastTicket >= 0) {
      OrderSelect(lastTicket, SELECT_BY_TICKET, MODE_TRADES);
   }
   if (!success) {
      Print("Never found #"+ticket+" in history! crap!");
   }
   return(success);
}//End bool O_R_CheckForHistory(int ticket)

//=============================================================================
//                              O_R_Sleep()
//
//  This sleeps a random amount of time defined by an exponential
//  probability distribution. The mean time, in Seconds is given
//  in 'mean_time'.
//  This returns immediately if we are backtesting
//  and does not sleep.
//
//=============================================================================
void O_R_Sleep(double mean_time, double max_time)
{
   if (IsTesting()) {
      return;   // return immediately if backtesting.
   }

   double p = (MathRand()+1) / 32768.0;
   double t = -MathLog(p)*mean_time;
   t = MathMin(t,max_time);
   int ms = t*1000;
   if (ms < 10) {
      ms=10;
   }
   Sleep(ms);
}//End void O_R_Sleep(double mean_time, double max_time)

void CountOpenTrades()
{
  
   BuyOpen = false;
   SellOpen = false;   
   OpenTrades = 0;
   BasketUpl = 0;
   OpenLots = 0;
   ArrayInitialize(TradeTicketNo, -1);
   BuyPending = false;
   SellPending = false;
   double target;
   LargestLot = 0;
   FilledBuys = 0;
   FilledSells = 0;
   HedgingInProgress = false;
   
   if (OrdersTotal() == 0) return;

  
   
      
   int ot = OrdersTotal() - 1;
   
   for (int cc = 0; cc <= ot; cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      
      if (OrderSymbol() == Symbol())
      {
         BasketUpl+= (OrderProfit() + OrderSwap() + OrderCommission());
      
         if (OrderType() == OP_BUYLIMIT) BuyPending = true;
         if (OrderType() == OP_SELLLIMIT) SellPending = true;
         if (OrderType() == OP_BUY) {OpenLots+= OrderLots(); FilledBuys++; BuyOpen = true;}
         if (OrderType() == OP_SELL) {OpenLots+= OrderLots(); FilledSells++; SellOpen = true;}
         //Set up ticket numbers
         if (OrderLots() == Lot1) TradeTicketNo[1] = OrderTicket();
         if (OrderLots() == Lot2) TradeTicketNo[2] = OrderTicket();
         if (OrderLots() == Lot3) TradeTicketNo[3] = OrderTicket();            
         if (OrderLots() == Lot4) TradeTicketNo[4] = OrderTicket();            
         
         if (OrderLots() > LargestLot) LargestLot = OrderLots();    
         OpenTrades++;
      }//if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      
   
   }//for (int cc = OrdersTotal() - 1; cc <= 0; cc--)
   
   if (BuyOpen && SellOpen) HedgingInProgress = true;
   
 
}//End void CountOpenTrades()


void CloseAllTrades()
{
   ForceTradeClosure = false;
   
   if (OrdersTotal() == 0) return;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderType() != OP_BUY && OrderType() != OP_SELL) continue;
      if (OrderSymbol() == Symbol() )
      {
         while(IsTradeContextBusy()) Sleep(100);
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 1000, Blue);
         if (result) cc++;
         if (!result) ForceTradeClosure = true;
      }//if (OrderSymbol() == Symbol() )
   
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)


}//End void CloseAllTrades()

///////////////////////////////////////////////////////////////////////////////////////////////////////
//Balance/swap filters module
void TradeDirectionBySwap()
{

   //Sets TradeLong & TradeShort according to the positive/negative swap it attracts

   double LongSwap = MarketInfo(Symbol(), MODE_SWAPLONG);
   double ShortSwap = MarketInfo(Symbol(), MODE_SWAPSHORT);
   

   if (CadPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" || StringSubstr(Symbol(), 3, 3) == "CAD" || StringSubstr(Symbol(), 3, 3) == "cad" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" )      
   }//if (CadPairsPositiveOnly)
   
   if (AudPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
   }//if (AudPairsPositiveOnly)
   
   
   if (NzdPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "NZD" || StringSubstr(Symbol(), 0, 3) == "nzd" || StringSubstr(Symbol(), 3, 3) == "NZD" || StringSubstr(Symbol(), 3, 3) == "nzd" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
   }//if (AudPairsPositiveOnly)
   
   

}//void TradeDirectionBySwap()

bool IsThisPairTradable()
{
   //Checks to see if either of the currencies in the pair is already being traded twice.
   //If not, then return true to show that the pair can be traded, else return false
   
   string c1 = StringSubstr(Symbol(), 0, 3);//First currency in the pair
   string c2 = StringSubstr(Symbol(), 3, 3);//Second currency in the pair
   int c1open = 0, c2open = 0;
   //CanTradeThisPair = true;
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      /////////////////////////////////////////////////////////////////////////////////////////////////
      //if (OrderSymbol() != Symbol() ) continue;
      //The previous like looks like a logic error,as it means the code will not check the trade unless it
      //has the same symbol as the calling chart. If the trade has the same symbol as the calling chart, then
      //the check is not needed.
      /////////////////////////////////////////////////////////////////////////////////////////////////
      
      int index = StringFind(OrderSymbol(), c1);
      if (index > -1)
      {
         c1open++;         
      }//if (index > -1)
   
      index = StringFind(OrderSymbol(), c2);
      if (index > -1)
      {
         c2open++;         
      }//if (index > -1)
   
      if (c1open == 1 && c2open == 1) 
      {
         //CanTradeThisPair = false;
         return(false);   
      }//if (c1open == 1 && c2open == 1) 
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so ok to trade
   return(true);
   
}//End bool IsThisPairTradable()

bool BalancedPair(int type)
{

   //Only allow an individual currency to trade if it is a balanced trade
   //e.g. UJ Buy open, so only allow Sell xxxJPY.
   //The passed parameter is the proposed trade, so an existing one must balance that

   //This code courtesy of Zeljko (zkucera) who has my grateful appreciation.
   string BuyCcy1, SellCcy1, BuyCcy2, SellCcy2;

   if (type == OP_BUY)
   {
      BuyCcy1 = StringSubstr(Symbol(), 0, 3);
      SellCcy1 = StringSubstr(Symbol(), 3, 3);
   }//if (type == OP_BUY || type == OP_BUYSTOP)
   else
   {
      if (type == OP_SELL)
      {
         BuyCcy1 = StringSubstr(Symbol(), 3, 3);
         SellCcy1 = StringSubstr(Symbol(), 0, 3);
      }//if (type == OP_SELL)
   }//else   


   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS)) continue;
      if (OrderSymbol() == Symbol()) continue;
      if (OrderMagicNumber() != MagicNumber) continue;      

      if (OrderType() == OP_BUY)
      {
         BuyCcy2 = StringSubstr(OrderSymbol(), 0, 3);
         SellCcy2 = StringSubstr(OrderSymbol(), 3, 3);
      }//if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP)
      else
      {
         if (OrderType() == OP_SELL)
         {
            BuyCcy2 = StringSubstr(OrderSymbol(), 3, 3);
            SellCcy2 = StringSubstr(OrderSymbol(), 0, 3);
         }//if (OrderType() == OP_SELL)
      }//else
      if (BuyCcy1 == BuyCcy2 || SellCcy1 == SellCcy2) return(false);
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so it is ok to send the trade
   return(true);

}//End bool BalancedPair(int type)



//End Balance/swap filters module
///////////////////////////////////////////////////////////////////////////////////////////////////////

bool ShouldWinningPositionClose()
{
   //Returns true if position should close, else returns false

   double target;
   RefreshRates();
   
   
   
   //Long trades. Closing at Bid captures the spread - result of research by Droland. Cheers Dave
   if (Band == 4)
   {
      if (OrderSelect(TradeTicketNo[1], SELECT_BY_TICKET) > -1 && OrderType() == OP_BUY && OrderProfit() > 0)
      {
         target = ObjectGet("mml4.5", OBJPROP_PRICE1);
         if (Bid >= target) return(true);
      }//if (!DoesTradeExist(Lot1) )      
   }//if (Band == 4)
   

   if (Band == 3)
   {
      if (OrderSelect(TradeTicketNo[2], SELECT_BY_TICKET) > -1 && OrderType() == OP_BUY && OrderProfit() > 0)
      {
         target = ObjectGet("mml3.5", OBJPROP_PRICE1);
         if (Bid >= target) return(true);
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 3)
   
   if (Band == 2)
   {
      if (OrderSelect(TradeTicketNo[3], SELECT_BY_TICKET) > -1 && OrderType() == OP_BUY && OrderProfit() > 0)
      {
         target = ObjectGet("mml2.5", OBJPROP_PRICE1);
         if (Bid >= target) return(true);
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 2)
   
   if (Band == 1)
   {
      if (OrderSelect(TradeTicketNo[4], SELECT_BY_TICKET) > -1 && OrderType() == OP_BUY && OrderProfit() > 0)
      {
         target = ObjectGet("mml1.5", OBJPROP_PRICE1);
         if (Bid >= target) return(true);
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 1)
   

   //Short trades Closing at Ask captures the spread - result of research by Droland. Cheers Dave
   if (Band == 9)
   {
      if (OrderSelect(TradeTicketNo[1], SELECT_BY_TICKET) > -1 && OrderType() == OP_SELL && OrderProfit() > 0)
      {
         target = ObjectGet("mml9.5", OBJPROP_PRICE1);
         if (Ask <= target) return(true);
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 9)
   
   if (Band == 10)
   {
      if (OrderSelect(TradeTicketNo[2], SELECT_BY_TICKET) > -1 && OrderType() == OP_SELL && OrderProfit() > 0)
      {
         target = ObjectGet("mml10.5", OBJPROP_PRICE1);
         if (Ask <= target) return(true);
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 10)
   
   if (Band == 11)
   {
      if (OrderSelect(TradeTicketNo[3], SELECT_BY_TICKET) > -1 && OrderType() == OP_SELL && OrderProfit() > 0)
      {
         target = ObjectGet("mml11.5", OBJPROP_PRICE1);
         if (Ask <= target) return(true);
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 11)

   if (Band == 12)
   {
      if (OrderSelect(TradeTicketNo[4], SELECT_BY_TICKET) > -1 && OrderType() == OP_SELL && OrderProfit() > 0)
      {
         target = ObjectGet("mml12.5", OBJPROP_PRICE1);
         if (Ask <= target) return(true);
      }//if (!DoesTradeExist(Lot1) )
   }//if (Band == 12)

  if (Band > 4 && Band < 9 && BasketUpl > 0) return(true);
   

   //Got this far, so position should remain open
   return(false);

}//End bool ShouldWinningPositionClose()

bool HasMarketPassedExtreme()
{
   //Returns true if the basket has hit the outermost Death line.
   //Only called if CloseLosingBasket/UseHedging is chosen by the user
   
   double target = ObjectGet(upperhedgeline, OBJPROP_PRICE1);

   RefreshRates();
   if (Bid > target) return(true);
   target = ObjectGet(lowerhedgeline, OBJPROP_PRICE1);
   if (Bid < target) return(true);
   
   return(false);
   
}//bool HasMarketPassedExtreme()

void HedgePosition()
{
   //Called if a position needs hedging.
   
   double SendLots = OpenLots * HedgeLotMultiplier;
   int type;
   double price;
   RefreshRates();
   if (BuyOpen) 
   {
      type = OP_SELL;
      price = Bid;
   }//if (BuyOpen) 
   
   if (SellOpen) 
   {
      type = OP_BUY;
      price = Ask;
   }//if (SellOpen) 
   
   
   bool result = SendSingleTrade(type, TradeComment, SendLots, price, 0, 0);
   if (result) HedgingInProgress = true;

}//End void HedgePosition()

void LookForFailedHedging()
{
   //Close an open hedge trade if the market has moved back inside the yellow lines
   
   double high = ObjectGet("mml12", OBJPROP_PRICE1);
   double low = ObjectGet("mml0", OBJPROP_PRICE1);
   
   int cc;
   if (Bid < high && Bid > low)
   {
      //Hedge easily recognised as a sell trade. There will be more filled buys than sells.
      if (FilledBuys > FilledSells)
      {
         for (cc = OrdersTotal() - 1; cc >= 0; cc--)
         {
            if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
            if (OrderMagicNumber() != OrderMagicNumber() ) continue;
            if (OrderSymbol() != Symbol() ) continue;
            if (OrderType() == OP_SELL) 
            {
               while (IsTradeContextBusy() ) Sleep(100);
               bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10000, Blue);
               if (!result) Alert("Order close fail");
               return;
            }//if (OrderType() == OP_SELL) 
            
         }//for (cc = OrdersTotal() - 1; cc >= 0; cc--)         
      }//if (FilledBuys > FilledSells)
      
      //Hedge easily recognised as a buy trade. There will be more filled sells than buys.
      if (FilledBuys < FilledSells)
      {
         for (cc = OrdersTotal() - 1; cc >= 0; cc--)
         {
            if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
            if (OrderMagicNumber() != OrderMagicNumber() ) continue;
            if (OrderSymbol() != Symbol() ) continue;
            if (OrderType() == OP_BUY) 
            {
               while (IsTradeContextBusy() ) Sleep(100);
               result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10000, Blue);
               if (!result) Alert("Order close fail");
               return;
            }//if (OrderType() == OP_SELL) 
            
         }//for (cc = OrdersTotal() - 1; cc >= 0; cc--)         
      }//if (FilledBuys > FilledSells)
      
   
   }//if (Bid < high && Bid > low)
   

}//void LookForFailedHedging()



void LookForPendingDeletion()
{
   //Unfilled pandings can need deleting for a variety of reasons
   
   bool Delete = false;
   
   if (Band > 4 && Band < 9 && (BuyPending || SellPending) )
   {
      Delete = true;
   }//if (Band > 4 && Band < 9 && (PendingBuy || PendingSell)
   
   //Balanced pairs
   if (UseZeljko)
   {
      if (BuyPending && !BalancedPair(OP_BUY) ) Delete = true;
      if (SellPending && !BalancedPair(OP_SELL) ) Delete = true;   
   }//if (UseZeljko)
   
   //Only trade a currency twice
   if (OnlyTradeCurrencyTwice && OpenTrades == 0)
   {
      if (!IsThisPairTradable() ) Delete = true;      
   }//if (OnlyTradeCurrencyTwice)

   
   if (Delete) DeletePendingTrades();

}//End void LookForPendingDeletion()


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{

   CountOpenTrades();
   if (OpenTrades == 0)
   {
      ForceTradeClosure = false;
      ForcePendingTradeDeletion = false;
      HedgingInProgress = false;
   }//if (OpenTrades == 0)

   //Deal with a trade closure failnre
   if (ForceTradeClosure)
   {
      CloseAllTrades();
      return;
   }//if (ForceTradeClosure)
   
   if (ForcePendingTradeDeletion)
   {
      DeletePendingTrades();
      return;
   }//if (ForcePendingTradeDeletion)
   
      
   DrawLines();//Also set up mml[] array values
   
   GetCurrentMMlPosition();
 
   /////////////////////////////////////////////////////////////////////////////////////////////////////////      
   //Position closure 
   if (OpenTrades > 0 && BasketUpl > 0)
   {
      double TPValue = 0;
      if (TakeProfitBasket) 
      {
         if (TakeProfitPercentage != 0 && TakeProfitDollar != 0) Alert("Both TakeProfitPercentage and TakeProfitDollar are set, I do not think you meant to do that??!!");
         if (TakeProfitPercentage == 0 && TakeProfitDollar == 0) Alert("TakeProfitBasket is true, but both TakeProfitPercentage and TakeProfitDollar are NOT set! One of these parameters needs to be greater than zero!");
         if (TakeProfitDollar > 0 ) TPValue=TakeProfitDollar;
         if (TakeProfitPercentage > 0) TPValue = AccountBalance()*(TakeProfitPercentage/100);    
      } // if (TakeProfiBasket)
      
      if (ShouldWinningPositionClose() || (TakeProfitBasket && BasketUpl >= TPValue) )
      {
         CloseAllTrades();
         return;
      }//if (ShouldWinningPositionClose() )      
   }//if (OPenTrades > 0 && OPenTrades < 4)
  
   if (OpenTrades > 0 && CloseLosingBasket)
   {
      if (HasMarketPassedExtreme() )
      {
         CloseAllTrades();
         return;
      }//if (HasMarketPassedExtreme() )   
   }//if (OpenTrades > 0 && CloseLosingBasket)
   
   
   //Successful hedging
   if (HedgingInProgress && BasketUpl > 0) 
   {
      CloseAllTrades();
      return;
   }//if (HedgingInProgress && BasketUpl > 0)
  
   //Failed hedging
   if (HedgingInProgress && BasketUpl < 0 && CloseHedgeOnReturnToGrid)
   {
      LookForFailedHedging();
   }//if (HedgingInProgres && BasketUpl < 0)
   
   
   //Delete pending trades for a variety of reasons
   if (DeleteUnwantedPendings) LookForPendingDeletion();
   
   
  /////////////////////////////////////////////////////////////////////////////////////////////////////////      
  //Hedge losing trades once the market passes the extremes
   if (OpenTrades > 0 && UseHedging && !HedgingInProgress && BasketUpl < 0)
   {
      if (HasMarketPassedExtreme() )
      {
         HedgePosition();
      }//if (HasMarketPassedExtreme() )   
   }//if (OpenTrades > 0 && UseHedging && !HedgingInProgress && BasketUpl < 0)
  
  /////////////////////////////////////////////////////////////////////////////////////////////////////////      
   
   //Available margin filters
   if (UseScoobsMarginCheck && OpenTrades > 0)
   {
      if(AccountMargin() > (AccountFreeMargin()/100)) 
      {
         Comment("                                     There is insufficient margin to allow trading. You might want to turn off the UseScoobsMarginCheck input.");
         return;
      }//if(AccountMargin() > (AccountFreeMargin()/100)) 
      
   }//if (UseScoobsMarginCheck)


   if (UseForexKiwi && AccountMargin() > 0)
   {
      
      double ml = NormalizeDouble(AccountEquity() / AccountMargin() * 100, 2);
      if (ml < FkMinimumMarginPercent)
      {
         Comment("                                     There is insufficient margin percent to allow trading. " + DoubleToStr(ml, 2) + "%");
         return;
      }//if (ml < FkMinimumMarginPercent)
      
   }//if (UseForexKiwi && AccountMargin() > 0)

   //Swap filter
   TradeDirectionBySwap();
   /////////////////////////////////////////////////////////////////////////////////////////////////////////      
   
   LookForTradingOpportunities();
   
   /////////////////////////////////////////////////////////////////////////////////////////////////////////      
   
   string gap = "                                ";
   string ScreenMessage;
   
   ScreenMessage = StringConcatenate(gap, TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), NL,
                                     gap, "Band high: ", DoubleToStr(BandHigh, Digits), NL,
                                     gap, "Band low: ", DoubleToStr(BandLow, Digits), NL,
                                     gap, "Band no: ", Band, NL);
   


   Comment(ScreenMessage);

}
//+------------------------------------------------------------------+