3pSAR_EA_V1.0





//+------------------------------------------------------------------+
//|                                                                  |
//|                                3pSAR_EA.mq4 - Ver 1.0            |
//|                                                                  |

//| Description of EA

//| Time Frame
//| M1, M15 and H1
 
//| Indicator
//| parabolic SAR changed to 0.01 and 0.1
 
//| Entry Strategy
//| When H1 and M15 are in the same direction then every time that M1 changes in that direction,
//| enter a trade at the completion of the candle.
 
//| Exit Strategy
//| At this stage apply a default Trailing Stop of 15 pips.
//| The TS must be enabled the minute it is applied, and not wait to trail at Break Even, to negate the need for a SL.
  
//+------------------------------------------------------------------+


#property copyright "Robert Hill"
#property link      "None"
#include <stdlib.mqh>
#include <stderror.mqh> 

// This makes code easier to read


extern string  Expert_Name    = "3pSar_EA_v1.0";
extern int     MagicNumberBase = 10000;
//+---------------------------------------------------+
//|Money Management                                   |
//+---------------------------------------------------+
extern double  Lots=0.1;

//+---------------------------------------------------+
//|Indicator Variables                                |
//| Change these to try your own system               |
//| or add more if you like                           |
//+---------------------------------------------------+
extern string  ps1 = "--pSAR inputs--";
extern int     pSAR_Step = 0.01;
extern double  pSAR_Max = 0.1;

//+---------------------------------------------------+
//|Profit controls                                    |
//+---------------------------------------------------+
extern string  st6 = "--Profit Controls--";
extern double  StopLoss=15;
extern double  TakeProfit=0;
extern int     Slippage=3;
extern int     MaxTrades = 999;

//+---------------------------------------------------+
//|General controls                                   |
//+---------------------------------------------------+
int            MagicNumber=0;
string         setup;
int            TradesInThisSymbol = 0;
datetime       timeprev = 0;

//+---------------------------------------------------+
//|  Indicator values for signals and filters         |
//|  Add or Change to test your system                |
//+---------------------------------------------------+

//+------------------------------------------------------------------+
//| Calculate MagicNumber, setup comment and assign RSI Period       |
//|                                                                  |
//+------------------------------------------------------------------+
int init()
{

	MagicNumber = MagicNumberBase + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); 
   setup=Expert_Name + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period()));
    
 return(0);
}

int deinit()
{
 return(0);
}

//+------------------------------------------------------------------+
//| CheckExitCondition                                               |
//|
//| BUY
//|  The exit comes one of two ways.
//|  Most common 8 MA go through the yellow mid keltner band,
//|  but occasionally the 2 MA will go through first.
//|  But which ever goes through first it should be the exit.
//|
//| SELL
//|
//+------------------------------------------------------------------+
int CheckExitCondition(int cmd)
{
   
   return (false);
}

//+------------------------------------------------------------------+
//| CheckEntryCondition                                              |
//|                                                                  |
//| Indicators used                                                  |
//| pSAR                                                             |
//| When H1 and M15 are in the same direction then
//| every time that M1 changes in that direction,
//| enter a trade at the completion of the candle.
//+------------------------------------------------------------------+
  
bool CheckEntryCondition(int cmd)
{
   double pSAR_H1, pSAR_M15, pSAR_M1, pSAR_M1Prev;
   
   pSAR_H1 = iSAR(Symbol(), PERIOD_H1, pSAR_Step, pSAR_Max, 1);
   pSAR_M15 = iSAR(Symbol(), PERIOD_M15, pSAR_Step, pSAR_Max, 1);
   pSAR_M1 = iSAR(Symbol(), PERIOD_M1, pSAR_Step, pSAR_Max, 1);
   pSAR_M1Prev = iSAR(Symbol(), PERIOD_M1, pSAR_Step, pSAR_Max, 2);
                         
   switch (cmd)
   {
     case OP_BUY  : if (pSAR_H1 > Bid)
                    {
                       if (pSAR_M15 > Bid)
                       {
                          if (pSAR_M1 > Bid && pSAR_M1Prev < Bid) return (true);
                       }
                    }
                    break;
     case OP_SELL : if (pSAR_H1 < Bid)
                    {
                       if (pSAR_M15 < Bid)
                       {
                          if (pSAR_M1 < Bid && pSAR_M1Prev > Bid) return (true);
                       }
                    }   }
   
   return (false);
}
  
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Start                                                            |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int start()
{ 


// Only run once per completed bar

     if(timeprev==Time[0]) return(0);
     timeprev = Time[0];
     
//+------------------------------------------------------------------+
//| Check for Open Position                                          |
//+------------------------------------------------------------------+

     HandleOpenPositions();
     
// Check if any open positions were not closed

     TradesInThisSymbol = CheckOpenPositions();
  
// Only allow 1 trade per Symbol

     if(TradesInThisSymbol >= MaxTrades) {
       return(0);}
   
 //+------------------------------------------------------------------+
//| Friday No trade zone                                             |
//+------------------------------------------------------------------+


	if (CheckEntryCondition(OP_BUY)==true)
	{
		   OpenBuyOrder(Lots, StopLoss,TakeProfit, Slippage, setup, MagicNumber, Green);
		   return(0);
	}

   
	if (CheckEntryCondition(OP_SELL)==true)
	{
         OpenSellOrder(Lots, StopLoss,TakeProfit, Slippage, setup, MagicNumber, Red);
	}

  return(0);
}


