TSD_MT4_MR_Trade_0_36





//+------------------------------------------------------------------+
//|                                   TSD_MR_Trade_OsMA_WPR_0_36.mq4 |
//|                                       Copyright © 2006 Mindaugas |
//|                                           TSD Trade version 0.36 |
//|                                                                  |
//|             o TSD idea and realization by Bob O'Brien / Barcode  |
//|               o TSD rewritten to MQL4 and enhanced by Mindaugas  |
//|                            o Enhanced comments by Mike aka FxMt  |
//|                    o Trailing Stop based on ATR by Loren Gordon  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006 Mindaugas"

#include <stdlib.mqh>
#define  DIRECTION_MACD 1
#define  DIRECTION_OSMA 2
#define  FILTER_WPR     1
#define  FILTER_FORCE   2

// Put new trades only on new bar or also on expert initialization. Default is to trade only on new bar.
extern bool TradeOnInit = false;
// Whether to put new orders or only track old ones. Default is to put new orders.
extern bool NewTrades = true;

// which indicators to use
int DirectionMode = DIRECTION_OSMA, FilterMode = FILTER_WPR;
// trading periods
int PeriodDirection = PERIOD_W1, PeriodTrade = PERIOD_D1, PeriodTrailing = PERIOD_H4, CandlesTrailing = 0;
// currency pairs to trade
string pairs[] = { "AUDUSD", "EURCHF", "EURGBP", "EURJPY", "EURUSD",
                   "GBPCHF", "GBPJPY", "GBPUSD", "USDCAD", "USDCHF", "USDJPY" };

// MM and broker parameters
double Risk = 0.00, Lots = 0.1;

// parameters for MACD and OsMA
int DirectionFastEMA = 12, DirectionSlowEMA = 26, DirectionSignal = 9;
// parameters for iWPR and iForce indicators
int WilliamsP = 24, WilliamsL = -75, WilliamsH = -25;
int ForceP = 2;

int MagicNumber = 2005072001;

bool TrailingStop = true;
int TakeProfit = 60, Slippage = 2, TrailingStopStep = 2;

string TradeSymbol, CommentHeader, CommentsPairs[];
int Pair = -1, SDigits;
double Spread, SPoint, STS, StopLevel;

//+------------------------------------------------------------------+
int init() {
   string DirInd, FilterInd;
   
   if ( ! TradeOnInit )  Print ("WARNING!!! Expert will place new orders only on the beginning of the new bar.");

   if ( IsTesting() ) { if ( ArrayResize(pairs,1) != 0 )  pairs[0] = Symbol(); }
   else {
      if ( DirectionMode == DIRECTION_MACD )       DirInd = "MACD";
      else if ( DirectionMode == DIRECTION_OSMA )  DirInd = "OsMA";
      
      if ( FilterMode == FILTER_WPR )         FilterInd = "WPR("+WilliamsP+","+WilliamsL+","+WilliamsH+")";
      else if ( FilterMode == FILTER_FORCE )  FilterInd = "Force("+ForceP+")";
      
      CommentHeader = ("\nTSD Trade P("+PeriodDirection+","+PeriodTrade+","+PeriodTrailing+","+CandlesTrailing+")"+
                       " "+DirInd+"("+DirectionFastEMA+","+DirectionSlowEMA+","+DirectionSignal+")"+
                       " "+FilterInd+"\n");
   }
   ArrayCopy (CommentsPairs, pairs);
   return(0);
}
//+------------------------------------------------------------------+
int deinit() { return(0); }
//+------------------------------------------------------------------+

