TRUE Forex

Просмотр кода форекс советника BigBob.mq4

//+-------------------------------------------------------------------+
//|            Nanningbob V10 auto trading robot by Steve Hopwood.mq4 |
//|                                  Copyright © 2009, Steve Hopwood  |
//|                              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  ranging "Ranging"
#define  upbutuntradable "Up, but not start of trend"
#define  downbutuntradable "Down, but not start of trend"
#define  buy "Buy"
#define  sell "Sell"
#define  confused "Confused, and so cannot trade"
#define  trending "Trending"
#define  opentrade "There is a trade open"
#define  stopped "Trading is stopped"
#define  breakevenlinename "Break even line"
#define  reentrylinename "Re entry line"
#define  trendorigin "Trend"
#define  rangeorigin "Range"
//Caterpillar
#define  buyline "Buy line"
#define  sellline "Sell 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



/*

Go to http://www.forexfactory.com/showthread.php?t=308304 to read about the trading methodology

carolco's grid idea: http://www.forexfactory.com/showthread.php?p=4887703#post4887703

Matt Kennel has provided the code for bool O_R_CheckForHistory(int ticket). Cheers Matt, You are a star.

This program uses Global Variables to tell BigBob whether the trade was originally a trend or range trade:
   - value 0 = trend
   - value 1 = range
The GV 'name' is the chart symbol. BB cleans out the redundant GV's during CountOpenTrades()

Navigate around the functions by highlighing them and pressing ctrl + F. YOu have to add the Bookmarks facility to
your code editor:
- Click View
- Click Customise
- Scroll down the 'Available' window until you find the bookmarks and click the Insert button to add them to your editor

Code for adding debugging Sleep
Alert("G");
int x = 0;
while (x == 0) Sleep(100);

FUNCTIONS LIST
int init()
int start()

----Trading----

void LookForTrendTradingOpps()
void LookForRangeTradingOpps()
bool IsTradingAllowed()
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
bool DoesTradeExist()
void CountOpenTrades()
bool CloseTrade(int ticket)
void LookForTradeClosure()
bool CheckTradingTimes()
void CloseAllTrades()

//Caterpillar
void StartCaterpillar()
void LookForCatTradingOpportunities()
void DeleteOrphanGlobals()

//Carolco
void StartCarolco()
void SendGrid()
void DeletePendings()


----Balance/swap filters module----
void TradeDirectionBySwap()
bool IsThisPairTradable()
bool BalancedPair(int type)

----Matt's Order Reliable library code
bool O_R_CheckForHistory(int ticket) Cheers Matt, You are a star.
void O_R_Sleep(double mean_time, double max_time)

----Indicator readings----
void ReadIndicatorValues()
void GetBB()
double GetMa(int tf, int period, int mashift, int method, int ap, int shift)
double CalculateVolatility(int period, int LookBack)

----Trend detection module----
void TrendDetectionModule()
void GetTrendConfirmationCandleDir()


----Balance/swap filters module----
void TradeDirectionBySwap()
bool IsThisPairTradable()
bool BalancedPair(int type)

----Hanover module. The functions----
bool HanoverFilter(int type)
void SetUpArrays()
void CleanUpInputString()
int CalculateParamsPassed()
void ReadHanover()
int LoadRSvalues()  
double ReadStrength(string curr, string tf, int shift)


----Recovery----
void RecoveryModule()
void CheckRecoveryTakeProfit()
int Analyze()
int SymbolsIndex(string SymbolName)
void RecoveryCandlesticktrailingStop()
void LockInRecoveryProfit()
void RecoveryCandlesticktrailingStop()

----Re-entry line----
void AddReEntryLine(double price)
void CalculateReEntryLinePips()
void ReplaceReEntryLine()

----Trade management module----
void TradeManagementModule()
void BreakEvenStopLoss()
bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
void JumpingStopLoss() 
void HiddenTakeProfit()
void HiddenStopLoss()
void TrailingStopLoss()

//sq's string to array module
void CleanUpInputString() Mine
int StringFindCount(string str, string str2)
void StrPairToStringArray(string str, string &a[], string p_suffix, string delim=",")
void StrToStringArray(string str, string &a[], string delim=",")

*/

//Defined constants from hanover. Thanks David
#define AUD 0
#define CAD 1
#define CHF 2
#define EUR 3
#define GBP 4
#define JPY 5
#define NZD 6
#define USD 7

#define M1  0
#define M5  1
#define M15 2
#define M30 3
#define H1  4
#define H4  5
#define D1  6
#define W1  7
#define MN  8



extern string  gen="----General inputs----";
extern double  Lot=0.02;
extern bool    StopTrading=false;
extern bool    TradeLong=true;
extern bool    TradeShort=true;
extern int     MagicNumber=0;
//extern string  TradeComment="";
extern bool    CriminalIsECN=true;
extern double  MaxSpread=120;

//Hanover
extern string  hm="----Hanover module----";
extern bool    UseHanover=true;
extern string  ctf="Tren trading time frames";
//extern string  TimeFrames="M1,M5,M15,M30,H1,H4,D1,W1,MN";
extern string  TrendTimeFrames="D1";
extern int     TrendSlopeConfirmationCandles=0;
extern int     TrendStrongThreshold=0;
extern int     TrendWeakThreshold=0;
extern string  hof="Hanover output file";
extern string  OutputFile            = "Output---Recent Strength.CSV";
extern int     NumPoints=15;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Arrays etc
string         InputString;//All purpose string to pass to CleanUpInputString() to remove unwanted leading/trailing stuff
int            NoOfTrendTimeFrames;//The number for timeframes inputted into the TimeFrames input
string         Tf[];//Holds the time frames inputted into the TimeFrames input
string         StrongWeak[];//Holds the pair that represents the strongest and weakest in each time frame
string         StrongestCcy[], WeakestCcy[];//Go on, take a guess
double         StrongVal[], PrevStrongVal[], WeakVal[], PrevWeakVal[];//Another guess?
string         ConstructedPair[];//Holds the pairs made out of the currencies
string         Ccy1, Ccy2;//First and second currency in the pair

//Variables copied from the Strength Alerts indi. int LoadRSvalues() came from this
int      dig, tmf, h, i, j, k;
string alrt[11];
double   RSvalue[8,9,99];   // [currency,timeframe,datapoint#]
                            // currency: 0=AUD, 1=CAD, 2=CHF, 3=EUR, 4=GBP, 5=JPY, 6=NZD, 7=USD
                            // timeframe: 0=M1, 1=M5, 2=M15, 3=M30, 4=H1, 5=H4, 6=D1, 7=W1, 8=MN
                         
string   ccy[8] = {"AUD","CAD","CHF","EUR","GBP","JPY","NZD","USD"};
string   tf[9]  = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
string   arr[11];

int      ReadBars;//Bot reads the output file when this != Bars   
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  bf="----Trading balance filters----";
extern bool    UseZeljko=true;
extern bool    OnlyTradeCurrencyTwice=true;

extern string  pts="----Swap filter----";
extern bool    CadPairsPositiveOnly=true;
extern bool    AudPairsPositiveOnly=true;
extern bool    NzdPairsPositiveOnly=true;


//Leave private for now and make external later on should there be a demand. At the mo, I am using the defaults
//from 10.0 4H CTR BOTH
string  bbi="----Bollinger Band inputs----";
int     BbPeriod=25;
int     BbDeviation=2;


extern string  vs="----Volatility inputs----";
extern int     LookBackDays=20;
/*
extern int     LowVolatility=100;
extern int     MediumVolatility=150;
extern int     HighVolatility=200;
extern int     PsychoticallyDeranged=250;
*/

//Trend detection MA's. Default to Bob's settings
extern string  tmas="----Trend detection moving averages----";
extern int     FastMaTdTF=1440;//Time frame defaults to D1 chart 
extern int     FastMaTdPeriod=2;
extern int     FastMaTdShift=2;//The MA Shift input
extern string  tmame="Method: 0=sma; 1=ema; 2=smma;  3=lwma";
extern int     FastMaTdMethod=2;
extern string  tmaap="Applied price: 0=Close; 1=Open; 2=High";
extern string  tmaap1="3=Low; 4=Median; 5=Typical; 6=Weighted";
extern int     FastMaTdAppliedPrice=4;
extern int     SlowMaTdTF=1440;//Time frame defaults to D1 chart 
extern int     SlowMaTdPeriod=8;
extern int     SlowMaTdMethod=2;
extern int     SlowMaTdShift=2;
extern int     SlowMaTdAppliedPrice=4;

extern string  spt="----Specific Trend trading inputs----";
extern bool    AllowTrendTrading=true;
extern bool    OnlyTradeStartOfTrend=true;
extern int     MinimumTrendTradingVolatility=150;
extern int     MinTriggerCandlePipsMovement=30;
extern int     TrendConfirmationCandleTF=15;
extern int     TrendTakeProfit=0;
extern int     TrendStopLoss=0;
extern string  TrendTradeComment="Trend";
extern string  cat="----Caterpillar trend trade entry and TS----";
extern bool    UseCaterpillar=false;
extern int     MaxTrades=5;
extern int     MinPipsBetweenCandles=5;//Min distance between trade open prices
extern int     CatTimeFrame=60;//Trading/updating tf can be independent of current chart
extern color   BuyLineColour=Green;
extern color   SellLineColour=Red;
extern string  CatTradeComment="Caterpillar";

extern string  car="----Carolco pending trade entries----";
extern bool    UseCarolco=true;
extern double  CarolcoGridLot=0.02;
extern bool    UseCarolcoStopLoss=true;
extern int     TradesInGrid=5;
extern int     PipsBetweenTrades=20;
extern string  CarolcoTradeComment="Carolco grid";

extern string  tte="--Trend trade exit strategies--";
extern string  mte="1) D1 candlestick median (osthafen's idea)";//Closes a trade when the mid-point of the D1 candle moves to the wrong side of fast ma
extern bool    UseOsthafen=false;//Set this as the default strategy - something has to be ds
//This one offers the use of a MA of the user's choice. Defaults to a rough median of the fast and slow trend ma's
extern string  drg="2) dragosd1 (median MA)";
extern bool    UseDragosd1=false;
extern bool    UseTouch=false;
extern bool    UseClose=false;
extern int     DragMaTdTF=1440;//Time frame defaults to D1 chart 
extern int     DragMaTdPeriod=5;
extern int     DragMaTdShift=2;//The MA Shift input
extern string  dmame="Method: 0=sma; 1=ema; 2=smma;  3=lwma";
extern int     DragMaTdMethod=2;
extern string  dmaap="Applied price: 0=Close; 1=Open; 2=High";
extern string  dmaap1="3=Low; 4=Median; 5=Typical; 6=Weighted";
extern int     DragMaTdAppliedPrice=4;
//This one closes a trade on an opposite signal
extern string  opp="3) Close on opposite signal";
extern bool    UseOppositeSignal=true;

//Hedging for losing trend trades
extern string  heg="----Hedging losing trend trades----";
extern bool    UseHedging=true;
extern int     HedgeLotMultiplier=3;
extern int     HedgeProfitTarget=10;
extern string  HedgeTradeComment="Hedge";

extern string  rpt="----Specific Range trading inputs----";
extern bool    AllowRangeTrading=true;
extern bool    TradeEveryTick=false;
extern int     MaximumRangeTradingVolatility=150;
extern int     RangeTakeProfit=0;
extern int     RangeStopLoss=0;
extern bool    AllowChangeOfOriginToTrend=false;
extern string  rec="Recovery";
extern bool    UseRecovery=true;
extern string    RecoveryLevels="2,6";
extern string  RangeTradeComment="Range";

//I have removed the ability of users to piss around with Start_Recovery_at_trades. Coders, change this and
//you will cause chaos.
int     Start_Recovery_at_trades=2;  //DC
extern int     ReEntryLinePips=0;
extern double  ReEntryLineVolMult=1;
extern color   ReEntryLineColour=Turquoise;
extern color   BreakEvenLineColour=Blue;
extern int     RecoveryBreakEvenProfitPips=20;
extern string  rts="Recovery trailing stop";
extern bool    UseRecoveryTrailingStop=false;
extern int     RecoveryTrailingStopAt=10;
extern color   RecoveryStopLossLineColour=Red;
bool    UseHardRecoveryStop=false;//Doesn't work but is part of the code and I cannot be bothered to remove it

extern string  amc="----Available Margin checks----";
extern string  sco="Scoobs";
extern bool    UseScoobsMarginCheck=false;
extern string  fk="ForexKiwi";
extern bool    UseForexKiwi=true;
extern int     FkMinimumMarginPercent=1500;


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  tmm="----Trade management module----";
extern string  BE="Break even settings";
extern bool    BreakEven=false;
extern int     BreakEvenPips=25;
extern int     BreakEvenProfit=2;
extern bool    HideBreakEvenStop=false;
extern int     PipsAwayFromVisualBE=5;
extern string  cts="----Candlestick trailing stop----";
extern bool    UseCandlestickTrailingStop=false;
extern string  JSL="Jumping stop loss settings";
extern bool    JumpingStop=true;
extern int     JumpingStopPips=100;
extern bool    AddBEP=true;
extern bool    JumpAfterBreakevenOnly=false;
extern bool    HideJumpingStop=false;
extern int     PipsAwayFromVisualJS=10;
extern string  TSL="Trailing stop loss settings";
extern bool    TrailingStop=false;
extern int     TrailingStopPips=50;
extern bool    HideTrailingStop=false;
extern int     PipsAwayFromVisualTS=10;
extern bool    TrailAfterBreakevenOnly=false;
extern bool    StopTrailAtPipsProfit=false;
extern int     StopTrailPips=0;
extern string  hsl1="Hidden stop loss settings";
extern bool    HideStopLossEnabled=false;
extern int     HiddenStopLossPips=20;
extern string  htp="Hidden take profit settings";
extern bool    HideTakeProfitEnabled=false;
extern int     HiddenTakeProfitPips=20;
extern string  mis="----Odds and ends----";
extern bool    ShowManagementAlerts=true;
extern int     DisplayGapSize=30;


//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
int            TicketNo, OpenTrades;
bool           CanTradeThisPair;//Will be false when this pair fails the currency can only trade twice filter, or the balanced trade filter
bool           BuyOpen, SellOpen;
string         TradeOrigin;//Will be 'Range' or 'Trend'

//Global Variables
string         GvName;

//Range trading
//BB variables so I can merely copy the code from Bob's EA's
double         Var1;//Upper extreme
double         Var2;//Upper
double         Var3;//Lower
double         Var4;//Lower extreme
double         Var5;//Moving average
int            OldRangeTradingBars;
int            RangeTradingTF=240;

//Volatility
double         Volatility;
int            D1VolatilityBars;

//Caterpillar
int            OldCatBars;
int            OnePip=1;//For adding to sl, candle close etc
bool           CandleTraded;//Only one trade per candle
string         CsGvName;
int            OldH1Bars;//For orphan gv removal
bool           TradeOpen;

//Carolco
int            NoOfPendingBuys, NoOfPendingSells;


//Trend detection
string         trend;
double         FastTrendMaVal, SlowTrendMaVal;//2 MA trend
string         TrendConfirmationCandleDir;
//Trend trade exit
double         DragMaVal;

//Hedging
bool           HedgingInProgress;
double         BasketUpl;

//Margin status display
bool           EnoughMargin;
string         MarginMessage;

//Misc
string         Gap, ScreenMessage;
int            OldBars;
int            OldCstBars;//For candlestick ts
string         PipDescription=" pips";
bool           ForceTradeClosure;
int            GlobalPipsMultiplier;//For x digit conversions

//Recovery
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;


