//+-------------------------------------------------------------------+
//|                                   jiva34's 5min Open/Close EA.mq4 |
//|                        Based on Moving Average cross with Hanover |
//|                           auto trading robot by Steve Hopwood.mq4 |
//|                            Copyright © 2011, Steve Hopwood, magft |
//|               http://www.forexfactory.com/showthread.php?t=319709 |
//|                                                                   |
//|                 jiva34's 5min Open/Close thread can be found here |
//|               http://www.forexfactory.com/showthread.php?t=322717 |
//+-------------------------------------------------------------------+
#property copyright "Copyright © 2011, Steve Hopwood, magft"
#property link      "http://www.forexfactory.com/showthread.php?t=319709"
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"
#define  up "Cross up"
#define  down "Cross down"
#define  none "None"
//Hidden sl and tp lines. If UseStealth enabled, the bot will close trades on a touch/break of these lines.
//Each line is named with its appropriate prefix and the ticket number of the relevant trade
#define  TpPrefix "Tp"
#define  SlPrefix "Sl"

//This 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


/*

The first function to be called will be void ReadIndicatorValues(). This function contains calls to some of the
more-often used indicators, via functions that contain the call. Remove those functions and inputs you do not need; add
any extra ones that you want.

void CountOpenTrades() and bool DoesTradeExist() essentially do the same thing; they ascertain whether there is already
an open trade and leaves the variable TicketNo set to the final trade in a sequence of trades. I generally use 
CountOpenTrades() when there are likely to be more than one trade open, and DoesTradeExist() when there is only ever
going to be one open trade. 

start() contains calls to all the functions that manage open trades, check trading times etc. 
void LookForTradingOpportunities() is the final function in start() before the feedback display.
void LookForTradingOpportunities() contains the trade-trigger code; simply adapt it to suit the trigger
you are using. IsTradingAllowed() is called from LookForTradingOpportunities(); it contains a variety of filters that
might cancel trading - swap, balance etc.

The code that adapts the bot to x digit criminals is in int init(). Remember to add any other pips inputs to the
list. 

Matt Kennel has provided the code for bool O_R_CheckForHistory(int ticket). Cheers Matt, You are a star.

Stealth: In the Aurora thread, we developed what I jokingly call Stealth Technology to hide some of our activities from the
crims. Hidden take profit and stop loss are automatic features:
   - sends a 'hard' sl/tp if required, then draws lines that represent the hidden stops. The lines have names
     consisting of the SlPrefix/TpPrefix plus the trade ticket number.
   - Breakeven, trailing jumping & candlestick trailing stops are operated by reference to the hidden sl line
The user turns off Stealth with a HiddenPips = 0 value in the input. The ea will close the
trade when the Bid touches/passes either of the lines. At the time of 
writing this - 5th October 2011 - Stealth has worked successfully but is still recent, so the odd bug may still
crawl out of the woodwork.


Code for adding debugging Sleep
Alert("G");
int x = 0;
while (x == 0) Sleep(100);

Code for returning a value as pips. The example returns the range of the previous candle
   int PipDivisor = 1;
   if (Digits == 3 || Digits == 5) PipDivisor = 10;
   double CandleRange = ((High[1] - Low[1]) / Point) / PipDivisor;

Standard order loop code
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;

   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)


FUNCTIONS LIST
int init()
int start()

----Trading----

void LookForTradingOpportunities()
bool IsTradingAllowed()
bool SendSingleTrade(string symbol, int type, string comment, double lotsize, double price, double stop, double take)
   void ModifyOrder(int ticket, double stop, double take)
bool DoesTradeExist()
void CountOpenTrades()
bool CloseTrade(int ticket)
void LookForTradeClosure()
bool CheckTradingTimes()
void CloseAllTrades()

----Hanover module----
bool HanoverFilter()
void SetUpArrays()
void CleanUpInputString()
int CalculateParamsPassed()
void ReadHanover()
int LoadRSvalues()  
double ReadStrength(string curr, string tf, int shift)

----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()
double GetMa(int tf, int period, int mashift, int method, int ap, int shift)




*/

extern string  gen="----General inputs----";
extern double  Lot=0.01; //set to 0 for MM
extern double  RiskPercent=1;
extern bool    StopTrading=false;
extern bool    TradeLong=true;
extern bool    TradeShort=true;
extern int     TakeProfit=0;
extern int     StopLoss=0;
extern int     MagicNumber=38827;
extern string  TradeComment="ma cross";
extern bool    CriminalIsECN=false;