int start() {
   static bool Alerted = false;

   int TradesThisSymbol, Direction;
   int i, ticket;
   
   bool okSell, okBuy, Deleted;
   
   double PriceOpen, Buy_Sl, Buy_Tp, LotMM;
   string ValueComment;
   
   Pair = (Pair+1) % ArraySize(pairs);
   TradeSymbol = pairs[Pair];

   if ( ! PairExists(TradeSymbol) ) {
      if ( ! Alerted )  Alert ("No data for the pair: ", TradeSymbol, ". Please review and fix pairs variable.");
      Alerted = true;
      return(0);
   }

   TradesThisSymbol = TotalTradesThisSymbol (TradeSymbol);

   SPoint    = MarketInfo (TradeSymbol, MODE_POINT);
   Spread    = MarketInfo (TradeSymbol, MODE_ASK) - MarketInfo (TradeSymbol, MODE_BID);
   SDigits   = MarketInfo (TradeSymbol, MODE_DIGITS);
   StopLevel = MarketInfo (TradeSymbol, MODE_STOPLEVEL) * SPoint + 1*SPoint;
   STS = iATR (TradeSymbol, PeriodTrailing, PeriodDirection*3/PeriodTrailing, 1) + Spread + 1*SPoint;
  
   Direction = Direction (TradeSymbol, PeriodDirection, DirectionMode);
   ValueComment = Filter(TradeSymbol, PeriodTrade, FilterMode, okBuy, okSell);
   
   CommentAll (Direction, ValueComment);

   if ( ! IsTradeAllowed() || MarketInfo(TradeSymbol, MODE_TRADEALLOWED) == 0 ) return(0);

   ///////////////////////////////////////////////////////////////////////////////
   //  Place new orders and modify pending ones only on the beginning of new bar
   ///////////////////////////////////////////////////////////////////////////////
   if ( NewBar() ) {
      /////////////////////////////////////////////////
      //  Place new order
      /////////////////////////////////////////////////
      if ( TradesThisSymbol < 1 && NewTrades ) {

         ticket = 0;
         LotMM = CalcMM_TSDTrade (Direction);
         if ( LotMM <= 0 )  return(0);

         if ( Direction == 1 && okBuy ) {
	         Print ("TSD BuyStop: ", TradeSymbol, " ", LotMM, " ", CalcOpenBuy(), " ", CalcSlBuy(), " ", CalcTpBuy(),
	                ", ", MarketInfo(TradeSymbol, MODE_ASK), " ", ValueComment);
            ticket = OrderSend (TradeSymbol, OP_BUYSTOP, LotMM, CalcOpenBuy(), Slippage, CalcSlBuy(), CalcTpBuy(),
		                       "TSD BuyStop", MagicNumber, 0);
         } 
		   
         if ( Direction == -1 && okSell ) {
	         Print ("TSD SellStop: ", TradeSymbol, " ", LotMM, " ", CalcOpenSell(), " ", CalcSlSell(), " ", CalcTpSell(),
	                ", ", MarketInfo(TradeSymbol, MODE_BID), " ", ValueComment);
	         ticket = OrderSend (TradeSymbol, OP_SELLSTOP, LotMM, CalcOpenSell(), Slippage, CalcSlSell(), CalcTpSell(),
	                             "TSD SellStop", MagicNumber, 0);
   	   }
 
   	   OrderError(ticket >= 0);
	      if ( ticket != 0 )   return(0);
   	} // End of TradesThisSymbol < 1 && NewTrades

      /////////////////////////////////////////////////
      //  Pending Order Management
      /////////////////////////////////////////////////
      for (i = 0; i < OrdersTotal(); i++) {
         if ( OrderSelect (i, SELECT_BY_POS) == false )  continue;
         if ( OrderSymbol() != TradeSymbol || OrderMagicNumber() != MagicNumber)  continue;
         if ( OrderOpenTime() > iTime(TradeSymbol, PeriodTrade, 0) ) continue;

         if ( OrderType () == OP_BUYSTOP ) {
            if ( Direction != 1 || ComparePrices (CalcOpenBuy(), OrderOpenPrice()) != 0 ||
                                   ComparePrices (CalcSlBuy(), OrderStopLoss()) != 0 ) {
   	         Print ("TSD delete BuyStop: ", TradeSymbol);
               Deleted = OrderDelete ( OrderTicket() );
               OrderError(Deleted);
               return(0);
            }
         }

         if ( OrderType () == OP_SELLSTOP ) {
            if ( Direction != -1 || ComparePrices (CalcOpenSell(), OrderOpenPrice()) != 0 ||
                                    ComparePrices (CalcSlSell(), OrderStopLoss()) != 0 ) {
   	         Print ("TSD delete SellStop: ", TradeSymbol);
               Deleted = OrderDelete ( OrderTicket() );
               OrderError(Deleted);
               return(0);
            }
         }
      } // End of Pending Order Management
   } // End of NewBar()

   /////////////////////////////////////////////////
   //  Stop Loss Management
   /////////////////////////////////////////////////
   if ( TrailingStop ) {
      for (i = 0; i < OrdersTotal(); i++) {
         if ( OrderSelect (i, SELECT_BY_POS) == false )  continue;
         if ( OrderSymbol() != TradeSymbol || OrderMagicNumber() != MagicNumber)  continue;
         if ( TrailStop (STS) )  return(0);
      }
   }

   return(0);
}
//+------------------------------------------------------------------+
double CalcOpenBuy  () { return (MathMax (iHigh(TradeSymbol, PeriodTrade, 1) + 1*SPoint + Spread,
                                          MarketInfo(TradeSymbol, MODE_ASK) + StopLevel)); }
