//+------------------------------------------------------------------+ //| ChannelSample.mqh | //| Copyright 2015, Vasiliy Sokolov. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Vasiliy Sokolov." #property link "http://www.mql5.com" #include //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ class CChannel : public CStrategy { private: int m_handle; // The handle of the indicator that we will use int m_period; // Bollinger period double m_std_dev; // Standard deviation value bool IsTrackEvents(const MarketEvent &event); protected: virtual void OnSymbolChanged(string new_symbol); virtual void OnTimeframeChanged(ENUM_TIMEFRAMES new_tf); virtual void InitBuy(const MarketEvent &event); virtual void SupportBuy(const MarketEvent &event,CPosition *pos); virtual void InitSell(const MarketEvent &event); virtual void SupportSell(const MarketEvent &event,CPosition *pos); virtual bool ParseXmlParams(CXmlElement *params); virtual string ExpertNameFull(void); bool CheckParams(void); public: CChannel(void); ~CChannel(void); int PeriodBands(void); void PeriodBands(int period); double StdDev(void); void StdDev(double std); }; //+------------------------------------------------------------------+ //| Default constructor | //+------------------------------------------------------------------+ CChannel::CChannel(void) : m_handle(INVALID_HANDLE) { } //+------------------------------------------------------------------+ //| The destructor frees the used handle of the indicator | //+------------------------------------------------------------------+ CChannel::~CChannel(void) { if(m_handle!=INVALID_HANDLE) IndicatorRelease(m_handle); } //+------------------------------------------------------------------+ //| React to symbol change | //+------------------------------------------------------------------+ void CChannel::OnSymbolChanged(string new_symbol) { if(!CheckParams())return; if(m_handle!=INVALID_HANDLE) IndicatorRelease(m_handle); m_handle=iBands(new_symbol,Timeframe(),m_period,0,m_std_dev,PRICE_CLOSE); } //+------------------------------------------------------------------+ //| React to timeframe change | //+------------------------------------------------------------------+ void CChannel::OnTimeframeChanged(ENUM_TIMEFRAMES new_tf) { if(!CheckParams())return; if(m_handle!=INVALID_HANDLE) IndicatorRelease(m_handle); m_handle=iBands(ExpertSymbol(),Timeframe(),m_period,0,m_std_dev,PRICE_CLOSE); } //+------------------------------------------------------------------+ //| Returns indicator period | //+------------------------------------------------------------------+ int CChannel::PeriodBands(void) { return m_period; } //+------------------------------------------------------------------+ //| Sets indicator period | //+------------------------------------------------------------------+ void CChannel::PeriodBands(int period) { if(m_period == period)return; m_period=period; if(!CheckParams())return; if(m_handle!=INVALID_HANDLE) IndicatorRelease(m_handle); m_handle=iBands(ExpertSymbol(),Timeframe(),m_period,0,m_std_dev,PRICE_CLOSE); } //+------------------------------------------------------------------+ //| Sets the standard deviation value | //+------------------------------------------------------------------+ double CChannel::StdDev(void) { return m_std_dev; } //+------------------------------------------------------------------+ //| Sets the standard deviation value | //+------------------------------------------------------------------+ void CChannel::StdDev(double std) { if(m_std_dev == std)return; m_std_dev=std; if(!CheckParams())return; if(m_handle!=INVALID_HANDLE) IndicatorRelease(m_handle); m_handle=iBands(ExpertSymbol(),Timeframe(),m_period,0,m_std_dev,PRICE_CLOSE); } //+------------------------------------------------------------------+ //| Long position opening rules | //+------------------------------------------------------------------+ void CChannel::InitBuy(const MarketEvent &event) { if(IsTrackEvents(event))return; // Enable logic only at the opening of a new bar if(positions.open_buy > 0)return; // Does not open more than one long position double bands[]; if(CopyBuffer(m_handle, UPPER_BAND, 1, 1, bands) == 0)return; if(Close[1]>bands[0]) Trade.Buy(1.0,ExpertSymbol()); } //+------------------------------------------------------------------+ //| Long position closing rules | //+------------------------------------------------------------------+ void CChannel::SupportBuy(const MarketEvent &event,CPosition *pos) { if(IsTrackEvents(event))return; // Enable logic only at the opening of a new bar double bands[]; if(CopyBuffer(m_handle, BASE_LINE, 1, 1, bands) == 0)return; double b = bands[0]; double s = Close[1]; if(Close[1] 0)return; // Does not open more than one long position double bands[]; if(CopyBuffer(m_handle, LOWER_BAND, 1, 1, bands) == 0)return; if(Close[1]bands[0]) pos.CloseAtMarket(); } //+------------------------------------------------------------------+ //| Filters incoming events. If the passed event is not | //| processed by the strategy, returns false; if it is processed | //| returns true. | //+------------------------------------------------------------------+ bool CChannel::IsTrackEvents(const MarketEvent &event) { //--- We handle only opening of a new bar on the working symbol and timeframe if(event.type != MARKET_EVENT_BAR_OPEN)return false; if(event.period != Timeframe())return false; if(event.symbol != ExpertSymbol())return false; return true; } //+------------------------------------------------------------------+ //| The strategy's specific parameters are parsed inside it in | //| this method overridden from CStrategy | //+------------------------------------------------------------------+ bool CChannel::ParseXmlParams(CXmlElement *params) { bool res=true; for(int i=0; i