//+------------------------------------------------------------------+
//| OpenBuyOrder                                                     |
//| If Stop Loss or TakeProfit are used the values are calculated    |
//| for each trade                                                   |
//+------------------------------------------------------------------+
int OpenBuyOrder(double mLots, double mStopLoss, double mTakeProfit, int mSlippage, string mComment, int mMagic, color mColor)
{
   int err,ticket;
   double myStopLoss = 0, myTakeProfit = 0;
   
   RefreshRates();
   myStopLoss = StopLong(Bid,mStopLoss);
   myTakeProfit = TakeLong(Bid,mTakeProfit);
 // Normalize all price / stoploss / takeprofit to the proper # of digits.
   if (Digits > 0) 
   {
     myStopLoss = NormalizeDouble( myStopLoss, Digits);
     myTakeProfit = NormalizeDouble( myTakeProfit, Digits); 
   }
   ticket=OrderSend(Symbol(),OP_BUY,mLots,Ask,mSlippage,myStopLoss,myTakeProfit,mComment,mMagic,0,mColor); 
   if (ticket > 0)
   {
    if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) 
     {
      Print("BUY order opened : ", OrderOpenPrice( ));
//      PlaySound("Alert.wav");
     }
   }
   else
   {
      err = GetLastError();
      Print("Error opening BUY order [" + setup + "]: (" + err + ") " + ErrorDescription(err)); 
   }
   
   return(ticket);
}

//+------------------------------------------------------------------+
//| OpenSellOrder                                                    |
//| If Stop Loss or TakeProfit are used the values are calculated    |
//| for each trade                                                   |
//+------------------------------------------------------------------+
int OpenSellOrder(double mLots, double mStopLoss, double mTakeProfit, int mSlippage, string mComment, int mMagic, color mColor)
{
   int err, ticket;
   double myBid, myAsk, myStopLoss = 0, myTakeProfit = 0;
   
   myStopLoss = StopShort(Ask,mStopLoss);
   myTakeProfit = TakeShort(Ask,mTakeProfit);
   
 // Normalize all price / stoploss / takeprofit to the proper # of digits.
   if (Digits > 0) 
   {
     myStopLoss = NormalizeDouble( myStopLoss, Digits);
     myTakeProfit = NormalizeDouble( myTakeProfit, Digits); 
   }
   ticket=OrderSend(Symbol(),OP_SELL,mLots,Bid,mSlippage,myStopLoss,myTakeProfit,mComment,mMagic,0,mColor); 
   if (ticket > 0)
   {
     if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) 
     {
      Print("Sell order opened : ", OrderOpenPrice());
//      PlaySound("Alert.wav");
     }
   }
   else
   {
      err = GetLastError();
      Print("Error opening Sell order [" + mComment + "]: (" + err + ") " + ErrorDescription(err));
   }
   
   return(ticket);
}


double StopLong(double price,int stop)
{
 if(stop==0)
  return(0);
 else
  return(price-(stop*Point));
}

double StopShort(double price,int stop)
{
 if(stop==0)
  return(0);
 else
  return(price+(stop*Point));
}

double TakeLong(double price,int take)
{
 if(take==0)
  return(0);
 else
  return(price+(take*Point));
}

double TakeShort(double price,int take)
{
 if(take==0)
  return(0);
 else
  return(price-(take*Point));
}

