.../MQL5> diff Experts/Downloads/signalmacd.mqh Include/Expert/Signal/SignalMACD.mqh 3,5c3,4 < //| Copyright ▒ 2010, MetaQuotes Software Corp. | < //| http://www.metaquotes.net | < //| Revision 2010.10.12 | --- > //| Copyright 2009-2013, MetaQuotes Software Corp. | > //| http://www.mql5.com | 11,12c10,11 < //| Title=Signals based on crossover of main and signal MACD lines | < //| Type=Signal | --- > //| Title=Signals of oscillator 'MACD' | > //| Type=SignalAdvanced | 13a13 > //| ShortName=MACD | 15,20c15,19 < //| Page= | < //| Parameter=PeriodFast,int,12 | < //| Parameter=PeriodSlow,int,24 | < //| Parameter=PeriodSignal,int,9 | < //| Parameter=StopLoss,int,20 | < //| Parameter=TakeProfit,int,50 | --- > //| Page=signal_macd | > //| Parameter=PeriodFast,int,12,Period of fast EMA | > //| Parameter=PeriodSlow,int,24,Period of slow EMA | > //| Parameter=PeriodSignal,int,9,Period of averaging of difference | > //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | 25,27c24,26 < //| Appointment: Class trading signals | < //| cross of the main and signal lines MACD. | < //| Derives from class CExpertSignal. | --- > //| Purpose: Class of generator of trade signals based on | > //| the 'Moving Average Convergence/Divergence' oscillator. | > //| Is derived from the CExpertSignal class. | 32,38c31,48 < CiMACD *m_MACD; < //--- input parameters < int m_period_fast; < int m_period_slow; < int m_period_signal; < int m_stop_loss; < int m_take_profit; --- > CiMACD m_MACD; // object-oscillator > //--- adjusted parameters > int m_period_fast; // the "period of fast EMA" parameter of the oscillator > int m_period_slow; // the "period of slow EMA" parameter of the oscillator > int m_period_signal; // the "period of averaging of difference" parameter of the oscillator > ENUM_APPLIED_PRICE m_applied; // the "price series" parameter of the oscillator > //--- "weights" of market models (0-100) > int m_pattern_0; // model 0 "the oscillator has required direction" > int m_pattern_1; // model 1 "reverse of the oscillator to required direction" > int m_pattern_2; // model 2 "crossing of main and signal line" > int m_pattern_3; // model 3 "crossing of main line an the zero level" > int m_pattern_4; // model 4 "divergence of the oscillator and price" > int m_pattern_5; // model 5 "double divergence of the oscillator and price" > //--- variables > double m_extr_osc[10]; // array of values of extremums of the oscillator > double m_extr_pr[10]; // array of values of the corresponding extremums of price > int m_extr_pos[10]; // array of shifts of extremums (in bars) > uint m_extr_map; // resulting bit-map of ratio of extremums of the oscillator and the price 41,55c51,71 < CSignalMACD(); < ~CSignalMACD(); < //--- methods initialize protected data < void PeriodFast(int period_fast) { m_period_fast=period_fast; } < void PeriodSlow(int period_slow) { m_period_slow=period_slow; } < void PeriodSignal(int period_signal) { m_period_signal=period_signal; } < void StopLoss(int stop_loss) { m_stop_loss=stop_loss; } < void TakeProfit(int take_profit) { m_take_profit=take_profit; } < virtual bool InitIndicators(CIndicators* indicators); < virtual bool ValidationSettings(); < //--- < virtual bool CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration); < virtual bool CheckCloseLong(double& price); < virtual bool CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration); < virtual bool CheckCloseShort(double& price); --- > CSignalMACD(void); > ~CSignalMACD(void); > //--- methods of setting adjustable parameters > void PeriodFast(int value) { m_period_fast=value; } > void PeriodSlow(int value) { m_period_slow=value; } > void PeriodSignal(int value) { m_period_signal=value; } > void Applied(ENUM_APPLIED_PRICE value) { m_applied=value; } > //--- methods of adjusting "weights" of market models > void Pattern_0(int value) { m_pattern_0=value; } > void Pattern_1(int value) { m_pattern_1=value; } > void Pattern_2(int value) { m_pattern_2=value; } > void Pattern_3(int value) { m_pattern_3=value; } > void Pattern_4(int value) { m_pattern_4=value; } > void Pattern_5(int value) { m_pattern_5=value; } > //--- method of verification of settings > virtual bool ValidationSettings(void); > //--- method of creating the indicator and timeseries > virtual bool InitIndicators(CIndicators *indicators); > //--- methods of checking if the market models are formed > virtual int LongCondition(void); > virtual int ShortCondition(void); 58,61c74,83 < double MainMACD(int ind) { return(m_MACD.Main(ind)); } < double SignalMACD(int ind) { return(m_MACD.Signal(ind)); } < double StateMACD(int ind) { return(MainMACD(ind)-SignalMACD(ind)); } < int ExtStateMACD(int ind); --- > //--- method of initialization of the oscillator > bool InitMACD(CIndicators *indicators); > //--- methods of getting data > double Main(int ind) { return(m_MACD.Main(ind)); } > double Signal(int ind) { return(m_MACD.Signal(ind)); } > double DiffMain(int ind) { return(Main(ind)-Main(ind+1)); } > int StateMain(int ind); > double State(int ind) { return(Main(ind)-Signal(ind)); } > bool ExtState(int ind); > bool CompareMaps(int map,int count,bool minimax=false,int start=0); 64,84c86 < //| Constructor CSignalMACD. | < //| INPUT: no. | < //| OUTPUT: no. | < //| REMARK: no. | < //+------------------------------------------------------------------+ < void CSignalMACD::CSignalMACD() < { < //--- initialize protected data < m_MACD =NULL; < //--- set default inputs < m_period_fast =12; < m_period_slow =24; < m_period_signal=9; < m_stop_loss =20; < m_take_profit =50; < } < //+------------------------------------------------------------------+ < //| Destructor CSignalMACD. | < //| INPUT: no. | < //| OUTPUT: no. | < //| REMARK: no. | --- > //| Constructor | 86c88,105 < void CSignalMACD::~CSignalMACD() --- > CSignalMACD::CSignalMACD(void) : m_period_fast(12), > m_period_slow(24), > m_period_signal(9), > m_applied(PRICE_CLOSE), > m_pattern_0(10), > m_pattern_1(30), > m_pattern_2(80), > m_pattern_3(50), > m_pattern_4(60), > m_pattern_5(100) > { > //--- initialization of protected data > m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW; > } > //+------------------------------------------------------------------+ > //| Destructor | > //+------------------------------------------------------------------+ > CSignalMACD::~CSignalMACD(void) 88d106 < //--- 92,94d109 < //| INPUT: no. | < //| OUTPUT: true-if settings are correct, false otherwise. | < //| REMARK: no. | 96c111 < bool CSignalMACD::ValidationSettings() --- > bool CSignalMACD::ValidationSettings(void) 97a113,116 > //--- validation settings of additional filters > if(!CExpertSignal::ValidationSettings()) > return(false); > //--- initial data checks 108,124c127,147 < //| INPUT: indicators -pointer of indicator collection. | < //| OUTPUT: true-if successful, false otherwise. | < //| REMARK: no. | < //+------------------------------------------------------------------+ < bool CSignalMACD::InitIndicators(CIndicators* indicators) < { < //--- check < if(indicators==NULL) return(false); < //--- create MACD indicator < if(m_MACD==NULL) < if((m_MACD=new CiMACD)==NULL) < { < printf(__FUNCTION__+": error creating object"); < return(false); < } < //--- add MACD indicator to collection < if(!indicators.Add(m_MACD)) --- > //+------------------------------------------------------------------+ > bool CSignalMACD::InitIndicators(CIndicators *indicators) > { > //--- check of pointer is performed in the method of the parent class > //--- > //--- initialization of indicators and timeseries of additional filters > if(!CExpertSignal::InitIndicators(indicators)) > return(false); > //--- create and initialize MACD oscilator > if(!InitMACD(indicators)) > return(false); > //--- ok > return(true); > } > //+------------------------------------------------------------------+ > //| Initialize MACD oscillators. | > //+------------------------------------------------------------------+ > bool CSignalMACD::InitMACD(CIndicators *indicators) > { > //--- add object to collection > if(!indicators.Add(GetPointer(m_MACD))) 127d149 < delete m_MACD; 130,131c152,153 < //--- initialize MACD indicator < if(!m_MACD.Create(m_symbol.Name(),m_period,m_period_fast,m_period_slow,m_period_signal,PRICE_CLOSE)) --- > //--- initialize object > if(!m_MACD.Create(m_symbol.Name(),m_period,m_period_fast,m_period_slow,m_period_signal,m_applied)) 140,146c162 < //| Check relative positions of the main and signal lines MACD. | < //| INPUT: ind - start index for check. | < //| OUTPUT: absolute value - the number of intervals | < //| from cross of the main and signal lines MACD,| < //| sign: minus - fast MA crosses slow MA down, | < //| plus - fast MA crosses slow MA upward. | < //| REMARK: no. | --- > //| Check of the oscillator state. | 148c164 < int CSignalMACD::ExtStateMACD(int ind) --- > int CSignalMACD::StateMain(int ind) 153c169 < for(int i=ind;i<5;i++) --- > for(int i=ind;;i++) 155,156c171,173 < if(MainMACD(i)==WRONG_VALUE || SignalMACD(i)==WRONG_VALUE) break; < var=StateMACD(i); --- > if(Main(i+1)==EMPTY_VALUE) > break; > var=DiffMain(i); 159c176,177 < if(var<0) break; --- > if(var<0) > break; 165c183,184 < if(var>0) break; --- > if(var>0) > break; 169,170c188,191 < if(var>0) res++; < if(var<0) res--; --- > if(var>0) > res++; > if(var<0) > res--; 176,188c197,273 < //| Check conditions for long position open. | < //| INPUT: price - refernce for price, | < //| sl - refernce for stop loss, | < //| tp - refernce for take profit, | < //| expiration - refernce for expiration. | < //| OUTPUT: true-if condition performed, false otherwise. | < //| REMARK: no. | < //+------------------------------------------------------------------+ < bool CSignalMACD::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration) < { < price=0.0; < sl =m_symbol.Ask()-m_stop_loss*m_adjusted_point; < tp =m_symbol.Ask()+m_take_profit*m_adjusted_point; --- > //| Extended check of the oscillator state consists | > //| in forming a bit-map according to certain rules, | > //| which shows ratios of extremums of the oscillator and price. | > //+------------------------------------------------------------------+ > bool CSignalMACD::ExtState(int ind) > { > //--- operation of this method results in a bit-map of extremums > //--- practically, the bit-map of extremums is an "array" of 4-bit fields > //--- each "element of the array" definitely describes the ratio > //--- of current extremums of the oscillator and the price with previous ones > //--- purpose of bits of an element of the analyzed bit-map > //--- bit 3 - not used (always 0) > //--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one > //--- (a higher peak or a deeper valley), otherwise - 0 > //--- bit 1 - not used (always 0) > //--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one > //--- (a higher peak or a deeper valley), otherwise - 0 > //--- in addition to them, the following is formed: > //--- array of values of extremums of the oscillator, > //--- array of values of price extremums and > //--- array of "distances" between extremums of the oscillator (in bars) > //--- it should be noted that when using the results of the extended check of state, > //--- you should consider, which extremum of the oscillator (peak or valley) > //--- is the "reference point" (i.e. was detected first during the analysis) > //--- if a peak is detected first then even elements of all arrays > //--- will contain information about peaks, and odd elements will contain information about valleys > //--- if a valley is detected first, then respectively in reverse > int pos=ind,off,index; > uint map; // intermediate bit-map for one extremum > //--- > m_extr_map=0; > for(int i=0;i<10;i++) > { > off=StateMain(pos); > if(off>0) > { > //--- minimum of the oscillator is detected > pos+=off; > m_extr_pos[i]=pos; > m_extr_osc[i]=Main(pos); > if(i>1) > { > m_extr_pr[i]=m_low.MinValue(pos-2,5,index); > //--- form the intermediate bit-map > map=0; > if(m_extr_pr[i-2] map+=1; // set bit 0 > if(m_extr_osc[i-2] map+=4; // set bit 2 > //--- add the result > m_extr_map+=map<<(4*(i-2)); > } > else > m_extr_pr[i]=m_low.MinValue(pos-1,4,index); > } > else > { > //--- maximum of the oscillator is detected > pos-=off; > m_extr_pos[i]=pos; > m_extr_osc[i]=Main(pos); > if(i>1) > { > m_extr_pr[i]=m_high.MaxValue(pos-2,5,index); > //--- form the intermediate bit-map > map=0; > if(m_extr_pr[i-2]>m_extr_pr[i]) > map+=1; // set bit 0 > if(m_extr_osc[i-2]>m_extr_osc[i]) > map+=4; // set bit 2 > //--- add the result > m_extr_map+=map<<(4*(i-2)); > } > else > m_extr_pr[i]=m_high.MaxValue(pos-1,4,index); > } > } 190c275 < return(ExtStateMACD(1)==1); --- > return(true); 193,196c278 < //| Check conditions for long position close. | < //| INPUT: price - refernce for price. | < //| OUTPUT: true-if condition performed, false otherwise. | < //| REMARK: no. | --- > //| Comparing the bit-map of extremums with pattern. | 198c280 < bool CSignalMACD::CheckCloseLong(double& price) --- > bool CSignalMACD::CompareMaps(int map,int count,bool minimax,int start) 200,202c282,330 < price=0.0; < //--- < return(ExtStateMACD(1)==-1); --- > int step =(minimax)?4:8; > int total=step*(start+count); > //--- check input parameters for a possible going out of range of the bit-map > if(total>32) > return(false); > //--- bit-map of the patter is an "array" of 4-bit fields > //--- each "element of the array" definitely describes the desired ratio > //--- of current extremums of the oscillator and the price with previous ones > //--- purpose of bits of an elements of the pattern of the bit-map pattern > //--- bit 3 - is equal to if the ratio of extremums of the oscillator is insignificant for us > //--- is equal to 0 if we want to "find" the ratio of extremums of the oscillator determined by the value of bit 2 > //--- bit 2 - is equal to 1 if we want to "discover" the situation when the current extremum of the "oscillator" is "more extreme" than the previous one > //--- (current peak is higher or current valley is deeper) > //--- is equal to 0 if we want to "discover" the situation when the current extremum of the oscillator is "less extreme" than the previous one > //--- (current peak is lower or current valley is less deep) > //--- bit 1 - is equal to 1 if the ratio of extremums is insignificant for us > //--- it is equal to 0 if we want to "find" the ratio of price extremums determined by the value of bit 0 > //--- bit 0 - is equal to 1 if we want to "discover" the situation when the current price extremum is "more extreme" than the previous one > //--- (current peak is higher or current valley is deeper) > //--- it is equal to 0 if we want to "discover" the situation when the current price extremum is "less extreme" than the previous one > //--- (current peak is lower or current valley is less deep) > uint inp_map,check_map; > int i,j; > //--- loop by extremums (4 minimums and 4 maximums) > //--- price and the oscillator are checked separately (thus, there are 16 checks) > for(i=step*start,j=0;i { > //--- "take" two bits - patter of the corresponding extremum of the price > inp_map=(map>>j)&3; > //--- if the higher-order bit=1, then any ratio is suitable for us > if(inp_map<2) > { > //--- "take" two bits of the corresponding extremum of the price (higher-order bit is always 0) > check_map=(m_extr_map>>i)&3; > if(inp_map!=check_map) > return(false); > } > //--- "take" two bits - pattern of the corresponding oscillator extremum > inp_map=(map>>(j+2))&3; > //--- if the higher-order bit=1, then any ratio is suitable for us > if(inp_map>=2) > continue; > //--- "take" two bits of the corresponding oscillator extremum (higher-order bit is always 0) > check_map=(m_extr_map>>(i+2))&3; > if(inp_map!=check_map) > return(false); > } > //--- ok > return(true); 205,219c333,368 < //| Check conditions for short position open. | < //| INPUT: price - refernce for price, | < //| sl - refernce for stop loss, | < //| tp - refernce for take profit, | < //| expiration - refernce for expiration. | < //| OUTPUT: true-if condition performed, false otherwise. | < //| REMARK: no. | < //+------------------------------------------------------------------+ < bool CSignalMACD::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration) < { < price=0.0; < sl =m_symbol.Bid()+m_stop_loss*m_adjusted_point; < tp =m_symbol.Bid()-m_take_profit*m_adjusted_point; < //--- < return(ExtStateMACD(1)==-1); --- > //| "Voting" that price will grow. | > //+------------------------------------------------------------------+ > int CSignalMACD::LongCondition(void) > { > int result=0; > int idx =StartIndex(); > //--- check direction of the main line > if(DiffMain(idx)>0.0) > { > //--- the main line is directed upwards, and it confirms the possibility of price growth > if(IS_PATTERN_USAGE(0)) > result=m_pattern_0; // "confirming" signal number 0 (10) > //--- if the model 1 is used, look for a reverse of the main line > if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)<0.0) > result=m_pattern_1; // signal number 1 (30) > //--- if the model 2 is used, look for an intersection of the main and signal line > if(IS_PATTERN_USAGE(2) && State(idx)>0.0 && State(idx+1)<0.0) > result=m_pattern_2; // signal number 2 (80) > //--- if the model 3 is used, look for an intersection of the main line and the zero level > if(IS_PATTERN_USAGE(3) && Main(idx)>0.0 && Main(idx+1)<0.0) > result=m_pattern_3; // signal number 3 (50) > //--- if the models 4 or 5 are used and the main line turned upwards below the zero level, look for divergences > if((IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) && Main(idx)<0.0) > { > //--- perform the extended analysis of the oscillator state > ExtState(idx); > //--- if the model 4 is used, look for the "divergence" signal > if(IS_PATTERN_USAGE(4) && CompareMaps(1,1)) // 0000 0001b > result=m_pattern_4; // signal number 4 (60) > //--- if the model 5 is used, look for the "double divergence" signal > if(IS_PATTERN_USAGE(5) && CompareMaps(0x11,2)) // 0001 0001b > return(m_pattern_5); // signal number 5 (100) > } > } > //--- return the result > return(result); 222,225c371 < //| Check conditions for short position close. | < //| INPUT: price - refernce for price. | < //| OUTPUT: true-if condition performed, false otherwise. | < //| REMARK: no. | --- > //| "Voting" that price will fall. | 227c373 < bool CSignalMACD::CheckCloseShort(double& price) --- > int CSignalMACD::ShortCondition(void) 229,231c375,406 < price=0.0; < //--- < return(ExtStateMACD(1)==1); --- > int result=0; > int idx =StartIndex(); > //--- check direction of the main line > if(DiffMain(idx)<0.0) > { > //--- main line is directed downwards, confirming a possibility of falling of price > if(IS_PATTERN_USAGE(0)) > result=m_pattern_0; // "confirming" signal number 0 > //--- if the model 1 is used, look for a reverse of the main line > if(IS_PATTERN_USAGE(1) && DiffMain(idx+1)>0.0) > result=m_pattern_1; // signal number 1 > //--- if the model 2 is used, look for an intersection of the main and signal line > if(IS_PATTERN_USAGE(2) && State(idx)<0.0 && State(idx+1)>0.0) > result=m_pattern_2; // signal number 2 > //--- if the model 3 is used, look for an intersection of the main line and the zero level > if(IS_PATTERN_USAGE(3) && Main(idx)<0.0 && Main(idx+1)>0.0) > result=m_pattern_3; // signal number 3 > //--- if the models 4 or 5 are used and the main line turned downwards above the zero level, look for divergences > if((IS_PATTERN_USAGE(4) || IS_PATTERN_USAGE(5)) && Main(idx)>0.0) > { > //--- perform the extended analysis of the oscillator state > ExtState(idx); > //--- if the model 4 is used, look for the "divergence" signal > if(IS_PATTERN_USAGE(4) && CompareMaps(1,1)) // 0000 0001b > result=m_pattern_4; // signal number 4 > //--- if the model 5 is used, look for the "double divergence" signal > if(IS_PATTERN_USAGE(5) && CompareMaps(0x11,2)) // 0001 0001b > return(m_pattern_5); // signal number 5 > } > } > //--- return the result > return(result);