Multi purpose trade manager





//+------------------------------------------------------------------+
//|                                  Multi-purpose trade manager.mq4 |
//|                                  Copyright © 2008, Steve Hopwood |
//|                              http://www.hopwood3.freeserve.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
/*
The Start function calls the MonitorTrades function. This cycles through the list of open orders,
checking to see which management style the user has chosen - by ticket number, magic number,
comment or all trades, regardelss of anything else etc. 

If an appropriate management style choice is found, the ManageTrade function is called. This in
turn calls functions that checks for action depending on the choice of facilities - breakeven, 
jumping stop etc.

The ea offers the option to close 50% of a profitable trade at a target 
set by the user (PartCloseOrder).

It offers a hedge-trade facility for when a trade starts to go wrong.

Start then calls GlobalOrderClosure. If enabled, this routine closes all open orders at
a $profit or % of account balance.

Start then calls ShirtProtection, a routine that closes all open trades at a upl loss point
chosen by the user. "Losing your shirt" is a slang expression to describe losing everything - money,
home etc.

The order of program run is: Start calls MonitorTrades (calls ManageTrade that calls all the 
functions that actually do the work) then GlobalOrderClosure, then ShirtProtection.
*/
#include <WinUser32.mqh>
#include <stdlib.mqh>
#define  NL    "\n"