//+------------------------------------------------------------------+
//| Handle Open Positions                                            |
//| Check if any open positions need to be closed or modified        |
//+------------------------------------------------------------------+
int HandleOpenPositions()
{
   int cnt, ticket, ExitRule;
   double ol;
   
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
   {
      OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES);
      if ( OrderSymbol() != Symbol()) continue;
      if ( OrderMagicNumber() != MagicNumber)  continue;
      
      ticket = OrderTicket();
      ol = OrderLots();
      if(OrderType() == OP_BUY)
      {
            
         if (CheckExitCondition(OP_BUY) == true)
          {
              CloseOrder(ticket,ol,OP_BUY);
          }

          else
          {
               HandleTrailingStop(OP_BUY,ticket,OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
          }
      }

      if(OrderType() == OP_SELL)
      {
          if (CheckExitCondition(OP_SELL) == true)
          {
             CloseOrder(ticket,ol,OP_SELL);
          }
          else
          {
               HandleTrailingStop(OP_SELL,ticket,OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit());
          }
      }
   }
}

//+------------------------------------------------------------------+
//| Check Open Position Controls                                     |
//+------------------------------------------------------------------+
  
int CheckOpenPositions()
{
   int cnt, total;
   int NumTrades;
   
   NumTrades = 0;
   total=OrdersTotal();
   for(cnt=OrdersTotal()-1;cnt>=0;cnt--)
     {
      OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES);
      if ( OrderSymbol() != Symbol()) continue;
      if ( OrderMagicNumber() != MagicNumber)  continue;
      
      if(OrderType() == OP_BUY )  NumTrades++;
      if(OrderType() == OP_SELL )  NumTrades++;
             
     }
     return (NumTrades);
  }
  

int CloseOrder(int ticket,double numLots,int cmd)
{
	bool result;
   int CloseCnt, err;
   double myPrice;
   
   // try to close 3 Times
      
    CloseCnt = 0;
    while (CloseCnt < 3)
    {
      if (cmd == OP_BUY) myPrice = Bid;
      if (cmd == OP_SELL) myPrice = Ask;
      if (Digits > 0)  myPrice = NormalizeDouble( myPrice, Digits);
      if ( OrderClose(ticket,numLots,myPrice,Slippage,Violet) == true)
         CloseCnt = 3;
      else
      {
         err=GetLastError();
         if (err > 0)	
		   {
            Print(" Error closing order : (", err , ") " + ErrorDescription(err));
            Sleep(5000);
			   RefreshRates(); 
		   }
		   CloseCnt++;
		}
	}  
	 
   return(0);

}

//+------------------------------------------------------------------+
//| HandleTrailingStop                                               |
//| Type 1 moves the stoploss without delay.                         |
//| Type 2 waits for price to move the amount of the trailStop       |
//| before moving stop loss then moves like type 1                   |
//| Type 3 uses up to 3 levels for trailing stop                     |
//|      Level 1 Move stop to 1st level                              |
//|      Level 2 Move stop to 2nd level                              |
//|      Level 3 Trail like type 1 by fixed amount other than 1      |
//| Type 4 Move stop to breakeven + Lockin, no trail                 |
//| Type 5 uses steps for 1, every step pip move moves stop 1 pip    |
//| Type 6 Uses EMA to set trailing stop                             |
//+------------------------------------------------------------------+
void HandleTrailingStop(int type, int ticket, double op, double os, double tp)
{
/*
   switch (TrailingStopType)
   {
     case 1 :
*/     
      Immediate_TrailingStop (type, ticket, op, os, tp);
//              break;
/*
     case 2 : Delayed_TrailingStop (type, ticket, op, os, tp);
              break;
     case 3 : ThreeLevel_TrailingStop (type, ticket, op, os, tp);
              break;
     case 4 : BreakEven_TrailingStop (type, ticket, op, os, tp);
              break;
	  case 5 : eTrailingStop (type, ticket, op, os, tp);
              break;
	  case 6 : MA_TrailingStop (type, ticket, op, os, tp);
              break;
	  case 7 : pSAR_TrailingStop (type, ticket, op, os, tp);
              break;
	}
*/
}
//+------------------------------------------------------------------+
//|                                       Immediate_TrailingStop.mq4 |
//|                                  Copyright © 2006, Forex-TSD.com |
//|                         Written by MrPip,robydoby314@yahoo.com   |
//|                                                                  |   
//| Moves the stoploss without delay.                                |
//+------------------------------------------------------------------+
void Immediate_TrailingStop(int type, int ticket, double op, double os, double tp)
{

   double pt, pp, BuyStop, SellStop;

   pp = MarketInfo(Symbol(), MODE_POINT);
   
   if (type==OP_BUY)
   {
     pt = StopLoss * pp;
     if(Bid-os > pt)
     {
       BuyStop = Bid - pt;
       if (Digits > 0) BuyStop = NormalizeDouble( BuyStop, Digits);
		 BuyStop = ValidStopLoss(OP_BUY,Bid, BuyStop);   
       if (os < BuyStop) ModifyOrder(ticket,op,BuyStop,tp,LightGreen);
		 return;
	  }
   }
   if (type==OP_SELL)
   {
     pt = StopLoss * pp;
     if(os - Ask > pt)
     {
       SellStop = Ask + pt;
       if (Digits > 0) SellStop = NormalizeDouble( SellStop, Digits);
       SellStop = ValidStopLoss(OP_SELL, Ask, SellStop);  
       if (os > SellStop) ModifyOrder(ticket,op,SellStop,tp,DarkOrange);
		 return;
     }
   }   
}

