//+------------------------------------------------------------------+ //| MACDStrategy.mqh | //| Copyrigth - Dev Solve LTDA | //+------------------------------------------------------------------+ #include "..\ExpertStrategy.mqh" #include #resource "\\Indicators\\Examples\\Custom_MACD.ex5" //+------------------------------------------------------------------+ //| Class CMACDStrategy. | //| Purpose: Class of strategy based on MACD signals strategy. | //| The ATR indicator is filter usage in strategy. | //| Derives from class CExpertStrategy. | //+------------------------------------------------------------------+ class CMACDStrategy : public CExpertStrategy { private: //--- fields of the strategy MqlRates m_rates[]; int m_macd_handle; double m_MACD_MAIN[]; double m_MACD_SIGNAL[]; double m_MACD_EMA_FAST[]; double m_MACD_EMA_SLOW[]; double m_MACD_STDDEV_UP[]; double m_MACD_STDDEV_DOWN[]; ENUM_TIMEFRAMES m_macd_timeframe; int m_macd_fast_ema_period; int m_macd_slow_ema_period; int m_macd_signal_period; ENUM_APPLIED_PRICE m_macd_applied_price; ENUM_TIMEFRAMES m_atr_timeframe; int m_atr_period; double m_atr_multiplier; int m_atr_candle_counter; int m_atr_counter; int m_atr_handle; double m_ATR[]; ENUM_MACD_TYPE_ENTRY M_MACD_TYPE_ENTRY; int m_macd_stddev_period; double m_macd_stddev_multiplier; int m_ema_fast_handle; int m_ema_slow_handle; double m_MACD_EMA_FAST_PLOT[]; double m_MACD_EMA_SLOW_PLOT[]; public: CMACDStrategy(); ~CMACDStrategy(); //--- setter of the direction strategy void SetDirection(ENUM_TYPE_DIRECTION value) { m_direction=value; } //--- setters of the fields void Set_m_macd_timeframe(ENUM_TIMEFRAMES value) {m_macd_timeframe = value;}; void Set_m_macd_fast_ema_period(int value) {m_macd_fast_ema_period = value;}; void Set_m_macd_slow_ema_period(int value) {m_macd_slow_ema_period = value;}; void Set_m_macd_signal_period(int value) {m_macd_signal_period = value;}; void Set_m_macd_applied_price(ENUM_APPLIED_PRICE value) {m_macd_applied_price = value;}; //--- void Set_m_atr_timeframe(ENUM_TIMEFRAMES value) {m_atr_timeframe = value;}; void Set_m_atr_period(int value) {m_atr_period = value;}; void Set_m_atr_multiplier(double value) {m_atr_multiplier = value;}; void Set_m_atr_candle_counter(int value) {m_atr_candle_counter = value;}; //--- void Set_m_macd_stddev_period(int value) {m_macd_stddev_period = value;}; void Set_m_macd_stddev_multiplier(double value) {m_macd_stddev_multiplier = value;}; void Set_m_macd_stddev_timeframe(ENUM_TIMEFRAMES value) {m_macd_stddev_period = value;}; //--- void Set_M_MACD_TYPE_ENTRY(ENUM_MACD_TYPE_ENTRY value) {M_MACD_TYPE_ENTRY = value;}; //--- validation input data virtual bool ValidationSettings(void); virtual bool InitIndicators(CIndicators *indicators); //--- methods of the current strategy virtual bool CheckOpenLong(double &price, double &sl, double &tp, datetime &expiration); virtual bool CheckOpenShort(double &price, double &sl, double &tp, datetime &expiration); virtual bool CheckTralilingOrder(COrderInfo *order, double &price, datetime &expiration); protected: bool CheckPriceWithDirection(ENUM_TYPE_DIRECTION direction,ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration); bool CheckPriceTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration); bool CheckPriceCounterTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration); bool CheckPriceMax(double &price,double &sl,double &tp,datetime &expiration); bool CheckPriceMin(double &price,double &sl,double &tp,datetime &expiration); bool Refresh(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CMACDStrategy::CMACDStrategy(): m_macd_handle(-1), m_macd_fast_ema_period(-1), m_macd_slow_ema_period(-1), m_macd_signal_period(-1), m_atr_period(-1), m_macd_stddev_period(-1), m_macd_stddev_multiplier(-1), m_atr_counter(0) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CMACDStrategy::~CMACDStrategy() { IndicatorRelease(m_atr_handle); IndicatorRelease(m_macd_handle); } //+------------------------------------------------------------------+ //| Validation Settings | //+------------------------------------------------------------------+ bool CMACDStrategy::ValidationSettings(void) { if(!CEngineBase::ValidationSettings()) return(false); //--- chek all inputs param if(m_macd_fast_ema_period <=0) { printf("Erro: parâmetro escolhido para o [Período da Média Rápida do MACD] de [MACD Strategy] é inválido."); return(false); } if(m_macd_slow_ema_period<=0) { printf("Erro: parâmetro escolhido para o [Período da Média Longa do MACD] de [MACD Strategy] é inválido."); return(false); } if(m_macd_signal_period<=0) { printf("Erro: parâmetro escolhido para o [Período do Sinal do MACD] de [MACD Strategy] é inválido."); return(false); } if(m_atr_period<=0) { printf("Erro: parâmetro escolhido para o [Período do ATR] de [MACD Strategy] é inválido."); return(false); } if(m_atr_multiplier<=0) { printf("Erro: parâmetro escolhido para o [Multiplicador do ATR] de [MACD Strategy] é inválido."); return(false); } //--- if(m_macd_timeframe==PERIOD_CURRENT) m_macd_timeframe=m_period; //--- if(m_atr_timeframe==PERIOD_CURRENT) m_atr_timeframe=m_period; //--- ok return(true); } //+------------------------------------------------------------------+ //| Init Indicators | //+------------------------------------------------------------------+ bool CMACDStrategy::InitIndicators(CIndicators *indicators) { //--- ArrayResize(m_MACD_MAIN, m_macd_stddev_period+2); ArrayResize(m_MACD_SIGNAL, m_macd_stddev_period+2); ArraySetAsSeries(m_MACD_MAIN, true); ArraySetAsSeries(m_MACD_SIGNAL, true); if (m_macd_stddev_period < 2) { ArrayResize(m_MACD_MAIN, 3); ArrayResize(m_MACD_SIGNAL, 3); } ArrayResize(m_ATR,m_atr_period+3); ArraySetAsSeries(m_ATR, true); //--- init MACD //m_macd_handle=iCustom(m_other_ticker,m_macd_timeframe,"::Indicators\\Examples\\MACD.ex5",m_macd_fast_ema_period,m_macd_slow_ema_period,m_macd_signal_period,m_macd_applied_price); m_macd_handle=iCustom(m_other_ticker,m_macd_timeframe,"::Indicators\\Examples\\Custom_MACD.ex5",m_macd_fast_ema_period,m_macd_slow_ema_period,m_macd_signal_period,m_macd_applied_price,m_macd_stddev_period,m_macd_stddev_multiplier); //--- check ResetLastError(); if(m_macd_handle==INVALID_HANDLE) { SetUserError(ERR_INVALID_HANDLE); printf("Erro ao carregar MACD - error: %d",GetLastError()); return(false); } //--- add to chart ChartIndicatorAdd(0,0,m_macd_handle); //--- init atr m_atr_handle=iATR(m_other_ticker,m_atr_timeframe,m_atr_period); //--- check ResetLastError(); if(m_atr_handle==INVALID_HANDLE) { SetUserError(ERR_INVALID_HANDLE); printf("Erro ao carregar Média Lenta - error: %d",GetLastError()); return(false); } //--- add to chart ChartIndicatorAdd(0,0,m_atr_handle); //--- init moving averages m_ema_fast_handle=iMA(m_other_ticker,m_macd_timeframe,m_macd_fast_ema_period,0,MODE_EMA,PRICE_CLOSE); m_ema_slow_handle=iMA(m_other_ticker,m_macd_timeframe,m_macd_slow_ema_period,0,MODE_EMA,PRICE_CLOSE); //--- check ResetLastError(); if(m_ema_fast_handle==INVALID_HANDLE || m_ema_slow_handle==INVALID_HANDLE ) { SetUserError(ERR_INVALID_HANDLE); printf("Erro ao carregar Média Móveis - error: %d",GetLastError()); return(false); } //--- add to chart ChartIndicatorAdd(0,0,m_ema_fast_handle); ChartIndicatorAdd(0,0,m_ema_slow_handle); //--- ok return(true); } //+------------------------------------------------------------------+ //| Checking if there is a possibility of opening a buy position. | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckOpenLong(double &price, double &sl, double &tp, datetime &expiration) { return(CheckPriceWithDirection(m_direction,POSITION_TYPE_BUY,price,sl,tp,expiration)); } //+------------------------------------------------------------------+ //| Checking if there is a possibility of opening a sell position. | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckOpenShort(double &price, double &sl, double &tp, datetime &expiration) { return(CheckPriceWithDirection(m_direction,POSITION_TYPE_SELL,price,sl,tp,expiration)); } //+------------------------------------------------------------------+ //| Checking price by direction | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckPriceWithDirection(ENUM_TYPE_DIRECTION direction,ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration) { //--- if trend direction if(direction==TREND_DIRECTION) return(CheckPriceTrendDirection(type,price,sl,tp,expiration)); //--- counter trend direction else return(CheckPriceCounterTrendDirection(type,price,sl,tp,expiration)); } //+------------------------------------------------------------------+ //| Checking price by trend direction | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckPriceTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration) { //--- check positon type if(type==POSITION_TYPE_BUY) return(CheckPriceMax(price,sl,tp,expiration)); else return(CheckPriceMin(price,sl,tp,expiration)); return(false); } //+------------------------------------------------------------------+ //| Checking price by counter trend direction | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckPriceCounterTrendDirection(ENUM_POSITION_TYPE type,double &price,double &sl,double &tp,datetime &expiration) { //--- check positon type if(type==POSITION_TYPE_BUY) return(CheckPriceMin(price,sl,tp,expiration)); else return(CheckPriceMax(price,sl,tp,expiration)); return(false); } //+------------------------------------------------------------------+ //| Obtain price max | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckPriceMax(double &price,double &sl,double &tp,datetime &expiration) { //--- if(!Refresh()) return false; // check strategy trigger bool authorizeATR = false; if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_1) { if(m_MACD_SIGNAL[1] < 0 && m_MACD_SIGNAL[0] > 0) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_2) { if(m_MACD_MAIN[1] < m_MACD_SIGNAL[1] && m_MACD_MAIN[0] > m_MACD_SIGNAL[0]) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_3) { if(m_MACD_MAIN[1] < m_MACD_STDDEV_UP[1] && m_MACD_MAIN[0] > m_MACD_STDDEV_UP[0]) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_4) { if(m_MACD_MAIN[1] < 0 && m_MACD_MAIN[0] > 0) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else { Print("Tipo de Entrada MACD não selecionada."); } if (m_atr_counter > 0) { m_atr_counter -= 1; int maxAtrArray = ArrayMaximum(m_ATR,0,m_atr_candle_counter); if (maxAtrArray == 0) { price = m_symbol.Last(); return true; } } //--- return(false); } //+------------------------------------------------------------------+ //| Obtain price min | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckPriceMin(double &price,double &sl,double &tp,datetime &expiration) { //--- if(!Refresh()) return false; // check strategy trigger if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_1) { if(m_MACD_SIGNAL[1] > 0 && m_MACD_SIGNAL[0] < 0) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_2) { if(m_MACD_MAIN[1] > m_MACD_SIGNAL[1] && m_MACD_MAIN[0] < m_MACD_SIGNAL[0]) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_3) { if(m_MACD_MAIN[1] > m_MACD_STDDEV_DOWN[1] && m_MACD_MAIN[0] < m_MACD_STDDEV_DOWN[0]) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else if(M_MACD_TYPE_ENTRY == MACD_TYPE_ENTRY_4) { if(m_MACD_MAIN[1] > 0 && m_MACD_MAIN[0] < 0) { m_atr_counter = m_atr_candle_counter; //price = m_symbol.Last(); //return true; } } else { Print("Tipo de Entrada MACD não selecionada."); } if (m_atr_counter > 0) { m_atr_counter -= 1; int maxAtrArray = ArrayMaximum(m_ATR,0,m_atr_candle_counter); if (maxAtrArray == 0) { price = m_symbol.Last(); return true; } } //--- return(false); } //+------------------------------------------------------------------+ //| Check Trailing Order | //+------------------------------------------------------------------+ bool CMACDStrategy::CheckTralilingOrder(COrderInfo *order,double &price,datetime &expiration) { //--- return(false); } //+------------------------------------------------------------------+ //| Refresh Indicators Data. | //+------------------------------------------------------------------+ bool CMACDStrategy::Refresh(void) { //--- check n bars in chart if(Bars(m_other_ticker,m_macd_timeframe)