//+-------------------------------------------------------------------+
//|                        Simple Beast! trading robot by Ribelo.mq4  |
//|                         Copyright © 2009, Steve Hopwood - Ribelo  |
//|                              http://www.hopwood3.freeserve.co.uk  |
//+-------------------------------------------------------------------+
#property copyright "Copyright © 2009, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"
#define  up "Up"
#define  down "Down"
#define  none "None"
#define  both "Both"
#define  buy "Buy_"
#define  sell "Sell_"
#define  ranging "Ranging"
#define  confused "Confused, and so cannot trade"
#define  trending "Trending"
#define  opentrade "There is a trade open"
#define  stopped "Trading is stopped"
#define  ct "Counter Trend"
#define  wb "White Box"
#define  GoLong "GoLong"
#define  GoShort "GoShort"

#define  _ "_"

//George's average tick lines
#define  AverageTick "Average Tick"
#define  AverageTickDn "Average Tick Down"
#define  AverageTickUp "Average Tick Up"


extern string  gen = "----General inputs----";
extern double  lot = 0.10;
extern double  money.per.micro.lot = 10000;
extern bool    stop.trading = false;
extern bool    trade.long = true;
extern bool    trade.short = true;
extern int     magic.number = 0;
extern string  trade.comment = "";
extern bool    criminal.is.ecn = false;
extern double  max.spread = 120;
extern int     max.open.pairs.allowed = 1;

int            no.of.pairs.trading;//Keeps a tally of the number of pairs with open trades

extern string  tts = "----Trade style choices----";
extern string  wbts = "White box trading style";
extern bool    do.white.box = true;
extern bool    use.orginal.method = false;
extern bool    auto.calculate.method = true;

extern string  acc = "----Trade closure----";
extern string  ctt = "Magenta line closure style";
extern bool    break.even.trade.at.gold = false;
extern bool    close.trade.at.gold = false;
extern bool    close.trade.at.green = false;
extern bool    close.trade.at.middle.white = false;
extern string  wbcs = "White box closure style";
extern bool    close.box.trade.at.magenta = false;
extern bool    close.box.trade.at.gold = false;
bool    trail.box.trade.at.magenta = false;
extern bool    trail.box.trade.at.gold = false;
extern string  acc1 = "AutoCalc over rides the above";
extern bool    auto.calc.trade.closure.line = true;

bool           inside.white.box;

//extern string  bc = "----bar.count----";
int     bar.count = 0;
//string  CCIHelp = "Hourly Period for CCI MA";
int     cci.period = 120;
int     ind.period = 0;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//CCI for dynamic bar.count
int            cur.bars, ind.timeframe;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  bf = "----Trading balance filters----";
extern bool    use.zeljko = true;
extern bool    only.trade.currenty.twice = true;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  rsiin = "----Rsi inputs----";
extern int     rsi.tf = 1440;
extern int     rsi.period = 20;
extern string  rsap = "Applied price: 0=Close; 1=Open; 2=High";
extern string  rsap1 = "3=Low; 4=Median; 5=Typical; 6=Weighted";
extern int     rsi.appiled.price = 0;
extern double  max.rsi.volatilty = 10;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double         rsi.val, rsi.val.prev, rsi.volatilty, rsi.factor;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


extern string  amc = "----Available Margin checks----";
extern string  sco = "Scoobs";
extern bool    use.scoobs.margin.check = false;
extern string  fk = "ForexKiwi";
extern bool    use.forex.kiwi = true;
extern int     fk.minimum.margin.procent = 700;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool           enough.margin;
string         margin.message;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  rec = "----Recovery----";
extern bool    use.recovery = true;
extern int     start.recovery.at.trades = 2; //DC
extern bool    use.1.1.3.3.recovery = false;
extern bool    use.1.1.2.4.recovery = false;
extern bool    use.1.2.6.recovery = true; //Pippo's idea
color   re.entry.line.colour = Turquoise;
color   break.even.line.colour = Blue;
extern int     recovery.break.even.profit.pips = 10;
extern string  rts = "Recovery trailing stop";
extern bool    use.recovery.trailing.stop = true;
extern int     recovery.trailing.stop.at = 30;
extern bool    candle.stick.trailing.stop = true;
extern int     rec.cst.time.frame = 240;
extern int     rec.cst.trail.candles = 1;
extern bool    jumping.trailing.stop = false;
extern int     rec.jump.stop.pips = 30;
extern bool    auto.calc.rec.var = true;
extern bool    automate.rts.choice = false;
color   recovery.stop.loss.line.colour = Red;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define  breakevenlinename "Break even line"
#define  reentrylinename "Re entry line"
//From iExposure for Recovery BE calcs
#define        SYMBOLS_MAX 1024
#define        DEALS          0
#define        BUY_LOTS       1
#define        BUY_PRICE      2
#define        SELL_LOTS      3
#define        SELL_PRICE     4
#define        NET_LOTS       5
#define        PROFIT         6
int            NoOfLevels;
string         RecoveryLevel[];//Holds the individual Recovery levels as strings - remember to convert to integer when using them
int            OldRecoverTrailBars;
bool           RecoveryInProgress, TpMoved;
int            RecoveryLockProfitsAt = 50;
int            RecoveryLockInPips = 10;
string         ExtSymbols[SYMBOLS_MAX];
int            ExtSymbolsTotal = 0;
double         ExtSymbolsSummaries[SYMBOLS_MAX][7];
int            ExtLines = -1;
string         ExtCols[8] = {"Symbol",
                             "Deals",
                             "Buy lots",
                             "Buy price",
                             "Sell lots",
                             "Sell price",
                             "Net lots",
                             "Profit"
                            };
int            ExtShifts[8] = { 10, 80, 130, 180, 260, 310, 390, 460 };
int            ExtVertShift = 14;
double         buy_price = 0.0;
double         sell_price = 0.0;
int            OldCountOpenTrades;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  cbi = "----Central Bank Intervention module----";
extern bool    use.cbi = false; //Saves altering all the existing code conditionals.
extern string  am = "Astral method"; //Tick table method
extern bool    use.astral = true; //No particular reason for the default
extern int     table.size = 20; //No of ticks to store in the table. Indexed 0 - 19
extern string  gm = "George method"; //Moving average of ticks
extern bool    use.george = false; //No particular reason for the default
extern int     nr.ticks.average = 40;           //number of ticks to average
extern int     channel.delta = 10; //delta above and below the average to draw lines
extern color   line.color = Yellow; //line color
extern string  ctb = "Common to both";
extern int     threshold = 30; //Distance in pips between the market and the norm that indicates something big happening
extern bool    close.on.cbi = false; //Close open trades
extern bool    hedge.on.cbi = true; //Hedge open trades
extern double  cbi.hedge.lot.multiplier = 4; //Multiplies the individual trade's lot size
extern double  hedge.break.even.profit = 20;
extern bool    trade.on.cbi = true; //Send a new trade
extern int     trade.on.cbi.tp = 0; //Take profit
extern int     trade.on.cbi.sl = 50; //Stoploss
extern int     broker.start.hour = 22;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double         TickTable[20]; // circular buffer to hold the ticks
int            tc = -1; // Tick counter. current position in table
int            is_filled = 0; // is the table full yet?
int            fill_check_counter = 0; // check if we have looped through the table once
double         PipMultiplier = 1.0; // needed to convert a price differenct into a pip value
double         TickDiff;//Difference between current quote and table.size quotes ago
//Some Booleans to tell the bot what it has already done
bool           TakingEmergencyAction;//Will be true if TickDiff crosses the threshold
bool           TradeSent, HedgeSent, TradesClosed;
bool           HedgingInProgress;//So the bot knows it is dealing with a hedged situation
string         direction;//Holds the up/down comparison of the 1st and last ticks in the table

//George filter
int            number_of_ticks = 0;
double         sum_of_ticks = 0;
double         moving_average = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  tt = "----Trading hours----";
extern string  Trade_Hours = "Set Morning & Evening Hours";
extern string  Trade_Hoursi = "Use 24 hour, local time clock";
extern string  Trade_Hours_M = "Morning Hours 0-12";
extern  int    start.hourm = 0;
extern  int    end.hourm = 12;
extern string  Trade_Hours_E = "Evening Hours 12-24";
extern  int    start.houre = 12;
extern  int    end.houre = 24;
extern string  spt = "----Specific time inputs----";
extern double  start.time = 22.15;

extern string  pts = "----Swap filter----";
extern bool    cad.pairs.positive.only = true;
extern bool    aud.pairs.positive.only = true;
extern bool    nzd.pairs.positive.only = true;

extern string  mis = "----Odds and ends----";
extern bool    show.management.alerts = true;
extern int     display.gap.size = 30;


//6ths variable.
double         SixthsRange, old.sixths.range;
double         BottomGoldLine;//Bottom, gold line
double         BottomGreenLine;//Bottom, green line
double         MiddleWhiteLine;//Middle, white line
double         TopGreenLine;//Top, green line
double         TopGoldLine;//Top, gold line
double         TopLine, BottomLine;
double         HalfTopLine, HalfBottomLine;
double         WhiteBoxHigh, WhiteBoxLow, WhiteBoxHighTrigger, WhiteBoxLowTrigger;//For hedge trade entry
double         MagentaCtBufferHigh, MagentaCtBufferLow;

//Matt's O-R stuff
int            O_R_Setting_max_retries    = 10;
double         O_R_Setting_sleep_time     = 4.0; /* seconds */
double         O_R_Setting_sleep_max      = 15.0; /* seconds */

//Trading variables
string         Beast, symbol, first.currency, second.currency, buy.first.curr, sell.first.curr, buy.sec.curr, sell.sec.curr;
int            ticket.no, total.trades[], open.trades, TotalBuyTrades, TotalSellTrades;
bool           CanTradeThisPair;//Will be false when this pair fails the currency can only trade twice filter, or the balanced trade filter
int            RetryCount = 10;//Will make this number of attempts to get around the trade context busy error.
bool           BuyOpen, SellOpen, BoxBuyOpen, BoxSellOpen, MagentaBuyOpen, MagentaSellOpen;
int            BoxBuyTicketNumber, BoxSellTicketNumber, MagentaBuyTicketNumber, MagentaSellTicketNumber;
string         BoxBuyTicketGv, BoxSellTicketGv, MagentaBuyTicketGv, MagentaSellTicketGv, TradeStyle, SendLotsGv;
double         calculated.lot, total.lots.open, basket.profit;


//Date/Time
datetime       ConvertedStartTime;




//Misc
string         Gap, ScreenMessage;
int            OldBars;
string         PipDescription = " pips";
bool           ForceTradeClosure;
bool           TriggerLong, TriggerShort;
int            OnePip = 1;

void DisplayUserFeedback() {
   if ( IsTesting() && !IsVisualMode() ) {
      return;
   }
   ScreenMessage = "";
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Simple Beast!", NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, TimeToStr ( TimeLocal(), TIME_DATE | TIME_MINUTES | TIME_SECONDS ), NL );
   //Code for time to bar-end display from Candle Time by Nick Bilak
   double i;
   int m, s, k;
   m = Time[0] + Period() * 60 - CurTime();
   i = m / 60.0;
   s = m % 60;
   m = ( m - m % 60 ) / 60;
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, m + " minutes " + s + " seconds left to bar end", NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
   if ( trade.long ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Taking long trades", NL );
   }
   if ( trade.short ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Taking short trades", NL );
   }
   if ( !trade.long && !trade.short ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Both trade.long and trade.short are set to false", NL );
   }
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "lot size: ", GlobalVariableGet(SendLotsGv), " (Criminal's minimum lot size: ", MarketInfo ( symbol, MODE_MINLOT ), ")", NL );
   if ( auto.calc.trade.closure.line ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "auto.calc.trade.closure.line",  NL );
      if ( close.trade.at.gold ) {
         ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "close.trade.at.gold",  NL );
      }
      if ( close.trade.at.green ) {
         ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "close.trade.at.green",  NL );
      }
      if ( close.trade.at.middle.white ) {
         ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "close.trade.at.middle.white",  NL );
      }
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
   }
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Magic number: ", magic.number, NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Trade comment: ", trade.comment, NL );
   if ( criminal.is.ecn ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "criminal.is.ecn = true", NL );
   } else {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "criminal.is.ecn = false", NL );
   }
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "max.spread = ", max.spread, ": Spread = ", MarketInfo ( symbol, MODE_SPREAD ), NL, NL );
   if ( no.of.pairs.trading >= max.open.pairs.allowed ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Trading only allowed for Recovery and Hedging, if enabled. Pairs trading: ", no.of.pairs.trading, NL, NL );
   } else {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Pairs trading: ", no.of.pairs.trading, NL );
   }
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "bar.count = ", bar.count, NL );
   //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Sixth: ", sixth/Point, PipDescription,  NL);
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Recovery starts at ", start.recovery.at.trades, " filled trades", NL );
   if ( RecoveryInProgress ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Recovery is in progress", NL );
   }
   //Adapt volatility display to x digit crims
   if ( Digits == 2 || Digits == 4 ) {
      m = 1;
   }
   if ( Digits == 3 || Digits == 5 ) {
      m = 10;
   }
   if ( Digits == 6 ) {
      m = 100;
   }
   if ( Digits == 7 ) {
      m = 1000;
   }
   //ScreenMessage = StringConcatenate(ScreenMessage, Gap, "volatility = ", volatility * m, ":  ReEntryLinePips = ", CalculateReEntryLinePips(), NL);
   if ( use.recovery.trailing.stop ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Using Recovery trailing stop. recovery.trailing.stop.at = ", recovery.trailing.stop.at, NL );
   }
   if ( stop.trading ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Trading suspended", NL );
   }
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Trading the white box", NL );
   if ( use.orginal.method ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Using the Original method", NL );
   }
   if ( auto.calculate.method ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Auto Calculate Method", NL );
   }
   if ( close.box.trade.at.magenta ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Close trades at Magenta", NL );
   }
   if ( close.box.trade.at.gold ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Close trades at Gold", NL );
   }
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Trading hours", NL );
   if ( start.hourm == 0 && end.hourm == 12 && start.houre && end.houre == 24 ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "            24H trading", NL );
   } else {
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "            start.hourm: ", DoubleToStr ( start.hourm, 2 ),
                                          ": end.hourm: ", DoubleToStr ( end.hourm, 2 ), NL );
      ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "            start.houre: ", DoubleToStr ( start.houre, 2 ),
                                          ": end.houre: ", DoubleToStr ( end.houre, 2 ), NL );
   }//else
   if ( start.time > 0 ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, NL, Gap, "Start time: ", TimeToStr ( ConvertedStartTime, TIME_MINUTES ), NL );
   }//if (start.time > 0)
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, "Rsi: ", rsi.val, "rsi.val.prev ", rsi.val.prev, " rsi.volatilty: ", rsi.volatilty, " rsi.factor: ", rsi.factor, NL );
   ScreenMessage = StringConcatenate ( ScreenMessage, Gap, NL );
   if ( margin.message != "" ) {
      ScreenMessage = StringConcatenate ( ScreenMessage, NL, Gap, margin.message, NL );
   }
   Comment ( ScreenMessage );
}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init() {
//----
   //Adapt to x digit criminals
   int 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;
   }
   if ( multiplier > 1 ) {
      PipDescription = " points";
   }
   trade.on.cbi.tp *= multiplier;
   trade.on.cbi.sl *= multiplier;
   recovery.break.even.profit.pips *= multiplier;
   recovery.trailing.stop.at *= multiplier;
   RecoveryLockProfitsAt *= multiplier;
   RecoveryLockInPips *= multiplier;

   OnePip *= multiplier;
   OnePip *= Point;
   if ( ind.period > 0 ) {
      ind.timeframe = ind.period;
   } else {
      ind.timeframe = Period();
   }
   Gap = "";
   if ( display.gap.size > 0 ) {
      for ( int cc = 0; cc < display.gap.size; cc++ ) {
         Gap = StringConcatenate ( Gap, " " );
      }
   }//if (display.gap.size >0)
   //Reset CriminIsECN if crim is IBFX and the punter does not know or, like me, keeps on forgetting
   string name = TerminalCompany();
   int ispart = StringFind ( name, "IBFX", 0 );
   if ( ispart < 0 ) {
      ispart = StringFind ( name, "Interbank FX", 0 );
   }
   if ( ispart > -1 ) {
      criminal.is.ecn = true;
   }
   if ( bar.count == 0 ) {
      GetBarCount();
   }//if (bar.count == 0)
   if ( trade.comment == "" ) {
      trade.comment = " ";
   }
   ConvertedStartTime = hhmm_to_time ( start.time );
   /////////////////////////////////////////////////////////////////////////////////////////////////////////
   //CBI module
   int ret = ArrayResize ( TickTable, table.size );
   if ( ret == -1 ) {
      Alert ( "Error: Could not initialize tick table!\n" );
   }//if (ret == -1)
   if ( Digits == 2 || Digits == 3 ) {
      PipMultiplier = 100.0;
   } else if ( Digits == 4 || Digits == 5 ) {
      PipMultiplier = 10000.0;
   }
   /////////////////////////////////////////////////////////////////////////////////////////////////////////
   SetStringVariables();
   ReadIndicatorValues();
   DisplayUserFeedback();
   //Call sq's show trades indi
   //iCustom(NULL, 0, "SQ_showTrades",Magic, 0,0);
   //Set up Recovery levels