int ModifyOrder(int ord_ticket,double op, double price,double tp, color mColor)
{
    int CloseCnt, err;
    
    CloseCnt=0;
    while (CloseCnt < 3)
    {
       if (OrderModify(ord_ticket,op,price,tp,0,mColor)== true)
       {
         CloseCnt = 3;
       }
       else
       {
          err=GetLastError();
          Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err));
          Sleep(5000);
          if (err>0) CloseCnt++;
       }
    }
}

double ValidStopLoss(int type, double price, double SL)
{

   double mySL;
   double minstop, pp;
   
   pp = MarketInfo(Symbol(), MODE_POINT);
   minstop = MarketInfo(Symbol(),MODE_STOPLEVEL);
   
   mySL = SL;
   if (type == OP_BUY)
   {
		 if((price - mySL) < minstop*pp) mySL = price - minstop*pp;
   }
   if (type == OP_SELL)
   {
       if((mySL-price) < minstop*pp)  mySL = price + minstop*pp;  
   }

   return(NormalizeDouble(mySL,MarketInfo(Symbol(), MODE_DIGITS)));   
}

int func_Symbol2Val(string symbol)
 {
   string mySymbol = StringSubstr(symbol,0,6);
   
	if(mySymbol=="AUDCAD") return(1);
	if(mySymbol=="AUDJPY") return(2);
	if(mySymbol=="AUDNZD") return(3);
	if(mySymbol=="AUDUSD") return(4);
	if(mySymbol=="CHFJPY") return(5);
	if(mySymbol=="EURAUD") return(6);
	if(mySymbol=="EURCAD") return(7);
	if(mySymbol=="EURCHF") return(8);
	if(mySymbol=="EURGBP") return(9);
	if(mySymbol=="EURJPY") return(10);
	if(mySymbol=="EURUSD") return(11);
	if(mySymbol=="GBPCHF") return(12);
	if(mySymbol=="GBPJPY") return(13);
	if(mySymbol=="GBPUSD") return(14);
	if(mySymbol=="NZDJPY") return(15);
	if(mySymbol=="NZDUSD") return(16);
	if(mySymbol=="USDCAD") return(17);
	if(mySymbol=="USDCHF") return(18);
	if(mySymbol=="USDJPY") return(19);
   Comment("unexpected Symbol");
	return(999);
}

//+------------------------------------------------------------------+
//| Time frame interval appropriation  function                      |
//+------------------------------------------------------------------+

int func_TimeFrame_Const2Val(int Constant ) {
   switch(Constant) {
      case 1:  // M1
         return(1);
      case 5:  // M5
         return(2);
      case 15:
         return(3);
      case 30:
         return(4);
      case 60:
         return(5);
      case 240:
         return(6);
      case 1440:
         return(7);
      case 10080:
         return(8);
      case 43200:
         return(9);
   }
}

//+------------------------------------------------------------------+
//| Time frame string appropriation  function                               |
//+------------------------------------------------------------------+

string func_TimeFrame_Val2String(int Value ) {
   switch(Value) {
      case 1:  // M1
         return("PERIOD_M1");
      case 2:  // M1
         return("PERIOD_M5");
      case 3:
         return("PERIOD_M15");
      case 4:
         return("PERIOD_M30");
      case 5:
         return("PERIOD_H1");
      case 6:
         return("PERIOD_H4");
      case 7:
         return("PERIOD_D1");
      case 8:
         return("PERIOD_W1");
      case 9:
         return("PERIOD_MN1");
   	default: 
   		return("undefined " + Value);
   }
}

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






Sample





Analysis



Market Information Used:

Series array that contains open time of each bar


Indicator Curves created:


Indicators Used:

Parabolic Stop and Reverse system


Custom Indicators Used:

Order Management characteristics:
It automatically opens orders when conditions are reached

Checks for the total of open orders
It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy

Other Features: