//+------------------------------------------------------------------+
//|                                                       MACENA.mq5 |
//|              Copyright Copyright 2010, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"

#include <ExpertAdvisor.mqh>

input int    SL        =  50; // Stop Loss distance
input int    TP        = 100; // Take Profit distance
input int    TS        =  50; // Trailing Stop distance
input int    FastEMA   =  15; // Fast EMA
input int    SlowEMA   =  26; // Slow EMA
input int    MACD_SMA  =   1; // MACD signal line
input int    EnvelPer  =  20; // Envelopes period
input double EnvelDev  = 0.4; // Envelopes deviation
input double Risk      = 0.1; // Risk
//---
class CMyEA : public CExpertAdvisor
  {
protected:
   double            m_risk;          // size of risk
   int               m_sl;            // Stop Loss
   int               m_tp;            // Take Profit
   int               m_ts;            // Trailing Stop
   int               m_pFastEMA;      // Fast EMA
   int               m_pSlowEMA;      // Slow EMA
   int               m_pMACD_SMA;     // MACD signal line
   int               m_EnvelPer;      // Envelopes period     
   double            m_EnvelDev;      // Envelopes deviation     
   int               m_hmacd;         // MACD indicator handle
   int               m_henvel;        // Envelopes indicator handle   
public:
   void              CMyEA();
   void             ~CMyEA();
   virtual bool      Init(string smb,ENUM_TIMEFRAMES tf); // initialization
   virtual bool      Main();                              // main function
   virtual void      OpenPosition(long dir);              // open position on signal
   virtual void      ClosePosition(long dir);             // close position on signal
   virtual long      CheckSignal(bool bEntry);            // check signal
  };
//------------------------------------------------------------------	CMyEA
void CMyEA::CMyEA() { }
//------------------------------------------------------------------	~CMyEA
void CMyEA::~CMyEA()
  {
   IndicatorRelease(m_hmacd); // delete MACD indicator
   IndicatorRelease(m_henvel);// delete Envelopes indicator
  }
//------------------------------------------------------------------	Init
bool CMyEA::Init(string smb,ENUM_TIMEFRAMES tf)
  {
   if(!CExpertAdvisor::Init(0,smb,tf)) return(false);                                // initialize parent class
                                                                                     // copy parameters
    m_risk=Risk;
   m_tp=TP;
   m_sl=SL;
   m_ts=TS;
   m_pFastEMA=FastEMA;
   m_pSlowEMA=SlowEMA;
   m_pMACD_SMA=MACD_SMA;
   m_EnvelPer = EnvelPer;
   m_EnvelDev = EnvelDev;
   m_hmacd=iMACD(m_smb,PERIOD_D1,m_pFastEMA,m_pSlowEMA,m_pMACD_SMA,PRICE_CLOSE);     // create MACD indicator
   m_henvel=iEnvelopes(m_smb,PERIOD_H1,m_EnvelPer,0,MODE_SMA,PRICE_CLOSE,m_EnvelDev);// create Envelopes indicator
   if(m_hmacd==INVALID_HANDLE ||m_henvel==INVALID_HANDLE ) return(false);            // if there is an error, then exit
   m_bInit=true; return(true);                                                       // trade allowed
  }
//------------------------------------------------------------------	Main
bool CMyEA::Main() // main function
  {
   if(!CExpertAdvisor::Main()) return(false); // call function of parent class

   if(Bars(m_smb,m_tf)<=100) return(false);   // if there are insufficient number of bars

   if(!CheckNewBar()) return(true);           // check new bar

                                              // check each direction
   long dir;
   dir=ORDER_TYPE_BUY;
   OpenPosition(dir); ClosePosition(dir); TrailingPosition(dir,m_ts);
   dir=ORDER_TYPE_SELL;
   OpenPosition(dir); ClosePosition(dir); TrailingPosition(dir,m_ts);

   return(true);
  }
//------------------------------------------------------------------	OpenPos
void CMyEA::OpenPosition(long dir)
  {
// if there is an order, then exit
   if(PositionSelect(m_smb)) return;
// if there is no signal for current direction
   if(dir!=CheckSignal(true)) return;
   double lot=CountLotByRisk(m_sl,m_risk,0);
// if lot is not defined
   if(lot<=0) return;
// open position
   DealOpen(dir,lot,m_sl,m_tp);
  }
//------------------------------------------------------------------	ClosePos
void CMyEA::ClosePosition(long dir)
  {
// if there is no position, then exit
   if(!PositionSelect(m_smb)) return;
// if position of unchecked direction
   if(dir!=PositionGetInteger(POSITION_TYPE)) return;
// if the close signal didn't match the current position
   if(dir!=CheckSignal(false)) return;
// close position
   m_trade.PositionClose(m_smb,1);
  }
//------------------------------------------------------------------	CheckSignal
long CMyEA::CheckSignal(bool bEntry)
  {
   double macd[4],   // Array of MACD indicator values
   env1[3],          // Array of Envelopes' upper border values
   env2[3];          // Array of Bollinger Bands' lower border values

   MqlRates rt[3];   // Array of price values of last 3 bars

   if(CopyRates(m_smb,m_tf,0,3,rt)!=3) // Copy price values of last 3 bars to array
     {
      Print("CopyRates ",m_smb," history is not loaded");
      return(WRONG_VALUE);
     }
// Copy indicator values to array
   if(CopyBuffer(m_hmacd,0,0,4,macd)<4 || CopyBuffer(m_henvel,0,0,2,env1)<2 || CopyBuffer(m_henvel,1,0,2,env2)<2)
     {
      Print("CopyBuffer - no data");
      return(WRONG_VALUE);
     }
// Buy if MACD is growing and if there is a bounce from the Evelopes' lower border
   if(rt[1].open<env2[1] && rt[1].close>env2[1] && macd[1]<macd[2] && macd[2]<macd[3])
      return(bEntry ? ORDER_TYPE_BUY:ORDER_TYPE_SELL); // condition for buy
// Sell if MACD is dwindling and if there is a bounce from the Evelopes' upper border   
   if(rt[1].open>env1[1] && rt[2].close<env1[1] && macd[1]>macd[2] && macd[2]>macd[3])
      return(bEntry ? ORDER_TYPE_SELL:ORDER_TYPE_BUY); // condition for sell

   return(WRONG_VALUE); // if there is no signal
  }

CMyEA ea; // class instance
//------------------------------------------------------------------	OnInit
int OnInit()
  {
   ea.Init(Symbol(),Period());   // initialize expert

                                 // initialization example
// ea.Init(Symbol(), PERIOD_M5); // for fixed timeframe
// ea.Init("USDJPY", PERIOD_H2); // for fixed symbol and timeframe

   return(0);
  }
//------------------------------------------------------------------	OnDeinit
void OnDeinit(const int reason) { }
//------------------------------------------------------------------	OnTick
void OnTick()
  {
   ea.Main(); // process incoming tick
  }
//+------------------------------------------------------------------+