void DisplayUserFeedback()
{
   
   if (IsTesting() && !IsVisualMode()) return;

   ScreenMessage = "";
   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);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Volatility: ", Volatility, NL);
   if (Volatility <= MaximumRangeTradingVolatility) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Can Range trade.", NL);
   if (Volatility >= MinimumTrendTradingVolatility) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Can Trend trade.", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", Lot, " (Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), ")");
   ScreenMessage = StringConcatenate(ScreenMessage, ": Magic number: ", MagicNumber, NL);
   //ScreenMessage = StringConcatenate(ScreenMessage, ": Trade comment: ", TradeComment, NL);
   if (CriminalIsECN) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = true", NL);
   else ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = false", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Buy swap = ", MarketInfo(Symbol(), MODE_SWAPLONG), ": Sell swap = ", MarketInfo(Symbol(), MODE_SWAPSHORT), NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "MaxSpread = ", MaxSpread, ": Spread = ", MarketInfo(Symbol(), MODE_SPREAD), 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
   
   
   //Trend
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trend is ", trend, NL);
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Fast MA ", DoubleToStr(FastTrendMaVal, Digits), ":  Slow MA ", DoubleToStr(SlowTrendMaVal, Digits), NL);
      
   
   //Trading method information
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   string tab = "        ";
   //Trending market
   if (trend != ranging)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trend trading information", NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Trade confirmation candle direction: ", TrendConfirmationCandleDir, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "MinTriggerCandlePipsMovement: ", MinTriggerCandlePipsMovement, PipDescription, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Take profit: ", TrendTakeProfit, PipDescription,  NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Stop loss: ", TrendStopLoss, PipDescription,  NL);
   if (UseHanover)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);      
      string now, then;         
      for (int cc = 0; cc < ArraySize(Tf); cc++)
      {
         double strength1 = ReadStrength(Ccy1, Tf[cc], 0);
         double strength2 = ReadStrength(Ccy2, Tf[cc], 0);
         if (TrendSlopeConfirmationCandles > 0) 
         {
            double prevstrength1 = ReadStrength(Ccy1, Tf[cc], TrendSlopeConfirmationCandles);
            now = StringConcatenate(": Shift ",TrendSlopeConfirmationCandles, " = ", DoubleToStr(prevstrength1, 2));
            double prevstrength2 = ReadStrength(Ccy2, Tf[cc], TrendSlopeConfirmationCandles);
            then = StringConcatenate(": Shift ", TrendSlopeConfirmationCandles, " = ", DoubleToStr(prevstrength2, 2));
         }//if (SlopeCandles[cc] > 0) 
      
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, "TF ", Tf[cc], 
                                           ": ", Ccy1, ": Now = ", DoubleToStr(strength1, 2),
                                           now,
                                           ": ", Ccy2, ": Now = ", DoubleToStr(strength2, 2),
                                           then,
                                           NL);
      }//for (int cc = 0; cc < ArraySize(Tf); cc++)
      if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0)
      {
         bool tradeable = false;
         if (strength1 > TrendStrongThreshold && strength2 < TrendWeakThreshold)
         {
            ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Can trade this pair long", NL);
            tradeable = true;
         }//if (strength1 > TrendStrongThreshold && strength2 < TrendWeakThreshold)
         
         if (strength2 > TrendStrongThreshold && strength1 < TrendWeakThreshold)
         {
            ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Can trade this pair short", NL);
            tradeable = true;
         }//if (strength1 > TrendStrongThreshold && strength2 < TrendWeakThreshold)
         
         if (!tradeable) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Cannot trade this pair yet", NL);
      }//if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0)
      
   }//if (UseHanover)
      
      
      //Trade entry.
      //carolco grid
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade entry", NL);
      
      if (UseCarolco)
      {
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using carolco grid", NL);
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, tab, "TradesInGrid: ", TradesInGrid, NL);
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, tab, "PipsBetweenTrades: ", PipsBetweenTrades, PipDescription, NL);
      }//if (UseCarolco)
      
      
      //Trade closure techniques
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade exit", NL);
      if (UseOsthafen) ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using osthafen to close trend trades", NL);
      if (UseDragosd1)
      {
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using dragosd1 to close trend trades ");
         ScreenMessage = StringConcatenate(ScreenMessage, ": MA = ", DoubleToStr(DragMaVal, Digits), NL);         
      }//if (UseDragosd1)
      //Opposite direction signal
      if (UseOppositeSignal)
      {
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using opposite trend signal to close trend trades ");
      }//if (UseOppositeSignal)
      
      
   }//if (trend != ranging)
   
   //Ranging market
   if (trend == ranging)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Range trading information", NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band upper extreme: ", Var2, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band upper: ", Var1, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band MA: ", DoubleToStr(Var5, Digits), NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band lower: ", Var3, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band lower extreme: ", Var4, NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Take profit: ", RangeTakeProfit, PipDescription,  NL);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Stop loss: ", RangeStopLoss, PipDescription,  NL);
      if (UseRecovery)
      {
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Recovery", NL);
         ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Levels ", RecoveryLevels, 
                                           ": ReEntryLinePips = ", ReEntryLinePips, PipDescription, NL);
         
      }//if (UseRecovery)
//extern string    RecoveryLevels="2,6";
//extern int     Start_Recovery_at_trades=2;  //DC
//extern int     ReEntryLinePips=0;
      
   }//if (trend = ranging)
   
   

   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);
   
   //Open trade
   if (OpenTrades > 0) ScreenMessage = StringConcatenate(ScreenMessage,Gap, TicketNo, " ", TradeOrigin,  NL, NL);
   if (OpenTrades == 0) ScreenMessage = StringConcatenate(ScreenMessage, NL);
   
   if (BreakEven)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Breakeven is set to ", BreakEvenPips, PipDescription);
      ScreenMessage = StringConcatenate(ScreenMessage,": BreakEvenProfit = ", BreakEvenProfit, PipDescription);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); 
   }//if (BreakEven)

   if (UseCandlestickTrailingStop)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Using candlestick trailing stop", NL);      
   }//if (UseCandlestickTrailingStop)
   
   if (JumpingStop)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Jumping stop is set to ", JumpingStopPips, PipDescription);
      if (AddBEP) ScreenMessage = StringConcatenate(ScreenMessage,": BreakEvenProfit = ", BreakEvenProfit, PipDescription);
      if (JumpAfterBreakevenOnly) ScreenMessage = StringConcatenate(ScreenMessage, ": JumpAfterBreakevenOnly = true");
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);   
   }//if (JumpingStop)
   

   if (TrailingStop)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trailing stop is set to ", TrailingStopPips, PipDescription);
      if (TrailAfterBreakevenOnly) ScreenMessage = StringConcatenate(ScreenMessage, ": TrailAfterBreakevenOnly = true");
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);   
   }//if (TrailingStop)

   if (HideStopLossEnabled)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Hidden stop loss enabled at ", HiddenStopLossPips, PipDescription, NL);
   }//if (HideStopLossEnabled)
   
   if (HideTakeProfitEnabled)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Hidden take profit enabled at ", HiddenTakeProfitPips, PipDescription, NL);
   }//if (HideTakeProfitEnabled)

   //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Upper line: ", DoubleToStr(BbUpper, Digits), NL);
   //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Middle line: ", DoubleToStr(BbMiddle, Digits), NL);
   //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Lower line: ", DoubleToStr(BbLower, Digits), NL);
   
   if (MarginMessage != "") ScreenMessage = StringConcatenate(ScreenMessage,NL, Gap, MarginMessage, NL);

   
   Comment(ScreenMessage);


}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----

   //Adapt to x digit criminals
   if(Digits == 2 || Digits == 4) GlobalPipsMultiplier = 1;
   if(Digits == 3 || Digits == 5) GlobalPipsMultiplier = 10;
   if(Digits == 6) GlobalPipsMultiplier = 100;   
   if(Digits == 7) GlobalPipsMultiplier = 1000;   
   
   if (GlobalPipsMultiplier > 1) PipDescription = " points";
   
   TrendTakeProfit*= GlobalPipsMultiplier;
   TrendStopLoss*= GlobalPipsMultiplier;
   RangeTakeProfit*= GlobalPipsMultiplier;
   RangeStopLoss*= GlobalPipsMultiplier;
   MinTriggerCandlePipsMovement*= GlobalPipsMultiplier;
   OnePip*= GlobalPipsMultiplier;
   PipsBetweenTrades*= GlobalPipsMultiplier;
   BreakEvenPips*= GlobalPipsMultiplier;
   BreakEvenProfit*= GlobalPipsMultiplier;
   PipsAwayFromVisualBE*= GlobalPipsMultiplier;
   JumpingStopPips*= GlobalPipsMultiplier;
   PipsAwayFromVisualJS*= GlobalPipsMultiplier;
   TrailingStopPips*= GlobalPipsMultiplier;
   PipsAwayFromVisualTS*= GlobalPipsMultiplier;
   StopTrailPips*= GlobalPipsMultiplier;
   HiddenStopLossPips*= GlobalPipsMultiplier;
   HiddenTakeProfitPips*= GlobalPipsMultiplier;
   ReEntryLinePips*= GlobalPipsMultiplier;
   RecoveryTrailingStopAt*= GlobalPipsMultiplier;
   
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }//if (DisplayGapSize >0)
   

   //if (TradeComment == "") TradeComment = " ";
   if (TrendTradeComment == "") TrendTradeComment = " ";
   if (HedgeTradeComment == "") HedgeTradeComment = " ";
   if (RangeTradeComment == "") RangeTradeComment = " ";
   if (CarolcoTradeComment == "") CarolcoTradeComment = " ";
   if (CatTradeComment == "") CatTradeComment = " ";

   //Set up the arrays
   if (UseHanover)
   {
      SetUpArrays();
      Ccy1 = StringSubstr(Symbol(), 0, 3);
      Ccy2 = StringSubstr(Symbol(), 3, 3);
      ReadBars = iBars(NULL, PERIOD_M1);//Don't need it again when start() triggers
      ReadHanover();
   }//if (UseHanover)
   
   //OldBars = Bars;
   //ReadIndicatorValues();//For initial display in case user has turned of constant re-display
   DisplayUserFeedback();
   OldRangeTradingBars = iBars(NULL, RangeTradingTF);  
   OldCatBars = iBars(NULL, CatTimeFrame);//Caterpillar
   GvName = Symbol();
   TradeOrigin = none;
   if (GlobalVariableCheck(GvName) )
   {
      int type = GlobalVariableGet(GvName);
      if (type == 0) TradeOrigin = trendorigin;
      if (type == 1) TradeOrigin = rangeorigin;      
   }//if (GlobalVariableCheck(GvName) )
   
   //If using cat, draw the initial line
   ReadIndicatorValues();
   if (UseCaterpillar && trend != ranging)
   {
      OldCatBars = iBars(NULL, CatTimeFrame);
   
      //Initial draw of buy/sell lines
      CountOpenTrades();
      //Ensure a minimum gap in between trades
      double target;
      double pipsgap = (OnePip * Point);
      if (OpenTrades > 0) 
      {
         pipsgap*= MinPipsBetweenCandles;
         OrderSelect(TicketNo, SELECT_BY_TICKET);
         target = OrderOpenPrice();
      }//if (OpenTrades > 0) 
   
   
      if (!TradeLong) ObjectDelete(buyline);
      if (!TradeShort) ObjectDelete(sellline);

      if (trend == up)
      {
         if (TradeLong && ObjectFind(buyline) == -1 && BuyOpen)
         {  
            //Add buyline above order open price if there is a trade open already
            if (OpenTrades > 0) 
            {
               if (Bid <= OrderOpenPrice() ) target = NormalizeDouble(OrderOpenPrice() + pipsgap, Digits);
               if (Bid > OrderOpenPrice() ) target = NormalizeDouble(iHigh(NULL, CatTimeFrame, 0) + pipsgap, Digits);            
            }//if (OpenTrades > 0)          
            else target = NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + pipsgap, Digits);//No open trade, so look at previous candle
            ObjectCreate(buyline,OBJ_HLINE,0,TimeCurrent(), target);
            ObjectSet(buyline,OBJPROP_COLOR,BuyLineColour);
            ObjectSet(buyline,OBJPROP_STYLE,STYLE_SOLID);      
         }//if (TradeLong)
      }//if (trend == up)
      
      if (trend == down)
      {
         if (TradeShort && ObjectFind(sellline) == -1 && SellOpen)
         {
            //Add sellline below order open price if there is a trade open already
            if (OpenTrades > 0) 
            {
               if (Bid >= OrderOpenPrice() ) target = NormalizeDouble(OrderOpenPrice() - pipsgap, Digits);
               if (Bid < OrderOpenPrice() ) target = NormalizeDouble(iLow(NULL, CatTimeFrame, 0) - pipsgap, Digits);
            }//if (OpenTrades > 0)          
            else target = NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - pipsgap, Digits);
            ObjectCreate(sellline,OBJ_HLINE,0,TimeCurrent(), target);
            ObjectSet(sellline,OBJPROP_COLOR,SellLineColour);
            ObjectSet(sellline,OBJPROP_STYLE,STYLE_SOLID);      
         }//if (TradeShort && ObjectFind(sellline) == -1)
      }//if (trend == down)
      
   }//if (UseCaterpillar)

   //Call sq's show trades indi
   //iCustom(NULL, 0, "SQ_showTrades",Magic, 0,0);

   //Set up Recovery levels
    //Extract the levels inputted by the user
   // Cleanup first
   InputString=RecoveryLevels;
   CleanUpInputString();
   NoOfLevels = StringFindCount(InputString,",");
    ArrayResize(RecoveryLevel, NoOfLevels);
    string AddChar = "";
    StrPairToStringArray(RecoveryLevels, RecoveryLevel, AddChar);

   /*
   for (cc = 0; cc < NoOfLevels; cc++)
   {
      Alert(RecoveryLevel[cc]);      
   }
   */
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
   ObjectDelete(buyline);
   ObjectDelete(sellline);

//----
   return(0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//sq's string to array module
void CleanUpInputString()
{
   // Does any tidying up of the user inputs
   
   //Remove unwanted spaces
   InputString = StringTrimLeft(InputString);
   InputString = StringTrimRight(InputString);

   //Add final comma if ommitted by user
   if (StringSubstr(InputString, StringLen(InputString)-1) != ",") 
      InputString = StringConcatenate(InputString,",");
      
   
}//void CleanUpInputString

//+------------------------------------------------------------------+
int StringFindCount(string str, string str2)
//+------------------------------------------------------------------+
// Returns the number of occurrences of STR2 in STR
// Usage:   int x = StringFindCount("ABCDEFGHIJKABACABB","AB")   returns x = 3
{
  int c = 0;
  for (int i=0; i<StringLen(str); i++)
    if (StringSubstr(str,i,StringLen(str2)) == str2)  c++;
  return(c);
} // End int StringFindCount(string str, string str2)


//+------------------------------------------------------------------+
void StrPairToStringArray(string str, string &a[], string p_suffix, string delim=",")
//+------------------------------------------------------------------+
{
    int z1=-1, z2=0;
    for (int i=0; i<ArraySize(a); i++)
    {
        z2 = StringFind(str,delim,z1+1);
        a[i] = StringSubstr(str,z1+1,z2-z1-1) + p_suffix;
        a[i] = StringTrimLeft(a[i]);
        a[i] = StringTrimRight(a[i]);
        if (z2 >= StringLen(str)-1)   break;
        z1 = z2;
    }
    return(0);
}
/*
//+------------------------------------------------------------------+
void StrToStringArray(string str, string &a[], string delim=",")
//+------------------------------------------------------------------+
{
    int z1=-1, z2=0;
    for (int i=0; i<ArraySize(a); i++)
    {
        z2 = StringFind(str,delim,z1+1);
        a[i] = StringSubstr(str,z1+1,z2-z1-1);
        if (z2 >= StringLen(str)-1)   break;
        z1 = z2;
    }
    return(0);
}
*/
//END sq's string to array module
//////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////
//TRADE MANAGEMENT MODULE

bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )
{
   //Reusable code that can be called by any of the stop loss manipulation routines except HiddenStopLoss().
   //Checks to see if the market has hit the hidden sl and attempts to close the trade if so. 
   //Returns true if trade closure is successful, else returns false
   
   //Check buy trade
   if (type == OP_BUY)
   {
      double sl = NormalizeDouble(stop + (iPipsAboveVisual * Point), Digits);
      if (Bid <= sl)
      {
         while(IsTradeContextBusy()) Sleep(100);
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Bid <= sl)  
   }//if (type = OP_BUY)
   
   //Check buy trade
   if (type == OP_SELL)
   {
      sl = NormalizeDouble(stop - (iPipsAboveVisual * Point), Digits);
      if (Ask >= sl)
      {
         while(IsTradeContextBusy()) Sleep(100);
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Ask >= sl)  
   }//if (type = OP_SELL)
   

}//End bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop )


void BreakEvenStopLoss() // Move stop loss to breakeven
{

   //Check hidden BE for trade closure
   if (HideBreakEvenStop)
   {
      bool TradeClosed = CheckForHiddenStopLossHit(OrderType(), PipsAwayFromVisualBE, OrderStopLoss() );
      if (TradeClosed) return;//Trade has closed, so nothing else to do
   }//if (HideBreakEvenStop)


   bool result;

   if (OrderType()==OP_BUY)
         {
            if (Bid >= OrderOpenPrice () + (Point*BreakEvenPips) && 
                OrderStopLoss()<OrderOpenPrice())
            {
               while(IsTradeContextBusy()) Sleep(100);
               result = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()+(BreakEvenProfit*Point), Digits),OrderTakeProfit(),0,CLR_NONE);
               if (result && ShowManagementAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               if (!result)
               {
                  int err=GetLastError();
                  if (ShowManagementAlerts==true) Alert("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
                  Print("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
               }//if !result && ShowManagementAlerts)      
               //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               //{
               //   bool PartCloseSuccess = PartCloseTradeFunction();
               //   if (!PartCloseSuccess) SetAGlobalTicketVariable();
               //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }
          }                                    
          
   if (OrderType()==OP_SELL)
         {
           if (Ask <= OrderOpenPrice() - (Point*BreakEvenPips) &&
              (OrderStopLoss()>OrderOpenPrice()|| OrderStopLoss()==0)) 
            {
               while(IsTradeContextBusy()) Sleep(100);
               result = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()-(BreakEvenProfit*Point), Digits),OrderTakeProfit(),0,CLR_NONE);
               if (result && ShowManagementAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
               if (!result && ShowManagementAlerts)
               {
                  err=GetLastError();
                  if (ShowManagementAlerts==true) Alert("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
                  Print("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
               }//if !result && ShowManagementAlerts)      
              //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
              // {
              //    PartCloseSuccess = PartCloseTradeFunction();
              //    if (!PartCloseSuccess) SetAGlobalTicketVariable();
              // }//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }    
         }
      

} // End BreakevenStopLoss sub

void JumpingStopLoss() 
{
   // Jump sl by pips and at intervals chosen by user .
   // Also carry out partial closure if the user requires this

   // Abort the routine if JumpAfterBreakevenOnly is set to true and be sl is not yet set
   if (JumpAfterBreakevenOnly && OrderType()==OP_BUY)
   {
      if(OrderStopLoss()<OrderOpenPrice()) return(0);
   }
  
   if (JumpAfterBreakevenOnly && OrderType()==OP_SELL)
   {
      if(OrderStopLoss()>OrderOpenPrice() || OrderStopLoss() == 0 ) return(0);
   }
  
   double sl=OrderStopLoss(); //Stop loss

   if (OrderType()==OP_BUY)
   {
      //Check hidden js for trade closure
      if (HideJumpingStop)
      {
         bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualJS, OrderStopLoss() );
         if (TradeClosed) return;//Trade has closed, so nothing else to do
      }//if (HideJumpingStop)
      
      // First check if sl needs setting to breakeven
      if (sl==0 || sl<OrderOpenPrice())
      {
         if (Ask >= OrderOpenPrice() + (JumpingStopPips*Point))
         {
            sl=OrderOpenPrice();
            if (AddBEP==true) sl=sl+(BreakEvenProfit*Point); // If user wants to add a profit to the break even
            while(IsTradeContextBusy()) Sleep(100);
            bool result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (result)
            {
               if (ShowManagementAlerts==true) Alert("Jumping stop set at breakeven ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Jumping stop set at breakeven: ", OrderSymbol(), ": SL ", sl, ": Ask ", Bid);
               //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               //{
                  //bool PartCloseSuccess = PartCloseTradeFunction();
                  //if (!PartCloseSuccess) SetAGlobalTicketVariable();
               //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }//if (result)
            if (!result)
            {
               int err=GetLastError();
               if (ShowManagementAlerts) Alert(OrderSymbol(), "Ticket ", OrderTicket(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(OrderSymbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
            }//if (!result)
             
            return(0);
         }//if (Ask >= OrderOpenPrice() + (JumpingStopPips*Point))
      } //close if (sl==0 || sl<OrderOpenPrice()

  
      // Increment sl by sl + JumpingStopPips.
      // This will happen when market price >= (sl + JumpingStopPips)
      if (Bid>= sl + ((JumpingStopPips*2)*Point) && sl>= OrderOpenPrice())      
      {
         sl=sl+(JumpingStopPips*Point);
         while(IsTradeContextBusy()) Sleep(100);
         result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
            //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
            //{
               //PartCloseSuccess = PartCloseTradeFunction();
               //if (!PartCloseSuccess) SetAGlobalTicketVariable();
            //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
         }//if (result)
         if (!result)
         {
            err=GetLastError();
            if (ShowManagementAlerts) Alert(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
            Print(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
         }//if (!result)
             
      }// if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())      
   }//if (OrderType()==OP_BUY)
   
   if (OrderType()==OP_SELL)
   {
      //Check hidden js for trade closure
      if (HideJumpingStop)
      {
         TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualJS, OrderStopLoss() );
         if (TradeClosed) return;//Trade has closed, so nothing else to do
      }//if (HideJumpingStop)
            
      // First check if sl needs setting to breakeven
      if (sl==0 || sl>OrderOpenPrice())
      {
         if (Ask <= OrderOpenPrice() - (JumpingStopPips*Point))
         {
            sl = OrderOpenPrice();
            if (AddBEP==true) sl=sl-(BreakEvenProfit*Point); // If user wants to add a profit to the break even
            while(IsTradeContextBusy()) Sleep(100);
            result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (result)
            {
               //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
               //{
                 // PartCloseSuccess = PartCloseTradeFunction();
                  //if (!PartCloseSuccess) SetAGlobalTicketVariable();
               //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
            }//if (result)
            if (!result)
            {
               err=GetLastError();
               if (ShowManagementAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
               Print(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err));
            }//if (!result)
             
            return(0);
         }//if (Ask <= OrderOpenPrice() - (JumpingStopPips*Point))
      } // if (sl==0 || sl>OrderOpenPrice()
   
      // Decrement sl by sl - JumpingStopPips.
      // This will happen when market price <= (sl - JumpingStopPips)
      if (Bid<= sl - ((JumpingStopPips*2)*Point) && sl<= OrderOpenPrice())      
      {
         sl=sl-(JumpingStopPips*Point);
         while(IsTradeContextBusy()) Sleep(100);
         result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
            //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked
            //{
              // PartCloseSuccess = PartCloseTradeFunction();
               //if (!PartCloseSuccess) SetAGlobalTicketVariable();
            //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots)
         }//if (result)          
         if (!result)
         {
            err=GetLastError();
            if (ShowManagementAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
            Print(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err));
         }//if (!result)

      }// close if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())         
   }//if (OrderType()==OP_SELL)

} //End of JumpingStopLoss sub

void HiddenStopLoss()
{
   //Called from ManageTrade if HideStopLossEnabled = true


   //Should the order close because the stop has been passed?
   //Buy trade
   if (OrderType() == OP_BUY)
   {
      double sl = NormalizeDouble(OrderOpenPrice() - (HiddenStopLossPips * Point), Digits);
      if (Bid <= sl)
      {
         while(IsTradeContextBusy()) Sleep(100);
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Bid <= sl)      
   }//if (OrderType() == OP_BUY)
   
   //Sell trade
   if (OrderType() == OP_SELL)
   {
      sl = NormalizeDouble(OrderOpenPrice() + (HiddenStopLossPips * Point), Digits);
      if (Ask >= sl)
      {
         while(IsTradeContextBusy()) Sleep(100);
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Ask >= sl)   
   }//if (OrderType() == OP_SELL)
   

}//End void HiddenStopLoss()

void HiddenTakeProfit()
{
   //Called from ManageTrade if HideStopLossEnabled = true


   //Should the order close because the stop has been passed?
   //Buy trade
   if (OrderType() == OP_BUY)
   {
      double tp = NormalizeDouble(OrderOpenPrice() + (HiddenTakeProfitPips * Point), Digits);
      if (Bid >= tp)
      {
         while(IsTradeContextBusy()) Sleep(100);
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            int err=GetLastError();
            if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Ask >= tp)      
   }//if (OrderType() == OP_BUY)
   
   //Sell trade
   if (OrderType() == OP_SELL)
   {
      tp = NormalizeDouble(OrderOpenPrice() - (HiddenTakeProfitPips * Point), Digits);
      if (Ask <= tp)
      {
         while(IsTradeContextBusy()) Sleep(100);
         result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE);
         if (result)
         {
            if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket());      
         }//if (result)
         else
         {
            err=GetLastError();
            if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
            Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err));
         }//else
      }//if (Bid <= tp)   
   }//if (OrderType() == OP_SELL)
   

}//End void HiddenTakeProfit()

void TrailingStopLoss()
{
      if (TrailAfterBreakevenOnly && OrderType()==OP_BUY)
      {
         if(OrderStopLoss()<OrderOpenPrice()) return(0);
      }
     
      if (TrailAfterBreakevenOnly && OrderType()==OP_SELL)
      {
         if(OrderStopLoss()>OrderOpenPrice()) return(0);
      }
     
   
   
   bool result;
   double sl=OrderStopLoss(); //Stop loss
   double BuyStop=0, SellStop=0;
   
   if (OrderType()==OP_BUY) 
      {
         if (HideTrailingStop)
         {
            bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualTS, OrderStopLoss() );
            if (TradeClosed) return;//Trade has closed, so nothing else to do
         }//if (HideJumpingStop)
           
           if (Bid >= OrderOpenPrice() + (TrailingStopPips*Point))
           {
               if (OrderStopLoss() == 0) sl = OrderOpenPrice();
               if (Bid > sl +  (TrailingStopPips*Point))
               {
                  sl= Bid - (TrailingStopPips*Point);
                  // Exit routine if user has chosen StopTrailAtPipsProfit and
                  // sl is past the profit Point already
                  if (StopTrailAtPipsProfit && sl>= OrderOpenPrice() + (StopTrailPips*Point)) return;
                  while(IsTradeContextBusy()) Sleep(100);
                  result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
               if (result)
               {
                  Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask);
               }//if (result) 
               else
               {
                  int err=GetLastError();
                  Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err));
               }//else
   
               }//if (Bid > sl +  (TrailingStopPips*Point))
           }//if (Bid >= OrderOpenPrice() + (TrailingStopPips*Point))
      }//if (OrderType()==OP_BUY) 

      if (OrderType()==OP_SELL) 
      {
           if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point))
           {
             if (HideTrailingStop)
             {
                TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualTS, OrderStopLoss() );
                if (TradeClosed) return;//Trade has closed, so nothing else to do
             }//if (HideJumpingStop)
           
               if (OrderStopLoss() == 0) sl = OrderOpenPrice();
               if (Ask < sl -  (TrailingStopPips*Point))
               {
                   sl= Ask + (TrailingStopPips*Point);
                     // Exit routine if user has chosen StopTrailAtPipsProfit and
                    // sl is past the profit Point already
                    if (StopTrailAtPipsProfit && sl<= OrderOpenPrice() - (StopTrailPips*Point)) return;
                    while(IsTradeContextBusy()) Sleep(100);
                    result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
                  if (result)
                  {
                     Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", Bid);
                  }//if (result)
                  else
                  {
                     err=GetLastError();
                     Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err));
                  }//else
    
               }//if (Ask < sl -  (TrailingStopPips*Point))
           }//if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point))
      }//if (OrderType()==OP_SELL) 

      
} // End of TrailingStopLoss sub

void CandlestickTrailingStop()
{
   
   //Trails the stop at the hi/lo of the previous candle.
   //Only tries to do this once per bar, so an invalid stop error will only be generated once.
   
   if (OldCstBars == Bars) return;
   OldCstBars = Bars;
   bool result = false, modify = false;
   int err;
   double stop;
   
   if (OrderType() == OP_BUY)
   {
      if (Low[1] > OrderStopLoss() && OrderProfit() >= 0)
      {
         stop = NormalizeDouble(Low[1], Digits);
         modify = true;
      }//if (Close[1] > OrderStopLoss() && OrderProfit() >= 0)
   }//if (OrderType == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      if ( (High[1] < OrderStopLoss() || OrderStopLoss() == 0) && OrderProfit() >= 0)
      {
         stop = NormalizeDouble(High[1], Digits);
         modify = true;
      }//if (Close[1] > OrderStopLoss() && OrderProfit() >= 0)
   }//if (OrderType() == OP_SELL)
   
   if (modify)
   {
      result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
      if (!result)
      {
         err = GetLastError();
         if (err != 130) OldBars = 0;//Retry the modify at the next tick unless the error is invalid stops
      }//if (!result)      
   }//if (modify)

}//End void CandlestickTrailingStop()

void TradeManagementModule()
{

   // Call the working subroutines one by one. 

   //Candlestick trailing stop
   if (UseCandlestickTrailingStop) CandlestickTrailingStop();

   // Hidden stop loss
   if (HideStopLossEnabled) HiddenStopLoss();

   // Hidden take profit
   if (HideTakeProfitEnabled) HiddenTakeProfit();

   // Breakeven
   if(BreakEven) BreakEvenStopLoss();

   // JumpingStop
   if(JumpingStop) JumpingStopLoss();

   //TrailingStop
   if(TrailingStop) TrailingStopLoss();

   

}//void TradeManagementModule()
//END TRADE MANAGEMENT MODULE
////////////////////////////////////////////////////////////////////////////////////////////////

bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
{
   
   
   int slippage = 10;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
   color col = Red;
   if (type == OP_BUY || type == OP_BUYSTOP) col = Green;
   
   int expiry = 0;
   //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60);

   if (!CriminalIsECN || (type != OP_BUY && type != OP_SELL) ) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, col);
   
   
   //Is a 2 stage criminal
   if (CriminalIsECN && (type == OP_BUY || type == OP_SELL) )
   {
      bool result;
      int err;
      ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, col);
      if (ticket > 0)
      {
         
         if (take > 0 && stop > 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)              
        }//if (take > 0 && stop > 0)
      
         if (take != 0 && stop == 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)              
        }//if (take == 0 && stop != 0)

        if (take == 0 && stop != 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           result = OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
           if (!result)
           {
               err=GetLastError();
               Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
           }//if (!result)              
        }//if (take == 0 && stop != 0)

      }//if (ticket > 0)
        
      
      
   }//if (CriminalIsECN)
   
   //Error trapping for both
   if (ticket < 0)
   {
      string stype;
      if (type == OP_BUY) stype = "OP_BUY";
      if (type == OP_SELL) stype = "OP_SELL";
      if (type == OP_BUYLIMIT) stype = "OP_BUYLIMIT";
      if (type == OP_SELLLIMIT) stype = "OP_SELLLIMIT";
      if (type == OP_BUYSTOP) stype = "OP_BUYSTOP";
      if (type == OP_SELLSTOP) stype = "OP_SELLSTOP";
      err=GetLastError();
      Alert(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
      Print(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (ticket < 0)  
   
   
   TicketNo = ticket;
   //Make sure the trade has appeared in the platform's history to avoid duplicate trades.
   //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)

bool DoesTradeExist()
{
   
   TicketNo = -1;
   
   if (OrdersTotal() == 0) return(false);
   
   for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)
   {
      if (!OrderSelect(cc,SELECT_BY_POS)) continue;
      
      if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
      {
         TicketNo = OrderTicket();
         return(true);         
      }//if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() )      
   }//for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--)

   return(false);

}//End bool DoesTradeExist()



bool IsTradingAllowed()
{
   //Returns false if any of the filters should cancel trading, else returns true to allow trading
   
      
   //Maximum spread
   if (MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread) return(false);
 
 
   //Swap filter
   if (OpenTrades == 0) TradeDirectionBySwap();

   //An individual currency can only be traded twice, so check for this
   CanTradeThisPair = true;
   if (OnlyTradeCurrencyTwice && OpenTrades == 0)
   {
      IsThisPairTradable();      
   }//if (OnlyTradeCurrencyTwice)
   if (!CanTradeThisPair) return(false);
   
   //Trend specific filters
   //Minimum candle movement
   if (trend != ranging)
   {
      if (iHigh(NULL, PERIOD_D1, 0) - iLow(NULL, PERIOD_D1, 0) < (MinTriggerCandlePipsMovement * Point) ) return(false);
   }//if (trend != ranging)
   
   
   
   return(true);


}//End bool IsTradingAllowed()


void LookForTrendTradingOpps()
{


   double take, stop, price;
   int type;
   bool SendTrade;

   double SendLots = Lot;
   
   
   //Check filters
   if (!IsTradingAllowed() ) return;
   RefreshRates();

   //Long 
   if (trend == up && TrendConfirmationCandleDir == up)
   {
      if (!TradeLong) return;
      if (UseHanover && !HanoverFilter(OP_BUY) ) return;
      if (Bid <= iOpen(NULL, PERIOD_D1, 0)) return;//Must be a rising candle
      //Balanced pair trade filter. Only apply to pre-recovery trades.
      //Will remove the comments when I add Recovery
      //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery)
      //{
         if (UseZeljko && !BalancedPair(OP_BUY) ) return;
      //}//if (OpenTrades + 1 < Start_Recovery_at_trades)
      if (TrendTakeProfit > 0) take = NormalizeDouble(Ask + (TrendTakeProfit * Point), Digits);
      if (TrendStopLoss > 0) stop = NormalizeDouble(Ask - (TrendStopLoss * Point), Digits);
      type = OP_BUY;
      price = Ask;
      SendTrade = true;
   }//if (Ttrend == up)
   
   
   //Short
   if (trend == down && TrendConfirmationCandleDir == down)
   {
      if (!TradeShort) return;
      if (UseHanover && !HanoverFilter(OP_SELL) ) return;
      if (Bid >= iOpen(NULL, PERIOD_D1, 0)) return;//Must be a falling candle
      //Balanced pair trade filter. Only apply to pre-recovery trades
      //Will remove the comments when I add Recovery
      //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery)
      //{
         if (UseZeljko && !BalancedPair(OP_SELL) ) return;
      //}//if (OpenTrades + 1 < Start_Recovery_at_trades)
      if (TrendTakeProfit > 0) take = NormalizeDouble(Bid - (TrendTakeProfit * Point), Digits);
      if (TrendStopLoss > 0) stop = NormalizeDouble(Bid + (TrendStopLoss * Point), Digits);
      type = OP_SELL;
      price = Bid;
      SendTrade = true;      
   }//if (Ttrend == down)
   

   if (SendTrade)
   {
      bool result = SendSingleTrade(type, TrendTradeComment, SendLots, price, stop, take);
   }//if (SendTrade)
   
   //Actions when trade send succeeds
   if (SendTrade && result)
   {
      GlobalVariableSet(GvName, 0);
      TradeOrigin = trendorigin;
   }//if (result)
   
   //Actions when trade send fails
   if (SendTrade && !result)
   {
   
   }//if (!result)
   
   

}//void LookForTrendTradingOpps()

void LookForRangeTradingOpps()
{
   //Looks for Range trading opportunities as directed by Bob's crt strategy.
   //Closes an opposite direction trade.
   
   
///////////////////////////////////////////////////////////////////////////////////////////////////////
//NOTE TO CODERS: I shoe-horned Recovery into the existing, working structure. This caused me huge
//problems. The code is rather messy because LUC called with all his best buddies, and a fix -here- caused 
// a problem -there- and so on. Even now, I am not certain that this is absolutely correct, so change stuff
//at your peril.
///////////////////////////////////////////////////////////////////////////////////////////////////////
   
   double take, stop, price, reentryprice, target;
   int type, count;
   bool SendTrade, result;

   double SendLots = Lot;
   
   //Using Recovery
   target = ObjectGet(reentrylinename, OBJPROP_PRICE1);
   //This idea from Pippo   
   if (UseRecovery && OpenTrades > 0)
   {
      if ( (OpenTrades + 1) >= Start_Recovery_at_trades) 
      {
         RecoveryInProgress = true;
      }//if ( (OpenTrades + 1) >= Start_Recovery_at_trades) 
      
      if (RecoveryInProgress)
      {
         //The first Recovery level inputed by the user equates to a L2 trade, so OpenTrades can be used
         //to point to the correct Recovery level
         if ( (OpenTrades + 1) <= NoOfLevels) 
         {
            int mult = StrToDouble(RecoveryLevel[OpenTrades - 1] );
            SendLots = Lot * mult;
         }//if (OpenTrades == 2) 
      
      
         if ( (OpenTrades + 1) > NoOfLevels) return;//No further trading is possible
      }//if (RecoveryInProgress)
   }//if (UseRecovery)
   
   //Check filters
   if (!IsTradingAllowed() ) return;
   RefreshRates();
   
   /*
   At the time of coding, there are two BOTH ea's with slightly different conditionals.
   '10 4H CTR BOTH'   is if ( Var5 < Var3 ) Order = SIGNAL_BUY;
                         if ( Var5 > Var1 ) Order = SIGNAL_SELL;
                  
   '10 4H CTR BOTH B' is if ( Var5 < Var3  && Bid < Var3 ) Order = SIGNAL_BUY;
                         if ( Var5 > Var1  && Bid > Var1 ) Order = SIGNAL_SELL;
   
   Using the B version for now
   */
   
   //Long 
   if (target == 0) target = 1000000;//Dummy value
      
   if ( Var5 < Var3  && Bid < Var3 && Bid < target)//B version plus Recovery
   //if ( Var5 < Var3  && Bid < Var3 && Bid < SlowTrendMaVal)//B version with my mod
   {
      //Abort this if there is an open sell and recovery is in progress
      //if (SellOpen && RecoveryInProgress) return;
      //Close an opposite direction trade. This might need ammending when Recovery is implemented i.e.
      //if (SellOpen && !UseRecovery)      
      if (SellOpen && OpenTrades == 1)//Nearly works
      {
         if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0 && OrderProfit() >= 0)
         //if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0)
         {
            result = false;
            count = 0;
            while (!result)
            {
               result = CloseTrade(TicketNo);
               if (result) 
               {
                  OpenTrades = 0;
                  SellOpen = false;
               }//if (result) 
               
               count++;
               if (count == 200)
               {
                  Alert(TicketNo, " BigBob tried and failed to close this trade 200 times. This may need manual intervention.");
                  result = true;
               }//if (count == 200)               
            }//while (!result)            
         }//if (OrderSelect(TicketNo, SELECT_BY_TICKET) && (OrderCloseTime() == 0)         
      }//if (SellOpen)
      
      //Don't want a buy if there is a sell already open
      if (SellOpen) return;
      
      //For Recovery
      if (OpenTrades > 0 && !UseRecovery) return;
      if (OpenTrades == 0) SendLots = Lot;//A fix for earlier chaos caused by Recovery lot calcs
      if (SellOpen && RecoveryInProgress) return;//Stops accidental hedging
      
      if (!TradeLong) return;
      //Balanced pair trade filter. Only apply to pre-recovery trades.
      //Will remove the comments when I add Recovery
      //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery)
      //{
         if (UseZeljko && !BalancedPair(OP_BUY) ) return;
      //}//if (OpenTrades + 1 < Start_Recovery_at_trades)
      if (RangeTakeProfit > 0) take = NormalizeDouble(Ask + (RangeTakeProfit * Point), Digits);
      if (RangeStopLoss > 0) stop = NormalizeDouble(Ask - (RangeStopLoss * Point), Digits);
      type = OP_BUY;
      price = Ask;
      reentryprice = NormalizeDouble(price - (ReEntryLinePips * Point), Digits);
      SendTrade = true;
   }//if ( Var5 < Var3  && Bid < Var3 )
   
   
   //Short
   if (target == 1000000) target = 0;//Dummy value
   
   if ( Var5 > Var1  && Bid > Var1 && Bid > target)//B version plus Recovery
   //if ( Var5 > Var1  && Bid > Var1 && Bid > SlowTrendMaVal )//B version with my mod
   {
      //Abort this if there is an open buy and recovery is in progress
      //if (BuyOpen && RecoveryInProgress) return;
      //Close an opposite direction trade. This might need ammending when Recovery is implemented i.e.
      //if (bUYOpen && !UseRecovery)      
      if (BuyOpen && OpenTrades == 1)
      {
         if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0 && OrderProfit() >= 0)
         //if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0)
         {
            result = false;
            count = 0;
            while (!result)
            {
               result = CloseTrade(TicketNo);
               if (result) 
               {
                  OpenTrades = 0;
                  BuyOpen = false;
               }//if (result) 
               count++;
               if (count == 200)
               {
                  Alert(TicketNo, " BigBob tried and failed to close this trade 200 times. This may need manual intervention.");
                  result = true;
               }//if (count == 200)               
            }//while (!result)            
         }//if (OrderSelect(TicketNo, SELECT_BY_TICKET) && (OrderCloseTime() == 0)         
      }//if (BuyOpen)
      
      //Recovery
      if (OpenTrades > 0 && !UseRecovery) return;
      if (OpenTrades == 0) SendLots = Lot;//A fix for earlier chaos caused by Recovery lot calcs
      if (BuyOpen && RecoveryInProgress) return;//Stops accidental hedging
      
      //Don't want a sell if there is a buy already open
      if (BuyOpen) return;
      
      if (!TradeShort) return;
      //Balanced pair trade filter. Only apply to pre-recovery trades
      //Will remove the comments when I add Recovery
      //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery)
      //{
         if (UseZeljko && !BalancedPair(OP_SELL) ) return;
      //}//if (OpenTrades + 1 < Start_Recovery_at_trades)
      if (RangeTakeProfit > 0) take = NormalizeDouble(Bid - (RangeTakeProfit * Point), Digits);
      if (RangeStopLoss > 0) stop = NormalizeDouble(Bid + (RangeStopLoss * Point), Digits);
      type = OP_SELL;
      price = Bid;
      reentryprice = NormalizeDouble(price + (ReEntryLinePips * Point), Digits);
      SendTrade = true;
   }//if ( Var5 > Var1  && Bid > Var1 )
   
   if (SendTrade)
   {
      result = SendSingleTrade(type, RangeTradeComment, SendLots, price, stop, take);
   }//if (SendTrade)
   
   //Actions when trade send succeeds
   if (SendTrade && result)
   {
      GlobalVariableSet(GvName, 1);
      TradeOrigin = rangeorigin;
      AddReEntryLine(reentryprice);
   }//if (result)
   
   //Actions when trade send fails
   if (SendTrade && !result)
   {
      OldRangeTradingBars = 0;
   }//if (!result)
   


}//End void LookForRangeTradingOpps()


bool CloseTrade(int ticket)
{   
   while(IsTradeContextBusy()) Sleep(100);
   bool result = OrderClose(ticket, OrderLots(), OrderClosePrice(), 1000, CLR_NONE);

   //Actions when trade send succeeds
   if (result)
   {
      OpenTrades--;
      return(true);
   }//if (result)
   
   //Actions when trade send fails
   if (!result)
   {
      return(false);
   }//if (!result)
   

}//End bool CloseTrade(ticket)

////////////////////////////////////////////////////////////////////////////////////////////////
//Indicator module


void GetBB()
{
   //Reads BB figures into BbUpper, BbMiddle, BbLower.
   //Copied from Bob's 10.0 CRT BOTH EA
   
   Var1 = iBands(NULL, RangeTradingTF, 20, 1, 0, PRICE_CLOSE, MODE_UPPER, 0);//PAIR, PERIODH1, MA period, Deviation, shift
   Var2 = iBands(NULL, RangeTradingTF, 20, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
   Var3 = iBands(NULL, RangeTradingTF, 20, 1, 0, PRICE_CLOSE, MODE_LOWER, 0);
   Var4 = iBands(NULL, RangeTradingTF, 20, 2, 0, PRICE_CLOSE, MODE_LOWER, 0);
   Var5 = iMA(NULL, RangeTradingTF, 3, 1, MODE_LWMA, PRICE_OPEN, 0);   
   
}//void GetBb()


double GetMa(int tf, int period, int mashift, int method, int ap, int shift)
{
   return(iMA(NULL, tf, period, mashift, method, ap, shift) );
}//End double GetMa(int tf, int period, int mashift, int method, int ap, int shift)


double CalculateVolatility(int period, int LookBack)
{
   //Calculates the volatility of a pair based on an average of their movement over LookBack periods
   
   double pips;
   for (int cc = 1; cc < LookBack; cc++)
   {
      pips+= iHigh(NULL, period, cc) - iLow(NULL, period, cc);      
   }//for (int cc = 1; cc < LookBack; cc++)
   
   pips/= LookBack;//Average pips movement per day
   //Alert(pips);

   //Convert to pips
   int multiplier;
   if (Digits == 2) multiplier = 100;
   if (Digits == 3) multiplier = 100;
   if (Digits == 4) multiplier = 10000;
   if (Digits == 5) multiplier = 10000;

   
   pips*= multiplier;
   int rpips = pips;//Convert to a simple integer - all we need
   
   
   return(rpips);
   
}//End double CalculateVolatility(int period, int LookBack)


void ReadIndicatorValues()
{

   TrendDetectionModule();//Detect the trend
   

   //Reads any indicators associated with range trading   
   if (trend == ranging)
   {
      GetBB();
   }//if (trend == ranging)
/*
extern string  drg="dragosd1";
extern bool    UseDragosd1=true;//Set this as the default strategy - something has to be ds
extern int     DragMaTdTF=1440;//Time frame defaults to D1 chart 
extern int     DragMaTdPeriod=5;
extern int     DragMaTdShift=2;//The MA Shift input
extern string  dmame="Method: 0=sma; 1=ema; 2=smma;  3=lwma";
extern int     DragMaTdMethod=2;
extern string  dmaap="Applied price: 0=Close; 1=Open; 2=High";
extern string  dmaap1="3=Low; 4=Median; 5=Typical; 6=Weighted";
extern int     DragMaTdAppliedPrice=4;
*/
   
   //Reads any indicators associated with trend trading   
   if (trend != ranging)
   {
      //dragosd1
      if (UseDragosd1)
      {
         DragMaVal = GetMa(DragMaTdTF, DragMaTdPeriod, DragMaTdShift, DragMaTdMethod, DragMaTdAppliedPrice, 0);   
      }//if (UseDragosd1)
      
   
   }//if (trend != ranging)
   
   
   
}//void ReadIndicatorValues()

//End Indicator module
////////////////////////////////////////////////////////////////////////////////////////////////

void LookForTradeClosure()
{
   //Consult the various trend trade closure strategies
   
   
   bool CloseTrade;
   bool CloseCarolco = false;//Set to true if carolco gris is being used and there is a successful trade close, to force a pending deletion
   RefreshRates();

   //CountOpenTrades() leaves TicketNo pointing at the last trade in the sequence, which could easily be
   //a pending if carolco is being used. To solve this, I have enclosed the following code in a loop that
   //cycles through the list of open trades and examines each one. This increases the processor use, but
   //I cannot think of another solution.
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderType() != OP_BUY && OrderType() != OP_SELL) continue;//Ignore pendings for now
      
      //Close the trade if the market retreats to the wrong side of either ma from the 'wrong' direction.
      //Uses the candle median suggested by osthafen to avoid premature trade closure, so median must cross
      //to the wrong side of the fast ma to cause a trade closure.
      if (UseOsthafen) 
      {
         double median = (iHigh(NULL, PERIOD_D1, 0) + iLow(NULL, PERIOD_D1, 0) ) /2;//Save some typing
      }//if (UseCandleMedian) 
   
      //The SlowTrendMaVal check is probably redundant.
      if (OrderType() == OP_BUY)
      {
         //osthafen - the default
         if (UseOsthafen) 
         {
            if (median < FastTrendMaVal || median < SlowTrendMaVal) CloseTrade = true;
         }//if (UseCandleMedian) 
      
         //dragosd1 (median MA)
         if (UseDragosd1) 
         {      
            if (UseTouch && Bid <= DragMaVal) CloseTrade = true;
            if (UseClose)
            {
               if (iClose(NULL, DragMaTdTF, 1) < DragMaVal) CloseTrade = true;
            }//if (UseClose)
         
         }//if (UseDragosd1) 
      
         //Opposite direction signal
         if (UseOppositeSignal)
         {
            if (iHigh(NULL, PERIOD_D1, 0) < FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) < FastTrendMaVal) CloseTrade = true;         
         }//if (UseOppositeSignal)
      
            
      }//if (OrderType() == OP_BUY)
   
   
      if (OrderType() == OP_SELL)
      {
         //osthafen - the default
         if (UseOsthafen) 
         {      
            if (median > FastTrendMaVal || median > SlowTrendMaVal) CloseTrade = true;
         }//if (UseOsthafen) 
      
         //dragosd1 (median MA)
         if (UseDragosd1) 
         {      
            if (UseTouch && Bid >= DragMaVal) CloseTrade = true;
            if (UseClose)
            {
               if (iClose(NULL, DragMaTdTF, 1) < DragMaVal)  CloseTrade = true;
            }//if (UseClose)         
         }//if (UseDragosd1) 

         //Opposite direction signal
         if (UseOppositeSignal)
         {
            if (iHigh(NULL, PERIOD_D1, 0) > FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) > FastTrendMaVal) CloseTrade = true;         
         }//if (UseOppositeSignal)
      
      }//if (OrderType() == OP_SELL)
   
      //Trade closure
      if (CloseTrade && !UseHedging)
      {
         bool result = CloseTrade(TicketNo);
      
         //Actions when trade close succeeds
         if (result)
         {
            OpenTrades--;
            if (OpenTrades <= 0) TradeOrigin = none;
            GlobalVariableDel(GvName);            
            CloseCarolco = true;
         
         }//if (result)
   
         //Actions when trade close fails
         if (!result)
         {
   
         }//if (!result)
      }//if (CloseTrade)

      //Hedging instead of closure   
      if (CloseTrade && UseHedging && !HedgingInProgress && OrderProfit() < 0)
      {
         double SendLots = OrderLots() * HedgeLotMultiplier;
         RefreshRates();
         if (OrderType() == OP_BUY)
         {
            result = SendSingleTrade(OP_SELL, HedgeTradeComment, SendLots, NormalizeDouble(Bid, Digits), 0, 0);
            if (result) 
            {
               //Delete outstanding pendings
               if (UseCarolco && (NoOfPendingBuys > 0 || NoOfPendingSells > 0 ) )
               {
                  DeletePendings();
                  CountOpenTrades();//Forces startcarolco() to do a rerun if any deletions fail. cot resets all the xxxOpen variables.                  
               }//if (UseCarolco)
               return;//Attempt to stop multiple hedge trades being taken
            }//if (result)             
         }//if (OrderType() == OP_BUY)
      
         if (OrderType() == OP_SELL)
         {
            result = SendSingleTrade(OP_BUY, HedgeTradeComment, SendLots, NormalizeDouble(Ask, Digits), 0, 0);
            if (result) 
            {
               //Delete outstanding pendings
               if (UseCarolco && (NoOfPendingBuys > 0 || NoOfPendingSells > 0 ) )
               {
                  DeletePendings();
                  CountOpenTrades();//Forces startcarolco() to do a rerun if any deletions fail. cot resets all the xxxOpen variables.                  
               }//if (UseCarolco)
               return;//Attempt to stop multiple hedge trades being taken
            }//if (result)         
         }//if (OrderType() == OP_SELL)
      
         
      }//if (CloseTrade && UseHedging && !HedgingInProgress)
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   
   //Delete carolco grid trades. Probably not needed in light of the previous code. We shall see.
   if (CloseCarolco)
   {
      DeletePendings();
      CloseAllTrades();
      CountOpenTrades();//Forces startcarolco() to do a rerun if any deletions fail. cot resets all the xxxOpen variables.
   }//if (CloseCarolco)
   
   
}//void LookForTradeClosure()

void CloseAllTrades()
{
   ForceTradeClosure= false;
   
   if (OrdersTotal() == 0) return;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() == Symbol() )
      {
         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;
      }//if (OrderSymbol() == Symbol() )
   
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)


}//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()

void CountOpenTrades()
{
   OpenTrades = 0;
   TicketNo = -1;
   BuyOpen = false;
   SellOpen = false;
   TradeOpen = false;//Cat
   //Carolco
   NoOfPendingBuys = 0;
   NoOfPendingSells = 0;
   //Hedging
   BasketUpl = 0;
 
   if (OrdersTotal() == 0) return;
   
   int OrdTot = OrdersTotal();//Makes BB finish the entire loop if a trade closes mid-loop. Not likely, but possible
   
   for (int cc = 0; cc <= OrdTot; cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      {
         BasketUpl+= (OrderProfit() + OrderSwap() + OrderCommission() );//For closing a hedged basket at BE
         OpenTrades++;
         TicketNo = OrderTicket();   
         if (OrderType() == OP_BUY) BuyOpen = true;
         if (OrderType() == OP_SELL) SellOpen = true;
         TradeOpen = true;//cat
         
         //Profitable trade management
         if (OrderProfit() > 0 && !RecoveryInProgress && !HedgingInProgress) TradeManagementModule();
         
         //carolco
         if (OrderType() == OP_BUYSTOP)
         {
            //BuyTicketNo = OrderTicket();
            NoOfPendingBuys++;
         }//if (OrderType() == OP_BUYSTOP)
         
         if (OrderType() == OP_SELLSTOP)
         {
            //SellTicketNo = OrderTicket();
            NoOfPendingSells++;
         }//if (OrderType() == OP_SELLSTOP)

         //Recovery
         if (ObjectFind(breakevenlinename) > -1 && !HedgingInProgress)
         {
            double take = ObjectGet(breakevenlinename, OBJPROP_PRICE1);
            if (OrderTakeProfit() != take && (OrderType() == OP_BUY || OrderType() == OP_SELL) && !UseRecoveryTrailingStop)
            {
               while(IsTradeContextBusy()) Sleep(100);
               OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);
            }//if (OrderTakeProfit() != take && (OrderType() == OP_BUY || OrderType() == OP_SELL) )
         }//if (ObjectFind(breakevenlinename) > -1)

      }//if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
   }//for (int cc = 0; cc <= OrdTot; cc++)
   
   //Delete rednundat gv
   if (OpenTrades == 0 && TradeOrigin != none)
   {
      TradeOrigin = none;
      GlobalVariableDel(GvName);
   }//if (OpenTrades == 0 && TradeOrigin != none)
   
   //Hedging
   HedgingInProgress = false;//Had to be moved here so the management module is not called to hedged trades
   if (BuyOpen && SellOpen) HedgingInProgress = true;
   
   //Recovery
   RecoveryInProgress = false;//Had to be moved here so the management module is not called to recovery trades
   if (UseRecovery)
   {
      if (OpenTrades >= Start_Recovery_at_trades && TradeOrigin == rangeorigin) RecoveryInProgress = true;
   }//if (UseRecovery)
   
   
}//End void CountOpenTrades();

//=============================================================================
//                           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 TradeLong & TradeShort according to the positive/negative swap it attracts

   double LongSwap = MarketInfo(Symbol(), MODE_SWAPLONG);
   double ShortSwap = MarketInfo(Symbol(), MODE_SWAPSHORT);
   

   if (CadPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" || StringSubstr(Symbol(), 3, 3) == "CAD" || StringSubstr(Symbol(), 3, 3) == "cad" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" )      
   }//if (CadPairsPositiveOnly)
   
   if (AudPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
   }//if (AudPairsPositiveOnly)
   
   
   if (NzdPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "NZD" || StringSubstr(Symbol(), 0, 3) == "nzd" || StringSubstr(Symbol(), 3, 3) == "NZD" || StringSubstr(Symbol(), 3, 3) == "nzd" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
   }//if (AudPairsPositiveOnly)
   
   

}//void TradeDirectionBySwap()

bool IsThisPairTradable()
{
   //Checks to see if either of the currencies in the pair is already being traded twice.
   //If not, then return true to show that the pair can be traded, else return false
   
   string c1 = StringSubstr(Symbol(), 0, 3);//First currency in the pair
   string c2 = StringSubstr(Symbol(), 3, 3);//Second currency in the pair
   int c1open = 0, c2open = 0;
   CanTradeThisPair = true;
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      int index = StringFind(OrderSymbol(), c1);
      if (index > -1)
      {
         c1open++;         
      }//if (index > -1)
   
      index = StringFind(OrderSymbol(), c2);
      if (index > -1)
      {
         c2open++;         
      }//if (index > -1)
   
      if (c1open == 1 && c2open == 1) 
      {
         CanTradeThisPair = false;
         return(false);   
      }//if (c1open == 1 && c2open == 1) 
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so ok to trade
   return(true);
   
}//End bool IsThisPairTradable()

bool BalancedPair(int type)
{

   //Only allow an individual currency to trade if it is a balanced trade
   //e.g. UJ Buy open, so only allow Sell xxxJPY.
   //The passed parameter is the proposed trade, so an existing one must balance that

   //This code courtesy of Zeljko (zkucera) who has my grateful appreciation.
   
   string BuyCcy1, SellCcy1, BuyCcy2, SellCcy2;

   if (type == OP_BUY || type == OP_BUYSTOP)
   {
      BuyCcy1 = StringSubstr(Symbol(), 0, 3);
      SellCcy1 = StringSubstr(Symbol(), 3, 3);
   }//if (type == OP_BUY || type == OP_BUYSTOP)
   else
   {
      BuyCcy1 = StringSubstr(Symbol(), 3, 3);
      SellCcy1 = StringSubstr(Symbol(), 0, 3);
   }//else

   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS)) continue;
      if (OrderSymbol() == Symbol()) continue;
      if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP)
      {
         BuyCcy2 = StringSubstr(OrderSymbol(), 0, 3);
         SellCcy2 = StringSubstr(OrderSymbol(), 3, 3);
      }//if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP)
      else
      {
         BuyCcy2 = StringSubstr(OrderSymbol(), 3, 3);
         SellCcy2 = StringSubstr(OrderSymbol(), 0, 3);
      }//else
      if (BuyCcy1 == BuyCcy2 || SellCcy1 == SellCcy2) return(false);
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so it is ok to send the trade
   return(true);

}//End bool BalancedPair(int type)



//End Balance/swap filters module
///////////////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////////////////////
//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 + (RecoveryBreakEvenProfitPips * Point), Digits);
   }//if (buy_price > 0) 
   
   if (sell_price > 0) 
   {
      recovery_profit = sell_price;
      recovery_profit = NormalizeDouble(sell_price - (RecoveryBreakEvenProfitPips * Point), Digits);
   }//if (sell_price > 0) 

   ObjectCreate(breakevenlinename,OBJ_HLINE,0,TimeCurrent(), recovery_profit );
   ObjectSet(breakevenlinename,OBJPROP_COLOR,BreakEvenLineColour);
   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;
            
            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)

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,ReEntryLineColour);
   ObjectSet(reentrylinename,OBJPROP_STYLE,STYLE_SOLID);
   ObjectSet(reentrylinename,OBJPROP_WIDTH,2);     


}//void AddReEntryLine(int type, double price)

void ReplaceReEntryLine()
{

   //Find the most recent trade in the sequence and replace the missing re-entry line
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {      
      if (OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) )
      {
         if (OrderSymbol() == Symbol())
         {            
            if (OrderType() == OP_BUY) AddReEntryLine(NormalizeDouble(OrderOpenPrice() - (ReEntryLinePips * Point), Digits) );
            if (OrderType() == OP_SELL) AddReEntryLine(NormalizeDouble(OrderOpenPrice() + (ReEntryLinePips * Point), Digits) );
            return;
         }//if (OrderSymbol() == Symbol() && OrderCloseTime() == 0)      
         
      }//if (OrderSelect(cc, SELECT_BY_POS) )
      
   }//for (cc = OpenTrades; cc >= 0; cc--)

}//void ReplaceReEntryLine()

void CalculateReEntryLinePips()
{
   if (ReEntryLinePips > 0) return;//User has chosen the value, so nothing else to do
   
   ReEntryLinePips = (Volatility * ReEntryLineVolMult) * GlobalPipsMultiplier;
   

}//End void CalculateReEntryLinePips()


void RecoveryCandlesticktrailingStop()
{

   //Called from start()
   //This function will only be called if Recovery is in progress.
   

    //* no tp in Recovery trades, just the breakeven line on the chart
    //* at be +10, the breakeven line becomes the stop loss line
    //* code a candlestick trail for the stop loss line
    //* close the Recovery basket when the market retraces to the stop loss line

   
   //Find the trade type. Function leaves an open trade selected   
   
   double target, stop;
   
   RefreshRates();
          
   if (BuyOpen)
   {
      //Should breakeven line be replaced by trailing stop line.
      //Irrelevant if be line has been deleted
      if (ObjectFind(breakevenlinename) > -1)
      {
         target = ObjectGet(breakevenlinename, OBJPROP_PRICE1);
         if (Ask >= target + (RecoveryTrailingStopAt * Point) )
         {
            ObjectDelete(breakevenlinename);
            ObjectCreate(breakevenlinename, 1,0,TimeCurrent(),target);
            ObjectSet(breakevenlinename,OBJPROP_COLOR,RecoveryStopLossLineColour);
            ObjectSet(breakevenlinename,OBJPROP_STYLE,STYLE_SOLID);
            ObjectSet(breakevenlinename,OBJPROP_WIDTH,2);     
            //return;
         }//if (Ask >= target + (RecoveryTrailingStopAt * Point) )
      }//if (ObjectFind(breakevenlinename) > -1)
      
      //Abort the function if be line is wrong colour
      if (ObjectGet(breakevenlinename, OBJPROP_COLOR) != RecoveryStopLossLineColour) return;
  
      //Move the stop at each new candle
      if (OldRecoverTrailBars != Bars)
      {
         target = ObjectGet(breakevenlinename, OBJPROP_PRICE1);
         
         if (Low[1] > target)
         {
            ObjectMove(breakevenlinename, 0, TimeCurrent(), Low[1]);            
         }//if (Low[1] > target)
         OldRecoverTrailBars = Bars;
         //return;
      }//if (OldRecoverTrailBars != Bars)
      
      //Has the market retraced to the recovery stop loss
      target = ObjectGet(breakevenlinename, OBJPROP_PRICE1);
      
      if (Ask <= target)
      {         
         ForceTradeClosure = true;
         CloseAllTrades();
         ObjectDelete(breakevenlinename);
         return;
      }//if (Ask <= target)
   }//if (OrderType() == OP_BUY)
   
   //The most recent trade selected in CountOpenTrades will show the type of trades involved
   if (SellOpen)
   {
      //Should breakeven line be replaced by trailing stop line
      //Irrelevant if be line has been deleted
      if (ObjectFind(breakevenlinename) > -1)
      {
         target = ObjectGet(breakevenlinename, OBJPROP_PRICE1);
         if (Bid <= target - (RecoveryTrailingStopAt * Point) )
         {            
            ObjectDelete(breakevenlinename);
            ObjectCreate(breakevenlinename, 1,0,TimeCurrent(),target);
            ObjectSet(breakevenlinename,OBJPROP_COLOR,RecoveryStopLossLineColour);
            ObjectSet(breakevenlinename,OBJPROP_STYLE,STYLE_SOLID);
            ObjectSet(breakevenlinename,OBJPROP_WIDTH,2);     
            //return;
         }//if (Bid <= target - (RecoveryTrailingStopAt * Point) )
      }//if (ObjectFind(breakevenlinename) > -1)
      
      
      //Abort the function if be line is wrong colour
      if (ObjectGet(breakevenlinename, OBJPROP_COLOR) != RecoveryStopLossLineColour) return;
      
      
      
      //Move the stop at each new candle
      if (OldRecoverTrailBars != Bars)
      {
         target = ObjectGet(breakevenlinename, OBJPROP_PRICE1);
         if (High[1] < target)
         {
            ObjectMove(breakevenlinename, 0, TimeCurrent(), High[1]);         
         }//if (High[1] < target)
         OldRecoverTrailBars = Bars;
         //return;
      }//if (OldRecoverTrailBars != Bars)
      
      //Has the market retraced to the recovery stop loss
      target = ObjectGet(breakevenlinename, OBJPROP_PRICE1);
      //Alert("Target = ", target);
      if (Bid >= target)
      {
         ForceTradeClosure = true;
         CloseAllTrades();
         ObjectDelete(breakevenlinename);
         return;
      }//if (Bid >= target)
   }//if (OrderType() == OP_SELL)
   
   

}//End void RecoveryCandlesticktrailingStop()


//End Recovery module
///////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////
//Trend detection module

void TrendDetectionModule()
{

   //Define the trend according to the user's choices.
   //Only called if UseTrendDetection is set to true - as it should be
   
   /*
   Trend definitions
      - uptrend: high and low of D1 candle above both MA's
      - downtrend: high and low of D1 candle below both MA's
      - ranging: any part of the candle in between the MA's
   */
   
   //Set the trend according to an open trade. This may change, but for now it makes little sense to me
   //to have a trades sent from one market type managed the the opposite following a change from trend
   //to range or vice versa   
   if (TradeOrigin == trendorigin)
   {
      //Read the moving averages for display
      FastTrendMaVal = GetMa(FastMaTdTF, FastMaTdPeriod, FastMaTdShift, FastMaTdMethod, FastMaTdAppliedPrice, 0);   
      SlowTrendMaVal = GetMa(SlowMaTdTF, SlowMaTdPeriod, SlowMaTdShift, SlowMaTdMethod, SlowMaTdAppliedPrice, 0); 

      
      if (OpenTrades == 0) CountOpenTrades();
      if (OpenTrades > 0)
      {
         OrderSelect(TicketNo, SELECT_BY_TICKET);
         if (OrderType() == OP_BUY)
         {
            trend = up;
            return;
         }//if (OrderType() == OP_BUY)
         
         if (OrderType() == OP_SELL)
         {
            trend = down;
            return;
         }//if (OrderType() == OP_SELL)
      }//if (OpenTrades > 0)
   }//if (TradeOrigin == trendorigin)
   
   /*
   if (TradeOrigin == rangeorigin)
   {
      trend = ranging;
      return;
   }//if (TradeOrigin == trendorigin)
   */
   
   //No open trade, so no restriction on trend setting
   
   trend = ranging;//Default
   

   //Read the moving averages
   FastTrendMaVal = GetMa(FastMaTdTF, FastMaTdPeriod, FastMaTdShift, FastMaTdMethod, FastMaTdAppliedPrice, 0);   
   SlowTrendMaVal = GetMa(SlowMaTdTF, SlowMaTdPeriod, SlowMaTdShift, SlowMaTdMethod, SlowMaTdAppliedPrice, 0); 
   //Calculate the trend
   //Uptrend
   if (iHigh(NULL, PERIOD_D1, 0) > FastTrendMaVal && iHigh(NULL, PERIOD_D1, 0) > SlowTrendMaVal 
       && iLow(NULL, PERIOD_D1, 0) > FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) > SlowTrendMaVal) trend = up;
   
   //Downtrend
   if (iHigh(NULL, PERIOD_D1, 0) < FastTrendMaVal && iHigh(NULL, PERIOD_D1, 0) < SlowTrendMaVal 
       && iLow(NULL, PERIOD_D1, 0) < FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) < SlowTrendMaVal) trend = down;
   
   
   //Check that we are entering the market at the start of the trend. We will be at the start of the trend
   //if either hi or lo of yesterdays candle was within the two MA's
   if (OnlyTradeStartOfTrend && trend != ranging)
   {
      double PrevFastTrendMaVal, PrevSlowTrendMaVal;
      PrevFastTrendMaVal = GetMa(FastMaTdTF, FastMaTdPeriod, FastMaTdShift, FastMaTdMethod, FastMaTdAppliedPrice, 1);   
      PrevSlowTrendMaVal = GetMa(SlowMaTdTF, SlowMaTdPeriod, SlowMaTdShift, SlowMaTdMethod, SlowMaTdAppliedPrice, 1); 
   
      if (trend == up)
      {
         trend = upbutuntradable;
         if (iHigh(NULL, PERIOD_D1, 1) < PrevFastTrendMaVal || iHigh(NULL, PERIOD_D1, 1) < PrevSlowTrendMaVal 
            || iLow(NULL, PERIOD_D1, 1) < PrevFastTrendMaVal || iLow(NULL, PERIOD_D1, 1) < PrevSlowTrendMaVal) trend = up;   
      }//if (trend == up)
      
      if (trend == down)
      {
         trend = downbutuntradable;
         if (iHigh(NULL, PERIOD_D1, 1) > PrevFastTrendMaVal || iHigh(NULL, PERIOD_D1, 1) > PrevSlowTrendMaVal 
            || iLow(NULL, PERIOD_D1, 1) > PrevFastTrendMaVal || iLow(NULL, PERIOD_D1, 1) > PrevSlowTrendMaVal) trend = down;   
      }//if (trend == down)
      
   
   }//if (OnlyTradeStartOfTrend && trend != ranging)
   
   
   //Allow for conversion of trade origin from range to trend if the market is now trending
   if (AllowChangeOfOriginToTrend && TradeOrigin == rangeorigin && trend != ranging)
   {
      TradeOrigin = trendorigin;
      GlobalVariableSet(GvName, 0);
      ObjectDelete(reentrylinename);
      ObjectDelete(breakevenlinename);      
   }//if (AllowChangeOfOriginToTrend && TradeOrigin == rangeorigin && trend != ranging)
   
}//void TrendDetectionModule()


//End Trend detection module
///////////////////////////////////////////////////////////////////////////////////////////////////////


void GetTrendConfirmationCandleDir()
{
   //BB uses a shorter-term candle direction filter to confirm that the market is moving in the correct
   //direction for the trade. This function ascertains the direction of movement of the candle
   
   TrendConfirmationCandleDir = none;
   
   if (iOpen(NULL, TrendConfirmationCandleTF, 1) > iClose(NULL, TrendConfirmationCandleTF, 1) ) TrendConfirmationCandleDir = down;
   if (iOpen(NULL, TrendConfirmationCandleTF, 1) < iClose(NULL, TrendConfirmationCandleTF, 1) ) TrendConfirmationCandleDir = up;
   
   
}//End void GetTrendConfirmationCandleDir()


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Caterpillar module
void DeleteOrphanGlobals()
{
   //Remove those globals left behind after a trade closes
   for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--)
   {
      CsGvName = GlobalVariableName(cc);
      int tn = StrToDouble(CsGvName);
      if (tn > 0)
      {
         if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) 
         {
            GlobalVariableDel(CsGvName);
            cc++;            
         }//if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) 
      }//if (tn > 0)
      
   }//for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--)
   

}//End void DeleteOrphanGlobals()
void MoveCaterpillarStopToBreakeven()
{
   //OpenTrades - 1 trade needs to have its stop moved to be at the opening of a new trade
   
   //Select OpenTrades - 1
   int found = 0;
   for (int cc = 0; cc <= OrdersTotal() - 1; cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber ) continue;
      
      //Order must belong to Cat
      found++;
      if (found == OpenTrades - 1) break;   
   }//for (int cc = 0; cc <= OrdersTotal() - 1; cc++)
   
   double stop = OrderOpenPrice();
   bool modify = false;
   
   if (OrderType() == OP_BUY && OrderStopLoss() < OrderOpenPrice() ) modify = true;
   if (OrderType() == OP_SELL && OrderStopLoss() > OrderOpenPrice() ) modify = true;
   
   if (modify)
   {
      int tries = 0;
      bool result = false;
      while (!result)
      {
         result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
         if (!result)
         {
            tries++;
            if (tries == 1) Alert(OrderTicket(), " stop loss move to BE failed");
            if (tries == 100) 
            {
               result = true;//Give up
               Alert(OrderTicket(), " Caterpillar failed to move the sl to breakeven after 100 attempts.");
            }//if (tries == 100)             
         }//if (!result)
      }//while (!result)      
   }//if (modify)
   
   

}//End void MoveCaterpillarStopToBreakeven()

void CaterpillarTrailingStop(int TradesToCheck)
{
   //Move trade stops 1 candle to the right when there is a new hi or lo, depending on the trade type
   //Also deletes redundant gv's
   
   if (GlobalVariablesTotal() == 0) return;//Shouldn't happen, but you never know
   
   int found, shift, ctime;
   bool result;
   double stop;
   int MaxTradesTicketNo = -1;//This will hold the ticket number of the final trade in the sequence, but which is checked first
   
   
   //Cycle through the Golbal Variables list to look for those with an integer as their name
   for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--)
   {
      CsGvName = GlobalVariableName(cc);
      int tn = StrToDouble(CsGvName);
      if (tn > 0)
      {
         //Delete the gv if the trade has closed
         if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) 
         {
            GlobalVariableDel(CsGvName);
            cc++;
            continue;
         }//if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) 
         
         //The trade is still open, so check for ownership
         if (OrderSymbol() != Symbol() ) continue;
         if (OrderMagicNumber() != MagicNumber ) continue;
      
         
         //Got this far, so Cat owns the trade and the stop needs moving.
         //Store the ticket number of the most recent trade in the sequence,for BE stop stuff further down
         if (MaxTradesTicketNo == -1) MaxTradesTicketNo = OrderTicket();
         //Calculate the shift back from current candle to the candle open time of the previous cts move
         shift = 0;
         ctime = GlobalVariableGet(CsGvName);
         while (Time[shift] > ctime && shift < Bars)
         {
            shift++;
         }//while (Time[shift} > ctime)
         //Point to the next candls
         shift--;
         //This is an attempt to stop the final trade in the sequence having its stop moved too early, because
         //this can result in it being stopped out as soon as it is opened
         if (shift < 2) continue;

         if (OrderType() == OP_BUY)
         {
            //stop = Low[shift];
            stop = iLow(NULL, CatTimeFrame, shift);
            if (OrderStopLoss() < stop && stop > 0)
            {
               while (IsTradeContextBusy() ) Sleep(100);
               result = OrderModify(tn, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
               GlobalVariableSet(CsGvName, Time[shift]);
            }//if (OrderStopLoss() < stop)            
         }//if (OrderType() == OP_BUY)
         
         if (OrderType() == OP_SELL)
         {
            //stop = High[shift];
            stop = iHigh(NULL, CatTimeFrame, shift);
            if (OrderStopLoss() > stop && stop > 0)
            {
               while (IsTradeContextBusy() ) Sleep(100);
               result = OrderModify(tn, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
               GlobalVariableSet(CsGvName, Time[shift]);
            }//if (OrderStopLoss() > stop)
         }//if (OrderType() == OP_SELL)
         
         found++;
         if (found >= TradesToCheck) break;//All finished

      }//if (tn > -1)
   }//for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--)
   
   //Attempt to move the stop of the final trade to BE asap, if OpenTrades has reached the max allowed.   
   if (OpenTrades == MaxTrades)
   {
      if (OrderSelect(MaxTradesTicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0)
      {
         stop = OrderOpenPrice();
         bool modify = false;
         if (OrderType() == OP_BUY && OrderStopLoss() < OrderOpenPrice() )
         {
            modify = true;
         }//if (OrderType() == OP_BUY && OrderStopLoss() < OrderOpenPrice() )
         
         if (OrderType() == OP_SELL && OrderStopLoss() > OrderOpenPrice() )
         {
            modify = true;
         }//if (OrderType() == OP_SELL && OrderStopLoss() > OrderOpenPrice() )
         
         if (modify)
         {
            result = OrderModify(MaxTradesTicketNo, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
         }//if (modify)
         
      
      }//if (OrderSelect(MaxTradesTicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0)
      
   }//if (OpenTrades == MaxTrades)

}//void CaterpillarTrailingStop()

void LookForCatTradingOpportunities()
{
   RefreshRates();
   double take, stop, price;
   int type;
   bool SendTrade;
   double spread = MarketInfo(Symbol(), MODE_SPREAD) * Point;

   //Ensure a minimum gap in between trades
   double pipsgap = (OnePip * Point);
   if (OpenTrades > 0) pipsgap*= MinPipsBetweenCandles;
   
   double SendLots = Lot;
   //Check filters
   if (!IsTradingAllowed() ) return;
   
   RefreshRates();
   //Long 
   double target;
   if (TradeLong)
   {      
      target = ObjectGet(buyline, OBJPROP_PRICE1);
      if (Bid > target)
      {
         //if (TakeProfit > 0) take = NormalizeDouble(Ask + (TakeProfit * Point), Digits);
         //stop = NormalizeDouble(Low[1] - spread - (OnePip * Point), Digits);
         //stop = NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - spread - (OnePip * Point), Digits);
         type = OP_BUY;
         price = Ask;
         SendTrade = true;
      }//if (Bid > target) return;
         
   }//if (TradeLong)
   
   
   //Short
   if (TradeShort)
   {
      target = ObjectGet(sellline, OBJPROP_PRICE1);
      if (Bid < target)
      {
         //stop = NormalizeDouble(High[1] + spread + (OnePip * Point), Digits);      
         //stop = NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + spread + (OnePip * Point), Digits);      
         type = OP_SELL;
         price = Bid;
         SendTrade = true;      
      }//if (Bid < target)      
   }//if (TradeShort)
   

   if (SendTrade)
   {
      bool result = SendSingleTrade(type, CatTradeComment, SendLots, price, stop, take);
   }//if (SendTrade)
   
   //Actions when trade send succeeds
   if (SendTrade && result)
   {
      OpenTrades++;
      TradeOpen = true;
      CandleTraded = true;
      if (OpenTrades > 1) MoveCaterpillarStopToBreakeven();//Move the stop of the previously opened trade to be
      if (OpenTrades > 2) CaterpillarTrailingStop(OpenTrades - 1);//All trades from OpenTrades - 2 should move their stops 1 candle to the right
      
      //Set up a trend origin GV
      GlobalVariableSet(GvName, 0);
      TradeOrigin = trendorigin;
      
      //Redraw the trade line
      pipsgap = (OnePip * Point);
      if (OpenTrades > 0) pipsgap*= MinPipsBetweenCandles;
      
      if (type == OP_BUY)
      {
         ObjectDelete(buyline);
         target = NormalizeDouble(price + pipsgap + spread, Digits);
         ObjectCreate(buyline,OBJ_HLINE,0,TimeCurrent(), target);
         ObjectSet(buyline,OBJPROP_COLOR,BuyLineColour);
         ObjectSet(buyline,OBJPROP_STYLE,STYLE_SOLID);  
      }//if (type == OP_BUY)
      
      if (type == OP_SELL)
      {
         ObjectDelete(sellline);
         target = NormalizeDouble(price - pipsgap - spread, Digits);
         ObjectCreate(sellline,OBJ_HLINE,0,TimeCurrent(), target);
         ObjectSet(sellline,OBJPROP_COLOR,SellLineColour);
         ObjectSet(sellline,OBJPROP_STYLE,STYLE_SOLID);         
      }//if (type == OP_SELL)

   }//if (result)
   
   //Actions when trade send fails
   if (SendTrade && !result)
   {
      
   }//if (!result)
   
   

}//void LookForCatTradingOpportunities()

void StartCaterpillar()
{
   //This function is the equivalent of start() in the independent Caterpillar EA. Please read BB's user guide
   //for details of how Cat works.
   
   static bool OldTradeOpen;

   //Delete orphan Caterpillar gv's
   if (OldH1Bars != iBars(NULL, PERIOD_H1) )
   {
      OldH1Bars = iBars(NULL, PERIOD_H1);
      if (GlobalVariablesTotal() > 0) DeleteOrphanGlobals();
   }//if (OldH1Bars != iBars(NULL, PERIOD_H1) )
   
   

   //Trading
   if (OpenTrades < MaxTrades && !CandleTraded)
   {
      LookForCatTradingOpportunities();
   }//if (OpenTrades < MaxTrades)

   ///////////////////////////////////////////////////////////////////////////////////////////////
   
   if (OldCatBars != iBars(NULL, CatTimeFrame))
   {
      OldCatBars = iBars(NULL, CatTimeFrame);
      CandleTraded = false;
      
     //Move lines
     //Ensure a minimum gap in between trades     
      double pipsgap = (OnePip * Point);
      if (OpenTrades > 0) pipsgap*= MinPipsBetweenCandles;
      double target;

      target = ObjectGet(buyline, OBJPROP_PRICE1);
      //if (TradeLong && NormalizeDouble(High[1] + pipsgap, Digits) > target)
      if (trend == up && TradeLong && NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + pipsgap, Digits) > target)
      {
         ObjectDelete(buyline);
         //target = NormalizeDouble(High[1] + pipsgap, Digits);
         if (UseHanover && !HanoverFilter(OP_BUY) ) return;      
         target = NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + pipsgap, Digits);
         ObjectCreate(buyline,OBJ_HLINE,0,TimeCurrent(), target);
         ObjectSet(buyline,OBJPROP_COLOR,BuyLineColour);
         ObjectSet(buyline,OBJPROP_STYLE,STYLE_SOLID);               
         if (OpenTrades > 1) CaterpillarTrailingStop(OpenTrades);
      }//if (TradeLong)
   
      target = ObjectGet(sellline, OBJPROP_PRICE1);
      if (trend == down && TradeShort && NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - pipsgap, Digits) < target)
      {
         ObjectDelete(sellline);
         //target = NormalizeDouble(Low[1] - pipsgap, Digits);
         if (UseHanover && !HanoverFilter(OP_SELL) ) return;      
         target = NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - pipsgap, Digits);
         ObjectCreate(sellline,OBJ_HLINE,0,TimeCurrent(), target);
         ObjectSet(sellline,OBJPROP_COLOR,SellLineColour);
         ObjectSet(sellline,OBJPROP_STYLE,STYLE_SOLID);         
         if (OpenTrades > 1) CaterpillarTrailingStop(OpenTrades);
      }//if (TradeShort && ObjectFind(sellline) == -1)
   }//if (OldCatBars != iBars(NULL, CatTimeFrame))
   
   ///////////////////////////////////////////////////////////////////////////////////////////////      


}//End void StartCaterpillar()