// User can choose a variety of trade managment triggers.
// These are for use on a chart that controls the currency of that chart
extern string  ManagementStyle="You can select more than one option";
extern bool    ManageByMagicNumber=false;
extern int     MagicNumber=274693;
extern bool    ManageByTradeComment=false;
extern string  TradeComment = "Fib";
extern bool    ManageByTickeNumber=false;
extern int     TicketNumber;
// This allows the ea to manage all existing trades
extern string  OverRide="ManageAllTrades will override all others";
extern bool    ManageAllTrades=false;
// Now give user a variety of facilities
extern string  bl1="---------------------------------------------------------------------";
extern string  ManagementFacilities="Select the management facilities you want";
extern string  slf="----Stop Loss & Take Profit Manipulation----";
extern string  BE="Break even settings";
extern bool    BreakEven=false;
extern int     BreakEvenPips=30;
extern int     BreakEvenProfit=2;
extern string  JSL="Jumping stop loss settings";
extern bool    JumpingStop=false;
extern int     JumpingStopPips=30;
extern bool    AddBEP=false;
extern bool    JumpAfterBreakevenOnly=false;
extern string  TSL="Trailing stop loss settings";
extern bool    TrailingStop=false;
extern int     TrailingStopPips=30;
extern string  ITSL="Instant trailing stop loss settings";
extern bool    InstantTrailingStop=false;
extern int     InstantTrailingStopPips=30;
//extern bool    HideStopLossEnabled=false;
//extern double  HiddenStopLossPips=0;
extern string  bl2="---------------------------------------------------------------------";
extern string  GOC="----Global order closure settings----";
extern bool    GlobalOrderClosureEnabled=false;
extern bool    IncludePendingOrdersInClosure=false;
extern bool    ProfitInDollars=false;
extern double  DollarProfit=100000;
extern bool    ProfitAsPercentageOfBalance=false;
extern double  PercentageProfit=10000;
extern string  bl3="---------------------------------------------------------------------";
extern string  PCS="----Part close settings----";
extern bool    PartCloseEnabled=false;
extern string  b1="-----------";
extern string  s1="EURUSD";
extern bool    EU=false;
extern double  EUTargetPrice;
extern double  EUTargetPips;
extern string  b2="-----------";
extern string  s2="GBPUSD";
extern bool    GU=false;
extern double  GUTargetPrice;
extern double  GUTargetPips;
extern string  b3="-----------";
extern string  s3="USDJPY";
extern bool    UJ=false;
extern double  UJTargetPrice;
extern double  UJTargetPips;
extern string  b4="-----------";
extern string  s4="USDCHF";
extern bool    UC=false;
extern double  UCTargetPrice;
extern double  UCTargetPips;
extern string  b5="-----------";
extern string  s5="USDCAD";
extern bool    UCad=false;
extern double  UCadTargetPrice;
extern double  UCadTargetPips;
extern string  b6="-----------";
extern string  s6="USDCAD";
extern bool    AU=false;
extern double  AUTargetPrice;
extern double  AUTargetPips;
extern string  b7="-----------";
extern string  s7="NZDUSD";
extern bool    NU=false;
extern double  NUTargetPrice;
extern double  NUTargetPips;
extern string  b8="-----------";
extern string  s8="EURGBP";
extern bool    EG=false;
extern double  EGTargetPrice;
extern double  EGTargetPips;
extern string  b9="-----------";
extern string  s9="EURJPY";
extern bool    EJ=false;
extern double  EJTargetPrice;
extern double  EJTargetPips;
extern string  b10="-----------";
extern string  s10="EURCHF";
extern bool    EC=false;
extern double  ECTargetPrice;
extern double  ECTargetPips;
extern string  b11="-----------";
extern string  s11="GBPJPY";
extern bool    GJ=false;
extern double  GJTargetPrice;
extern double  GJTargetPips;
extern string  b12="-----------";
extern string  s12="GBPCHF";
extern bool    GC=false;
extern double  GCTargetPrice;
extern double  GCTargetPips;
extern string  b13="-----------";
extern string  s13="AUDJPY";
extern bool    AJ=false;
extern double  AJTargetPrice;
extern double  AJTargetPips;
extern string  b14="-----------";
extern string  s14="CHFJPY";
extern bool    CJ=false;
extern double  CJTargetPrice;
extern double  CJTargetPips;
extern string  b15="-----------";
extern string  s15="EURCAD";
extern bool    ECad=false;
extern double  ECadTargetPrice;
extern double  ECadTargetPips;
extern string  b16="-----------";
extern string  s16="EURAUD";
extern bool    EA=false;
extern double  EATargetPrice;
extern double  EATargetPips;
extern string  b17="-----------";
extern string  s17="AUDCAD";
extern bool    AC=false;
extern double  ACTargetPrice;
extern double  ACTargetPips;
extern string  b18="-----------";
extern string  s18="AUDNZD";
extern bool    AN=false;
extern double  ANTargetPrice;
extern double  ANTargetPips;
extern string  b19="-----------";
extern string  s19="NZDJPY";
extern bool    NJ=false;
extern double  NJTargetPrice;
extern double  NJTargetPips;
extern string  bl4="---------------------------------------------------------------------";
extern string  hs="----Hedge settings----";
extern bool    HeadgeEnabled=false;
extern int     HedgeAtLossPips=0;
extern int     HedgeTradeStopLoss=0;
extern int     HedgeTradeTakeProfit=0;
extern string  bl5="---------------------------------------------------------------------";
extern string  sps="----Shirt-protection settings----";
extern string  spsi="Close all open trades at this $ loss";
extern bool    ShirtProtectionEnabled=false;
extern double  MaxLoss=-10000000;
extern string  bl6="---------------------------------------------------------------------";
extern string  OtherStuff="----Other stuff----";
extern bool    ShowAlerts=true;