double CalcOpenSell () { return (MathMin (iLow(TradeSymbol, PeriodTrade, 1) - 1*SPoint,
                                          MarketInfo(TradeSymbol, MODE_BID) - StopLevel)); }
double CalcSlBuy  () { return (iLow (TradeSymbol, PeriodTrade, 1) - 1*SPoint); }
double CalcSlSell () { return (iHigh(TradeSymbol, PeriodTrade, 1) + 1*SPoint + Spread); }
double CalcTpBuy  () {
   double PriceOpen = CalcOpenBuy(), SL = CalcSlBuy();
   if ( TakeProfit == 0 )  return(0);
   return (PriceOpen + MathMax( MathMax(TakeProfit*SPoint, STS*3), (PriceOpen - SL)*2) );
}
double CalcTpSell () {
   double PriceOpen = CalcOpenSell(), SL = CalcSlSell();
   if ( TakeProfit == 0 )  return(0);
   return (PriceOpen - MathMax( MathMax(TakeProfit*SPoint, STS*3), (SL - PriceOpen)*2));
}
//+------------------------------------------------------------------+
bool TrailStop (double TrailingStop) {
   double StopLoss;
   bool Modified;

   if ( OrderType() == OP_BUY ) {
      if ( MarketInfo (TradeSymbol, MODE_BID) < OrderOpenPrice()+TrailingStop )  return(false);
      StopLoss = iLow(TradeSymbol, PeriodTrailing, Lowest (TradeSymbol, PeriodTrailing, MODE_LOW, CandlesTrailing+1, 0)) - 1*SPoint;
      StopLoss = MathMin (MarketInfo (TradeSymbol, MODE_BID)-TrailingStop, StopLoss);
      if ( ComparePrices (StopLoss, OrderStopLoss() + TrailingStopStep*SPoint) == 1 ) {
         Print ("TSD trailstop Buy: ", TradeSymbol, " ", StopLoss, ", ", MarketInfo(TradeSymbol, MODE_ASK));
         Modified = OrderModify (OrderTicket(), OrderOpenPrice(), StopLoss, OrderTakeProfit(), 0);
         OrderError(Modified, false);
         return(true);
      }
   }
   
   if ( OrderType() == OP_SELL ) {
      if ( MarketInfo (TradeSymbol, MODE_ASK) > OrderOpenPrice()-TrailingStop )  return(false);
      StopLoss = iHigh(TradeSymbol, PeriodTrailing, Highest (TradeSymbol, PeriodTrailing, MODE_HIGH, CandlesTrailing+1, 0)) + 1*SPoint
                 + Spread;
      StopLoss = MathMax (MarketInfo (TradeSymbol, MODE_ASK)+TrailingStop, StopLoss);
      if ( ComparePrices (StopLoss, OrderStopLoss() - TrailingStopStep*SPoint) == -1 ) {
         Print ("TSD trailstop Sell: ", TradeSymbol, " ", StopLoss, ", ", MarketInfo(TradeSymbol, MODE_BID));
         Modified = OrderModify (OrderTicket(), OrderOpenPrice(), StopLoss, OrderTakeProfit(), 0);
         OrderError(Modified, false);
         return(true);
      }
   }
   
   return(false);
}
//+------------------------------------------------------------------+
int Direction (string TradeSymbol, int PeriodDirection, int Mode) {
   double Previous, Previous2;

   if (Mode == DIRECTION_MACD ) {
	   Previous  = iMACD (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal,
	                      PRICE_CLOSE, MODE_MAIN, 1);
	   Previous2 = iMACD (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal,
	                      PRICE_CLOSE, MODE_MAIN, 2);
	}
	else if (Mode == DIRECTION_OSMA) {
	   Previous  = iOsMA (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal,
	                      PRICE_CLOSE, 1);
	   Previous2 = iOsMA (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal,
	                      PRICE_CLOSE, 2);
	}

   if ( Previous > Previous2 )
      return(1);
   if ( Previous < Previous2 )
      return(-1);
   return(0);
}
//+------------------------------------------------------------------+
string Filter (string TradeSymbol, int PeriodTrade, int Mode, bool &okBuy, bool &okSell) {
   double Value;
   
   okBuy = false; okSell = false;
   
   if (Mode == FILTER_WPR) {
      Value = iWPR(TradeSymbol, PeriodTrade, WilliamsP, 1);
	   if (Value < WilliamsH)  okBuy = true;
   	if (Value > WilliamsL)  okSell = true;
   	return ("iWPR: " + DoubleToStr(Value, 2));
   }
   else if (Mode == FILTER_FORCE) {
      Value = iForce (TradeSymbol, PeriodTrade, ForceP, MODE_EMA, PRICE_CLOSE, 1);
      if (Value < 0)  okBuy = true;
      if (Value > 0)  okSell = true;
   	return ("iForce: " + DoubleToStr(Value, 2));
   }
}
//+------------------------------------------------------------------+
double CalcMM_TSDTrade (int Direction) {
   if ( Direction == 1 ) 
      return ( CalcMM (TradeSymbol, (CalcOpenBuy()-CalcSlBuy())/SPoint) );
   else if ( Direction == -1 ) 
      return ( CalcMM (TradeSymbol, (CalcSlSell()-CalcOpenSell())/SPoint) );
}
//+------------------------------------------------------------------+
double CalcMM (string TradeSymbol, int StopLoss) {

   double MinLot  = MarketInfo(TradeSymbol, MODE_MINLOT);
   double LotStep = MarketInfo(TradeSymbol, MODE_LOTSTEP);
   double LotsToTrade, LotsMM = Lots;

   if ( Risk > 0 ) {
      LotsToTrade = AccountBalance() * Risk / (StopLoss * PipCost(TradeSymbol));
      for (LotsMM = MinLot; NormalizeDouble(LotsToTrade-LotsMM, 8) >= 0; LotsMM += LotStep ) {}
      LotsMM = MathMax (MinLot, LotsMM - LotStep);
   }

   if ( AccountFreeMargin() < LotsMM * LotMarginSize(TradeSymbol) ) {
      Alert("Not enough money to open trade. Free Margin = ", AccountFreeMargin(),
            ". Number of Lots to trade = ", LotsMM);
      return(-1); 
   }

   return (LotsMM);
}
//+------------------------------------------------------------------+
double PipCost (string TradeSymbol) {
   double Base, Cost;
   string TS_13, TS_46, TS_4L;

   TS_13 = StringSubstr (TradeSymbol, 0, 3);
   TS_46 = StringSubstr (TradeSymbol, 3, 3);
   TS_4L = StringSubstr (TradeSymbol, 3, StringLen(TradeSymbol)-3);
   
   Base = MarketInfo (TradeSymbol, MODE_LOTSIZE) * MarketInfo (TradeSymbol, MODE_POINT);
   if ( TS_46 == "USD" )
      Cost = Base;
   else if ( TS_13 == "USD" )
           Cost = Base / MarketInfo (TradeSymbol, MODE_BID);
        else if ( PairExists ("USD"+TS_4L) )
                Cost = Base / MarketInfo ("USD"+TS_4L, MODE_BID);
             else
                Cost = Base * MarketInfo (TS_46+"USD", MODE_BID);

   return(Cost);
}
//+------------------------------------------------------------------+
double LotMarginSize (string TradeSymbol) {
   double Margin, MarginSize = MarketInfo (TradeSymbol, MODE_LOTSIZE) / AccountLeverage();
   string TS_13, TS_7L;

   TS_13 = StringSubstr (TradeSymbol, 0, 3);
   TS_7L = StringSubstr (TradeSymbol, 6, StringLen(TradeSymbol)-6);
   
   if ( TS_13 == "USD" )
      Margin = MarginSize;
   else if ( PairExists (TS_13+"USD"+TS_7L) )
           Margin = MarginSize * MarketInfo (TS_13+"USD"+TS_7L, MODE_BID);
        else
           Margin = MarginSize / MarketInfo ("USD"+TS_13+TS_7L, MODE_BID);

   return(Margin);
}
//+------------------------------------------------------------------+
bool PairExists (string TradeSymbol) {
   return ( MarketInfo (TradeSymbol, MODE_LOTSIZE) > 0 );
}
//+------------------------------------------------------------------+
int TotalTradesThisSymbol (string TradeSymbol) {
   int i, TradesThisSymbol = 0;
   
   for (i = 0; i < OrdersTotal(); i++)
      if ( OrderSelect (i, SELECT_BY_POS) )
         if ( OrderSymbol() == TradeSymbol && OrderMagicNumber() == MagicNumber )
            TradesThisSymbol++;

   return (TradesThisSymbol);
}
//+------------------------------------------------------------------+
void OrderError (bool OK, bool ResetNewBar=true) {
   if ( ! OK ) {
      if ( ResetNewBar )  NewBar(-1);
      ReportError();
   }
}
//+------------------------------------------------------------------+
void ReportError () {
   int err = GetLastError();
   Print("Error(",err,"): ", ErrorDescription(err));
}
//+------------------------------------------------------------------+
int ComparePrices (double Price1, double Price2) {
   double p1 = NormalizeDouble (Price1, SDigits), p2 = NormalizeDouble (Price2, SDigits);
   if ( p1 > p2 )  return(1);
   if ( p1 < p2 )  return(-1);
   return(0);
}
//+------------------------------------------------------------------+
bool NewBar (int how=1) {
   static int ProcessNumber = 2;
   static datetime PairTime[0];
   static int PairNewBar[0];
   
   if ( ArraySize(PairTime) != ArraySize(pairs) ) {
      ArrayResize (PairTime, ArraySize(pairs) );
      ArrayResize (PairNewBar, ArraySize(pairs) );  ArrayInitialize (PairNewBar, 100);

      if ( TradeOnInit )  ArrayInitialize (PairTime, 0);
      else                ArrayInitialize (PairTime, iTime (TradeSymbol, PeriodTrade, 0 ));
   }

   if ( how == -1 ) {
      PairNewBar[Pair] = MathMax ( 0, PairNewBar[Pair]-1 );
      return(true);
   }
   
   if ( PairNewBar[Pair] <= ProcessNumber ) {
      if ( how == 1 )
         PairNewBar[Pair]++;
      return(true);
   }
   
   if ( PairTime[Pair] != iTime (TradeSymbol, PeriodTrade, 0 ) ) {
      PairTime[Pair] = iTime (TradeSymbol, PeriodTrade, 0 );
      PairNewBar[Pair] = 0;
   }

   return(false);
}
//+------------------------------------------------------------------+
void CommentAll (int Direction, string ValueComment) {
   string Comments = "";
   int i, next = (Pair+1) % ArraySize(pairs);
   
   CommentsPairs[Pair] = TradeSymbol + ": " + " Dir("+Direction+") " + ValueComment + 
                         " TS(" + DoubleToStr (STS/SPoint, 0) + ")";
   CommentsPairs[next] = ">" + CommentsPairs[next];
   for (i=0; i < ArraySize(CommentsPairs); i++)
      Comments = Comments + "\n" + CommentsPairs[i];
   if ( ! IsTesting() )  Comment (CommentHeader, Comments);
}





Sample





Analysis



Market Information Used:

Series array that contains the highest prices of each bar
Series array that contains the lowest prices of each bar
Series array that contains open time of each bar


Indicator Curves created:


Indicators Used:

Larry William percent range indicator


Custom Indicators Used:

Order Management characteristics:
Checks for the total of open orders


Other Features:

It issuies visual alerts to the screen