//Hidden tp/sl inputs.
extern string  hts="----Stealth stop loss and take profit inputs----";
extern int     HiddenPips=0;//Added to the 'hard' sl and tp and used for closure calculations

extern string  hm="----Hanover module----";
extern bool    UseHanover=false;
extern string  ctf="Time frames";
//extern string  TimeFrames="M1,M5,M15,M30,H1,H4,D1,W1,MN";
extern string  TimeFrames="D1";
extern int     SlopeConfirmationCandles=0;
extern int     StrongThreshold=0;
extern int     WeakThreshold=0;
extern string  hof="Hanover output file";
extern string  OutputFile            = "Output---Recent Strength.CSV";
extern int     NumPoints=20;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Arrays etc
string         InputString;//All purpose string to pass to CleanUpInputString() to remove unwanted leading/trailing stuff
int            NoOfTimeFrames;//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
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   
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Moving averages
extern string  tmas="----Two MA inputs----";
extern int     FastMaTF=0;//Time frame defaults to current chart 
extern int     FastMaPeriod=21;
extern int     FastMaShift=0;//The MA Shift input
extern string  tmame="Method: 0=sma; 1=ema; 2=smma;  3=lwma";
extern int     FastMaMethod=0;
extern string  tmaap="Applied price: 0=Close; 1=Open; 2=High";
extern string  tmaap1="3=Low; 4=Median; 5=Typical; 6=Weighted";
extern int     FastMaAppliedPrice=0;
extern int     SlowMaTF=0;//Time frame defaults to current chart 
extern int     SlowMaPeriod=21;
extern int     SlowMaShift=0;
extern int     SlowMaMethod=0;
extern int     SlowMaAppliedPrice=1;
extern bool    CloseOnOppositeSignal=true; //magft
extern bool    UseClosedCandle=true;//magft
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
double         FastMaVal, SlowMaVal;
double         PrevFastMaVal, PrevSlowMaVal;
double         MAShift=0;//magft
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


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----";
//Breakeven has to be enabled for JS and TS to work.
extern string  BE="Break even settings";
extern bool    BreakEven=false;
extern int     BreakEvenPips=10;
extern int     BreakEvenProfit=5;
extern string  cts="----Candlestick trailing stop----";
extern bool    UseCandlestickTrailingStop=false;
extern int     CstTimeFrame=0;//Defaults to current chart
extern int     CstTrailCandles=1;//Defaults to previous candle
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int            OldCstBars;//For candlestick ts
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern string  JSL="Jumping stop loss settings";
extern bool    JumpingStop=false;
extern int     JumpingStopPips=10;
extern string  TSL="Trailing stop loss settings";
extern bool    TrailingStop=false;
extern int     TrailingStopPips=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;
int            RetryCount = 10;//Will make this number of attempts to get around the trade context busy error.
string         TradePair;//Will hold the pair being traded
int            TradeType;//Will be OP_BUY or OP_SELL depending in which ccy comes first in the pair
bool           OkToTrade;
string         TradingStatus;

//Pending price inputs. Keeps things hidden from the crims
bool           PendingBuy, PendingSell;
double         PendingPrice, PendingStop, PendingTake;
datetime       PendingTime;
double         PendingCandleRange;
double         PendingRecreationCancelPips = 2;
//Hidden stops variables
double         HiddenStopLoss, HiddenTakeProfit;



//Trend detection
string         cross;


