//+------------------------------------------------------------------+ //| MA_Cross.mqh | //| Copyright 2012, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2012, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" #include "..\ExpertSignal.mqh" // The CExpertSignal class is in the file ExpertSignal #property tester_indicator "Examples\\Custom Moving Average.ex5" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals at the intersection of two MAs | //| Type=SignalAdvanced | //| Name=My_MA_Cross | //| ShortName=MaCross | //| Class=MA_Cross | //| Page=Not needed | //| Parameter=FastPeriod,int,13,Period of fast MA | //| Parameter=FastMethod,ENUM_MA_METHOD,MODE_SMA,Method of fast MA | //| Parameter=SlowPeriod,int,21,Period of slow MA | //| Parameter=SlowMethod,ENUM_MA_METHOD,MODE_SMA,Method of slow MA | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class MA_Cross : public CExpertSignal { private: CiCustom m_fast_ma; // The indicator as an object CiCustom m_slow_ma; // The indicator as an object //--- Configurable module parameters int m_period_fast; // Period of the fast MA ENUM_MA_METHOD m_method_fast; // Type of smoothing of the fast MA int m_period_slow; // Period of the slow MA ENUM_MA_METHOD m_method_slow; // Type of smoothing of the slow MA public: //--- Constructor of class MA_Cross(void); //--- Destructor of class ~MA_Cross(void); //--- Methods for placing void FastPeriod(const int value) { m_period_fast=value; } void FastMethod(const ENUM_MA_METHOD value) { m_method_fast=value; } void SlowPeriod(const int value) { m_period_slow=value; } void SlowMethod(const ENUM_MA_METHOD value) { m_method_slow=value; } //--- Checking correctness of input data bool ValidationSettings(void); //--- Creating indicators and timeseries for the module of signals bool InitIndicators(CIndicators *indicators); //--- Access to indicator data double FastMA(const int index) const { return(m_fast_ma.GetData(0,index)); } double SlowMA(const int index) const { return(m_slow_ma.GetData(0,index)); } //--- Checking Buy and Sell conditions virtual int LongCondition(); virtual int ShortCondition(); protected: //--- Creating MA indicators bool CreateFastMA(CIndicators *indicators); bool CreateSlowMA(CIndicators *indicators); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ MA_Cross::MA_Cross(void) : m_period_fast(13), m_method_fast(MODE_SMA), m_period_slow(21), m_method_slow(MODE_SMA) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ MA_Cross::~MA_Cross(void) { } //+------------------------------------------------------------------+ //| Checks input parameters and returns true if everything is OK | //+------------------------------------------------------------------+ bool MA_Cross::ValidationSettings(void) { //--- Call the base class method if(!CExpertSignal::ValidationSettings()) return(false); //--- Check periods, number of bars for the calculation of the MA >=1 if(m_period_fast<1 || m_period_slow<1) { PrintFormat("Incorrect value set for one of the periods! FastPeriod=%d, SlowPeriod=%d", m_period_fast,m_period_slow); return false; } //--- Slow MA period must be greater that the fast MA period if(m_period_fast>m_period_slow) { PrintFormat("SlowPeriod=%d must be greater than FastPeriod=%d!", m_period_slow,m_period_fast); return false; } //--- Fast MA smoothing type must be one of the four values of the enumeration if(m_method_fast!=MODE_SMA && m_method_fast!=MODE_EMA && m_method_fast!=MODE_SMMA && m_method_fast!=MODE_LWMA) { PrintFormat("Invalid type of smoothing of the fast MA!"); return false; } //--- Show MA smoothing type must be one of the four values of the enumeration if(m_method_slow!=MODE_SMA && m_method_slow!=MODE_EMA && m_method_slow!=MODE_SMMA && m_method_slow!=MODE_LWMA) { PrintFormat("Invalid type of smoothing of the slow MA!"); return false; } //--- All checks are completed, everything is ok return true; } //+------------------------------------------------------------------+ //| Creates indicators | //| Input: a pointer to a collection of indicators | //| Output: true if successful, otherwise false | //+------------------------------------------------------------------+ bool MA_Cross::InitIndicators(CIndicators *indicators) { //--- Standard check of the collection of indicators for NULL if(indicators==NULL) return(false); //--- Initializing indicators and timeseries in additional filters if(!CExpertSignal::InitIndicators(indicators)) return(false); //--- Creating our MA indicators if(!CreateFastMA(indicators)) return(false); if(!CreateSlowMA(indicators)) return(false); //--- Reached this part, so the function was successful, return true return(true); } //+------------------------------------------------------------------+ //| Creates the "Fast MA" indicator | //+------------------------------------------------------------------+ bool MA_Cross::CreateFastMA(CIndicators *indicators) { //--- Checking the pointer if(indicators==NULL) return(false); //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_fast_ma))) { printf(__FUNCTION__+": Error adding an object of the fast MA"); return(false); } //--- Setting parameters of the fast MA MqlParam parameters[4]; //--- parameters[0].type=TYPE_STRING; parameters[0].string_value="Examples\\Custom Moving Average.ex5"; parameters[1].type=TYPE_INT; parameters[1].integer_value=m_period_fast; // Period parameters[2].type=TYPE_INT; parameters[2].integer_value=0; // Shift parameters[3].type=TYPE_INT; parameters[3].integer_value=m_method_fast; // Method of averaging //--- Object initialization if(!m_fast_ma.Create(m_symbol.Name(),m_period,IND_CUSTOM,4,parameters)) { printf(__FUNCTION__+": Error initializing the object of the fast MA"); return(false); } //--- Number of buffers if(!m_fast_ma.NumBuffers(1)) return(false); //--- Reached this part, so the function was successful, return true return(true); } //+------------------------------------------------------------------+ //| Creates the "Slow MA" indicator | //+------------------------------------------------------------------+ bool MA_Cross::CreateSlowMA(CIndicators *indicators) { //--- Checking the pointer if(indicators==NULL) return(false); //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_slow_ma))) { printf(__FUNCTION__+": Error adding an object of the slow MA"); return(false); } //--- Setting parameters of the slow MA MqlParam parameters[4]; //--- parameters[0].type=TYPE_STRING; parameters[0].string_value="Examples\\Custom Moving Average.ex5"; parameters[1].type=TYPE_INT; parameters[1].integer_value=m_period_slow; // Period parameters[2].type=TYPE_INT; parameters[2].integer_value=0; // Shift parameters[3].type=TYPE_INT; parameters[3].integer_value=m_method_slow; // Method of averaging //--- Object initialization if(!m_slow_ma.Create(m_symbol.Name(),m_period,IND_CUSTOM,4,parameters)) { printf(__FUNCTION__+": Error initializing the object of the slow MA"); return(false); } //--- Number of buffers if(!m_slow_ma.NumBuffers(1)) return(false); //--- Reached this part, so the function was successful, return true return(true); } //+------------------------------------------------------------------+ //| Returns the strength of the buy signal | //+------------------------------------------------------------------+ int MA_Cross::LongCondition() { int signal=0; //--- For operation with ticks idx=0, for operation with formed bars idx=1 int idx=StartIndex(); //--- Values of MAs at the last formed bar double last_fast_value=FastMA(idx); double last_slow_value=SlowMA(idx); //--- Values of MAs at the last but one formed bar double prev_fast_value=FastMA(idx+1); double prev_slow_value=SlowMA(idx+1); //--- If the fast MA crossed the slow MA from bottom upwards on the last two closed bars if((last_fast_value>last_slow_value) && (prev_fast_valueprev_slow_value)) { signal=100; // There is a signal to sell } //--- Return the signal value return(signal); } //+------------------------------------------------------------------+