//----
   return ( 0 );
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit() {
//----
   Comment ( "" );
   //Delete the Sixths lines
   ObjectDelete ( "zerosixth" );
   ObjectDelete ( "onesixth" );
   ObjectDelete ( "twosixth" );
   ObjectDelete ( "threesixth" );
   ObjectDelete ( "foursixth" );
   ObjectDelete ( "fivesixth" );
   ObjectDelete ( "sixsixth" );
   ObjectDelete ( "halfbottomsixth" );
   ObjectDelete ( "halftopsixth" );
   ObjectDelete ( "whitehigh" );
   ObjectDelete ( "whitelow" );
   ObjectDelete ( "CT buffer high" );
   ObjectDelete ( "CT buffer low" );
   if ( IsTesting() ) {
      CleanGlobalVariables ( "Testing" );
   }
//----
   return ( 0 );
}

void SetStringVariables() {
   symbol = Symbol();
   first.currency = StringSubstr ( symbol, 0, 3 );
   second.currency = StringSubstr ( symbol, 3, 6 );
   if ( IsTesting() ) {
      Beast = "Testing_";
      CleanGlobalVariables ( "Testing" );
    buy.first.curr = StringConcatenate ( Beast, buy, _, first.currency );
      sell.first.curr = StringConcatenate ( Beast, sell, _, first.currency );
      buy.sec.curr = StringConcatenate ( Beast, buy, _, second.currency );
      sell.sec.curr = StringConcatenate ( Beast, sell, _, second.currency );
   } else {
      Beast = "SimpleBeast_";
      buy.first.curr = StringConcatenate ( buy, _, first.currency );
      sell.first.curr = StringConcatenate (sell, _, first.currency );
      buy.sec.curr = StringConcatenate ( buy, _, second.currency );
      sell.sec.curr = StringConcatenate ( sell, _, second.currency );
   }
   BoxBuyTicketGv = StringConcatenate ( Beast, symbol, " Box buy ticket number" );
   BoxSellTicketGv = StringConcatenate ( Beast, symbol, " Box sell ticket number" );
   if ( GlobalVariableCheck ( BoxBuyTicketGv ) ) {
      BoxBuyTicketNumber = GlobalVariableGet ( BoxBuyTicketGv );
   } else {
      BoxBuyTicketNumber = -1;
   }
   if ( GlobalVariableCheck ( BoxSellTicketGv ) ) {
      BoxSellTicketNumber = GlobalVariableGet ( BoxSellTicketGv );
   } else {
      BoxSellTicketNumber = -1;
   }
   MagentaBuyTicketGv = StringConcatenate ( Beast, symbol, " Magenta buy ticket number" );
   MagentaSellTicketGv = StringConcatenate ( Beast, symbol, " Magenta sell ticket number" );
   if ( GlobalVariableCheck ( MagentaBuyTicketGv ) ) {
      MagentaBuyTicketNumber = GlobalVariableGet ( MagentaBuyTicketGv );
   } else {
      MagentaBuyTicketNumber = -1;
   }
   if ( GlobalVariableCheck ( MagentaSellTicketGv ) ) {
      MagentaSellTicketNumber = GlobalVariableGet ( MagentaSellTicketGv );
   } else {
      MagentaSellTicketNumber = -1;
   }
   SendLotsGv = StringConcatenate ( Beast, symbol, " Calculated lot" );
   if ( GlobalVariableCheck ( SendLotsGv ) ) {
      calculated.lot = GlobalVariableGet ( SendLotsGv );
   }
   CheckOpenCurrency();
}