int            cnt=0; //loop counter
double         bid, ask; // For storing the Bid\Ask so that one instance of the ea can manage all trades, if required
double         point, digits; // Saves the Point and Digits of an order
// Variables for part-close reoutine
double         TargetAsPrice, TargetAsPips;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   Comment("");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----

   // Stop if there is nothing to do
   if (OrdersTotal()==0)
   {
      Comment("No trades to manage. I am bored witless.");
      return(0);
   }
   
   Comment("Monitoring trades");
   
   MonitorTrades(); // Stop loss adjusting, part closure
   
   if (GlobalOrderClosureEnabled) GlobalOrderClosure(); // Whole position closing at set profit level
   
   // Account protection in event of catastrophe
   if (ShirtProtectionEnabled) ShirtProtection();
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
void MonitorTrades()
{

   bool ManageTrade; // tell the program when there is a trade to manage
   string ScreenMessage;
   
   
   for (cnt=0;cnt<OrdersTotal();cnt++)
   { 
      OrderSelect(cnt, SELECT_BY_POS);   
      ManageTrade=false;
      if (OrderSymbol()==Symbol() || ManageAllTrades==true) // Continue if order is correct symbol or the ea is to manage all trades regardless
      {
         ScreenMessage = StringConcatenate("Managing ", Symbol(), " by: ");
         // Set up bid and ask so the program can use them to calculate jumping stops, be's etc
         bid = MarketInfo(OrderSymbol(), MODE_BID);           
         ask = MarketInfo(OrderSymbol(), MODE_ASK);
         point = MarketInfo(OrderSymbol(), MODE_POINT);
         digits = MarketInfo(OrderSymbol(), MODE_DIGITS);
         
         // Test whether this individual trade needs managing
         // MagicNumber
         if (ManageByMagicNumber && OrderMagicNumber()==MagicNumber)
         {   
            ManageTrade=true;
            ScreenMessage=StringConcatenate(ScreenMessage, "Magic Number=", MagicNumber,"; ");
         }   
         
         // TradeComment
         if (ManageByTradeComment && OrderComment()==TradeComment)
         {   
            ManageTrade=true;
            ScreenMessage=StringConcatenate(ScreenMessage, "Trade Comment=",TradeComment,"; ");
         }   
         
         // ManageByTickeNumber
         if (ManageByTickeNumber && OrderTicket()==TicketNumber)
         {   
            ManageTrade=true;
            ScreenMessage=StringConcatenate(ScreenMessage, "Ticket Number=", TicketNumber, "; ");
         }
                                            
         
         // ManageAllTrades
         if (ManageAllTrades)
         {   
            ManageTrade=true;
            ScreenMessage="Managing all open trades";
         }   
         
         
         
         // Is this trade being managed by the ea?
         if (ManageTrade) ManageTrade(); // The subroutine that calls the other working subroutines
         
      } // Close if (OrderSymbol()==Symbol())
      
   
   } // Close For loop
   
   // Set up some user feedback
   if(BreakEven)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Break even set to ", BreakEvenPips, ". BreakEvenProfit is set to ", BreakEvenProfit, " pips");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Break even disabled");
   }
   
   if(JumpingStop==true)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Jumping stop set to ", JumpingStopPips);
      if (JumpAfterBreakevenOnly) ScreenMessage = StringConcatenate(ScreenMessage, " after breakeven is achieved");
      if(AddBEP==true)
      {
         ScreenMessage = StringConcatenate(ScreenMessage, ", also adding BreakEvenProfit (", BreakEvenProfit, " pips)");      
      }      
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Jumping stop disabled");
   }
   
   if(TrailingStop==true)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Trailing stop on and set to ", TrailingStopPips);
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Trailing stop disabled");
   }
   
   if (InstantTrailingStop)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Instant trailing stop on and set to ", InstantTrailingStopPips);
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Instant trailing stop disabled");
   }
   
   // Include global profit closure
   if (GlobalOrderClosureEnabled)   
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Global order closure enabled");
      if (IncludePendingOrdersInClosure) ScreenMessage = StringConcatenate(ScreenMessage, ", including pending orders");
   }
   else ScreenMessage = StringConcatenate(ScreenMessage, NL, "Global order closure disabled");
   
   if (PartCloseEnabled)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Order part close enabled");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Order part close not enabled");
   }
   
   // HeadgeEnabled
   if (HeadgeEnabled)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Hedge trade enabled at ", HedgeAtLossPips, " pips loss");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Hedge trade not enabled");
   }
         
   // Account protection
   if (ShirtProtectionEnabled)
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Shirt protection enabled at ", MaxLoss, " dollars upl");
   }
   else
   {
      ScreenMessage = StringConcatenate(ScreenMessage, NL, "Shirt protection not enabled");
   }
   
   
   Comment(ScreenMessage); // User feedback
   
   
   
} // end of MonitorTrades