//Misc
string         Gap, ScreenMessage;
int            OldBars;
string         PipDescription=" pips";
bool           ForceTradeClosure;
int            multiplier;//magft
double         SendLots;

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);      
   
   if (UseHanover)
   {
      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 (SlopeConfirmationCandles > 0) 
         {
            double prevstrength1 = ReadStrength(Ccy1, Tf[cc], SlopeConfirmationCandles);
            now = StringConcatenate(": Shift ",SlopeConfirmationCandles, " = ", DoubleToStr(prevstrength1, 2));
            double prevstrength2 = ReadStrength(Ccy2, Tf[cc], SlopeConfirmationCandles);
            then = StringConcatenate(": Shift ", SlopeConfirmationCandles, " = ", 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 (StrongThreshold > 0 && WeakThreshold > 0)
      {
         bool tradeable = false;
         if (strength1 > StrongThreshold && strength2 < WeakThreshold)
         {
            ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Can trade this pair long", NL);
            tradeable = true;
         }//if (strength1 > StrongThreshold && strength2 < WeakThreshold)
         
         if (strength2 > StrongThreshold && strength1 < WeakThreshold)
         {
            ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Can trade this pair short", NL);
            tradeable = true;
         }//if (strength1 > StrongThreshold && strength2 < WeakThreshold)
         
         if (!tradeable) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Cannot trade this pair yet", NL);
      }//if (StrongThreshold > 0 && WeakThreshold > 0)
      
   }//if (UseHanover)
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Fast MA ", FastMaVal, ":  Slow MA ", SlowMaVal,  NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Previous Fast MA ", PrevFastMaVal, ":  Previous Slow MA ", PrevSlowMaVal,  NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Cross status: ", cross,  NL);
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);      
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", SendLots, " (Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), ")", NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Take profit: ", TakeProfit, PipDescription,  NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Stop loss: ", StopLoss, PipDescription,  NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Magic number: ", MagicNumber, NL);
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, "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, "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
   
   ScreenMessage = StringConcatenate(ScreenMessage,Gap, 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);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);   
   }//if (JumpingStop)
   

   if (TrailingStop)
   {
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trailing stop is set to ", TrailingStopPips, PipDescription);
      ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL);   
   }//if (TrailingStop)

   Comment(ScreenMessage);


}//void DisplayUserFeedback()


//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
//----

   //Adapt to x digit criminals
   //int multiplier;
   if(Digits == 2 || Digits == 4) multiplier = 1;
   if(Digits == 3 || Digits == 5) multiplier = 10;
   if(Digits == 6) multiplier = 100;   
   if(Digits == 7) multiplier = 1000;   
   
   if (multiplier > 1) PipDescription = " points";
   
   TakeProfit*= multiplier;
   StopLoss*= multiplier;
   BreakEvenPips*= multiplier;
   BreakEvenProfit*= multiplier;
   JumpingStopPips*= multiplier;
   TrailingStopPips*= multiplier;
   
   Gap="";
   if (DisplayGapSize >0)
   {
      for (int cc=0; cc< DisplayGapSize; cc++)
      {
         Gap = StringConcatenate(Gap, " ");
      }   
   }//if (DisplayGapSize >0)
   
   //Reset CriminIsECN if crim is IBFX and the punter does not know or, like me, keeps on forgetting
   string name = TerminalCompany();
   int ispart = StringFind(name, "IBFX", 0);
   if (ispart < 0) ispart = StringFind(name, "Interbank FX", 0);
   if (ispart > -1) CriminalIsECN = true;   
   
   
   //Set up the arrays
   SetUpArrays();
   
   
   if (TradeComment == "") TradeComment = " ";
   //OldBars = Bars;
   //Hanover. Isolate the pair currencies and read the output file
   if (UseHanover)
   {
      Ccy1 = StringSubstr(Symbol(), 0, 3);
      Ccy2 = StringSubstr(Symbol(), 3, 6);
      ReadBars = iBars(NULL, PERIOD_M1);//Don't need it again when start() triggers
      ReadHanover();
   }//if (UseHanover)
   
   cross = none;
   
   if (UseClosedCandle) MAShift=1;//magft
   
   ReadIndicatorValues();//For initial display in case user has turned of constant re-display
   SendLots=Lot;
   DisplayUserFeedback();
   
   //Alert(RSvalue[_USD][_H1][2]);
   for (cc = 0; cc < NumPoints; cc++)
   {
      //Alert(DoubleToStr(RSvalue[0][0][cc], 5));
   }   
   //Call sq's show trades indi
   //iCustom(NULL, 0, "SQ_showTrades",Magic, 0,0);

   
//----
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   Comment("");
//----
   return(0);
}

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 = TimeFrames;
   CleanUpInputString();
   TimeFrames = InputString;
   NoOfTimeFrames = CalculateParamsPassed();
   string NewArray2 = ArrayResize(Tf, NoOfTimeFrames);
   
   Index = 0;//For searching InputString
   LastIndex = 0;//Points the the most recent Index
   for (cc = 0; cc < NoOfTimeFrames; 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 < NoOfTimeFrames; cc ++)

   //StrongWeak
   string NewArray3 = ArrayResize(StrongWeak, NoOfTimeFrames);
   string NewArray4 = ArrayResize(StrongestCcy, NoOfTimeFrames);
   string NewArray5 = ArrayResize(WeakestCcy, NoOfTimeFrames);
   double NewArray6 = ArrayResize(StrongVal, NoOfTimeFrames);
   double NewArray7 = ArrayResize(WeakVal, NoOfTimeFrames);
   double NewArray8 = ArrayResize(PrevStrongVal, NoOfTimeFrames);
   double NewArray9 = ArrayResize(PrevWeakVal, NoOfTimeFrames);
   double NewArray10 = ArrayResize(ConstructedPair, NoOfTimeFrames);
   
   
   
   
}//End void SetUpArrays()




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 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()