//END Caterp[illar module
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Carolco module

void DeletePendings()
{
   //Deletes pending grid trades after all filled trades have closed
   
   if (OrdersTotal() == 0) return;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderType() != OP_BUY && OrderType() != OP_SELL && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      {
         bool result = OrderDelete(OrderTicket() );
         if (result) cc++;
      }//if (OrderType() != OP_BUY && OrderType() != OP_SELL && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)


}//End void DeletePendings()


void SendGrid()
{
   //Sends the carolco grid trades
   
   RefreshRates();
   double take, stop, price;
   int type;
   bool result;
   int cc;
   double spread = MarketInfo(Symbol(), MODE_SPREAD) * Point;

   //Check filters
   if (!IsTradingAllowed() ) return;
   
   RefreshRates();
   //Send market trades.
   //Long
   if (trend == up && TradeLong && TrendConfirmationCandleDir == up)
   {      
      if (UseZeljko && !BalancedPair(OP_BUY) ) return;
      //First trade without tp and sl
      result = SendSingleTrade(OP_BUY, CarolcoTradeComment, Lot, NormalizeDouble(Ask, Digits), 0, 0);
      if (!result) return;
      Sleep(100);
      //Second trade with tp
      RefreshRates();
      take = NormalizeDouble(Ask + (PipsBetweenTrades * Point), Digits);
      result = SendSingleTrade(OP_BUY, CarolcoTradeComment, Lot, NormalizeDouble(Ask, Digits), 0, take);
      if (result)
      {
         GlobalVariableSet(GvName, 0);
         TradeOrigin = trendorigin;
      }//if (result)      
   }//if (trend == up && TradeLong)
   
   
   //Short
   if (trend == down && TradeShort && TrendConfirmationCandleDir == down)
   {      
      if (UseZeljko && !BalancedPair(OP_SELL) ) return;
      //First trade without tp and sl
      result = SendSingleTrade(OP_SELL, CarolcoTradeComment, Lot, NormalizeDouble(Bid, Digits), 0, 0);
      if (!result) return;
      Sleep(100);
      //Second trade with tp
      RefreshRates();
      take = NormalizeDouble(Bid - (PipsBetweenTrades * Point), Digits);
      result = SendSingleTrade(OP_SELL, CarolcoTradeComment, Lot, NormalizeDouble(Bid, Digits), 0, take);
      if (result)
      {
         GlobalVariableSet(GvName, 0);
         TradeOrigin = trendorigin;
      }//if (result)
   }//if (trend == dowb && TradeShort)
   
   
   
   //Send peding trade grid
   //Long 
   double target;
   if (trend == up && TradeLong && TrendConfirmationCandleDir == up)
   {      
      price = Ask;
      for (cc = 1; cc <= TradesInGrid; cc++)
      {
         price = NormalizeDouble(price + spread + (PipsBetweenTrades * Point), Digits);
         take = NormalizeDouble(price + (PipsBetweenTrades * Point), Digits);
         stop = 0;
         if (UseCarolcoStopLoss) stop = NormalizeDouble(price - (PipsBetweenTrades * Point), Digits);
         result = false;
         while (!result)
         {
            result = SendSingleTrade(OP_BUYSTOP, CarolcoTradeComment, CarolcoGridLot, price, stop, take);
            if (!result) Sleep(100);
         }//while (!result)
         Sleep(100);
      }//for (cc = 1; cc < TradesInGrid; cc++)
   }//if (TradeLong)
   
   //Short
   if (trend == down && TradeShort && TrendConfirmationCandleDir == down)
   {
      price = Bid;
      for (cc = 1; cc <= TradesInGrid; cc++)
      {
         price = NormalizeDouble(price - spread - (PipsBetweenTrades * Point), Digits);
         take = NormalizeDouble(price - (PipsBetweenTrades * Point), Digits);
         stop = 0;
         if (UseCarolcoStopLoss) stop = NormalizeDouble(price + (PipsBetweenTrades * Point), Digits);
         result = false;
         while (!result)
         {
            result = SendSingleTrade(OP_SELLSTOP, CarolcoTradeComment, CarolcoGridLot, price, stop, take);
            if (!result) Sleep(100);
         }//while (!result)
         Sleep(100);
      }//for (cc = 1; cc < TradesInGrid; cc++)
   }//if (TradeShort)
   

}//End void SendGrid()


void StartCarolco()
{
   //Equates to start() in a stand-alone ea
   
   //Send initial trades
   if (NoOfPendingBuys == 0 && NoOfPendingSells == 0 && !BuyOpen && !SellOpen)
   {
      SendGrid();   
   }//if (NoOfPendingBuys == 0 && NoOfPendingSells == 0)
   
   //Delete pendings after all open trades have closed
   if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) )
   {
      DeletePendings();
   }//if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) )
   

}//void StartCarolco()

//End Carolco module
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////
//Hanover module
void SetUpArrays()
{
   //Sets up all the arrays required by this program

   int cc;
   int Index = 0;//For searching InputString
   int LastIndex = 0;//Points the the most recent Index
   

   //TimeFrames
   InputString = TrendTimeFrames;
   CleanUpInputString();
   TrendTimeFrames = InputString;
   NoOfTrendTimeFrames = CalculateParamsPassed();
   string NewArray2 = ArrayResize(Tf, NoOfTrendTimeFrames);
   
   Index = 0;//For searching InputString
   LastIndex = 0;//Points the the most recent Index
   for (cc = 0; cc < NoOfTrendTimeFrames; cc ++)
   {
      Index = StringFind(InputString, ",",LastIndex);
      if (Index > -1)
      {
         Tf[cc] = StringSubstr(InputString, LastIndex,Index-LastIndex);
         Tf[cc] = StringTrimLeft(Tf[cc]);
         Tf[cc] = StringTrimRight(Tf[cc]);
         LastIndex = Index+1;
      }//if (Index > -1)      
   }//for (cc = 0; cc < NoOfTrendTimeFrames; cc ++)

   //StrongWeak
   string NewArray3 = ArrayResize(StrongWeak, NoOfTrendTimeFrames);
   string NewArray4 = ArrayResize(StrongestCcy, NoOfTrendTimeFrames);
   string NewArray5 = ArrayResize(WeakestCcy, NoOfTrendTimeFrames);
   double NewArray6 = ArrayResize(StrongVal, NoOfTrendTimeFrames);
   double NewArray7 = ArrayResize(WeakVal, NoOfTrendTimeFrames);
   double NewArray8 = ArrayResize(PrevStrongVal, NoOfTrendTimeFrames);
   double NewArray9 = ArrayResize(PrevWeakVal, NoOfTrendTimeFrames);
   double NewArray10 = ArrayResize(ConstructedPair, NoOfTrendTimeFrames);
   
   
   
   
}//End void SetUpArrays()


int CalculateParamsPassed()
{
   // Calculates the numbers of paramaters passed in LongMagicNumber and TradeComment.
   
   int Index = 0;//For searching NoTradePairs
   int LastIndex;//Points the the most recent Index
   int NoOfParams = 0;
   
   while(Index > -1)
   {
      Index = StringFind(InputString, ",",LastIndex);
      if (Index > -1)
      {
         NoOfParams++;
         LastIndex = Index+1;            
      }//if (Index > -1)
   }//while(int cc > -1)
      
  return(NoOfParams);
}//int CalculateParamsPassed()


//+------------------------------------------------------------------+
string StringRight(string str, int n=1)
//+------------------------------------------------------------------+
// Returns the rightmost N characters of STR, if N is positive
// Usage:    string x=StringRight("ABCDEFG",2)  returns x = "FG"
//
// Returns all but the leftmost N characters of STR, if N is negative
// Usage:    string x=StringRight("ABCDEFG",-2)  returns x = "CDEFG"
{
  if (n > 0)  return(StringSubstr(str,StringLen(str)-n,n));
  if (n < 0)  return(StringSubstr(str,-n,StringLen(str)-n));
  return("");
}



string StringUpper(string str)
//+------------------------------------------------------------------+
// Converts any lowercase characters in a string to uppercase
// Usage:    string x=StringUpper("The Quick Brown Fox")  returns x = "THE QUICK BROWN FOX"
{
  string outstr = "";
  string lower  = "abcdefghijklmnopqrstuvwxyz";
  string upper  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  for(int i=0; i<StringLen(str); i++)  {
    int t1 = StringFind(lower,StringSubstr(str,i,1),0);
    if (t1 >=0)  
      outstr = outstr + StringSubstr(upper,t1,1);
    else
      outstr = outstr + StringSubstr(str,i,1);
  }
  return(outstr);
}  

//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
string StringTrim(string str)
//+------------------------------------------------------------------+
// Removes all spaces (leading, traing embedded) from a string
// Usage:    string x=StringUpper("The Quick Brown Fox")  returns x = "TheQuickBrownFox"
{
  string outstr = "";
  for(int i=0; i<StringLen(str); i++)  {
    if (StringSubstr(str,i,1) != " ")
      outstr = outstr + StringSubstr(str,i,1);
  }
  return(outstr);
}

//+------------------------------------------------------------------+
int StrToStringArray(string str, string &a[], string delim=",", string init="")  {
//+------------------------------------------------------------------+
// Breaks down a single string into string array 'a' (elements delimited by 'delim')
  for (int i=0; i<ArraySize(a); i++)
    a[i] = init;
  int z1=-1, z2=0;
  if (StringRight(str,1) != delim)  str = str + delim;
  for (i=0; i<ArraySize(a); i++)  {
    z2 = StringFind(str,delim,z1+1);
    a[i] = StringSubstr(str,z1+1,z2-z1-1);
    if (z2 >= StringLen(str)-1)   break;
    z1 = z2;
  }
  return(StringFindCount(str,delim));
}


//+------------------------------------------------------------------+
int ArrayLookupString(string str, string a[])   {
//+------------------------------------------------------------------+
 for (int i=0; i<ArraySize(a); i++)   {
   if (str == a[i])   return(i);
 }  
 return(-1);
} 

//+------------------------------------------------------------------+
double StrToNumber(string str)  {
//+------------------------------------------------------------------+
// Usage: strips all non-numeric characters out of a string, to return a numeric (double) value
//  valid numeric characters are digits 0,1,2,3,4,5,6,7,8,9, decimal point (.) and minus sign (-)
  int    dp   = -1;
  int    sgn  = 1;
  double num  = 0.0;
  for (int i=0; i<StringLen(str); i++)  {
    string s = StringSubstr(str,i,1);
    if (s == "-")  sgn = -sgn;   else
    if (s == ".")  dp = 0;       else
    if (s >= "0" && s <= "9")  {
      if (dp >= 0)  dp++;
      if (dp > 0)
        num = num + StrToInteger(s) / MathPow(10,dp);
      else
        num = num * 10 + StrToInteger(s);
    }
  }
  return(num*sgn);
}

int LoadRSvalues()  
{
  //This code courtesy of hanover. Many thanks David. You are a star.
  
  //Ccy[] holds the individual currency symbol
  //Tf[] holds the time frames
  //God knows where we go from here
  
  // Initialize array......
  for (i=0; i<8; i++)
    for (j=0; j<9; j++)
      for (k=0; k<99; k++)
         RSvalue[i][j][k] = 0;

         // Read data from Recent Strength export file into RSvalue array.......
         h = FileOpen(OutputFile,FILE_CSV|FILE_READ,'~');
         i=0; j=0; k=0;
         string prevtf = "";
         while (!FileIsEnding(h))     
         {
           StrToStringArray(FileReadString(h),arr);
           if (FileIsEnding(h))   break;
           if (arr[1] == "TF ")   
           {                                     // get ccy IDs from header record
             for (i=0; i<8; i++)  
             {
               ccy[i] = StringUpper(StringTrim(arr[i+3]));               
             }//for (i=0; i<8; i++)  
             continue;
           }//if (arr[1] == "TF ")   
           string currtf = StringUpper(StringTrimRight(arr[1]));
           j = ArrayLookupString(currtf,tf);
           if (j<0)     continue;                                    // unknown timeframe - should never happen
           if (currtf != prevtf)                                     // reset datapoint counter on change of timeframe
             k = 0;
           else
             k++;
           if (k>=99)   continue;                                    // max of 99 data points only
           for (i=0; i<8; i++)  
           {                                    // load array values for all currencies
             RSvalue[i][j][k] = StrToNumber(arr[i+3]);
             
           }//for (i=0; i<8; i++)  
           prevtf = currtf;  
         }//while (!FileIsEnding(h))     
  FileClose(h);
  return(0);
}//End int LoadRSvalues()  

void ReadHanover()
{
   //This function reads the output from the indi output file.
   LoadRSvalues();

/* Posted by hanover
If we use RSvalue[i][j][k], then
i = the currency
j = the timeframe
k = the datapoint#. Point #0 is rightmost point on the RS plot; point #1 is the second point from the right; 
point #2 is the third point from the right; and so on, up to the number of points being 
output (set by the NumPoints parameter in RS)

Hence, supposing you want to retrieve the value of the third datapoint for USD,H1, then (using the constants defined earlier) you could use the code:

double value = RSvalue[_USD][_H1][2];
*/
   //Find the strongest and weakest currency
   //Strongest
   double s, ps;//Strongest and previous strongest value
   double w, pw;//Weakest and previous weakest value


   //Currencies
   for (i = 0; i < ArraySize(StrongVal); i++)
   {
      StrongVal[i] = 0;//Initialize the strongest datapoint
      WeakVal[i] = 100000;//Initialize the weakest datapoint
   }//for (i = 0; i < ArraySize(StrongVal); i++)
   
   for (i = 0; i < ArraySize(ccy); i++)
   {
      //Timeframes
      for (j = 0; j < ArraySize(Tf); j++)
      {
         //Data point
         //Extract the timeframe - uses David's constants
         int DatapointTf;
         if (Tf[j] == "M1") DatapointTf = M1;
         if (Tf[j] == "M5") DatapointTf = M5;
         if (Tf[j] == "M15") DatapointTf = M15;
         if (Tf[j] == "M30") DatapointTf = M30;
         if (Tf[j] == "H1") DatapointTf = H1;
         if (Tf[j] == "H4") DatapointTf = H4;
         if (Tf[j] == "D1") DatapointTf = D1;
         if (Tf[j] == "W1") DatapointTf = W1;
         if (Tf[j] == "MN") DatapointTf = MN;
         
         for (k = 0; k < NumPoints; k++)
         {
            //Find the strongest datapoint on the current currency and timeframe
            if (RSvalue[i, DatapointTf, 0] > StrongVal[j])
            {
               StrongestCcy[j] = ccy[i];
               StrongVal[j] = RSvalue[i, DatapointTf, 0];
               PrevStrongVal[j] = RSvalue[i, DatapointTf, TrendSlopeConfirmationCandles];
            }//if (RSvalue[i, j, k] > StrongVal[cc])
            
            //Find the seakest datapoint on the current currency and timeframe
            if (RSvalue[i, DatapointTf, 0] < WeakVal[j])
            {
               WeakestCcy[j] = ccy[i];
               WeakVal[j] = RSvalue[i, DatapointTf, 0];
               PrevWeakVal[j] = RSvalue[i, DatapointTf, TrendSlopeConfirmationCandles];
            }//if (RSvalue[i, j, k] > StrongVal[cc])            
         }//for (k = 0; k <= NumPoints; k++)         
      }//for (j = 0; j < ArraySize(Tf); j++)
   }//for (i = 0; i < ArraySize(ccy); i++)
   //Alert("Strongest ", StrongestCcy[0], "  ", StrongVal[0], " Weakest ", WeakestCcy[0], "  ", WeakVal[0]);
   

   
   


}//End void ReadHanover()

double ReadStrength(string curr, string tf, int shift)
{
   /*
   Returns the strength of the individual currency referenced by the parameters:
      - curr is the currency
      - tf is the time frame
      - shift is how far back in time to look
   */

   //Extract the timeframe - uses David's constants
   int DatapointTf;
   if (tf == "M1") DatapointTf = M1;
   if (tf == "M5") DatapointTf = M5;
   if (tf == "M15") DatapointTf = M15;
   if (tf == "M30") DatapointTf = M30;
   if (tf == "H1") DatapointTf = H1;
   if (tf == "H4") DatapointTf = H4;
   if (tf == "D1") DatapointTf = D1;
   if (tf == "W1") DatapointTf = W1;
   if (tf == "MN") DatapointTf = MN;

   //Allign the curr param with David's constant
   int cc;
   if (curr == "AUD") cc = AUD;
   if (curr == "CAD") cc = CAD;
   if (curr == "CHF") cc = CHF;
   if (curr == "EUR") cc = EUR;
   if (curr == "GBP") cc = GBP;
   if (curr == "JPY") cc = JPY;
   if (curr == "NZD") cc = NZD;
   if (curr == "USD") cc = USD;
   
   return(RSvalue[cc, DatapointTf, shift]);
   
}//End double ReadStrength(string curr, string tf, int shift)

bool HanoverFilter(int type)
{
   //Returns true if the filter indicates sufficient strength/weakness in the pair.
   //Works by running through the tests and returning false if any of them fail. If all pass, the eventually
   //returns true.
   //Tests all fail if the two currencies have equal strength values

   //Read the strength values
   for (int cc = 0; cc < ArraySize(Tf); cc++)
   {
      //First filter. Compare the strength over the chosen time frames
      double strength1 = ReadStrength(Ccy1, Tf[cc], 0);
      double strength2 = ReadStrength(Ccy2, Tf[cc], 0);
      if (TrendSlopeConfirmationCandles > 0) 
      {
         double prevstrength1 = ReadStrength(Ccy1, Tf[cc], TrendSlopeConfirmationCandles);
         double prevstrength2 = ReadStrength(Ccy2, Tf[cc], TrendSlopeConfirmationCandles);   
      }//if (SlopeCandles[cc] > 0)    

     
      //EA is looking to buy. 
      if (type == OP_BUY)
      {
         //First currency must be the strongest
         if (strength1 <= strength2) return(false);

         //Slope must be rising in the first curr and falling in the second
         if (TrendSlopeConfirmationCandles > 0)
         {
            if (prevstrength1 >= strength1) return(false);
            if (prevstrength2 <= strength2) return(false);
         }//if (TrendSlopeConfirmationCandles > 0 
         
         //Threshold. First currency must be above TrendStrongThreshold. Second currency must be below WeakThreshopld
         if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0)
         {
            if (strength1 < TrendStrongThreshold || strength2 > TrendWeakThreshold) return(false);
         }//if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0)
      }//if (type == OP_BUY)
      
      //EA is looking to sell, so first currency must be the weakest
      if (type == OP_SELL && strength1 >= strength2) return(false);
      
      //EA is looking to sell. 
      if (type == OP_SELL)
      {
         //First currency must be the weakest
         if (strength1 >= strength2) return(false);

         //Slope must be falling in the first curr and rising in the second curr
         if (TrendSlopeConfirmationCandles > 0)
         {
            if (prevstrength1 <= strength1) return(false);
            if (prevstrength2 >= strength2) return(false);
         }//if (TrendSlopeConfirmationCandles > 0 
         
         //Threshold. First currency must be below TrendWeakThreshold. Second currency must be above StrongThreshopld
         if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0)
         {
            if (strength1 > TrendWeakThreshold || strength2 < TrendStrongThreshold) return(false);
         }//if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0)
      }//if (type == OP_SELL)
         
   }//for (int cc = 0; cc < ArraySize(Tf); cc++)

   

   //Got this far, so all tests have passed.
   return(true);

}//End bool HanoverFilter()


//End Hanover module
////////////////////////////////////////////////////////////////////////////////////////////////


//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----

   //A little bit of code to turn off functions that I do not want to remove yet in case we turn out to need them
   int x = 0;

   //Read a pair's volatility
   if (D1VolatilityBars != iBars(NULL, PERIOD_D1) )
   {
      D1VolatilityBars = iBars(NULL, PERIOD_D1);
      Volatility = CalculateVolatility(PERIOD_D1, LookBackDays);
      CalculateReEntryLinePips();//Range trade Rocovery
   }//if (D1VolatilityBars != iBars(NULL, PERIOD_D1)
   
   
   //ReadIndicatorValues() contains the call to TrendDetectionModule()
   ReadIndicatorValues();
   
   //Other stuff associated with trend trading
   if (trend != ranging)
   {
      GetTrendConfirmationCandleDir();      
   }//if (trend != ranging)
   
   
   static bool TradeExists = false;
   
   if (OrdersTotal() == 0)
   {
      TicketNo = -1;
      ForceTradeClosure = false;
   }//if (OrdersTotal() == 0)

   if (ForceTradeClosure) 
   {
      CloseAllTrades();
      return;
   }//if (ForceTradeClosure) 

   if (trend == ranging) ReadIndicatorValues();

   
      
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Find open trades.   
   CountOpenTrades();
   if (!BuyOpen && !SellOpen) 
   {
      GlobalVariableDel(GvName);//Make sure there are no probs from this source      
      TradeOrigin = none;
      OpenTrades = 0;
   }//if (!BuyOpen && !SellOpen) 
     
   //Manage a single open trade's possible closure
   if (OpenTrades >= 1)
   {
      if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0)
      {
         if (TradeOrigin == trendorigin && !HedgingInProgress) LookForTradeClosure();         
      }//if (OrderSelect(TicketNo, SELECT_BY_TICKET) || OrderCloseTime() == 0) )       
   }//if (OpenTrades == 1)
   
   //Deal with hedged pair
   if (HedgingInProgress && BasketUpl >= HedgeProfitTarget)
   {
      CloseAllTrades();
      return;
   }//if (HedgingInProgress && BasketUpl >=)
   
   //Tidying up
   if (OpenTrades == 0)
   {
      ObjectDelete(breakevenlinename);
      ObjectDelete(reentrylinename);
      
   }//if (OpenTrades == 0)
   
   if (x == 1) //Function turned off for now
   {
      TradeExists = DoesTradeExist();
      if (TradeExists)
      {
         if (OrderProfit() > 0) TradeManagementModule();
         LookForTradeClosure();
      }//if (TradeExists)
   }//if (x == 1) //Function turned off for now
   
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Recovery
   if (UseRecovery && TradeOrigin == rangeorigin)
   {
      if (OpenTrades >= Start_Recovery_at_trades) RecoveryInProgress = true;
      
      
      
      //Replace accidentally deleted be line
      if (RecoveryInProgress && ObjectFind(breakevenlinename) == -1)
      {
         RecoveryModule();      
      }//if (RecoveryInProgress && ObjectFind(breakevenlinename) == -1)
      
      //Recovery trailing sl
      if (RecoveryInProgress && UseRecoveryTrailingStop)
      {
         RecoveryCandlesticktrailingStop();     
      }//if (RecoveryInProgress && UseRecoveryTrailingStop)
      
      
   }//if (UseRecovery)

   //Replace deleted reentry line
   if (RecoveryInProgress && ObjectFind(reentrylinename) == -1)
   {
      ReplaceReEntryLine();
   }//if (RecoveryInProgress && ObjectFind(reentrylinename) == -1)
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   ///////////////////////////////////////////////////////////////////////////////////////////////
   
   //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
   EnoughMargin = true;//For user display
   MarginMessage = "";
   if (UseScoobsMarginCheck && OpenTrades > 0)
   {
      if(AccountMargin() > (AccountFreeMargin()/100)) 
      {
         MarginMessage = "There is insufficient margin to allow trading. You might want to turn off the UseScoobsMarginCheck input.";
         DisplayUserFeedback();
         return;
      }//if(AccountMargin() > (AccountFreeMargin()/100)) 
      
   }//if (UseScoobsMarginCheck)


   if (UseForexKiwi && AccountMargin() > 0)
   {
      
      double ml = NormalizeDouble(AccountEquity() / AccountMargin() * 100, 2);
      if (ml < FkMinimumMarginPercent)
      {
         MarginMessage = StringConcatenate("There is insufficient margin percent to allow trading. ", DoubleToStr(ml, 2), "%");
         DisplayUserFeedback();
         return;
      }//if (ml < FkMinimumMarginPercent)
      
   }//if (UseForexKiwi && AccountMargin() > 0)

   if (UseHanover)
   {
      //Read the indi once a minute
      if (ReadBars != iBars(NULL, PERIOD_M1) && UseHanover)
      {
         ReadBars = iBars(NULL, PERIOD_M1);
         ReadHanover();
      }//if (ReadBars != iBars(NULL, PERIOD_M1)
   }//if (UseHanover)


   ///////////////////////////////////////////////////////////////////////////////////////////////         
   //Trading. 
   //Trend trading
   if (trend != ranging && AllowTrendTrading && Volatility >= MinimumTrendTradingVolatility) 
   {
      if (!UseCaterpillar && !UseCarolco && !StopTrading && TicketNo == -1) LookForTrendTradingOpps();
      if (UseCaterpillar && !StopTrading) StartCaterpillar();
      if (UseCarolco && !StopTrading) StartCarolco();      
   }//if (trend != ranging && AllowTrendTrading && Volatility <= MaximumRangeTradingVolatility)       
   
   //Fix for carolco initial trade closing and leaving behind pending trades when the hi-lo of the D1 candle has
   //moved into Ranging
   if (trend == ranging && UseCarolco)
   {
      if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) )
      {
         DeletePendings();
      }//if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) )   
   }//if (trend == ranging && UseCarolco)
   
  
   if (TradeEveryTick) OldRangeTradingBars = 0;//Look for trades every tick, not every candle
   //Range trading opps need checking even though there may a trade already open, else the open trade never gets closed
   if (trend == ranging && AllowRangeTrading && OldRangeTradingBars != iBars(NULL, RangeTradingTF) && Volatility <= MaximumRangeTradingVolatility) 
   {
      OldRangeTradingBars = iBars(NULL, RangeTradingTF);
      LookForRangeTradingOpps();
   }//if (trend == ranging && AllowRangeTrading && OldRangeTradingBars != iBars(NULL, RangeTradingTF)) 

   ///////////////////////////////////////////////////////////////////////////////////////////////      

   DisplayUserFeedback();
   
//----
   return(0);
}
//+------------------------------------------------------------------+

Комментарии к исходному коду форекс советника BigBob.mq4
В целях безопасности и борьбы со спамом в тексте комментариев запрещено размещать html-теги и ссылки. Благодарим за понимание.

  • X
  • 0% загружено
« советник Big Stochastic v1.1 Combo.mq4
советник BigProfitLittleStop.mq4 »