void ShirtProtection()
{
   // Code for this routine is based on code in CloseTrades_After_Account_Loss_TooMuch.mq4
   // by Tradinator, so my appreciation to Tradinator.
   
   if (MaxLoss==0) return; // Idiotic user entry
   if (MaxLoss>0) 
   {
      Alert("ShirtProtection MaxLoss must be a negative number"); // In case user forgets to enter a negative figure
      return;
   }
   
   if (AccountProfit()<= MaxLoss)
   {
    for(int i=OrdersTotal()-1;i>=0;i--)
       {
       OrderSelect(i, SELECT_BY_POS);
       int ordertype   = OrderType();
               
       bool result = false;
              
       switch(ordertype)
          {
          //Close opened long positions
          case OP_BUY  : result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),10,CLR_NONE);
                         break;
               
          //Close opened short positions
          case OP_SELL : result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),10,CLR_NONE);
                          
          }
          
       if(result == false) // In case of problems like broker disconnection, trade context busy etc
          {
            Sleep(3000);
          }  
       }
      if (ShowAlerts) Alert("Disaster has happend. Your shirt protection loss point has been reached and all open orders have been closed.");
      Print ("All Open Trades Have Been Closed - Shirt protection loss point reached");
      return(0);
   }  
   
   
  return(0);
   

}//End of ShirtProtection()

void BreakEvenStopLoss() // Move stop loss to breakeven
{
   int ticket;

           
   if (OrderType()==OP_BUY)
         {
            if (bid >= OrderOpenPrice () + (point*BreakEvenPips) && 
                OrderStopLoss()<OrderOpenPrice())
            {
               ticket = OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+(BreakEvenProfit*point),OrderTakeProfit(),0,CLR_NONE);
               if (ticket>0 && ShowAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
            }
   	   }               			         
          
   if (OrderType()==OP_SELL)
         {
           if (ask <= OrderOpenPrice() - (point*BreakEvenPips) &&
              (OrderStopLoss()>OrderOpenPrice()|| OrderStopLoss()==0)) 
            {
               ticket = OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-(BreakEvenProfit*point),OrderTakeProfit(),0,CLR_NONE);
               if (ticket>0 && ShowAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket());
            }    
         }
      

} // End BreakevenStopLoss sub

void JumpingStopLoss() // Jump sl by pips and at intervals chosen by user 
{
 
   // 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);
   }
     
   int ticket;
   double sl=OrderStopLoss(); //Stop loss
  
   if (OrderType()==OP_BUY)
   {
      // First check if sl needs setting to breakeven
      if (sl==0 || sl<OrderOpenPrice())
      {
         if (bid >= OrderOpenPrice() + (JumpingStopPips*point))
         {
            sl=OrderOpenPrice();
            if (AddBEP==true) sl=sl+(BreakEvenProfit*point); // If user wants to add a profit to the break even
            ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (ticket>0)
            {
               if (ShowAlerts==true) Alert("Jumping stop set at breakeven ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Jumping stop set at breakeven: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
            }            
            return(0);
         }
      } //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);
         ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (ticket>0)
         {
            if (ShowAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
         }            
            
      }// close if (bid>= sl + (JumpingStopPips*point) && sl>= OrderOpenPrice())      
   }
      
   if (OrderType()==OP_SELL)
   {
      // 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
            ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (ticket>0)
            {
               if (ShowAlerts==true) Alert("Jumping stop set at breakeven ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
               Print("Jumping stop set at breakeven: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
            }            
            return(0);
         }
      } //close 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);
         ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
         if (ticket>0)
         {
            if (ShowAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket());
            Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
         }            
            
      }// close if (bid>= sl + (JumpingStopPips*point) && sl>= OrderOpenPrice())      
   
   
   }

} //End of JumpingStopLoss sub

void TrailingStopLoss()
{
   int ticket;
   double sl=OrderStopLoss(); //Stop loss
   double BuyStop=0, SellStop=0;
   
   if (OrderType()==OP_BUY) 
      {
		   if (bid >= OrderOpenPrice() + (TrailingStopPips*point))
		   {
		       if (bid > sl +  (TrailingStopPips*point))
		       {
		          sl= bid - (TrailingStopPips*point);
		          ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
               if (ticket>0)
               {
                  Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
               } 
		       }
		   }
      }

if (OrderType()==OP_SELL) 
      {
		   if (ask <= OrderOpenPrice() - (TrailingStopPips*point))
		   {
		       if (ask < sl -  (TrailingStopPips*point))
		       {
		          sl= ask + (TrailingStopPips*point);
		          //Alert(OrderSymbol(), " ", sl);
		            ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
                  if (ticket>0)
                  {
                     Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", bid);
                  } 
		       }
		   }
      }


} // End of TrailingStopLoss sub
   
