//+------------------------------------------------------------------+ //| MACD Sample.mq5 | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2009-2013, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "5.20" #property description "It is important to make sure that the expert works with a normal" #property description "chart and the user did not make any mistakes setting input" #property description "variables (Lots, TakeProfit, TrailingStop) in our case," #property description "we check TakeProfit on a chart of more than 2*trend_period bars" //--- #include #include #include #include //--- input double InpLots =0.1; // Lots input int InpTakeProfit =50; // Take Profit (in pips) input int InpTrailingStop =30; // Trailing Stop Level (in pips) input int InpMACDOpenLevel =3; // MACD open level (in pips) input int InpMACDCloseLevel=2; // MACD close level (in pips) input int InpMATrendPeriod =26; // MA trend period //--- int ExtTimeOut=10; // time out in seconds between trade operations //+------------------------------------------------------------------+ //| MACD Sample expert class | //+------------------------------------------------------------------+ class CSampleExpert { protected: double m_adjusted_point; // point value adjusted for 3 or 5 points CTrade m_trade; // trading object CSymbolInfo m_symbol; // symbol info object CPositionInfo m_position; // trade position object CAccountInfo m_account; // account info wrapper //--- indicators int m_handle_macd; // MACD indicator handle int m_handle_ema; // moving average indicator handle //--- indicator buffers double m_buff_MACD_main[]; // MACD indicator main buffer double m_buff_MACD_signal[]; // MACD indicator signal buffer double m_buff_EMA[]; // EMA indicator buffer //--- indicator data for processing double m_macd_current; double m_macd_previous; double m_signal_current; double m_signal_previous; double m_ema_current; double m_ema_previous; //--- double m_macd_open_level; double m_macd_close_level; double m_traling_stop; double m_take_profit; public: CSampleExpert(void); ~CSampleExpert(void); bool Init(void); void Deinit(void); bool Processing(void); protected: bool InitCheckParameters(const int digits_adjust); bool InitIndicators(void); bool LongClosed(void); bool ShortClosed(void); bool LongModified(void); bool ShortModified(void); bool LongOpened(void); bool ShortOpened(void); }; //--- global expert CSampleExpert ExtExpert; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSampleExpert::CSampleExpert(void) : m_adjusted_point(0), m_handle_macd(INVALID_HANDLE), m_handle_ema(INVALID_HANDLE), m_macd_current(0), m_macd_previous(0), m_signal_current(0), m_signal_previous(0), m_ema_current(0), m_ema_previous(0), m_macd_open_level(0), m_macd_close_level(0), m_traling_stop(0), m_take_profit(0) { ArraySetAsSeries(m_buff_MACD_main,true); ArraySetAsSeries(m_buff_MACD_signal,true); ArraySetAsSeries(m_buff_EMA,true); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSampleExpert::~CSampleExpert(void) { } //+------------------------------------------------------------------+ //| Initialization and checking for input parameters | //+------------------------------------------------------------------+ bool CSampleExpert::Init(void) { //--- initialize common information m_symbol.Name(Symbol()); // symbol m_trade.SetExpertMagicNumber(12345); // magic //--- tuning for 3 or 5 digits int digits_adjust=1; if(m_symbol.Digits()==3 || m_symbol.Digits()==5) digits_adjust=10; m_adjusted_point=m_symbol.Point()*digits_adjust; //--- set default deviation for trading in adjusted points m_macd_open_level =InpMACDOpenLevel*m_adjusted_point; m_macd_close_level=InpMACDCloseLevel*m_adjusted_point; m_traling_stop =InpTrailingStop*m_adjusted_point; m_take_profit =InpTakeProfit*m_adjusted_point; //--- set default deviation for trading in adjusted points m_trade.SetDeviationInPoints(3*digits_adjust); //--- if(!InitCheckParameters(digits_adjust)) return(false); if(!InitIndicators()) return(false); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Checking for input parameters | //+------------------------------------------------------------------+ bool CSampleExpert::InitCheckParameters(const int digits_adjust) { //--- initial data checks if(InpTakeProfit*digits_adjustm_symbol.LotsMax()) { printf("Lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); return(false); } if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10) { printf("Lots amount is not corresponding with lot step %f",m_symbol.LotsStep()); return(false); } //--- warning if(InpTakeProfit<=InpTrailingStop) printf("Warning: Trailing Stop must be less than Take Profit"); //--- succeed return(true); } //+------------------------------------------------------------------+ //| Initialization of the indicators | //+------------------------------------------------------------------+ bool CSampleExpert::InitIndicators(void) { //--- create MACD indicator if(m_handle_macd==INVALID_HANDLE) if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE) { printf("Error creating MACD indicator"); return(false); } //--- create EMA indicator and add it to collection if(m_handle_ema==INVALID_HANDLE) if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE) { printf("Error creating EMA indicator"); return(false); } //--- succeed return(true); } //+------------------------------------------------------------------+ //| Check for long position closing | //+------------------------------------------------------------------+ bool CSampleExpert::LongClosed(void) { bool res=false; //--- should it be closed? if(m_macd_current>0) if(m_macd_currentm_signal_previous) if(m_macd_current>m_macd_close_level) { //--- close position if(m_trade.PositionClose(Symbol())) printf("Long position by %s to be closed",Symbol()); else printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment()); //--- processed and cannot be modified res=true; } //--- result return(res); } //+------------------------------------------------------------------+ //| Check for short position closing | //+------------------------------------------------------------------+ bool CSampleExpert::ShortClosed(void) { bool res=false; //--- should it be closed? if(m_macd_current<0) if(m_macd_current>m_signal_current && m_macd_previousm_macd_close_level) { //--- close position if(m_trade.PositionClose(Symbol())) printf("Short position by %s to be closed",Symbol()); else printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment()); //--- processed and cannot be modified res=true; } //--- result return(res); } //+------------------------------------------------------------------+ //| Check for long position modifying | //+------------------------------------------------------------------+ bool CSampleExpert::LongModified(void) { bool res=false; //--- check for trailing stop if(InpTrailingStop>0) { if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop) { double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits()); double tp=m_position.TakeProfit(); if(m_position.StopLoss()0) { if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop)) { double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits()); double tp=m_position.TakeProfit(); if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0) { //--- modify position if(m_trade.PositionModify(Symbol(),sl,tp)) printf("Short position by %s to be modified",Symbol()); else { printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Modify parameters : SL=%f,TP=%f",sl,tp); } //--- modified and must exit from expert res=true; } } } //--- result return(res); } //+------------------------------------------------------------------+ //| Check for long position opening | //+------------------------------------------------------------------+ bool CSampleExpert::LongOpened(void) { bool res=false; //--- check for long position (BUY) possibility if(m_macd_current<0) if(m_macd_current>m_signal_current && m_macd_previous(m_macd_open_level) && m_ema_current>m_ema_previous) { double price=m_symbol.Ask(); double tp =m_symbol.Bid()+m_take_profit; //--- check for free money if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_BUY,InpLots,price)<0.0) printf("We have no money. Free Margin = %f",m_account.FreeMargin()); else { //--- open position if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,InpLots,price,0.0,tp)) printf("Position by %s to be opened",Symbol()); else { printf("Error opening BUY position by %s : '%s'",Symbol(),m_trade.ResultComment()); printf("Open parameters : price=%f,TP=%f",price,tp); } } //--- in any case we must exit from expert res=true; } //--- result return(res); } //+------------------------------------------------------------------+ //| Check for short position opening | //+------------------------------------------------------------------+ bool CSampleExpert::ShortOpened(void) { bool res=false; //--- check for short position (SELL) possibility if(m_macd_current>0) if(m_macd_currentm_signal_previous) if(m_macd_current>(m_macd_open_level) && m_ema_current=limit_time) { //--- check for data if(Bars(Symbol(),Period())>2*InpMATrendPeriod) { //--- change limit time by timeout in seconds if processed if(ExtExpert.Processing()) limit_time=TimeCurrent()+ExtTimeOut; } } } //+------------------------------------------------------------------+