void BreakEvenAtGold() {
   double Stop = OrderStopLoss();
   double NewStop;
   bool modify = false;
   if ( OrderType() == OP_BUY ) {
      if ( Bid >= BottomGoldLine ) {
         NewStop = OrderOpenPrice() + OnePip;
         if ( NewStop != Stop && isNewBar ( 15 ) ) {
            modify = true;
         }
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= TopGoldLine ) {
         NewStop = OrderOpenPrice() - OnePip;
         if ( NewStop != Stop && isNewBar ( 15 ) ) {
            modify = true;
         }
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( modify ) {
      ModifyOrder ( ticket.no, NewStop, OrderTakeProfit() );
   }//if (modify)
}//void BreakEvenAtGold()

void CloseAtGold() {
   bool result = true;
   if ( OrderType() == OP_BUY ) {
      if ( Ask >= BottomGoldLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Ask >= BottomGoldLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= TopGoldLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Bid <= TopGoldLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_SELL)
   if ( !result ) {
      int err = GetLastError();
      Alert ( "TOB order close at Gold ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
      Print ( "TOB order close at Gold ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
   }//if !result && show.management.alerts)
}//void CloseAtGold()


void CloseAtGreen() {
   bool result = true;
   if ( OrderType() == OP_BUY ) {
      if ( Ask >= BottomGreenLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Ask >= BottomGreenLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= TopGreenLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Bid <= TopGreenLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_SELL)
   if ( !result ) {
      int err = GetLastError();
      Alert ( "TOB order close at Green ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
      Print ( "TOB order close at Green ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
   }//if !result && show.management.alerts)
}//void CloseAtGreen()

void CloseAtMiddle() {
   bool result = true;
   if ( OrderType() == OP_BUY ) {
      if ( Ask >= MiddleWhiteLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= MiddleWhiteLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Bid <= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_SELL)
   if ( !result ) {
      int err = GetLastError();
      Alert ( "TOB order close at Middle White ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
      Print ( "TOB order close at Middle White ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
   }//if !result && show.management.alerts)
}//void CloseAtMiddle()

void CloseBoxAtMagenta() {
   bool result = true;
   if ( OrderType() == OP_BUY ) {
      if ( Ask >= TopLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= BottomLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Bid <= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_SELL)
   if ( !result ) {
      int err = GetLastError();
      Alert ( "TOB order close at HalfMagenta ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
      Print ( "TOB order close at HalfMagenta ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
   }//if !result && show.management.alerts)
}//void CloseBoxAtMagenta()

void CloseBoxAtGold() {
   bool result = true;
   if ( OrderType() == OP_BUY ) {
      if ( Ask >= TopGoldLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= BottomGoldLine ) {
         result = CloseTrade ( ticket.no );
      }//if (Bid <= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_SELL)
   if ( !result ) {
      int err = GetLastError();
      Alert ( "TOB order close at Gold ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
      Print ( "TOB order close at Gold ", OrderSymbol(), " ticket no ", ticket.no, " failed with error (", err, "): ", ErrorDescription ( err ) );
   }//if !result && show.management.alerts)
}//void CloseBoxAtMagenta()

void TrailBoxAtMagenta() {
   double Stop = OrderStopLoss();
   double NewStop;
   bool modify = false;
   bool result = true;
   if ( OrderType() == OP_BUY ) {
      if ( Bid >= MagentaCtBufferHigh ) {
         NewStop = HalfTopLine;
         if ( NewStop != Stop && isNewBar ( 15 ) ) {
            modify = true;
         }
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= MagentaCtBufferLow ) {
         NewStop = HalfBottomLine;
         if ( NewStop != Stop && isNewBar ( 15 ) ) {
            modify = true;
         }
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( modify ) {
      ModifyOrder ( ticket.no, NewStop, OrderTakeProfit() );
   }//if (modify)
}//void TrailBoxAtMagenta()

void TrailBoxAtGold() {
   double Stop = OrderStopLoss();
   double NewStop;
   bool modify = false;
   bool result = true;
   if ( OrderType() == OP_BUY ) {
      if ( Bid >= MagentaCtBufferHigh ) {
         NewStop = TopGoldLine;
         if ( NewStop != Stop && isNewBar ( 15 ) ) {
            modify = true;
         }
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( OrderType() == OP_SELL ) {
      if ( Bid <= MagentaCtBufferLow ) {
         NewStop = BottomGoldLine;
         if ( NewStop != Stop && isNewBar ( 15 ) ) {
            modify = true;
         }
      }//if (Ask >= MiddleWhiteLine && OrderStopLoss() == 0)
   }//if (OrderType() == OP_BUY)
   if ( modify ) {
      ModifyOrder ( ticket.no, NewStop, OrderTakeProfit() );
   }//if (modify)
}//void TrailBoxAtMagenta()

void TradeManagementModule() {
   double profit = OrderProfit() + OrderSwap() + OrderCommission();
   if (profit > 0) {
      if ( MagentaBuyOpen || MagentaSellOpen ) {
         if ( break.even.trade.at.gold && profit > 0 ) {
            BreakEvenAtGold();
         }
         if ( close.trade.at.gold && profit > 0 ) {
            CloseAtGold();
         }
         if ( close.trade.at.green && profit > 0 ) {
            CloseAtGreen();
         }
         if ( close.trade.at.middle.white && profit > 0 ) {
            CloseAtMiddle();
         }
      }
      if ( BoxBuyOpen || BoxSellOpen ) {
         if ( close.box.trade.at.magenta && profit > 0 ) {
            CloseBoxAtMagenta();
         }
         if ( close.box.trade.at.gold && profit > 0 ) {
            CloseBoxAtGold();
         }
         if ( trail.box.trade.at.magenta && profit > 0 ) {
            TrailBoxAtMagenta();
         }
         if ( trail.box.trade.at.gold && profit > 0 ) {
            TrailBoxAtGold();
         }
      }
   }
}//void TradeManagementModule()
//END TRADE MANAGEMENT MODULE
////////////////////////////////////////////////////////////////////////////////////////////////


bool SendSingleTrade ( int type, string comment, double lotsize, double price, double stop, double take ) {
   //pah (Paul) contributed the code to get around the trade context busy error. Many thanks, Paul.
   int slippage = 10;
   if ( Digits == 3 || Digits == 5 ) {
      slippage = 100;
   }
   color col = Red;
   if ( type == OP_BUY || type == OP_BUYSTOP || type == OP_BUYLIMIT ) {
      col = Green;
   }
   int expiry = 0;
   //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60);
   //RetryCount is declared as 10 in the Trading variables section at the top of this file
   for ( int cc = 0; cc < RetryCount; cc++ ) {
      for ( int d = 0; ( d < RetryCount ) && IsTradeContextBusy(); d++ ) {
         Sleep ( 100 );
      }
      RefreshRates();
      if ( type == OP_BUY ) {
         price = NormalizeDouble ( Ask, Digits );
      }
      if ( type == OP_SELL ) {
         price = NormalizeDouble ( Bid, Digits );
      }
      if ( !criminal.is.ecn ) {
         int ticket = OrderSend ( symbol, type, lotsize, price, slippage, stop, take, comment, magic.number, expiry, col );
      }
      //Is a 2 stage criminal
      if ( criminal.is.ecn ) {
         ticket = OrderSend ( symbol, type, lotsize, price, slippage, 0, 0, comment, magic.number, expiry, col );
         if ( ticket > -1 ) {
            ModifyOrder ( ticket, stop, take );
         }//if (ticket > 0)}
      }//if (criminal.is.ecn)
      if ( ticket > -1 ) {
         break;   //Exit the trade send loop
      }
      if ( cc == RetryCount - 1 ) {
         return ( false );
      }
      //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";
         }
         int err = GetLastError();
         Alert ( symbol, " jor ", stype, " order send failed with error(", err, "): ", ErrorDescription ( err ) );
         Print ( symbol, " jor ", stype, " order send failed with error(", err, "): ", ErrorDescription ( err ) );
         return ( false );
      }//if (ticket < 0)
   }//for (int cc = 0; cc < RetryCount; cc++);
   ticket.no = ticket;
   //Make sure the trade has appeared in the platform's history to avoid duplicate trades.
   //My mod of Matt's code attempts to overcome the bastard crim's attempts to overcome Matt's code.
   bool TradeReturnedFromCriminal = false;
   while ( !TradeReturnedFromCriminal ) {
      TradeReturnedFromCriminal = O_R_CheckForHistory ( ticket );
      if ( !TradeReturnedFromCriminal ) {
         Alert ( symbol, " sent trade not in your trade history yet. Turn of this ea NOW." );
      }//if (!TradeReturnedFromCriminal)
   }//while (!TradeReturnedFromCriminal)
   //Got this far, so trade send succeeded
   return ( true );
}//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)

void ModifyOrder ( int ticket, double stop, double take ) {
   //Modifies an order already sent if the crim is ECN.
   if ( OrderSelect ( ticket, SELECT_BY_TICKET ) ) { //Trade does not exist, so no mod needed
      //RetryCount is declared as 10 in the Trading variables section at the top of this file
      if ( OrderTakeProfit() == take && OrderStopLoss() == stop ) {
         return;
      }
      if ( OrderTakeProfit() == take && stop == 0) {
         return;
      }
      if ( take == 0 && OrderStopLoss() == stop ) {
         return;
      }
      if ( take == 0 && stop == 0 ) {
            return;
      }//if (take == 0 && stop != 0)      
      for ( int cc = 0; cc < RetryCount; cc++ ) {
         for ( int d = 0; ( d < RetryCount ) && IsTradeContextBusy(); d++ ) {
            Sleep ( 100 );
         }
         if ( take > 0 && stop > 0 ) {
            while ( IsTradeContextBusy() ) {
               Sleep ( 100 );
            }
            if ( OrderModify ( ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE ) ) {
               return;
            }
         }//if (take > 0 && stop > 0)
         if ( take != 0 && stop == 0 ) {
            while ( IsTradeContextBusy() ) {
               Sleep ( 100 );
            }
            if ( OrderModify ( ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE ) ) {
               return;
            }
         }//if (take == 0 && stop != 0)
         if ( take == 0 && stop != 0 ) {
            while ( IsTradeContextBusy() ) {
               Sleep ( 100 );
            }
            if ( OrderModify ( ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE ) ) {
               return;
            }
         }//if (take == 0 && stop != 0)
      }//for (int cc = 0; cc < RetryCount; cc++)
   }//if (OrderSelect(ticket, SELECT_BY_TICKET) )
   //Got this far, so the order modify failed
   int err = GetLastError();
   Print ( symbol, " SL/TP  order modify failed with error(", err, "): ", ErrorDescription ( err ) );
   Alert ( symbol, " SL/TP  order modify failed with error(", err, "): ", ErrorDescription ( err ) );
}//void ModifyOrder(int ticket, double tp, double sl)

bool IsTradingAllowed ( string style ) {
   //Returns false if any of the filters should cancel trading, else returns true to allow trading
   //Maximum spread
   if ( MarketInfo ( symbol, MODE_SPREAD ) > max.spread ) {
      return ( false );
   }
   //Swap filter
   if ( open.trades == 0 ) {
      TradeDirectionBySwap();
   }
   //An individual currency can only be traded twice, so check for this
   CanTradeThisPair = true;
   if ( only.trade.currenty.twice && open.trades == 0 ) {
      IsThisPairTradable();
   }//if (only.trade.currenty.twice)
   if ( !CanTradeThisPair ) {
      return ( false );
   }
   //Maximum open pairs check
   if ( !PairsNotAtMaximumCheck() && open.trades == 0 ) {
      return ( false );   //Sorry about the confusing double negative guys
   }
   if ( use.recovery ) {
      if ( RecoveryInProgress ) {
         if ( open.trades == 7 ) {
            return ( false ); //No further trading is possible
         }
      }//if (RecoveryInProgress)
      //This idea from Pippo
     if ( use.1.2.6.recovery && open.trades + 1 >= start.recovery.at.trades ) {
         if ( open.trades == start.recovery.at.trades + 4 ) {
            return ( false );
         }
      }//if (use.1.2.6.recovery)
   }//if (use.recovery)
   return ( true );
}//End bool IsTradingAllowed()

bool PairsNotAtMaximumCheck() {
   //Returns true if the no of pairs being trades is <= max.open.pairs.allowed, else false
   no.of.pairs.trading = 0;
   //if (OrdersTotal() < max.open.pairs.allowed) return(true);
   if ( OrdersTotal() == 0 ) {
      return ( true );
   }
   no.of.pairs.trading = 1;
   //Put the pair symbols into an array
   string OpenPairs[];
   ArrayResize ( OpenPairs, OrdersTotal() );
   OrderSelect ( 0, SELECT_BY_POS );
   OpenPairs[0] = OrderSymbol();
   for ( int cc = 1; cc < OrdersTotal(); cc++ ) {
      OrderSelect ( cc, SELECT_BY_POS );
      OpenPairs[cc] = OrderSymbol();
      no.of.pairs.trading++;
      //Loop back to see if this is a fresh pair
      for ( int d = cc - 1; d >= 0; d-- ) {
         if ( OpenPairs[cc] == OpenPairs[d] ) {
            no.of.pairs.trading--;
            break;
         }//if (OpenPairs[cc] == OpenPairs[d] )
      }//for (int d = cc - 1; d >= 0; d--)
   }//for (int cc = 0; cc < OrdersTotal(); cc++)
   if ( no.of.pairs.trading < max.open.pairs.allowed ) {
      return ( true );
   }
   //max.open.pairs.allowed is reached, so see if there is already a trade open for this pair. If so, allow the
   //trade send as it might be required for recovery/hedging
   for ( cc = 0; cc < OrdersTotal(); cc++ ) {
      if ( !OrderSelect ( cc, SELECT_BY_POS ) ) {
         continue;
      }
      if ( OrderSymbol() == symbol ) {
         return ( true );
      }
   }//for (cc = 0; cc < OrdersTotal(); cc++)
   //Got this far, so max.open.pairs.allowed is reached and the trade is not required for hedging or recover,
   //and so should be cancelled
   return ( false );
}//End bool PairsNotAtMaximumCheck()

double LotCalculate() {
   double LotStep = MarketInfo ( symbol, MODE_LOTSTEP );
   double MinLots = MarketInfo ( symbol, MODE_MINLOT );
   double MaxLots = MarketInfo ( symbol, MODE_MAXLOT );
   int    Decimal = 1;
   if ( LotStep == 0.01 ) {
      Decimal = 2;
   }
   if ( lot == 0 ) {
      if ( open.trades == 0 ) {
         calculated.lot = AccountEquity() * ( 1 / ( money.per.micro.lot ) );
         calculated.lot = MathFloor ( calculated.lot ) / 100;
         calculated.lot = NormalizeDouble ( calculated.lot, Decimal );
         GlobalVariableSet ( SendLotsGv, calculated.lot );
      }
   } else {
      if ( GlobalVariableCheck ( SendLotsGv ) ) {
         if ( GlobalVariableGet ( SendLotsGv ) != lot ) {
            GlobalVariableSet ( SendLotsGv, lot );
         }
         calculated.lot = GlobalVariableGet ( SendLotsGv );
      }//if (GlobalVariableCheck(SendLotsGv))
      else {
         GlobalVariableSet ( SendLotsGv, lot );
      }
      if ( calculated.lot != GlobalVariableGet ( SendLotsGv ) ) {
         calculated.lot = GlobalVariableGet ( SendLotsGv );
      }
   }
   if ( calculated.lot != GlobalVariableGet ( SendLotsGv ) ) {
      calculated.lot = GlobalVariableGet ( SendLotsGv );
   }
   if ( calculated.lot < MinLots ) {
      calculated.lot = MinLots;
      GlobalVariableSet ( SendLotsGv, MinLots );
   }
   if ( calculated.lot > MaxLots ) {
      calculated.lot = MaxLots;
      GlobalVariableSet ( SendLotsGv, MaxLots );
   }
   if ( open.trades > 0 ) {
      if ( calculated.lot != GlobalVariableGet ( SendLotsGv ) ) {
         calculated.lot = GlobalVariableGet ( SendLotsGv );
      }
      if ( use.recovery ) {
         if ( RecoveryInProgress ) {
            if ( open.trades == 2 ) {
               if ( use.1.1.2.4.recovery ) {
                  calculated.lot *= 1.34;
               }
               if ( use.1.1.3.3.recovery ) {
                  calculated.lot *= 3;
               }
            }//if (open.trades == 2)
            if ( open.trades == 3 ) {
               if ( use.1.1.2.4.recovery ) {
                  calculated.lot *= 1.79;
               }
               if ( use.1.1.3.3.recovery ) {
                  calculated.lot *= 3;
               }
            }//if (open.trades == 3)
            if ( open.trades == 4 ) {
if ( use.1.1.2.4.recovery ) {
                  calculated.lot *= 2.4;
               }
              
            }//if (open.trades == 4)
            if ( open.trades == 5 ) {
               if ( use.1.1.2.4.recovery ) {
                  calculated.lot *= 3.22;
               }
               
            }//if (open.trades == 5)
            
             if ( open.trades == 6 ) {
               if ( use.1.1.2.4.recovery ) {
                  calculated.lot *= 4.32;
               }
              
            }
            
            
            if ( open.trades == 7 ) {
               return;   //No further trading is possible
            }
         }//if (RecoveryInProgress)
         //This idea from Pippo
         if ( use.1.2.6.recovery && open.trades + 1 >= start.recovery.at.trades ) {
            if ( open.trades == start.recovery.at.trades - 1 ) {
               calculated.lot *= 1.34;
            }
            if ( open.trades == start.recovery.at.trades ) {
               calculated.lot *= 1.79;
            }
       
             if ( open.trades == start.recovery.at.trades +1) {
               calculated.lot *= 2.4;
            }
            if ( open.trades == start.recovery.at.trades +2) {
               calculated.lot *= 3.22;
            }
            if ( open.trades == start.recovery.at.trades +3) {
               calculated.lot *= 4.32;
            }
            
            if ( open.trades == start.recovery.at.trades + 4 ) {
               return;
            }
         }//if (use.1.2.6.recovery)
      }//if (use.recovery)
   }//if (open.trades > 0)
   return ( calculated.lot );
}//End int CalculateStopLoss(int type, double price)

void CalculateTradeClosureLine ( int type ) {
   close.trade.at.gold = false;
   close.trade.at.green = false;
   close.trade.at.middle.white = false;
   close.box.trade.at.magenta = false;
   close.box.trade.at.gold = false;
   trail.box.trade.at.magenta = false;
   trail.box.trade.at.gold = false;
   //Low
   if ( type == OP_BUY ) {
      if ( rsi.val <= 45 ) {
         close.trade.at.gold = true;
         close.box.trade.at.gold = true;
      }
      if ( rsi.val > 45 && rsi.val < 55 ) {
         close.trade.at.green = true;
         close.box.trade.at.magenta = true;
      }
      if ( rsi.val >= 55 ) {
         close.trade.at.middle.white = true;
         trail.box.trade.at.gold = true;
      }
   }
   if ( type == OP_SELL ) {
      if ( rsi.val <= 45 ) {
         close.trade.at.middle.white = true;
         trail.box.trade.at.gold = false;
      }
      if ( rsi.val > 45 && rsi.val < 55 ) {
         close.trade.at.green = true;
         close.box.trade.at.magenta = true;
      }
      if ( rsi.val >= 55 ) {
         close.trade.at.gold = true;
         close.box.trade.at.gold = true;
      }
   }
}//void CalculateTradeClosureLine()


bool CheckMagenta ( string type ) {
   static bool InsideBottomBox, InsideTopBox;
   if ( Ask < HalfBottomLine ) {
      InsideBottomBox = true;
   }
   if ( Bid > HalfTopLine ) {
      InsideTopBox = true;
   }
   if ( type == GoLong ) {
      if ( InsideBottomBox ) {
         if ( Ask > HalfBottomLine ) {
            InsideBottomBox = false;
            return ( true );
         }
      }
   }
   if ( type == GoShort ) {
      if ( InsideTopBox ) {
         if ( Bid < HalfTopLine ) {
            InsideTopBox = false;
            return ( true );
         }
      }
   }
   return ( false );
}


void MagentaLineTradingOpportunities() {
   if ( !IsTradingAllowed ( ct ) ) {
      return;
   }
   RefreshRates();
   double take, stop, price;
   double ReEntryLineVal = ObjectGet ( reentrylinename, OBJPROP_PRICE1 );
   int type;
   bool SendTrade;
   double SendLots = LotCalculate();
   string CurrencyBuy, CurrencySell;
   //Long
   if ( CheckMagenta ( GoLong ) ) {
      if ( !trade.long ) {
         return;
      }
      //Balanced pair trade filter. Only apply to pre-recovery trades.
      //Will remove the comments when I add Recovery
      if ( open.trades + 1 < start.recovery.at.trades || !use.recovery ) {
         if ( use.zeljko && !BalancedPair ( OP_BUY ) ) {
            return;
         }
      }//if (open.trades + 1 < start.recovery.at.trades)
      if ( SellOpen ) {
         return;
      }
      //if (RecoveryInProgress) return;
      if ( ObjectFind(reentrylinename) == -1){
         if (open.trades > 0 ) {
            Alert("Re Entry Line is not found and the amount of open orders is greater than zero! Check GlobalVariables");
            return;
         }
      } else {
      if ( ReEntryLineVal > 0 ) {
         if ( Ask > ReEntryLineVal ) {
            return;
         }
         if ( BottomLine > ReEntryLineVal ) {
            return;
         }
        } else {
            Alert("Re Entry Line is equal to zero");
            return;
         }
      }
      if ( open.trades + 1 < start.recovery.at.trades || !use.recovery && !rsi.volatilty ( OP_BUY ) ) {
         return;
      }
      type = OP_BUY;
      price = Ask;
      SendTrade = true;
   }//if (Ask > 1000000)
   //Short
   if ( CheckMagenta ( GoShort ) ) {
      if ( !trade.short ) {
         return;
      }
      //Balanced pair trade filter. Only apply to pre-recovery trades
      //Will remove the comments when I add Recovery
      if ( open.trades + 1 < start.recovery.at.trades || !use.recovery ) {
         if ( use.zeljko && !BalancedPair ( OP_SELL ) ) {
            return;
         }
      }//if (open.trades + 1 < start.recovery.at.trades)
      if ( BuyOpen ) {
         return;
      }
      //if (RecoveryInProgress) return;
      if ( ObjectFind(reentrylinename) == -1){
         if (open.trades > 0 ) {
            Alert("Re Entry Line is not found and the amount of open orders is greater than zero! Check GlobalVariables");
            return;
         }
      } else {
      if ( ReEntryLineVal > 0 ) {
         if ( Bid < ReEntryLineVal ) {
            return;
         }
         if ( TopLine < ReEntryLineVal ) {
            return;
         }
        } else {
            Alert("Re Entry Line is equal to zero");
            return;
         }
      }
      if ( open.trades + 1 < start.recovery.at.trades || !use.recovery && !rsi.volatilty ( OP_SELL ) ) {
         return;
      }
      type = OP_SELL;
      price = Bid;
      SendTrade = true;
   }//if (Ask < 0)
   if ( SendTrade ) {
      bool result = SendSingleTrade ( type, trade.comment, SendLots, price, 0, 0 );
   }//if (SendTrade)
   //Actions when trade send succeeds
   if ( SendTrade && result ) {
      if ( type == OP_SELL ) {
         AddReEntryLine ( NormalizeDouble ( TopLine + ( CalculateReEntryLinePips ( OP_SELL ) * Point ), Digits ) );
         GlobalVariableSet ( MagentaSellTicketGv, ticket.no );
         MagentaSellTicketNumber = ticket.no;
      }
      if ( type == OP_BUY ) {
         AddReEntryLine ( NormalizeDouble ( BottomLine - ( CalculateReEntryLinePips ( OP_BUY ) * Point ), Digits ) );
         GlobalVariableSet ( MagentaBuyTicketGv, ticket.no );
         MagentaBuyTicketNumber = ticket.no;
      }
      if ( ObjectFind ( breakevenlinename ) != -1 ) {
         ObjectDelete ( breakevenlinename );
      }
      CalculateTradeClosureLine ( type );
   }//if (result)
   //Actions when trade send fails
   if ( SendTrade && !result ) {
   }//if (!result)
}//void MagentaLineTradingOpportunities()

bool CheckWhiteBox ( string type ) {
   static bool InsideBox;
   if ( !InsideBox && Bid < WhiteBoxHigh && Ask > WhiteBoxLow ) {
      InsideBox = true;
   }
   if ( InsideBox ) {
      if ( type == GoLong ) {
         if ( Ask > WhiteBoxHighTrigger ) {
            InsideBox = false;
            if ( auto.calculate.method ) {
               if ( rsi.val > 45 ) {
                  return ( true );
               }
            } else {
               return ( true );
            }
         }
      }
      if ( type == GoShort ) {
         if ( Bid < WhiteBoxLowTrigger ) {
            InsideBox = false;
            if ( auto.calculate.method ) {
               if ( rsi.val < 55 ) {
                  return ( true );
               }
            } else {
               return ( true );
            }
         }
      }
   }
   return ( false );
}

void WhiteBoxTradingOpportunities() {
   if ( !IsTradingAllowed ( wb ) ) {
      return;
   }
   RefreshRates();
   double take, stop, price;
   double ReEntryLineVal = ObjectGet ( reentrylinename, OBJPROP_PRICE1 );
   int type;
   bool SendTrade;
   double SendLots = LotCalculate();
   //Long
   if ( CheckWhiteBox ( GoLong ) ) {
      if ( !trade.long ) {
         return;
      }
      //Balanced pair trade filter. Only apply to pre-recovery trades.
      //Will remove the comments when I add Recovery
      if ( use.zeljko && !BalancedPair ( OP_BUY ) ) {
         return;
      }//if (open.trades + 1 < start.recovery.at.trades)
      type = OP_BUY;
      price = Ask;
      SendTrade = true;
   }//if (Ask > 1000000)
   //Short
   if ( CheckWhiteBox ( GoShort ) ) {
      if ( !trade.short ) {
         return;
      }
      //Balanced pair trade filter. Only apply to pre-recovery trades
      //Will remove the comments when I add Recovery
      if ( use.zeljko && !BalancedPair ( OP_SELL ) ) {
         return;
      }//if (open.trades + 1 < start.recovery.at.trades)
      type = OP_SELL;
      price = Bid;
      SendTrade = true;
   }//if (Ask < 0)
   if ( SendTrade ) {
      bool result = SendSingleTrade ( type, trade.comment, SendLots, price, 0, 0 );
   }//if (SendTrade)
   //Actions when trade send succeeds
   if ( SendTrade && result ) {
      if ( type == OP_SELL ) {
         AddReEntryLine ( TopLine - SixthsRange / 12 );
         GlobalVariableSet ( BoxSellTicketGv, ticket.no );
         BoxSellTicketNumber = ticket.no;
      }
      if ( type == OP_BUY ) {
         AddReEntryLine ( HalfBottomLine + SixthsRange / 12 );
         GlobalVariableSet ( BoxBuyTicketGv, ticket.no );
         BoxBuyTicketNumber = ticket.no;
      }
      CalculateTradeClosureLine ( type );
   }//if (result)
   //Actions when trade send fails
   if ( SendTrade && !result ) {
   }//if (!result)
}//void WhiteBoxTradingOpportunities()


bool CloseTrade ( int ticket ) {
   while ( IsTradeContextBusy() ) {
      Sleep ( 100 );
   }
   bool result = OrderClose ( ticket, OrderLots(), OrderClosePrice(), 1000, CLR_NONE );
   //Actions when trade send succeeds
   if ( result ) {
      open.trades--;
      LotCalculate();
      return ( true );
   }//if (result)
   //Actions when trade send fails
   if ( !result ) {
      return ( false );
   }//if (!result)
}//End bool CloseTrade(ticket)

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() != magic.number ) {
         continue;
      }
      if ( OrderSymbol() != Symbol() ) {
         continue;
      }
      while ( IsTradeContextBusy() ) {
         Sleep ( 100 );
      }
      if ( OrderType() == OP_BUY || OrderType() == OP_SELL ) {
         bool result = OrderClose ( OrderTicket(), OrderLots(), OrderClosePrice(), 1000, CLR_NONE );
      }
      if ( result ) {
         cc++;
      }
      if ( !result ) {
         ForceTradeClosure = true;
      }
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   //If full closure succeeded, then allow new trading
   if ( !ForceTradeClosure ) {
      open.trades = 0;
      BuyOpen = false;
      SellOpen = false;
   }//if (!ForceTradeClosure)
}//End void CloseAllTrades()

bool CheckTradingTimes() {
   int hour = TimeHour ( TimeLocal() );
   if ( end.hourm < start.hourm ) {
      end.hourm += 24;
   }
   if ( end.houre < start.houre ) {
      end.houre += 24;
   }
   bool ok2Trade = true;
   ok2Trade = ( hour >= start.hourm && hour <= end.hourm ) || ( hour >= start.houre && hour <= end.houre );
   // adjust for past-end-of-day cases
   // eg in AUS, USDJPY trades 09-17 and 22-06
   // so, the above check failed, check if it is because of this condition
   if ( !ok2Trade && hour < 12 ) {
      hour += 24;
      ok2Trade = ( hour >= start.hourm && hour <= end.hourm ) || ( hour >= start.houre && hour <= end.houre );
      // so, if the trading hours are 11pm - 6am and the time is between  midnight to 11am, (say, 5am)
      // the above code will result in comparing 5+24 to see if it is between 23 (11pm) and 30(6+24), which it is...
   }
   // check for end of day by looking at *both* end-hours
   if ( hour >= MathMax ( end.hourm, end.houre ) ) {
      ok2Trade = false;
   }//if (hour >= MathMax(end.hourm, end.houre))
   return ( ok2Trade );
}//bool CheckTradingTimes()

bool isNewBar ( datetime time ) {
   static datetime prevTime15;
   static datetime prevTime60;
   static datetime prevTime1440;
   bool newBar = false;
   if ( time == 15 ) {
      if ( iTime ( NULL, time, 0 ) != prevTime15 ) {
         newBar = true;
         prevTime15 = iTime ( NULL, time, 0 );
      }
   }
   if ( time == 60 ) {
      if ( iTime ( NULL, time, 0 ) != prevTime60 ) {
         newBar = true;
         prevTime60 = iTime ( NULL, time, 0 );
      }
   }
   if ( time == 1440 ) {
      if ( iTime ( NULL, time, 0 ) != prevTime1440 ) {
         newBar = true;
         prevTime1440 = iTime ( NULL, time, 0 );
      }
   }
   return ( newBar );
}

void CountOpenTrades() {
   ArrayResize ( total.trades, 0 ); //reset array
   open.trades = 0;
   TotalBuyTrades = 0;
   TotalSellTrades = 0;
   total.lots.open = 0;
   basket.profit = 0;
   ticket.no = -1;
   BuyOpen = false;
   SellOpen = false;
   RecoveryInProgress = false;
   BoxBuyOpen = false;
   BoxSellOpen = false;
   MagentaBuyOpen = false;
   MagentaSellOpen = false;

   //Check to see if box trades are still open. Additional coding further down the function, to alter the status
   //of a single remaining box trade
   if ( BoxBuyTicketNumber > -1 ) {
      if ( OrderSelect ( BoxBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) && OrderCloseTime() == 0 ) {
         BoxBuyOpen = true;
      }
      if ( !OrderSelect ( BoxBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) ||  OrderCloseTime() > 0 ) {
         GlobalVariableDel ( BoxBuyTicketGv );
         BoxBuyTicketNumber = -1;
      }//if (!OrderSelect(BoxBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES))
   }//if (BoxBuyTicketNumber > -1)
   if ( BoxSellTicketNumber > -1 ) {
      if ( OrderSelect ( BoxSellTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) && OrderCloseTime() == 0 ) {
         BoxSellOpen = true;
      }
      if ( !OrderSelect ( BoxSellTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) ||  OrderCloseTime() > 0 ) {
         GlobalVariableDel ( BoxSellTicketGv );
         BoxSellTicketNumber = -1;
      }//if (!OrderSelect(BoxBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES))
   }//if (BoxSellTicketNumber > -1)
   if ( MagentaBuyTicketNumber > -1 ) {
      if ( OrderSelect ( MagentaBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) && OrderCloseTime() == 0 ) {
         MagentaBuyOpen = true;
      }
      if ( !OrderSelect ( MagentaBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) ||  OrderCloseTime() > 0 ) {
         GlobalVariableDel ( MagentaBuyTicketGv );
         MagentaBuyTicketNumber = -1;
      }//if (!OrderSelect(BoxBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES))
   }//if (BoxBuyTicketNumber > -1)
   if ( MagentaSellTicketNumber > -1 ) {
      if ( OrderSelect ( MagentaSellTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) && OrderCloseTime() == 0 ) {
         MagentaSellOpen = true;
      }
      if ( !OrderSelect ( MagentaSellTicketNumber, SELECT_BY_TICKET, MODE_TRADES ) ||  OrderCloseTime() > 0 ) {
         GlobalVariableDel ( MagentaSellTicketGv );
         MagentaSellTicketNumber = -1;
      }//if (!OrderSelect(BoxBuyTicketNumber, SELECT_BY_TICKET, MODE_TRADES))
   }//if (BoxSellTicketNumber > -1)
   if ( OrdersTotal() == 0 ) {
      return;
   } else {
      ArrayResize ( total.trades, OrdersTotal() );
   }
   for ( int i = 0; i < ArraySize ( total.trades ); i++ ) {
      if ( OrderSelect ( i, SELECT_BY_POS ) ) {
         if ( OrderSymbol() == symbol && OrderMagicNumber() == magic.number ) {
            open.trades++;
            ticket.no = OrderTicket();
            total.trades[i] = ticket.no;
            total.lots.open += OrderLots();
            basket.profit += (OrderProfit() + OrderSwap() + OrderCommission()); 
            if ( OrderType() == OP_BUY ) {
               TotalBuyTrades++;
               BuyOpen = true;
               CalculateTradeClosureLine ( OP_BUY );
            }
            if ( OrderType() == OP_SELL ) {
               TotalSellTrades++;
               SellOpen = true;
               CalculateTradeClosureLine ( OP_SELL );
            }
            if ( ObjectFind ( breakevenlinename ) > -1 ) {
               double take = NormalizeDouble ( ObjectGet ( breakevenlinename, OBJPROP_PRICE1 ), Digits );
               if ( OrderTakeProfit() != take && !use.recovery.trailing.stop ) {
                  ModifyOrder ( ticket.no, OrderStopLoss(), take );
               }//if (OrderTakeProfit() != take && (OrderType() == OP_BUY || OrderType() == OP_SELL) )
               if ( use.recovery.trailing.stop && OrderTakeProfit() != 0 ) {
                  ModifyOrder ( ticket.no, OrderStopLoss(), 0 );
               }
            }//if (ObjectFind(breakevenlinename) > -1)
            if ( ObjectFind ( reentrylinename ) == -1 ) {
               if ( BoxBuyOpen && !MagentaBuyOpen ) {
                  AddReEntryLine ( NormalizeDouble ( BottomLine + SixthsRange / 12, Digits ) );
               }
               if ( BoxSellOpen && !MagentaSellOpen ) {
                  AddReEntryLine ( NormalizeDouble ( TopLine - SixthsRange / 12, Digits ) );
               }
               if ( MagentaBuyOpen ) {
                  AddReEntryLine ( NormalizeDouble ( BottomLine - ( CalculateReEntryLinePips ( OP_BUY ) * Point ), Digits ) );
               }
               if ( MagentaSellOpen ) {
                  AddReEntryLine ( NormalizeDouble ( TopLine + ( CalculateReEntryLinePips ( OP_SELL ) * Point ), Digits ) );
               }
            }
            if ( ObjectFind ( reentrylinename ) != -1 ) {
               if ( BoxBuyOpen && !MagentaBuyOpen ) {
                  if ( ObjectGet ( reentrylinename, OBJPROP_PRICE1 ) != BottomLine + SixthsRange / 12 ) {
                     AddReEntryLine ( NormalizeDouble ( BottomLine + SixthsRange / 12, Digits ) );
                  }
               }
               if ( BoxSellOpen && !MagentaSellOpen ) {
                  if ( ObjectGet ( reentrylinename, OBJPROP_PRICE1 ) != TopLine - SixthsRange / 12 ) {
                     AddReEntryLine ( NormalizeDouble ( TopLine - SixthsRange / 12, Digits ) );
                  }
               }
            }
            //Check for possible trade closure
         }//if (OrderSymbol() == symbol && OrderMagicNumber() == magic.number)
      }//if (OrderSelect(cc, SELECT_BY_POS))
   }//for (int cc = 0; cc < OrdersTotal() - 1; cc++)
   ArrayResize ( total.trades, open.trades );
}//End void CountOpenTrades();

void WatchOpenTrades() {
   static int old.open.trades;
   CountOpenTrades();
   
   if (old.open.trades != open.trades){
      CheckOpenCurrency();
      old.open.trades = open.trades;
   }
   
   if ( open.trades == 0 ) {
      CleanGlobalVariables ( "balance" );
      if ( ObjectFind ( breakevenlinename ) > -1 ) {
         ObjectDelete ( breakevenlinename );
      }
      if ( ObjectFind ( reentrylinename ) > -1 ) {
         ObjectDelete ( reentrylinename );
      }
      RecoveryInProgress = false;
   }
   if ( !HedgingInProgress ) {
      if ( open.trades == 1 ) {
         if ( !OrderSelect ( ticket.no, SELECT_BY_TICKET ) ) {
            return;
         }
         if ( OrderCloseTime() > 0 ) {
            return;
         }
         if ( OrderProfit() > 0 ) {
            TradeManagementModule();
         }
      }
   }
}

void CheckOpenCurrency() {
   string f.curr, s.curr, buy.curr[], sell.curr[];
   int count.buy.first.curr, count.buy.sec.curr, count.sell.first.curr, count.sell.sec.curr;
   int total.orders = OrdersTotal();
   
   if ( total.orders == 0 && open.trades != 0 ) {
      return;
   } else {
      ArrayResize ( buy.curr, total.orders );
      ArrayResize ( sell.curr, total.orders );
      for ( int i = total.orders-1; i >= 0; i-- ) {
         if ( OrderSelect ( i, SELECT_BY_POS ) ) {
            int type = OrderType();
            if ( type == OP_BUY ) {
               buy.curr[i] = StringSubstr ( OrderSymbol(), 0, 3 );
               sell.curr[i] = StringSubstr ( OrderSymbol(), 3, 6 );
            } else {
               buy.curr[i] = StringSubstr ( OrderSymbol(), 3, 6 );
               sell.curr[i] = StringSubstr ( OrderSymbol(), 0, 3 );
            }
         }
      }
      for ( int cc = total.orders-1; cc >= 0; cc-- ) {
         f.curr = StringSubstr ( symbol, 0, 3 );
         s.curr = StringSubstr ( symbol, 3, 6 );
         if ( buy.curr[cc] == f.curr ) {
            count.buy.first.curr ++;
         }
         if ( buy.curr[cc] == s.curr ) {
            count.buy.sec.curr ++;
         }
         if ( sell.curr[cc] == f.curr ) {
            count.sell.first.curr ++;
         }
         if ( sell.curr[cc] == s.curr ) {
            count.sell.sec.curr ++;
         }
      }
      if ( count.buy.first.curr >= 0 ) {
         if ( GlobalVariableCheck ( buy.first.curr ) ) {
            if ( GlobalVariableGet ( buy.first.curr ) != count.buy.first.curr ) {
               GlobalVariableSet ( buy.first.curr, count.buy.first.curr );
            }
         } else {
            if ( count.buy.first.curr != 0 ) {
               GlobalVariableSet ( buy.first.curr, count.buy.first.curr );
            }
         }
      }
      if ( count.buy.sec.curr >= 0 ) {
         if ( GlobalVariableCheck ( buy.sec.curr ) ) {
            if ( GlobalVariableGet ( buy.sec.curr ) != count.buy.sec.curr ) {
               GlobalVariableSet ( buy.sec.curr, count.buy.sec.curr );
            }
         } else {
            if ( count.buy.sec.curr != 0 ) {
               GlobalVariableSet ( buy.sec.curr, count.buy.sec.curr );
            }
         }
      }
      if ( count.sell.first.curr >= 0 ) {
         if ( GlobalVariableCheck ( sell.first.curr ) ) {
            if ( GlobalVariableGet ( sell.first.curr ) != count.sell.first.curr ) {
               GlobalVariableSet ( sell.first.curr, count.sell.first.curr );
            }
         } else {
            if ( count.buy.first.curr != 0 ) {
               GlobalVariableSet ( sell.first.curr, count.sell.first.curr );
            }
         }
      }
      if ( count.sell.sec.curr >= 0 ) {
         if ( GlobalVariableCheck ( sell.sec.curr ) ) {
            if ( GlobalVariableGet ( sell.sec.curr ) != count.sell.sec.curr ) {
               GlobalVariableSet ( sell.sec.curr, count.sell.sec.curr );
            }
         } else {
            if ( count.buy.first.curr != 0 ) {
               GlobalVariableSet ( sell.sec.curr, count.sell.sec.curr );
            }
         }
      }
   }
}

//=============================================================================
//                           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)


///////////////////////////////////////////////////////////////////////////////////////////////////////
//Balance/swap filters module
void TradeDirectionBySwap() {
   //Sets trade.long & trade.short according to the positive/negative swap it attracts
   double LongSwap = MarketInfo ( symbol, MODE_SWAPLONG );
   double ShortSwap = MarketInfo ( symbol, MODE_SWAPSHORT );
   if ( cad.pairs.positive.only ) {
      if ( StringSubstr ( symbol, 0, 3 ) == "CAD" || StringSubstr ( symbol, 0, 3 ) == "cad" || StringSubstr ( symbol, 3, 3 ) == "CAD" || StringSubstr ( symbol, 3, 3 ) == "cad" ) {
         if ( LongSwap > 0 ) {
            trade.long = true;
         } else {
            trade.long = false;
         }
         if ( ShortSwap > 0 ) {
            trade.short = true;
         } else {
            trade.short = false;
         }
      }//if (StringSubstr(symbol, 0, 3) == "CAD" || StringSubstr(symbol, 0, 3) == "cad" )
   }//if (cad.pairs.positive.only)
   if ( aud.pairs.positive.only ) {
      if ( StringSubstr ( symbol, 0, 3 ) == "AUD" || StringSubstr ( symbol, 0, 3 ) == "aud" || StringSubstr ( symbol, 3, 3 ) == "AUD" || StringSubstr ( symbol, 3, 3 ) == "aud" ) {
         if ( LongSwap > 0 ) {
            trade.long = true;
         } else {
            trade.long = false;
         }
         if ( ShortSwap > 0 ) {
            trade.short = true;
         } else {
            trade.short = false;
         }
      }//if (StringSubstr(symbol, 0, 3) == "AUD" || StringSubstr(symbol, 0, 3) == "aud" || StringSubstr(symbol, 3, 3) == "AUD" || StringSubstr(symbol, 3, 3) == "aud" )
   }//if (aud.pairs.positive.only)
   if ( nzd.pairs.positive.only ) {
      if ( StringSubstr ( symbol, 0, 3 ) == "NZD" || StringSubstr ( symbol, 0, 3 ) == "nzd" || StringSubstr ( symbol, 3, 3 ) == "NZD" || StringSubstr ( symbol, 3, 3 ) == "nzd" ) {
         if ( LongSwap > 0 ) {
            trade.long = true;
         } else {
            trade.long = false;
         }
         if ( ShortSwap > 0 ) {
            trade.short = true;
         } else {
            trade.short = false;
         }
      }//if (StringSubstr(symbol, 0, 3) == "AUD" || StringSubstr(symbol, 0, 3) == "aud" || StringSubstr(symbol, 3, 3) == "AUD" || StringSubstr(symbol, 3, 3) == "aud" )
   }//if (aud.pairs.positive.only)
}//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
   int f.cur.open, s.cur.open, var.get;
   CanTradeThisPair = true;
   if ( GlobalVariableCheck ( buy.first.curr ) ) {
      if ( GlobalVariableGet ( buy.first.curr ) > 0 ) {
         var.get = GlobalVariableGet ( buy.first.curr );
         f.cur.open = f.cur.open + var.get;
      }
   }
   if ( GlobalVariableCheck ( sell.first.curr ) ) {
      if ( GlobalVariableGet ( sell.first.curr ) > 0 ) {
         var.get = GlobalVariableGet ( sell.first.curr );
         f.cur.open = f.cur.open + var.get;
      }
   }
   if ( GlobalVariableCheck ( buy.sec.curr ) ) {
      if ( GlobalVariableGet ( buy.sec.curr ) > 0 ) {
         var.get = GlobalVariableGet ( buy.sec.curr );
         s.cur.open = s.cur.open + var.get;
      }
   }
   if ( GlobalVariableCheck ( sell.sec.curr ) ) {
      if ( GlobalVariableGet ( sell.sec.curr ) > 0 ) {
         var.get = GlobalVariableGet ( sell.sec.curr );
         s.cur.open = s.cur.open + var.get;
      }
   }
   if ( f.cur.open >= 1 && s.cur.open >= 1 ) {
      CanTradeThisPair = false;
      return ( false );
   }//if (c1open == 1 && c2open == 1)
   //Got this far, so ok to trade
   return ( true );
}//End bool IsThisPairTradable()

bool BalancedPair ( int type ) {
   if ( type == OP_BUY || type == OP_BUYSTOP || type == OP_BUYLIMIT ) {
      if ( GlobalVariableCheck ( buy.first.curr ) ) {
         if ( GlobalVariableGet ( buy.first.curr ) > 0 ) {
            return ( false );
         }
      }
      if ( GlobalVariableCheck ( sell.sec.curr ) ) {
         if ( GlobalVariableGet ( sell.sec.curr ) > 0 ) {
            return ( false );
         }
      }
   } else {
      if ( GlobalVariableCheck ( sell.first.curr ) ) {
         if ( GlobalVariableGet ( sell.first.curr ) > 0 ) {
            return ( false );
         }
      }
      if ( GlobalVariableCheck ( buy.sec.curr ) ) {
         if ( GlobalVariableGet ( buy.sec.curr ) > 0 ) {
            return ( false );
         }
      }
   }
   return ( true );
}//End bool BalancedPair(int type)



//End Balance/swap filters module
///////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////
//Indicator module

double GetRsi ( int tf, int period, int ap, int shift ) {
   return ( iRSI ( NULL, tf, period, ap, shift ) );
}//End double GetRsi(int tf, int period, int ap, int shift)

int GetBarCount() {
   int PeriodCount = 0;
   int PeriodTotal = 0;
   int TempAbovePer = 0;
   int TempBelowPer = 0;
   int CCIPos = 0;
   int TempCCIPos = 0;
   int RSIPos = 0;
   int TempRSIPos = 0;
   double TempIndTimeframe = ind.timeframe;
   double TempPeriod = Period();
   double multiplier = 1;
   if ( ind.period != Period() ) {
      multiplier = TempIndTimeframe / TempPeriod;
   } else {
      multiplier = 1;
   }
   cur.bars = iBars ( NULL, ind.timeframe );
   int IndBars = MathMin ( 720, cur.bars );
   for ( int i = 1; i <= IndBars; i++ ) {
      TempCCIPos = CCIPos;
      if ( iCCI ( NULL, ind.timeframe, cci.period, PRICE_WEIGHTED, i ) > 100 && CCIPos != 1 ) {
         TempAbovePer = i;
         CCIPos = 1;
      }
      if ( iCCI ( NULL, ind.timeframe, cci.period, PRICE_WEIGHTED, i ) < -100 && CCIPos != -1 ) {
         TempBelowPer = i;
         CCIPos = -1;
      }
      if ( TempAbovePer > 0 && TempBelowPer > 0 && CCIPos != TempCCIPos && CCIPos != 0 ) {
         PeriodCount++;
         PeriodTotal += MathAbs ( TempAbovePer - TempBelowPer );
      }
   }
   if ( PeriodCount == 0 ) {
      bar.count = 170;
   } else {
      bar.count = PeriodTotal / PeriodCount;
   }
   //Print("Tot Bars: ", PeriodTotal, " / Total Reversals: ", PeriodCount, " * TimeframeMultiplier: ", multiplier, " = ", bar.count);
}//End of int GetBarCount()

void GetSixths() {
   if ( isNewBar ( 60 ) ) {
      GetBarCount();
   }
   TopLine = High[iHighest ( NULL, 0, MODE_HIGH, bar.count, 1 )];
   if ( High[0] > TopLine ) {
      TopLine = NormalizeDouble ( High[0], Digits );
   }
   BottomLine = Low[iLowest ( NULL, 0, MODE_LOW, bar.count, 1 )];
   if ( Low[0] < BottomLine ) {
      BottomLine = NormalizeDouble ( Low[0], Digits );
   }
   double value = TopLine - BottomLine;
   double sixth = value / 6;
   double RsiSixth = sixth * rsi.factor;
   SixthsRange = NormalizeDouble ( value, Digits );
   HalfTopLine = NormalizeDouble ( BottomLine + sixth + sixth + sixth + sixth + sixth + ( sixth * 0.75 ), Digits );
   HalfBottomLine = NormalizeDouble ( BottomLine + ( sixth * 0.25 ), Digits );
   BottomGoldLine = NormalizeDouble ( BottomLine + sixth, Digits );
   BottomGreenLine = NormalizeDouble ( BottomLine + sixth + sixth, Digits );
   MiddleWhiteLine = NormalizeDouble ( BottomLine + sixth + sixth + sixth, Digits );
   TopGreenLine = NormalizeDouble ( BottomLine + sixth + sixth + sixth + sixth, Digits );
   TopGoldLine = NormalizeDouble ( BottomLine + sixth + sixth + sixth + sixth + sixth, Digits );
   MagentaCtBufferHigh = NormalizeDouble ( BottomLine + sixth + sixth + sixth + sixth + sixth + ( sixth / 2 ) + ( sixth / 4 ), Digits );
   MagentaCtBufferLow = NormalizeDouble ( BottomLine + ( sixth / 4 ), Digits );
   WhiteBoxHigh = NormalizeDouble ( MiddleWhiteLine + ( RsiSixth / 4 ), Digits );
   WhiteBoxLow = NormalizeDouble ( MiddleWhiteLine - ( RsiSixth / 4 ), Digits );
   WhiteBoxHighTrigger = NormalizeDouble ( MiddleWhiteLine + ( RsiSixth / 2 ), Digits );
   WhiteBoxLowTrigger = NormalizeDouble ( MiddleWhiteLine - ( RsiSixth / 2 ), Digits );
   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
   if ( !IsTesting() || IsVisualMode() ) {
      //Draw the lines
      double tl = ObjectGet ( "fivesixth", OBJPROP_PRICE1 );
      double bl = ObjectGet ( "onesixth", OBJPROP_PRICE1 );
      if ( tl != TopGoldLine || bl != BottomGoldLine ) {
         if ( ObjectFind ( "zerosixth" ) == -1 ) {
            ObjectCreate ( "zerosixth", 1, 0, TimeCurrent(), BottomLine );
            ObjectSet ( "zerosixth", OBJPROP_COLOR, Magenta );
            ObjectSet ( "zerosixth", OBJPROP_STYLE, STYLE_SOLID );
            ObjectSet ( "zerosixth", OBJPROP_WIDTH, 2 );
         }//if (ObjectFind("zerosixth") == -1)
         else {
            ObjectMove ( "zerosixth", 0, TimeCurrent(), BottomLine );
         }
         if ( ObjectFind ( "halfbottomsixth" ) == -1 ) {
            ObjectCreate ( "halfbottomsixth", 1, 0, TimeCurrent(), HalfBottomLine );
            ObjectSet ( "halfbottomsixth", OBJPROP_COLOR, Magenta );
            ObjectSet ( "halfbottomsixth", OBJPROP_STYLE, STYLE_DASH );
            ObjectSet ( "halfbottomsixth", OBJPROP_WIDTH, 1 );
         }//if (ObjectFind("halfbottomsixth") == -1)
         else {
            ObjectMove ( "halfbottomsixth", 0, TimeCurrent(), HalfBottomLine );
         }
         if ( ObjectFind ( "onesixth" ) == -1 ) {
            ObjectCreate ( "onesixth", 1, 0, TimeCurrent(), BottomGoldLine );
            ObjectSet ( "onesixth", OBJPROP_COLOR, Gold );
            ObjectSet ( "onesixth", OBJPROP_STYLE, STYLE_SOLID );
            ObjectSet ( "onesixth", OBJPROP_WIDTH, 2 );
         }//if (ObjectFind("onesixth") == -1)
         else {
            ObjectMove ( "onesixth", 0, TimeCurrent(), BottomGoldLine );
         }
         if ( ObjectFind ( "twosixth" ) == -1 ) {
            ObjectCreate ( "twosixth", 1, 0, TimeCurrent(), BottomGreenLine );
            ObjectSet ( "twosixth", OBJPROP_COLOR, Green );
            ObjectSet ( "twosixth", OBJPROP_STYLE, STYLE_SOLID );
            ObjectSet ( "twosixth", OBJPROP_WIDTH, 2 );
         }//if (ObjectFind(
         else {
            ObjectMove ( "twosixth", 0, TimeCurrent(), BottomGreenLine );
         }
         if ( ObjectFind ( "threesixth" ) == -1 ) {
            ObjectCreate ( "threesixth", 1, 0, TimeCurrent(), MiddleWhiteLine );
            ObjectSet ( "threesixth", OBJPROP_COLOR, White );
            ObjectSet ( "threesixth", OBJPROP_STYLE, STYLE_SOLID );
            ObjectSet ( "threesixth", OBJPROP_WIDTH, 2 );
         }//if (ObjectFind(
         else {
            ObjectMove ( "threesixth", 0, TimeCurrent(), MiddleWhiteLine );
         }
         if ( ObjectFind ( "foursixth" ) == -1 ) {
            ObjectCreate ( "foursixth", 1, 0, TimeCurrent(), TopGreenLine );
            ObjectSet ( "foursixth", OBJPROP_COLOR, Green );
            ObjectSet ( "foursixth", OBJPROP_STYLE, STYLE_SOLID );
            ObjectSet ( "foursixth", OBJPROP_WIDTH, 2 );
         }//if (ObjectFind(
         else {
            ObjectMove ( "foursixth", 0, TimeCurrent(), TopGreenLine );
         }
         if ( ObjectFind ( "fivesixth" ) == -1 ) {
            ObjectCreate ( "fivesixth", 1, 0, TimeCurrent(), TopGoldLine );
            ObjectSet ( "fivesixth", OBJPROP_COLOR, Gold );
            ObjectSet ( "fivesixth", OBJPROP_STYLE, STYLE_SOLID );
            ObjectSet ( "fivesixth", OBJPROP_WIDTH, 2 );
         }//if (ObjectFind(
         else {
            ObjectMove ( "fivesixth", 0, TimeCurrent(), TopGoldLine );
         }
         if ( ObjectFind ( "halftopsixth" ) == -1 ) {
            ObjectCreate ( "halftopsixth", 1, 0, TimeCurrent(), HalfTopLine );
            ObjectSet ( "halftopsixth", OBJPROP_COLOR, Magenta );
            ObjectSet ( "halftopsixth", OBJPROP_STYLE, STYLE_DASH );
            ObjectSet ( "halftopsixth", OBJPROP_WIDTH, 1 );
         }//if (ObjectFind("halftopsixth") == -1)
         else {
            ObjectMove ( "halftopsixth", 0, TimeCurrent(), HalfTopLine );
         }
         if ( ObjectFind ( "sixsixth" ) == -1 ) {
            ObjectCreate ( "sixsixth", 1, 0, TimeCurrent(), TopLine );
            ObjectSet ( "sixsixth", OBJPROP_COLOR, Magenta );
            ObjectSet ( "sixsixth", OBJPROP_STYLE, STYLE_SOLID );
            ObjectSet ( "sixsixth", OBJPROP_WIDTH, 2 );
         }//if (ObjectFind("sixsixth") == -1)
         else {
            ObjectMove ( "sixsixth", 0, TimeCurrent(), TopLine );
         }
         if ( ObjectFind ( "CT buffer high" ) == -1 ) {
            ObjectCreate ( "CT buffer high", 1, 0, TimeCurrent(), MagentaCtBufferHigh );
            ObjectSet ( "CT buffer high", OBJPROP_COLOR, Magenta );
            ObjectSet ( "CT buffer high", OBJPROP_STYLE, STYLE_DOT );
            ObjectSet ( "CT buffer high", OBJPROP_WIDTH, 1 );
         }//if (ObjectFind("CT buffer high") == -1)
         else {
            ObjectMove ( "CT buffer high", 0, TimeCurrent(), MagentaCtBufferHigh );
         }
         if ( ObjectFind ( "CT buffer low" ) == -1 ) {
            ObjectCreate ( "CT buffer low", 1, 0, TimeCurrent(), MagentaCtBufferLow );
            ObjectSet ( "CT buffer low", OBJPROP_COLOR, Magenta );
            ObjectSet ( "CT buffer low", OBJPROP_STYLE, STYLE_DOT );
            ObjectSet ( "CT buffer low", OBJPROP_WIDTH, 1 );
         }//if (ObjectFind("CT buffer low") == -1)
         else {
            ObjectMove ( "CT buffer low", 0, TimeCurrent(), MagentaCtBufferLow );
         }
         if ( ObjectFind ( "whitehigh" ) == -1 ) {
            ObjectCreate ( "whitehigh", 1, 0, TimeCurrent(), WhiteBoxHigh );
            ObjectSet ( "whitehigh", OBJPROP_COLOR, White );
            ObjectSet ( "whitehigh", OBJPROP_STYLE, STYLE_DOT );
            ObjectSet ( "whitehigh", OBJPROP_WIDTH, 1 );
         }//if (ObjectFind("whitehigh") == -1)
         else {
            ObjectMove ( "whitehigh", 0, TimeCurrent(), WhiteBoxHigh );
         }
         if ( ObjectFind ( "whitelow" ) == -1 ) {
            ObjectCreate ( "whitelow", 1, 0, TimeCurrent(), WhiteBoxLow );
            ObjectSet ( "whitelow", OBJPROP_COLOR, White );
            ObjectSet ( "whitelow", OBJPROP_STYLE, STYLE_DOT );
            ObjectSet ( "whitelow", OBJPROP_WIDTH, 1 );
         }//if (ObjectFind("whitelow") == -1)
         else {
            ObjectMove ( "whitelow", 0, TimeCurrent(), WhiteBoxLow );
         }
      }//if(ctgl != TopGoldLine || cbgl != BottomGoldLine)
   }//if (!IsTesting() && !IsVisualMode() )
}//void GetSixths()

bool rsi.volatilty ( int type ) {
   rsi.volatilty = NormalizeDouble ( rsi.val - rsi.val.prev, Digits );
   if ( rsi.volatilty > 0 ) {
      if ( type == OP_SELL ) {
         if ( rsi.volatilty > max.rsi.volatilty ) {
            return ( false );
         }
      }
   }
   if ( rsi.volatilty < 0 ) {
      if ( type == OP_BUY ) {
         if ( rsi.volatilty < -max.rsi.volatilty ) {
            return ( false );
         }
      }
   }
   return ( true );
}//bool rsi.volatilty ( int type )

double GetAtr ( int tf, int period, double multiplier ) {
   double atr = iATR ( NULL, tf, period, 0 );
   atr *= multiplier;
   return ( atr );
}

void ReadIndicatorValues() {
   rsi.val = GetRsi ( rsi.tf, rsi.period, rsi.appiled.price, 0 );
   rsi.val.prev = GetRsi ( rsi.tf, rsi.period, rsi.appiled.price, 1 );
   rsi.factor = MathAbs ( rsi.val - 50.0 ) / 25;
   rsi.factor = MathExp ( rsi.factor );
   GetSixths();
}//void ReadIndicatorValues()

//End Indicator module

///////////////////////////////////////////////////////////////////////////////////////////////////////
//Recovery module

void RecoveryModule() {
   //Draw a breakeven line if there is not one in place already.
   //The bot will adjust the tp's during the CountOpenTrades function.
   if ( ObjectFind ( breakevenlinename ) > -1 ) {
      return;
   }
   //Do not need a breakeven line if Recovery is already at be
   //if (ObjectFind(breakevenlinename) > -1) return;
   buy_price = 0;
   sell_price = 0;
   CheckRecoveryTakeProfit();
   double recovery_profit;
   if ( buy_price > 0 ) {
      recovery_profit = buy_price;
      recovery_profit = NormalizeDouble ( buy_price + ( recovery.break.even.profit.pips * Point ), Digits );
   }//if (buy_price > 0)
   if ( sell_price > 0 ) {
      recovery_profit = sell_price;
      recovery_profit = NormalizeDouble ( sell_price - ( recovery.break.even.profit.pips * Point ), Digits );
   }//if (sell_price > 0)
   ObjectCreate ( breakevenlinename, OBJ_HLINE, 0, TimeCurrent(), recovery_profit );
   ObjectSet ( breakevenlinename, OBJPROP_COLOR, break.even.line.colour );
   ObjectSet ( breakevenlinename, OBJPROP_STYLE, STYLE_SOLID );
   ObjectSet ( breakevenlinename, OBJPROP_WIDTH, 2 );
}//End void RecoveryModule()

void CheckRecoveryTakeProfit() {
   //This is adapted from the NB iExposure indicator. I do not understand how it works.
   //There will be redundant code, so anybody wishing to clear it up is most welcome to do so.
   ExtLines = 0;
   int    i, col, line;
   ArrayInitialize ( ExtSymbolsSummaries, 0.0 );
   int total = Analyze();
   if ( total > 0 ) {
      line = 0;
      for ( i = 0; i < ExtSymbolsTotal; i++ ) {
         if ( ExtSymbols[i] != symbol ) {
            continue;
         }
         if ( ExtSymbolsSummaries[i][DEALS] <= 0 ) {
            continue;
         }
         line++;
         //---- add line
         if ( line > ExtLines ) {
            int y_dist = ExtVertShift * ( line + 1 ) + 1;
            /*for(col=0; col<8; col++)
              {
               name="Line_"+line+"_"+col;
               if(ObjectCreate(name,OBJ_LABEL,windex,0,0))
                 {
                  ObjectSet(name,OBJPROP_XDISTANCE,ExtShifts[col]);
                  ObjectSet(name,OBJPROP_YDISTANCE,y_dist);
                 }
              }*/
            ExtLines++;
         }//if(line>ExtLines)
         //---- set line
         //color  price_colour;//Steve mod
         int    digits = MarketInfo ( ExtSymbols[i], MODE_DIGITS );
         double buy_lots = ExtSymbolsSummaries[i][BUY_LOTS];
         double sell_lots = ExtSymbolsSummaries[i][SELL_LOTS];
         if ( buy_lots != 0 ) {
            buy_price = NormalizeDouble ( ExtSymbolsSummaries[i][BUY_PRICE] / buy_lots, Digits );
         }
         if ( sell_lots != 0 ) {
            sell_price = NormalizeDouble ( ExtSymbolsSummaries[i][SELL_PRICE] / sell_lots, Digits );
         }
      }//for(i=0; i<ExtSymbolsTotal; i++)
   }//if(total>0)
}//End void CheckRecoveryTakeProfit()

int Analyze() {
   double profit;
   int    i, index, type, total = OrdersTotal();
//----
   for ( i = 0; i < total; i++ ) {
      if ( !OrderSelect ( i, SELECT_BY_POS ) ) {
         continue;
      }
      type = OrderType();
      if ( type != OP_BUY && type != OP_SELL ) {
         continue;
      }
      index = SymbolsIndex ( OrderSymbol() );
      if ( index < 0 || index >= SYMBOLS_MAX ) {
         continue;
      }
      //----
      ExtSymbolsSummaries[index][DEALS]++;
      profit = OrderProfit() + OrderCommission() + OrderSwap();
      ExtSymbolsSummaries[index][PROFIT] += profit;
      if ( type == OP_BUY ) {
         ExtSymbolsSummaries[index][BUY_LOTS] += OrderLots();
         ExtSymbolsSummaries[index][BUY_PRICE] += OrderOpenPrice() * OrderLots();
      } else {
         ExtSymbolsSummaries[index][SELL_LOTS] += OrderLots();
         ExtSymbolsSummaries[index][SELL_PRICE] += OrderOpenPrice() * OrderLots();
      }
   }
//----
   total = 0;
   for ( i = 0; i < ExtSymbolsTotal; i++ ) {
      if ( ExtSymbolsSummaries[i][DEALS] > 0 ) {
         total++;
      }
   }
//----
   return ( total );
}//int Analyze()

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int SymbolsIndex ( string SymbolName ) {
   bool found = false;
//----
   for ( int i = 0; i < ExtSymbolsTotal; i++ ) {
      if ( SymbolName == ExtSymbols[i] ) {
         found = true;
         break;
      }
   }
//----
   if ( found ) {
      return ( i );
   }
   if ( ExtSymbolsTotal >= SYMBOLS_MAX ) {
      return ( -1 );
   }
//----
   i = ExtSymbolsTotal;
   ExtSymbolsTotal++;
   ExtSymbols[i] = SymbolName;
   ExtSymbolsSummaries[i][DEALS] = 0;
   ExtSymbolsSummaries[i][BUY_LOTS] = 0;
   ExtSymbolsSummaries[i][BUY_PRICE] = 0;
   ExtSymbolsSummaries[i][SELL_LOTS] = 0;
   ExtSymbolsSummaries[i][SELL_PRICE] = 0;
   ExtSymbolsSummaries[i][NET_LOTS] = 0;
   ExtSymbolsSummaries[i][PROFIT] = 0;
//----
   return ( i );
}//End int SymbolsIndex(string SymbolName)

double CalculateReEntryLinePips ( int type ) {
   int ReEntryLinePips;
   double RsiFactor1;
   if ( type == OP_BUY ) {
      if ( rsi.val >= 50 ) {
         RsiFactor1 = ( 50.0 - rsi.val ) / 25;
      }
   }
   if ( type == OP_SELL ) {
      if ( rsi.val < 50 ) {
         RsiFactor1 = ( rsi.val - 50.0 ) / 25;
      }
   }
   RsiFactor1 = MathExp ( RsiFactor1 );
   double factor = open.trades;
   if ( factor == 0 ) {
      factor = 1;
   }
   ReEntryLinePips = NormalizeDouble ( SixthsRange / 6 / Point * RsiFactor1 , 0 );
   //ReEntryLinePips = (volatility/3*factor)*multiplier;
   return ( ReEntryLinePips );
}//End void CalculateReEntryLinePips()

void AddReEntryLine ( double price ) {
   if ( ObjectFind ( reentrylinename ) > -1 ) {
      ObjectDelete ( reentrylinename );
   }
   if ( !ObjectCreate ( reentrylinename, OBJ_HLINE, 0, TimeCurrent(), price ) ) {
      int err = GetLastError();
      Alert ( "Re-entry line draw failed with error(", err, "): ", ErrorDescription ( err ) );
      Print ( "Re-entry line draw failed with error(", err, "): ", ErrorDescription ( err ) );
      return ( 0 );
   }//if (!ObjectCreate(reentrylinename,OBJ_HLINE,0,TimeCurrent(),price) )
   ObjectSet ( reentrylinename, OBJPROP_COLOR, re.entry.line.colour );
   ObjectSet ( reentrylinename, OBJPROP_STYLE, STYLE_SOLID );
   ObjectSet ( reentrylinename, OBJPROP_WIDTH, 2 );
}//void AddReEntryLine(int type, double price)

void RecoveryTrailingStop() {
   double break.even, new.stop;
   static bool reached;
   RefreshRates();
   if ( ObjectFind ( breakevenlinename ) > -1 ) {
      break.even = ObjectGet ( breakevenlinename, OBJPROP_PRICE1 );
   } else {
      return;
   }
   if ( candle.stick.trailing.stop ) {
      if ( BuyOpen ) {
         if ( Ask >= break.even + ( recovery.trailing.stop.at * Point ) ) {
            reached = true;
            if ( ObjectGet ( breakevenlinename, OBJPROP_COLOR ) != recovery.stop.loss.line.colour ) {
               ObjectSet ( breakevenlinename, OBJPROP_COLOR, recovery.stop.loss.line.colour );
            }
         }
         if ( reached ) {
            if ( OldRecoverTrailBars != Bars ) {
               if ( MathMin ( iLow ( NULL, rec.cst.time.frame, rec.cst.trail.candles ), Low[1] ) > break.even ) {
                  ObjectMove ( breakevenlinename, 0, Time[0], Low[1] );
               }
               OldRecoverTrailBars = Bars;
            }
            if ( Ask <= break.even ) {
               reached = false;
               ForceTradeClosure = true;
               CloseAllTrades();
               ObjectDelete ( breakevenlinename );
               return;
            }
         }
      }
      if ( SellOpen ) {
         if ( Bid <= break.even - ( recovery.trailing.stop.at * Point ) ) {
            reached = true;
            if ( ObjectGet ( breakevenlinename, OBJPROP_COLOR ) != recovery.stop.loss.line.colour ) {
               ObjectSet ( breakevenlinename, OBJPROP_COLOR, recovery.stop.loss.line.colour );
            }
         }
         if ( reached ) {
            if ( OldRecoverTrailBars != Bars ) {
               if ( MathMax ( iHigh ( NULL, rec.cst.time.frame, rec.cst.trail.candles ), High[1] ) < break.even ) {
                  ObjectMove ( breakevenlinename, 0, Time[0], High[1] );
               }
               OldRecoverTrailBars = Bars;
            }
            if ( Bid >= break.even ) {
               reached = false;
               ForceTradeClosure = true;
               CloseAllTrades();
               ObjectDelete ( breakevenlinename );
               return;
            }
         }
      }
   }
   if ( jumping.trailing.stop ) {
      if ( BuyOpen ) {
         if ( Ask >= break.even + ( ( rec.jump.stop.pips * 2 ) * Point ) ) {
            reached = true;
            new.stop = break.even + rec.jump.stop.pips * Point  ;
            ObjectSet ( breakevenlinename, OBJPROP_COLOR, recovery.stop.loss.line.colour );
            ObjectMove ( breakevenlinename, 0, Time[0], new.stop );
         }
         if ( reached ) {
            if ( Ask <= break.even ) {
               reached = false;
               ForceTradeClosure = true;
               CloseAllTrades();
               ObjectDelete ( breakevenlinename );
               return;
            }
         }
      }
      if ( SellOpen ) {
         if ( Bid <= break.even - ( ( rec.jump.stop.pips * 2 ) * Point ) ) {
            reached = true;
            new.stop = break.even - rec.jump.stop.pips * Point ;
            ObjectSet ( breakevenlinename, OBJPROP_COLOR, recovery.stop.loss.line.colour );
            ObjectMove ( breakevenlinename, 0, Time[0], new.stop );
         }
         if ( reached ) {
            if ( Bid >= break.even ) {
               reached = false;
               ForceTradeClosure = true;
               CloseAllTrades();
               ObjectDelete ( breakevenlinename );
               return;
            }
         }
      }
   }
}

void AutoCalculateRecoveryVariable() {
   use.1.1.2.4.recovery = false;
   use.1.2.6.recovery = false;
   if ( BoxBuyOpen || BoxSellOpen ) {
      use.1.1.2.4.recovery = true;
   } else {
      use.1.2.6.recovery = true;
   }
   if ( automate.rts.choice ) {
      use.recovery.trailing.stop = false;
      if ( rsi.val > 45 ) {
         if ( BuyOpen ) {
            use.recovery.trailing.stop = true;
         }
      }
      if ( rsi.val < 55 ) {
         if ( SellOpen ) {
            use.recovery.trailing.stop = true;
         }
      }
      recovery.break.even.profit.pips = NormalizeDouble ( GetAtr ( 60, 14, 1.5 ) / Point, 0 );
   } else {
      use.recovery.trailing.stop = true;
      recovery.break.even.profit.pips = NormalizeDouble ( GetAtr ( 5, 14, 1.5 ) / Point, 0 );
      recovery.trailing.stop.at = NormalizeDouble ( GetAtr ( 60, 14, 1.5 ) / Point, 0 );
      if ( jumping.trailing.stop ) {
         rec.jump.stop.pips = NormalizeDouble ( GetAtr ( 60, 14, 1.5 ) / Point, 0 );
      }
   }
}

//End Recovery module
///////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////
//Central Bank Intervention module

bool CentralBankInterventionModule()
{
   /*
   Called from start() if use.cbi is enabled.
   There are two methods of detecting a violent move:
      astral:
         Monitors the TickTable array and reacts to the movement in the market being >= the threshold.
         The circular TickTable code is provided by Carsten. Many thanks Carsten. You are a star.
      George
         Builds up an swma of the Bid and draws a line to represent that moving averages, plus optional hilo lines
         that represent the price the market has to reach in order to trigger CB intervention/heavy news status.
   Function returns true if all actions succeed or none are necessary, and false to force the bot to keep on retrying.
   I got into a bit of a tangle with the various while(some condition met, keep on looping around) snippets and kept on
   setting up infinite loops, so each of them has a max tries of 20 before forcible exit.
   */
   double take, stop, price, type;
   bool result;
   int tries;
   bool ThresholdPassed = false;//Set to true if the threshold is breached, so the bot knows to take action
   //astral-inspired tick table
   if ( use.astral ) {
      //Store the latest quote in TickTable
      StoreQuote();
      if ( is_filled == 0 ) { // table not full yet, so nothing to do
         return ( true );
      }//if (is_filled == 0)
      //Calculate the direction of the move, and whether it is big enough to trigger action
      direction = none;
      int index = ( tc + 1 ) % table.size;
      if ( TickTable[tc] < TickTable[index] ) {
         direction = down;
      }
      if ( TickTable[tc] > TickTable[index] ) {
         direction = up;
      }
      if ( TickDiff > threshold ) {
         ThresholdPassed = true;
      }
   }//if (use.astral)
   //George's smma
   if ( use.george ) {
      CalculateMaOfTicks();
      if ( number_of_ticks < nr.ticks.average ) {
         return ( true ); //Not enough ticks for the ma to be meaningful yet
      }//if (number_of_ticks >= nr.ticks.average)
      //Calculate the direction of the move, and whether it is big enough to trigger action
      direction = none;
      double target = ObjectGet ( AverageTick, OBJPROP_PRICE1 );
      if ( Bid > target ) {
         direction = up;
      }
      if ( Bid < target ) {
         direction = down;
      }
      //Look for a break of the upper trigger line
      if ( direction == up ) {
         target = ObjectGet ( AverageTickUp, OBJPROP_PRICE1 );
         if ( Bid >= target ) {
            ThresholdPassed = true;
         }
      }//if (direction == up)
      //Look for a break of the lower trigger line
      if ( direction == down ) {
         target = ObjectGet ( AverageTickDn, OBJPROP_PRICE1 );
         if ( Bid <= target ) {
            ThresholdPassed = true;
         }
      }//if (direction == up)
   }//if (use.george)
   // table is full, now we can check for the big moves
   //ThresholdPassed tells the bot that there is a big move in progress
   //direction tells the bot whether that move is up or down
   if ( ThresholdPassed ) {
      int day.of.week = DayOfWeek();
      if ( day.of.week == 0 || day.of.week == 1){
         double hour = TimeHour(Time[0]);
         if ( hour == broker.start.hour ) {
            return ( true );
         }
      }
      TakingEmergencyAction = true;//Used in SendSingleTrade to create a mahoosive slippage allowance
      // The price difference between the latest and the first entry in
      // our table is above the threshold, so take action.
      /////////////////////////////////////////////////////////////////////////////////////////////////
      //Close trade
      if ( close.on.cbi && !TradesClosed && open.trades > 0 ) {
         result = false;
         if ( direction == down ) {
            tries = 0;
            while ( !result ) {
               result = CbiCloseTrades ( OP_BUY );
               if ( result ) {
                  TradesClosed = true;
               }
               tries++;
               if ( tries == 20 ) {
                  return ( true );
               }
            }//while (!result)
         }//if (direction == down)
         if ( direction == up ) {
            tries = 0;
            while ( !result ) {
               result = CbiCloseTrades ( OP_SELL );
               if ( result ) {
                  TradesClosed = true;
               }
               tries++;
               if ( tries == 20 ) {
                  return ( true );
               }
            }//while (!result)
         }//if (direction == ip)
      }//if (close.on.cbi)
      /////////////////////////////////////////////////////////////////////////////////////////////////
      /////////////////////////////////////////////////////////////////////////////////////////////////
      //Hedge an existing trade
      if ( hedge.on.cbi && !HedgeSent && ticket.no > -1 ) {
         result = false;
         if ( direction == down ) {
            tries = 0;
            while ( !result ) {
               result = CbiHedging ( OP_BUY ); //Long trades need hedging short
               if ( result ) {
                  HedgeSent = true;
               }
               tries++;
               if ( tries == 20 ) {
                  return ( true );
               }
            }//while (!result)
         }//if (direction == down)
         if ( direction == up ) {
            tries = 0;
            while ( !result ) {
               result = CbiHedging ( OP_SELL ); //Short trades need hedging long
               if ( result ) {
                  HedgeSent = true;
               }
               tries++;
               if ( tries == 20 ) {
                  return ( true );
               }
            }//while (!result)
         }//if (direction == ip)
      }//if (hedge.on.cbi)
      /////////////////////////////////////////////////////////////////////////////////////////////////
      /////////////////////////////////////////////////////////////////////////////////////////////////
      //Take a new trade
      if ( trade.on.cbi && !TradeSent ) {
         double SendLot = LotCalculate();
         if ( direction == up ) {
            type = OP_BUY;
            RefreshRates();
            price = Ask;
            if ( trade.on.cbi.tp > 0 ) {
               take = NormalizeDouble ( Ask + ( trade.on.cbi.tp * Point ), Digits );
            }
            if ( trade.on.cbi.sl > 0 ) {
               stop = NormalizeDouble ( Ask - ( trade.on.cbi.sl * Point ), Digits );
            }
         }//if (direction == up)
         if ( direction == down ) {
            type = OP_SELL;
            RefreshRates();
            price = Bid;
            if ( trade.on.cbi.tp > 0 ) {
               take = NormalizeDouble ( Bid - ( trade.on.cbi.tp * Point ), Digits );
            }
            if ( trade.on.cbi.sl > 0 ) {
               stop = NormalizeDouble ( Bid + ( trade.on.cbi.sl * Point ), Digits );
            }
         }//if (direction == up)
         result = SendSingleTrade ( type, trade.comment, SendLot, price, stop, take );
         if ( result ) {
            TradeSent = true;
         }//if (result)
         if ( !result ) {
            return ( false );
         }//if (result)
      }//if (trade.on.cbi)
      /////////////////////////////////////////////////////////////////////////////////////////////////
   }//if (ThresholdPassed)
   else {
      TakingEmergencyAction = false;
      //TradeSent = false;
      //HedgeSent = false;
      TradesClosed = false;
   }//else
   //Got this far, so everything has worked as required
   return ( true );
}//End bool CentralBankInterventionModule()

void StoreQuote()
{
   //New code - see 'original code' at the end of this function
   // increment the counter
   tc += 1;
   tc = tc % table.size;// keeps tc within table.size
   // fill the current tick value into the table
   TickTable[tc] = Bid;
   if ( is_filled == 0 ) { // table not full yet
      fill_check_counter += 1;
      if ( fill_check_counter == table.size ) {
         is_filled = 1;
      }
   }//if (is_filled == 0)
   else {
      TickDiff = MathAbs ( TickTable[ ( tc + 1 ) % table.size] - TickTable[tc] ) * PipMultiplier;
   }//else
   /*
   Original code
   // increment the counter
   tc += 1;
   tc = tc % table.size;// keeps tc within table.size
   */
}//End void StoreQuote()

void CalculateMaOfTicks()
{
   //This code from George Heitman, or wfh2006 at FF. Cheers George.
   //we got an incoming tick
   number_of_ticks += 1;
   //make sure we have gotten at least nr.ticks.average ticks before displaying an average
   if ( number_of_ticks >= nr.ticks.average ) {
      sum_of_ticks -= moving_average;
      moving_average = ( sum_of_ticks + Bid ) / nr.ticks.average;
      if ( ObjectFind ( AverageTick ) == -1 ) {
         ObjectCreate ( AverageTick, OBJ_HLINE, 0, 0, moving_average, 0 );
         ObjectSet ( AverageTick, OBJPROP_WIDTH, 2 );
         ObjectSet ( AverageTick, OBJPROP_COLOR, line.color );
         ObjectCreate ( AverageTickUp, OBJ_HLINE, 0, 0, moving_average, 0 );
         ObjectSet ( AverageTickUp, OBJPROP_WIDTH, 1 );
         ObjectSet ( AverageTickUp, OBJPROP_COLOR, line.color );
         ObjectCreate ( AverageTickDn, OBJ_HLINE, 0, 0, moving_average, 0 );
         ObjectSet ( AverageTickDn, OBJPROP_WIDTH, 1 );
         ObjectSet ( AverageTickDn, OBJPROP_COLOR, line.color );
      }//if (ObjectFind(AverageTick) == -1)
      ObjectSet ( AverageTick, OBJPROP_PRICE1, moving_average );
      ObjectSet ( AverageTickUp, OBJPROP_PRICE1, moving_average + channel.delta * Point );
      ObjectSet ( AverageTickDn, OBJPROP_PRICE1, moving_average - channel.delta * Point );
   }//if (number_of_ticks >= nr.ticks.average)
   sum_of_ticks += Bid;
}//End void CalculateMaOfTicks()


bool CbiCloseTrades ( int type )
{
   bool success = true;
   if ( OrdersTotal() == 0 ) {
      return ( true );
   }
   for ( int cc = OrdersTotal() - 1; cc >= 0; cc-- ) {
      if ( !OrderSelect ( cc, SELECT_BY_POS ) ) {
         continue;
      }
      if ( OrderMagicNumber() != magic.number ) {
         continue;
      }
      if ( OrderSymbol() != Symbol() ) {
         continue;
      }
      while ( IsTradeContextBusy() ) {
         Sleep ( 100 );
      }
      if ( OrderType() == type ) {
         bool result = OrderClose ( OrderTicket(), OrderLots(), OrderClosePrice(), 1000, CLR_NONE );
      }
      if ( result ) {
         cc++;
      }
      if ( !result ) {
         success = false;
      }
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   return ( success );
}//End bool CbiCloseTrades(int type)


bool CbiHedging ( int type )
{
   //Opens an opposite direction hedge trade to that of the passed param
   bool success = true;
   bool result;
   int HedgeType = OP_SELL;
   if ( type == OP_SELL ) {
      HedgeType = OP_BUY;
   }
   if ( OrdersTotal() == 0 ) {
      return ( true );
   }
   for ( int cc = 0; cc <= OrdersTotal() - 1; cc++ ) {
      if ( !OrderSelect ( cc, SELECT_BY_POS ) ) {
         continue;
      }
      if ( OrderMagicNumber() != magic.number ) {
         continue;
      }
      if ( OrderSymbol() != Symbol() ) {
         continue;
      }
      if ( OrderType() != type ) {
         continue;
      }
      while ( IsTradeContextBusy() ) {
         Sleep ( 100 );
      }
      //Check to see if the trade is already hedged.
      bool hedged = IsTradeAlreadyHedged ( cc );
      if ( hedged ) {
         //ticket.no is set in CountOpenTrades(). Reset the selected trade in case the intervening code leaves it unselected.
         OrderSelect ( ticket.no, SELECT_BY_TICKET, MODE_TRADES );
      }//if (IsTradeAlreadyHedged(index))
      if ( !hedged ) {
         if ( OrderType() == type ) {
            result = SetupHedgeTrade ( HedgeType );
         }
         if ( !result ) {
            success = false;
         }
      }//if (!hedged)
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   return ( success );
}//End bool CbiHedging(int type)

bool SetupHedgeTrade ( int type )
{
   //Order that needs hedging is already selected. This function sets up and sends the hedge trade
   bool result = false;
   int tries = 0;
   double SendLots;
   double price;
   SendLots = total.lots.open * cbi.hedge.lot.multiplier;
   if ( type == OP_SELL ) {
      //Check the trade does need hedging
      if ( OrderProfit() > 0 && OrderStopLoss() > OrderOpenPrice() ) {
         return ( true );   //No need to hedge a safe trade
      }
      RefreshRates();
      price = Bid;
   }//if (type == OP_SELL)
   if ( type == OP_BUY ) {
      //Check the trade does need hedging
      if ( OrderProfit() > 0 && OrderStopLoss() < OrderOpenPrice() ) {
         return ( true );   //No need to hedge a safe trade
      }
      RefreshRates();
      price = Ask;
   }//if (type == OP_BUY)
   while ( IsTradeContextBusy() ) {
      Sleep ( 100 );
   }
   int tn = OrderTicket();//Need this to reselect the trade to remove the tp and sl from the trade
   while ( !result ) {
      result = SendSingleTrade ( type, trade.comment, SendLots, price, 0, 0 );
      //Remove existing tp/sl from the hedged trade. I will tidy this up later
      if ( result ) {
         HedgingInProgress = true;
         OrderSelect ( tn, SELECT_BY_TICKET );
         if ( OrderTakeProfit() > 0 ) {
            while ( IsTradeContextBusy() ) {
               Sleep ( 100 );
            }
            ModifyOrder ( tn, OrderStopLoss(), 0);
         }//if (OrderTakeProfit() > 0)
         if ( OrderStopLoss() > 0 ) {
            while ( IsTradeContextBusy() ) {
               Sleep ( 100 );
            }
            ModifyOrder ( tn, 0, OrderTakeProfit() );
         }//if (OrderTakeProfit() > 0)
      }//if (result)
      tries++;
      if ( tries == 20 ) {
         result = true;
      }
   }//while (!result)
   return ( result );
}//bool SetupHedgeTrade()

bool IsTradeAlreadyHedged ( int index )
{
   /*
   Trade will already be hedged if:
      - there is an opposite direction trade open
      - the opp trade has a lot size x HedgeLotsMultiplier
   */
   //Alread at the end of the trade loop?
   if ( index == OrdersTotal() - 1 ) {
      return ( false );
   }
   //Need to know the order type and lot size
   int type = OrderType();
   double LotSize = OrderLots();
   //Loop through the remaining trades to find a hedge. Reselect original trade and teturn true if found
   for ( int cc = index + 1; cc < OrdersTotal(); cc++ ) {
      if ( !OrderSelect ( cc, SELECT_BY_POS ) ) {
         continue;
      }
      if ( OrderSymbol() != Symbol() ) {
         continue;
      }
      if ( OrderMagicNumber() != magic.number ) {
         continue;
      }
      //All EA belonging conditions satisfied, so examine the trades
      if ( type == OP_BUY && OrderType() == OP_SELL && OrderLots() == LotSize * cbi.hedge.lot.multiplier ) {
         //ticket.no is set in CountOpenTrades(). Reset the selected trade.
         OrderSelect ( ticket.no, SELECT_BY_TICKET, MODE_TRADES );
         return ( true ); //Is a hedge
      }//if (type == OP_BUY && OrderType() == OP_SELL && OrderLots() == LotSize * 2)
      if ( type == OP_SELL && OrderType() == OP_BUY && OrderLots() == LotSize * cbi.hedge.lot.multiplier ) {
         //ticket.no is set in CountOpenTrades(). Reset the selected trade.
         OrderSelect ( ticket.no, SELECT_BY_TICKET, MODE_TRADES );
         return ( true ); //Is a hedge
      }//if (type == OP_SELL && OrderType() == OP_BUY && OrderLots() == LotSize * 2)
   }//for (int cc = index + 1); cc < OrdersTotal(); cc++)
   //ticket.no is set in CountOpenTrades(). Reset the selected trade.
   OrderSelect ( ticket.no, SELECT_BY_TICKET, MODE_TRADES );
   //Got this far, so trade is not already hedged
   return ( false );
}//End bool IsTradeAlreadyHedged(int index)

//End Central Bank Intervention module
////////////////////////////////////////////////////////////////////////////////////////////////



void CleanGlobalVariables ( string type ) {
   if ( type == "balance" ) {
      if ( GlobalVariableGet ( buy.first.curr ) == 0 ) {
         GlobalVariableDel ( buy.first.curr );
      }
      if ( GlobalVariableGet ( buy.sec.curr ) == 0 ) {
         GlobalVariableDel ( buy.sec.curr );
      }
      if ( GlobalVariableGet ( sell.first.curr ) == 0 ) {
         GlobalVariableDel ( sell.first.curr );
      }
      if ( GlobalVariableGet ( sell.sec.curr ) == 0 ) {
         GlobalVariableDel ( sell.sec.curr );
      }
   }
   if ( type == "Testing" ) {
      int count = GlobalVariablesDeleteAll ( Beast );
      Print ( "GlobalVariablesDeleted :", count );
   }
}


datetime hhmm_to_time ( double hhmm ) {
   return ( StrToTime ( DoubleToStr ( MathFloor ( hhmm ), 0 ) + ":" + DoubleToStr ( ( hhmm - MathFloor ( hhmm ) ) * 100, 0 ) ) );
}//End datetime hhmm_to_time(double hhmm)


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start() {
//----

   if ( OrdersTotal() == 0 ) {
      ticket.no = -1;
      ForceTradeClosure = false;
      HedgingInProgress = false;
   }//if (OrdersTotal() == 0)
   if ( ForceTradeClosure ) {
      CloseAllTrades();
      return;
   }//if (ForceTradeClosure)
   ReadIndicatorValues();
   static int ReadBars;
   /////////////////////////////////////////////////////////////////////////////////////////////////////
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Find open trades.
   //Will not normally need both routines.
   WatchOpenTrades();
   //Reset the CBI bools
   if ( open.trades == 0 ) {
      TakingEmergencyAction = false;
      TradeSent = false;
      HedgeSent = false;
      TradesClosed = false;
   }//if (open.trades > 0)
   //Hedging. This might need removing
   if ( HedgingInProgress ) {
      if ( basket.profit >= hedge.break.even.profit ) {
         CloseAllTrades();
      }//if (upl <= HedgeStopLoss && HedgeStopLoss != 0)
      if ( ForceTradeClosure ) {
         return;
      }
   }//if (UseHedging)
   /////////////////////////////////////////////////////////////////////////////////////////////////////
   //Central Bank Intervention module
   if ( use.cbi ) {
      int tries;
      bool ok = false;
      while ( !ok ) {
         ok = CentralBankInterventionModule();
         tries++;
         if ( tries == 20 ) {
            ok = true;
         }
      }//while (!ok)
   }//if (use.cbi)
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Recovery
   if ( use.recovery && !HedgingInProgress ) {
      if ( open.trades >= start.recovery.at.trades ) {
         RecoveryInProgress = true;
      }
      if ( auto.calc.rec.var ) {
         AutoCalculateRecoveryVariable();
      }
      if ( RecoveryInProgress && ObjectFind ( breakevenlinename ) == -1 ) {
         RecoveryModule();
      }//if (RecoveryInProgress && ObjectFind(breakevenlinename) == -1)
      //Recovery trailing sl
      if ( RecoveryInProgress && use.recovery.trailing.stop ) {
         RecoveryTrailingStop();
      }//if (RecoveryInProgress && use.recovery.trailing.stop)
   }//if (use.recovery)
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //Trading times
   bool TradeTimeOk = CheckTradingTimes();
   if ( !TradeTimeOk ) {
      Comment ( "Outside trading hours\nstart_hourm-end.hourm: ", start.hourm, "-", end.hourm, "\nstart_houre-end.houre: ", start.houre, "-", end.houre );
      return;
   }//if (hour < start.hourm)
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //Available margin filters
   enough.margin = true;//For user display
   margin.message = "";
   if ( use.scoobs.margin.check && open.trades > 0 ) {
      if ( AccountMargin() > ( AccountFreeMargin() / 100 ) ) {
         margin.message = "There is insufficient margin to allow trading. You might want to turn off the use.scoobs.margin.check input.";
         DisplayUserFeedback();
         return;
      }//if(AccountMargin() > (AccountFreeMargin()/100))
   }//if (use.scoobs.margin.check)
   if ( use.forex.kiwi && AccountMargin() > 0 ) {
      double ml = NormalizeDouble ( AccountEquity() / AccountMargin() * 100, 2 );
      if ( ml < fk.minimum.margin.procent ) {
         margin.message = StringConcatenate ( "There is insufficient margin percent to allow trading. ", DoubleToStr ( ml, 2 ), "%" );
         DisplayUserFeedback();
         return;
      }//if (ml < fk.minimum.margin.procent)
   }//if (use.forex.kiwi && AccountMargin() > 0)
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Trading
   if ( !stop.trading ) {
      //Trend detection
      if ( open.trades == 0 && do.white.box ) {
         WhiteBoxTradingOpportunities();
      }
      MagentaLineTradingOpportunities();
   }//if (!stop.trading)
   ///////////////////////////////////////////////////////////////////////////////////////////////
   DisplayUserFeedback();
//----
   return ( 0 );
}
//+------------------------------------------------------------------+