void InstantTrailingStopLoss()
/* This is the same as TrailingStopLoss, except that it moves the sl as soon as
 the market moves ion favour of the trade. 
 It will set an initial sl of market price +- UtsPips, depending on the type of trade,
 then move it every time the market moves in favour of the trade. It will therefore override
 any user set sl on the trade.
 Market price +- UtsPips will result in breakeven, and move into profit after that.
*/ 
{
   int ticket;
   double sl=OrderStopLoss(); //Stop loss
   double BuyStop=0, SellStop=0;
   
   if (OrderType()==OP_BUY) 
      {
		   if (bid >= sl+(InstantTrailingStopPips*point)) // Has to overcome the spread first
		   {
	         sl= bid - (InstantTrailingStopPips*point);
	         ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
            if (ticket>0)
            {
               Print("Instant trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", ask);
            } 
		    }
      }

      if (OrderType()==OP_SELL) 
      {
	       if ((ask <= sl + (InstantTrailingStopPips*point)) || sl==0)
	       {
	            sl= ask + (InstantTrailingStopPips*point);
	            ticket = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE);
               if (ticket>0)
               {
                  Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", bid);
               } 
	       }		   
      }


} // End of InstantTrailingStopLoss() sub
   
void GlobalOrderClosure()
{
   bool CloseOrders=false;
   double ProfitPercentage=0;

   // First calculate whether the upl is >= the point at which the position is to close

   // Profit in dollars enabled
   if (ProfitInDollars)
   {
      if(AccountProfit()>=DollarProfit) CloseOrders=true;
   }
   
   // Profit as percentage of account balance enabled
   if (ProfitAsPercentageOfBalance)
   {
      ProfitPercentage=AccountBalance() * (PercentageProfit/100);
      if (AccountProfit()>= ProfitPercentage) CloseOrders=true;
   }

   // Abort routine if profit has not hit the required level
   if (!CloseOrders) return(0);
   
   // Got this far, so orders are to be closed.
   // Code lifted from CloseAll-PL, so thanks to whoever wrote the ea. Ok, so I could
   // have written my own, buy why re-invent the wheel?
   
   int _total=OrdersTotal(); // number of lots or trades  ????
   int _ordertype;// order type   
   if (_total==0) {return;}  // if total==0
   int _ticket; // ticket number
   double _priceClose;// price to close orders;
   for(int _i=_total-1;_i>=0;_i--)
         {  //# for loop
         if (OrderSelect(_i,SELECT_BY_POS))
            { //# if 
            _ordertype=OrderType();
            _ticket=OrderTicket();
            switch(_ordertype)
               {  //# switch
          case OP_BUYLIMIT:
            if(IncludePendingOrdersInClosure) OrderDelete(OrderTicket());
          case OP_BUYSTOP:
            if(IncludePendingOrdersInClosure) OrderDelete(OrderTicket());
          case OP_BUY:
                  // close buy                
                  _priceClose=MarketInfo(OrderSymbol(),MODE_BID);
                  Print("Close on ",_i," position order with ticket ¹",_ticket);
                  OrderClose(_ticket,OrderLots(),_priceClose,3,Red);
                  break;
          case OP_SELLLIMIT:
            if(IncludePendingOrdersInClosure) OrderDelete(OrderTicket());
          case OP_SELLSTOP:
            if(IncludePendingOrdersInClosure) OrderDelete(OrderTicket());
          case OP_SELL:
                  // close sell
                  _priceClose=MarketInfo(OrderSymbol(),MODE_ASK);
                  Print("Close on ",_i," position order with ticket ¹",_ticket);
                  OrderClose(_ticket,OrderLots(),_priceClose,3,Red);
                  break;
               default:
                  // values from  1 to 5, deleting pending orders
   //               Print("Delete on ",_i," position order with ticket ¹",_ticket);
   //               OrderDelete(_ticket);  
                  break;
               }    //# switch
         }  // # if 
   }  // # for loop

   // User feedback
   if (ShowAlerts) Alert("Global profit hit your target, so all open trades should have been closed");
   
} //End of GlobalOrderClosure()