////////////////////////////////////////////////////////////////////////////////////////////////
//TRADE MANAGEMENT MODULE

void ReportError()
{
   //All purpose sl mod error reporter. Called when a sl mod fails
   
   int err=GetLastError();
   
   if (err==1) return; //magft to stop no error msg  
   if (ShowManagementAlerts) Alert(OrderTicket()," stop loss modification failed with error(",err,"): ",ErrorDescription(err));
   Print(OrderTicket()," stop loss modification failed with error(",err,"): ",ErrorDescription(err));      

}//void ReportError()



void BreakEvenStopLoss() // Move stop loss to breakeven
{

   double NewStop;
   bool result;
   bool modify=false;
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   
   if (OrderType()==OP_BUY)
   {
      if (sl >= OrderOpenPrice() ) return;
      if (Bid >= OrderOpenPrice () + (Point*BreakEvenPips))          
      {
         //Calculate the new stop
         NewStop = NormalizeDouble(OrderOpenPrice()+(BreakEvenProfit*Point), Digits);
         if (HiddenPips > 0)
         {
            if (ObjectFind(LineName) == -1)
            {
               ObjectCreate(LineName, OBJ_HLINE, 0, TimeCurrent(), 0);
               ObjectSet(LineName, OBJPROP_COLOR, Red);
               ObjectSet(LineName, OBJPROP_WIDTH, 1);
               ObjectSet(LineName, OBJPROP_STYLE, STYLE_DOT);
            }//if (ObjectFind(LineName == -1) )
         
            ObjectMove(LineName, 0, TimeCurrent(), NewStop);         
         }//if (HiddenPips > 0)
         modify = true;   
      }//if (Bid >= OrderOpenPrice () + (Point*BreakEvenPips) && 
   }//if (OrderType()==OP_BUY)               			         
    
   if (OrderType()==OP_SELL)
   {
     if (sl <= OrderOpenPrice() && sl > 0) return;
     if (Ask <= OrderOpenPrice() - (Point*BreakEvenPips)) 
     {
         //Calculate the new stop
         NewStop = NormalizeDouble(OrderOpenPrice()-(BreakEvenProfit*Point), Digits);
         if (HiddenPips > 0)
         {
            if (ObjectFind(LineName) == -1)
            {
               ObjectCreate(LineName, OBJ_HLINE, 0, TimeCurrent(), 0);
               ObjectSet(LineName, OBJPROP_COLOR, Red);
               ObjectSet(LineName, OBJPROP_WIDTH, 1);
               ObjectSet(LineName, OBJPROP_STYLE, STYLE_DOT);
            }//if (ObjectFind(LineName == -1) )
         
            ObjectMove(LineName, 0, Time[0], NewStop);
         }//if (HiddenPips > 0)         
         modify = true;   
     }//if (Ask <= OrderOpenPrice() - (Point*BreakEvenPips) && (OrderStopLoss()>OrderOpenPrice()|| OrderStopLoss()==0))     
   }//if (OrderType()==OP_SELL)

   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify && HiddenStopLoss > 0 && OrderStopLoss() != NewStop)
   {
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();
   }//if (modify)
   
} // End BreakevenStopLoss sub

void JumpingStopLoss() 
{
   // Jump sl by pips and at intervals chosen by user .

   if (OrderProfit() < 0) return;//Nothing to do
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   if (sl == 0) return;//No line, so nothing to do
   double NewStop;
   bool modify=false;
   bool result;
   
   
   if (OrderType()==OP_BUY)
   {
      if (sl < OrderOpenPrice() ) return;//Not at breakeven yet
      // Increment sl by sl + JumpingStopPips.
      // This will happen when market price >= (sl + JumpingStopPips)
      if (Bid>= sl + ((JumpingStopPips*2)*Point) )
      {
         NewStop = NormalizeDouble(sl + (JumpingStopPips * Point), Digits);
         if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
         modify = true;   
      }// if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())      
   }//if (OrderType()==OP_BUY)
   
   if (OrderType()==OP_SELL)
   {
      if (sl > OrderOpenPrice() ) return;//Not at breakeven yet
      // Decrement sl by sl - JumpingStopPips.
      // This will happen when market price <= (sl - JumpingStopPips)
      if (Bid<= sl - ((JumpingStopPips*2)*Point))
      {
         NewStop = NormalizeDouble(sl - (JumpingStopPips * Point), Digits);
         if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
         modify = true;   
      }// close if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())         
   }//if (OrderType()==OP_SELL)

   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify && HiddenStopLoss > 0 && OrderStopLoss() != NewStop)
   {
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();
   }//if (modify)

} //End of JumpingStopLoss sub


void TrailingStopLoss()
{
   
   if (OrderProfit() < 0) return;//Nothing to do
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   if (sl == 0) return;//No line, so nothing to do
   double NewStop;
   bool modify=false;
   bool result;
   
   if (OrderType()==OP_BUY)
   {
      if (sl < OrderOpenPrice() ) return;//Not at breakeven yet
      // Increment sl by sl + TrailingStopPips.
      // This will happen when market price >= (sl + JumpingStopPips)
      if (Bid>= sl + (TrailingStopPips * Point) )
      {
         NewStop = NormalizeDouble(sl + (TrailingStopPips * Point), Digits);
         if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
         modify = true;   
      }// if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())      
   }//if (OrderType()==OP_BUY)
   
   if (OrderType()==OP_SELL)
   {
      if (sl > OrderOpenPrice() ) return;//Not at breakeven yet
      // Decrement sl by sl - TrailingStopPips.
      // This will happen when market price <= (sl - JumpingStopPips)
      if (Bid<= sl - (TrailingStopPips * Point) )
      {
         NewStop = NormalizeDouble(sl - (TrailingStopPips * Point), Digits);
         if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
         modify = true;   
      }// close if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice())         
   }//if (OrderType()==OP_SELL)

   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify && HiddenStopLoss > 0 && OrderStopLoss() != NewStop)
   {
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();
   }//if (modify)
      
} // End of TrailingStopLoss sub

void CandlestickTrailingStop()
{
   
   //Trails the stop at the hi/lo of the previous candle shifted by the user choice.
   //Only tries to do this once per bar, so an invalid stop error will only be generated once. I could code for
   //a too-close sl, but cannot be arsed. Coders, sort this out for yourselves.
   
   if (OldCstBars == Bars) return;
   OldCstBars = Bars;

   if (OrderProfit() < 0) return;//Nothing to do
   string LineName = SlPrefix + DoubleToStr(OrderTicket(), 0);
   double sl = ObjectGet(LineName, OBJPROP_PRICE1);
   if (sl == 0) return;//No line, so nothing to do
   double NewStop;
   bool modify=false;
   bool result;
   

   if (OrderType() == OP_BUY)
   {
      if (iLow(NULL, CstTimeFrame, CstTrailCandles) > sl)
      {
         NewStop = NormalizeDouble(Low[1], Digits);
         if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
         modify = true;   
      }//if (iLow(NULL, CstTimeFrame, CstTrailCandles) > sl)
   }//if (OrderType == OP_BUY)
   
   if (OrderType() == OP_SELL)
   {
      if (iHigh(NULL, CstTimeFrame, CstTrailCandles) < sl)
      {
         NewStop = NormalizeDouble(High[1], Digits);
         if (HiddenPips > 0) ObjectMove(LineName, 0, Time[0], NewStop);
         modify = true;   
      }//if (iHigh(NULL, CstTimeFrame, CstTrailCandles) < sl)
   }//if (OrderType() == OP_SELL)
   
   //Move 'hard' stop loss whether hidden or not. Don't want to risk losing a breakeven through disconnect.
   if (modify && HiddenStopLoss > 0 && OrderStopLoss() != NewStop)
   {
      while (IsTradeContextBusy() ) Sleep(100);
      result = OrderModify(OrderTicket(), OrderOpenPrice(), NewStop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);      
      if (!result) ReportError();
   }//if (modify)

}//End void CandlestickTrailingStop()

void TradeManagementModule()
{

   // Call the working subroutines one by one. 

   //Candlestick trailing stop
   if (UseCandlestickTrailingStop) CandlestickTrailingStop();


   // Breakeven
   if(BreakEven) BreakEvenStopLoss();

   // JumpingStop
   if(JumpingStop) JumpingStopLoss();

   //TrailingStop
   if(TrailingStop) TrailingStopLoss();

   

}//void TradeManagementModule()
//END TRADE MANAGEMENT MODULE
////////////////////////////////////////////////////////////////////////////////////////////////

bool SendSingleTrade(string symbol, int type, string comment, double lotsize, double price, double stop, double take)
{
   //pah (Paul) contributed the code to get around the trade context busy error. Many thanks, Paul.
   
   int slippage = 10;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
  
   int expiry = 0;
   //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60);
   //RetryCount is declared as 10 in the Trading variables section at the top of this file
   for (int cc = 0; cc < RetryCount; cc++)
   {
      for (int d = 0; (d < RetryCount) && IsTradeContextBusy(); d++) Sleep(100);

      if (!CriminalIsECN) int ticket = OrderSend(symbol, type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, CLR_NONE);
   
   
      //Is a 2 stage criminal
      if (CriminalIsECN)
      {
         ticket = OrderSend(symbol, type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, CLR_NONE);
         if (ticket > -1)
         {
	           ModifyOrder(ticket, stop, take);
         }//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";
         int err=GetLastError();
         if (ShowManagementAlerts) Alert(symbol, " jiva34's 5min Open/Close ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
         Print(symbol, " jiva34's 5min Open/Close ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
         return(false);
      }//if (ticket < 0)  

      if (ticket > -1) break;//Exit the trade send loop
      if (cc == RetryCount - 1) return(false);

   }//for (int cc = 0; cc < RetryCount; cc++);
   
   
   
   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)

void ModifyOrder(int ticket, double stop, double take)
{
   //Modifies an order already sent if the crim is ECN.
   if (!OrderSelect(ticket, SELECT_BY_TICKET) ) return;//Trade does not exist, so no mod needed
   
   //RetryCount is declared as 10 in the Trading variables section at the top of this file   
   for (int cc = 0; cc < RetryCount; cc++)
   {
      for (int d = 0; (d < RetryCount) && IsTradeContextBusy(); d++) Sleep(100);
        if (take > 0 && stop > 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE)) return;           
        }//if (take > 0 && stop > 0)
   
        if (take != 0 && stop == 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE)) return;
        }//if (take == 0 && stop != 0)

        if (take == 0 && stop != 0)
        {
           while(IsTradeContextBusy()) Sleep(100);
           if (OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE)) return;
        }//if (take == 0 && stop != 0)
   }//for (int cc = 0; cc < RetryCount; cc++)
   
   //Got this far, so the order modify failed
   int err=GetLastError();
   Print(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               
   if (ShowManagementAlerts) Alert(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               

}//void ModifyOrder(int ticket, double tp, double sl)

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
   
      
   
   
   
   
   return(true);


}//End bool IsTradingAllowed()


void LookForTradingOpportunities()
{


   RefreshRates();
   double take, stop, price;
   int type;
   bool SendTrade;
   bool result;

   //Check filters
   if (!IsTradingAllowed() ) return;
   
   
   //Long 
   if (cross == up)
   {

      if (!TradeLong) return;
      
      if (UseHanover && !HanoverFilter(OP_BUY) ) return(false);
      
      price = Ask;

      
      if (TakeProfit > 0) 
      {
         take = NormalizeDouble(price + (TakeProfit * Point), Digits);
         HiddenTakeProfit = take;
         if (HiddenPips > 0) take = NormalizeDouble(take + (HiddenPips * Point), Digits);
      }//if (TakeProfit > 0) 
      
      if (StopLoss > 0) 
      {
         stop = NormalizeDouble(price - (StopLoss * Point), Digits);
         HiddenStopLoss = stop;
         if (HiddenPips > 0) stop = NormalizeDouble(stop - (HiddenPips * Point), Digits);
      }//if (StopLoss > 0) 
      
      type = OP_BUY;
      SendTrade = true;
   }//if (TradeType == OP_BUY)
   
   //Short
   if (cross == down)
   {
      if (!TradeShort) return;
      
      if (UseHanover && !HanoverFilter(OP_SELL) ) return(false);
      
      price = Bid;
      
      if (TakeProfit > 0) 
      {
         take = NormalizeDouble(price - (TakeProfit * Point), Digits);
         HiddenTakeProfit = take;
         if (HiddenPips > 0) take = NormalizeDouble(take - (HiddenPips * Point), Digits);
      }//if (TakeProfit > 0) 
      
      if (StopLoss > 0) 
      {
         stop = NormalizeDouble(price + (StopLoss * Point), Digits);
         HiddenStopLoss = stop;
         if (HiddenPips > 0) stop = NormalizeDouble(stop + (HiddenPips * Point), Digits);
      }//if (StopLoss > 0) 
      
      type = OP_SELL;
      SendTrade = true;      
   }//if (TradeType == OP_SELL)
   

   if (SendTrade)
   {
      //check if Lot set to 0 to use MM - magft
      SendLots=Lot;
      if (Lot<=0) SendLots=CalculateLotSize(); //magft

      result = SendSingleTrade(Symbol(), type, TradeComment, SendLots, price, stop, take);
   }//if (SendTrade)
   
   //Actions when trade send succeeds
   if (SendTrade && result)
   {
      cross = none;
   }//if (result)
   
   //Actions when trade send fails
   if (SendTrade && !result)
   {
   
   }//if (!result)

}//void LookForTradingOpportunities()

//magft
double CalculateLotSize()
{
   double MinLot=0,MaxLot=0,tmpLot=0;
   double Lotstep,digits,tickval;
   
   MinLot=MarketInfo(Symbol(),MODE_MINLOT);
   MaxLot=MarketInfo(Symbol(),MODE_MAXLOT);
   tickval=MarketInfo(Symbol(),MODE_TICKVALUE)*multiplier;
   Lotstep=MarketInfo(Symbol(),MODE_LOTSTEP);
   
   if (Lotstep==0.01) digits=2;
   if (Lotstep==0.1) digits=1;
   
   tmpLot=(AccountBalance()*RiskPercent/100);
   if (StopLoss>0) tmpLot=tmpLot/(StopLoss*tickval);
   else tmpLot=tmpLot/1000;
   
   tmpLot=NormalizeDouble(tmpLot,digits);
         
   if(tmpLot < MinLot)
   {
      Print("Lot size less than minimum lot size!");
      return(MinLot);
   }
   
   if(tmpLot > MaxLot)
   {
      Print("Lot size greater than maximum lot size!");
      return(MaxLot);
   }
   return(tmpLot);
}

bool CloseTrade(int ticket)
{   
   while(IsTradeContextBusy()) Sleep(100);
   bool result = OrderClose(ticket, OrderLots(), OrderClosePrice(), 1000, CLR_NONE);

   //Actions when trade send succeeds
   if (result)
   {
      return(true);
   }//if (result)
   
   //Actions when trade send fails
   if (!result)
   {
      return(false);
   }//if (!result)
   

}//End bool CloseTrade(ticket)

////////////////////////////////////////////////////////////////////////////////////////////////
//Hanover module
//+------------------------------------------------------------------+
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("");
}


//+------------------------------------------------------------------+
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);
}


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, SlopeConfirmationCandles];
            }//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, SlopeConfirmationCandles];
            }//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 (SlopeConfirmationCandles > 0) 
      {
         double prevstrength1 = ReadStrength(Ccy1, Tf[cc], SlopeConfirmationCandles);
         double prevstrength2 = ReadStrength(Ccy2, Tf[cc], SlopeConfirmationCandles);   
      }//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 (SlopeConfirmationCandles > 0)
         {
            if (prevstrength1 >= strength1) return(false);
            if (prevstrength2 <= strength2) return(false);
         }//if (SlopeConfirmationCandles > 0 
         
         //Threshold. First currency must be above StrongThreshold. Second currency must be below WeakThreshopld
         if (StrongThreshold > 0 && WeakThreshold > 0)
         {
            if (strength1 < StrongThreshold || strength2 > WeakThreshold) return(false);
         }//if (StrongThreshold > 0 && WeakThreshold > 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 (SlopeConfirmationCandles > 0)
         {
            if (prevstrength1 <= strength1) return(false);
            if (prevstrength2 >= strength2) return(false);
         }//if (SlopeConfirmationCandles > 0 
         
         //Threshold. First currency must be below WeakThreshold. Second currency must be above StrongThreshopld
         if (StrongThreshold > 0 && WeakThreshold > 0)
         {
            if (strength1 > WeakThreshold || strength2 < StrongThreshold) return(false);
         }//if (StrongThreshold > 0 && WeakThreshold > 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
////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////////////////
//Indicator module

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)


void ReadIndicatorValues()
{

   //Spots a cross of the slow ma by the fast ma
   
   //Set a default cross of none. It there was a previous cross that was not traded, the is was irrelevant. The only
   //cross that is important is the most recent one.
   
   cross = none;
   
   FastMaVal = GetMa(FastMaTF, FastMaPeriod, FastMaShift, FastMaMethod, FastMaAppliedPrice, 0+MAShift);   //magft
   SlowMaVal = GetMa(SlowMaTF, SlowMaPeriod, SlowMaShift, SlowMaMethod, SlowMaAppliedPrice, 0+MAShift); //magft
   PrevFastMaVal = GetMa(FastMaTF, FastMaPeriod, FastMaShift, FastMaMethod, FastMaAppliedPrice, 1+MAShift);   //magft
   PrevSlowMaVal = GetMa(SlowMaTF, SlowMaPeriod, SlowMaShift, SlowMaMethod, SlowMaAppliedPrice, 1+MAShift); //magft
   
   //Spot cross upwards
   if (FastMaVal > SlowMaVal && PrevFastMaVal < PrevSlowMaVal) cross = up;
   //Spot cross downwards
   if (FastMaVal < SlowMaVal && PrevFastMaVal > PrevSlowMaVal) cross = down;
   
   
}//void ReadIndicatorValues()

//End Indicator module
////////////////////////////////////////////////////////////////////////////////////////////////

void LookForTradeClosure()
{
   //return;//Turn this off for now
   
   if (!OrderSelect(TicketNo, SELECT_BY_TICKET) ) return;
   if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() > 0) return;
   
   bool CloseTrade;
   
   if (OrderType() == OP_BUY)
   {
      if (CloseOnOppositeSignal && cross == down) CloseTrade=true;//magft
   }//if (OrderType() == OP_BUY)
   
   
   if (OrderType() == OP_SELL)
   {
      if (CloseOnOppositeSignal && cross == up) CloseTrade=true;//magft
   }//if (OrderType() == OP_SELL)
   
   if (CloseTrade)
   {
      bool result = CloseTrade(TicketNo);
      //Actions when trade send succeeds
      if (result)
      {

      }//if (result)
   
      //Actions when trade send fails
      if (!result)
      {
   
      }//if (!result)
   

   }//if (CloseTrade)
   
   
}//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 (OrderMagicNumber() != MagicNumber) continue;
      if (OrderSymbol() != Symbol() ) continue;
      while(IsTradeContextBusy()) Sleep(100);
      if (OrderType() == OP_BUY || OrderType() == OP_SELL) bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 1000, CLR_NONE);
      if (result) cc++;
      if (!result) ForceTradeClosure= true;
      
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)


}//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;

   if (OrdersTotal() == 0) return;
   
   for (int cc = 0; cc <= OrdersTotal(); cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      {
         OpenTrades++;
         TicketNo = OrderTicket();   
         if (OrderType() == OP_BUY) BuyOpen = true;
         if (OrderType() == OP_SELL) SellOpen = true;
         //Check for possible trade closure
         LookForTradeClosure();
      }//if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
   }//for (int cc = 0; cc < OrdersTotal() - 1; cc++)
   
   
}//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)



//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----

   static bool TradeExists;
   
   if (OrdersTotal() == 0)
   {
      TicketNo = -1;
      ForceTradeClosure = false;
   }//if (OrdersTotal() == 0)

   if (ForceTradeClosure) 
   {
      CloseAllTrades();
      return;
   }//if (ForceTradeClosure) 

   if (ReadBars != iBars(NULL, PERIOD_M1) && UseHanover)
   {
      ReadBars = iBars(NULL, PERIOD_M1);
      ReadHanover();
   }//if (ReadBars != iBars(NULL, PERIOD_M1)
   
   ReadIndicatorValues();
      
   ///////////////////////////////////////////////////////////////////////////////////////////////
   //Find open trades.
   TradeExists = DoesTradeExist();
   if (TradeExists)
   {
      if (OrderProfit() > 0) TradeManagementModule();
      LookForTradeClosure();
   }//if (TradeExists)

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //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)
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //Trading
      
   if (TicketNo == -1 && !StopTrading)
   {
      LookForTradingOpportunities();
   }//if (!TradeExists && !StopTrading)
   ///////////////////////////////////////////////////////////////////////////////////////////////      

   DisplayUserFeedback();
   
//----
   return(0);
}
//+------------------------------------------------------------------+