bool ExtractPartCloseVariables()
{
   /*
   This routine extracts the targets at which PartCloseOrder closes part of a position.
   Also tells PartCloseOrder whether the pair is enabled for part-closure.
   Written as a separate function because it is huge, so avoids clutter in PartCloseOrder
   */
   
   bool PairEnabled=false;
   
   if (OrderSymbol()=="EURUSD" || OrderSymbol()=="EURUSDm") 
   {
      TargetAsPrice=EUTargetPrice;
      TargetAsPips=EUTargetPips;
      if(EU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="GBPUSD" || OrderSymbol()=="GBPUSDm") 
   {
      TargetAsPrice=GUTargetPrice;
      TargetAsPips=GUTargetPips;
      if(GU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="USDJPY" || OrderSymbol()=="USDJPYm") 
   {
      TargetAsPrice=UJTargetPrice;
      TargetAsPips=UJTargetPips;
      if(UJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="USDCHF" || OrderSymbol()=="USDCHFm") 
   {
      TargetAsPrice=UCTargetPrice;
      TargetAsPips=UCTargetPips;
      if(UC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="USDCAD" || OrderSymbol()=="USDCADm") 
   {
      TargetAsPrice=UCadTargetPrice;
      TargetAsPips=UCadTargetPips;
      if(UCad) PairEnabled=true;
   }
      
   if (OrderSymbol()=="AUDUSD" || OrderSymbol()=="AUDUSDm") 
   {
      TargetAsPrice=AUTargetPrice;
      TargetAsPips=AUTargetPips;
      if(AU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="NZDUSD" || OrderSymbol()=="NZDUSDm") 
   {
      TargetAsPrice=NUTargetPrice;
      TargetAsPips=NUTargetPips;
      if(NU) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURGBP" || OrderSymbol()=="EURGBPm") 
   {
      TargetAsPrice=EGTargetPrice;
      TargetAsPips=EGTargetPips;
      if(EG) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURJPY" || OrderSymbol()=="EURJPYm") 
   {
      TargetAsPrice=EJTargetPrice;
      TargetAsPips=EJTargetPips;
      if(EJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURCHF" || OrderSymbol()=="EURCHFm") 
   {
      TargetAsPrice=ECTargetPrice;
      TargetAsPips=ECTargetPips;
      if(EC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="GBPJPY" || OrderSymbol()=="GBPJPYm") 
   {
      TargetAsPrice=GJTargetPrice;
      TargetAsPips=GJTargetPips;
      if(GJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="GBPCHF" || OrderSymbol()=="GBPCHFm") 
   {
      TargetAsPrice=GCTargetPrice;
      TargetAsPips=GCTargetPips;
      if(GC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="AUDJPY" || OrderSymbol()=="AUDJPYm") 
   {
      TargetAsPrice=AJTargetPrice;
      TargetAsPips=AJTargetPips;
      if(AJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="CHFJPY" || OrderSymbol()=="CHFJPYm") 
   {
      TargetAsPrice=CJTargetPrice;
      TargetAsPips=CJTargetPips;
      if(CJ) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURCAD" || OrderSymbol()=="EURCADm") 
   {
      TargetAsPrice=ECadTargetPrice;
      TargetAsPips=ECadTargetPips;
      if(ECad) PairEnabled=true;
   }
      
   if (OrderSymbol()=="EURAUD" || OrderSymbol()=="EURAUDm") 
   {
      TargetAsPrice=EATargetPrice;
      TargetAsPips=EATargetPips;
      if(EA) PairEnabled=true;
   }

   if (OrderSymbol()=="AUDCAD" || OrderSymbol()=="AUDCADm") 
   {
      TargetAsPrice=ACTargetPrice;
      TargetAsPips=ACTargetPips;
      if(AC) PairEnabled=true;
   }
      
   if (OrderSymbol()=="AUDNZD" || OrderSymbol()=="AUDNZDm") 
   {
      TargetAsPrice=ANTargetPrice;
      TargetAsPips=ANTargetPips;
      if(AN) PairEnabled=true;
   }
      
   if (OrderSymbol()=="NZDJPY" || OrderSymbol()=="NZDJPYm") 
   {
      TargetAsPrice=NJTargetPrice;
      TargetAsPips=NJTargetPips;
      if(NJ) PairEnabled=true;
   }
      

   return (PairEnabled);

} // End ExtractPartCloseVariables

void PartCloseOrder()
{

   int index=StringFind(OrderComment(), "split from");
   if (index>-1) return(0); // Order already part-closed
   // Extract the external part-close variables for this pairing.Put this into 
   //a separate routine to avoid clutter here. Ascertain if this pair is 
   // enabled for partial closure. 
   TargetAsPrice=0;
   TargetAsPips=0;
   bool PairEnabled=ExtractPartCloseVariables();   
   if (!PairEnabled) return(0); // Not wanted on this pair
   if(TargetAsPrice==0 && TargetAsPips==0) return(0); // User entry error

   // Got this far, so pair is enabled, trade is not already split and no user errors, so continue
   int ticket;
   double ProfitTarget;
   double LotsToClose=OrderLots()/2;
   if(!TargetAsPrice==0) ProfitTarget=TargetAsPrice;
   
            
   if (OrderType()==OP_BUY)
   {
      if(TargetAsPips>0) ProfitTarget=NormalizeDouble(OrderOpenPrice()+(TargetAsPips*point),digits);
      if (bid>=ProfitTarget)
      {         
         ticket=OrderClose(OrderTicket(), LotsToClose,bid,3,CLR_NONE);
         if (ticket>0)
         {
            if(ShowAlerts) Alert("Partial closure on ", OrderSymbol(), ": ticket no ",OrderTicket());
         } 

      }
   }
   
   if (OrderType()==OP_SELL)
   {
      if(TargetAsPips>0) ProfitTarget=NormalizeDouble(OrderOpenPrice()-(TargetAsPips*point),digits);
      if (ask<=ProfitTarget)
      {         
         ticket=OrderClose(OrderTicket(), LotsToClose,ask,3,CLR_NONE);
         if (ticket>0)
         {
            if(ShowAlerts) Alert("Partial closure on ", OrderSymbol(), ": ticket no ",OrderTicket());
         
         } 

      }
         
   }

   
} // End of PartCloseOrder()

bool CheckForExistingHedge()
{
   int index;
   double ticketno=OrderTicket();
   string StringTicketNo=DoubleToStr(OrderTicket(),0);
   for (int cc=0;cc<OrdersTotal();cc++)
   {
      OrderSelect(cc, SELECT_BY_POS);
      index=StringFind(OrderComment(),StringTicketNo);
      if (index>-1) return(true);
   }

   return(false);
   
} //End CheckForExistingHedge

void HedgeTrade()
{
   if(HedgeAtLossPips==0) return(0); //Silly user choice
   
   // Check that order is not already hedged
   int TempTicket = OrderTicket(); // Temporary store for selected order ticket no
   int index; // If OrderComment includes "Hedge ";
   int HedgeTicket; // For ticket number of hedge trade
   
   // Is this trade a hedge trade?
   index = StringFind(OrderComment(), "Hedge ");
   if (index > -1) return(0);
   
   // Does this order need hedging?
   double HedgePrice;
   if (OrderType()==OP_BUY)
   {
      HedgePrice=NormalizeDouble(OrderOpenPrice()-(HedgeAtLossPips*point),digits);
      if (!ask<= HedgePrice) return; // Trade not failing sufficiently to need hedging
   }   

   if (OrderType()==OP_SELL)
   {
      HedgePrice=NormalizeDouble(OrderOpenPrice()+(HedgeAtLossPips*point),digits);
      if (!bid>= HedgePrice) return; // Trade not failing sufficiently to need hedging
    }
      
   // Got this far, so the trade needs a hedge.
   // Is it already hedged? CheckForExistingHedge returns true if so, false if not
   if(CheckForExistingHedge())
   {
      OrderSelect(TempTicket, SELECT_BY_TICKET); //Re-select the current order
      return;
   }
   OrderSelect(TempTicket, SELECT_BY_TICKET);//Re-select the current order


   // Got this far, so send the hedge order
   double takeprofit=0;
   double stoploss=0;
   int ticket;
   double Lots=OrderLots();
   int error;
   
   if (OrderType()==OP_BUY)
   {
      if(!HedgeTradeTakeProfit==0) takeprofit=NormalizeDouble(bid-(HedgeTradeTakeProfit*point),digits);
      
      if(!HedgeTradeStopLoss==0) stoploss=NormalizeDouble(ask+(HedgeTradeStopLoss*point),digits); 
      
      
      ticket=OrderSend(OrderSymbol(),OP_SELL,Lots,MarketInfo(OrderSymbol(),MODE_BID),0,stoploss,takeprofit,"Hedge " + OrderTicket(),MagicNumber,0,CLR_NONE);
      if (ticket>0)
      {
         if(ShowAlerts) Alert("Sell hedge trade set for ", OrderSymbol(), " buy");
      } 
      else
      {
         error=GetLastError();
         Print("Error = ",ErrorDescription(error));
         return;
      }
      
   }

if (OrderType()==OP_SELL)
   {
      if(!HedgeTradeTakeProfit==0) takeprofit=NormalizeDouble(ask+(HedgeTradeTakeProfit*point),digits);
      
      if(!HedgeTradeStopLoss==0) stoploss=NormalizeDouble(bid-(HedgeTradeStopLoss*point),digits); 
      
     
      ticket=OrderSend(OrderSymbol(),OP_BUY,Lots,MarketInfo(OrderSymbol(),MODE_ASK),0,stoploss,takeprofit,"Hedge " + OrderTicket(),MagicNumber,0,CLR_NONE);
      if (ticket>0)
      {
         if(ShowAlerts) Alert("Sell hedge trade set for ", OrderSymbol(), " buy");
      } 
      else
      {
         error=GetLastError();
         Print("Error = ",ErrorDescription(error));
         return;
      }
      
   }

} // End of HedgeTrade()

void ManageTrade()
{
     
   // Call the working subroutines one by one. 
   
   // Breakeven
   if(BreakEven) BreakEvenStopLoss();
   
   // JumpingStop
   if(JumpingStop) JumpingStopLoss();
   
   // TrailingStop
   if(TrailingStop) TrailingStopLoss();

   // Trailing stop loss that moves as soon as the market moves in the direction of the trade.
   if (InstantTrailingStop) InstantTrailingStopLoss();

   // Partial order closure at profit point chosen by user
   if (PartCloseEnabled) PartCloseOrder();

   // Hedge trade
   if (HeadgeEnabled) HedgeTrade();

   
} // End of ManageTrade()






Sample





Analysis



Market Information Used:



Indicator Curves created:


Indicators Used:



Custom Indicators Used:

Order Management characteristics:
Checks for the total of open orders

It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy
It automatically opens orders when conditions are reached

Other Features:

It issuies visual alerts to the screen

BackTest : EURUSD on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.00 Total Net Profit:0.00

BackTest : USDJPY on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2009-12-01 to 2010-01-17 Profit Factor:0.00 Total Net Profit:0.00

BackTest : USDCAD on H1

From 2009-12-01 to 2010-01-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2009-08-01 to 2009-10-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-02-27 Profit Factor:0.00 Total Net Profit:0.00

BackTest : USDCAD on H1

From 2009-01-01 to 2010-01-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-03-01 to 2010-03-27 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-04-01 to 2010-04-30 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-05-01 to 2010-05-31 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-06-01 to 2010-06-30 Profit Factor:0.00 Total Net Profit:0.00

Request Backtest for Multi purpose trade manager


From : (yyyy/mm/dd) To: (yyyy/mm/dd)

Pair: Period: