Three indicators

Author: Copyright © 2018, Vladimir Karputov
Price Data Components
Series array that contains tick volumes of each bar
Indicators Used
MACD HistogramStochastic oscillatorRelative strength index
Miscellaneous
It issuies visual alerts to the screen
10 Views
0 Downloads
0 Favorites
Three indicators
ÿþ//+------------------------------------------------------------------+

//|                                             Three indicators.mq5 |

//|                              Copyright © 2018, Vladimir Karputov |

//|                                           http://wmua.ru/slesar/ |

//+------------------------------------------------------------------+

#property copyright "Copyright © 2018, Vladimir Karputov"

#property link      "http://wmua.ru/slesar/"

#property version   "1.000"

//---

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>  

#include <Trade\AccountInfo.mqh>

CPositionInfo  m_position;                   // trade position object

CTrade         m_trade;                      // trading object

CSymbolInfo    m_symbol;                     // symbol info object

CAccountInfo   m_account;                    // account info wrapper

//--- input parameters

input ENUM_TIMEFRAMES      InpTimeframe               = PERIOD_M1;   // Work timeframe

input double               InpLots                    = 1.0;         // Lots

input int                  Inp_MACD_fast_ema_period   = 11;          // MACD: period for Fast average calculation 

input int                  Inp_MACD_slow_ema_period   = 53;          // MACD: period for Slow average calculation 

input int                  Inp_MACD_signal_period     = 26;          // MACD: period for their difference averaging 

input ENUM_APPLIED_PRICE   Inp_MACD_applied_price     = PRICE_CLOSE; // MACD: type of price

//---

input int                  Inp_STO_Kperiod            = 40;          // STO: K-period (number of bars for calculations) 

input int                  Inp_STO_Dperiod            = 23;          // STO: D-period (period of first smoothing) 

input int                  Inp_STO_slowing            = 82;          // STO: final smoothing 

input ENUM_MA_METHOD       Inp_STO_ma_method          = MODE_SMA;    // STO: type of smoothing 

input ENUM_STO_PRICE       Inp_STO_price_field        = STO_LOWHIGH; // STO: stochastic calculation method 

//---

input int                  Inp_RSI_ma_period          = 86;          // RSI: averaging period 

input ENUM_APPLIED_PRICE   Inp_RSI_applied_price      = PRICE_CLOSE; // RSI: type of price

//---

input ulong                m_magic=310370640;                        // magic number

//---

ulong  m_slippage=10;         // slippage

int    handle_iMACD;          // variable for storing the handle of the iMACD indicator 

int    handle_iStochastic;    // variable for storing the handle of the iStochastic indicator 

int    handle_iRSI;           // variable for storing the handle of the iRSI indicator

double m_adjusted_point;      // point value adjusted for 3 or 5 points

//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

  {

//---

   if(!m_symbol.Name(Symbol())) // sets symbol name

      return(INIT_FAILED);

   RefreshRates();

//--- check the input parameter "Lots"

   string err_text="";

   if(!CheckVolumeValue(InpLots,err_text))

     {

      //--- when testing, we will only output to the log about incorrect input parameters

      if(MQLInfoInteger(MQL_TESTER))

        {

         Print(__FUNCTION__,", ERROR: ",err_text);

         return(INIT_FAILED);

        }

      else // if the Expert Advisor is run on the chart, tell the user about the error

        {

         Alert(__FUNCTION__,", ERROR: ",err_text);

         return(INIT_PARAMETERS_INCORRECT);

        }

     }

//---

   m_trade.SetExpertMagicNumber(m_magic);

   m_trade.SetMarginMode();

   m_trade.SetTypeFillingBySymbol(m_symbol.Name());

   m_trade.SetDeviationInPoints(m_slippage);

//--- create handle of the indicator iMACD

   handle_iMACD=iMACD(m_symbol.Name(),InpTimeframe,Inp_MACD_fast_ema_period,Inp_MACD_slow_ema_period

                      ,Inp_MACD_signal_period,Inp_MACD_applied_price);

//--- if the handle is not created 

   if(handle_iMACD==INVALID_HANDLE)

     {

      //--- tell about the failure and output the error code 

      PrintFormat("Failed to create handle of the iMACD indicator for the symbol %s/%s, error code %d",

                  m_symbol.Name(),

                  EnumToString(InpTimeframe),

                  GetLastError());

      //--- the indicator is stopped early 

      return(INIT_FAILED);

     }

//--- create handle of the indicator iStochastic

   handle_iStochastic=iStochastic(m_symbol.Name(),InpTimeframe,Inp_STO_Kperiod,Inp_STO_Dperiod,

                                  Inp_STO_slowing,Inp_STO_ma_method,Inp_STO_price_field);

//--- if the handle is not created 

   if(handle_iStochastic==INVALID_HANDLE)

     {

      //--- tell about the failure and output the error code 

      PrintFormat("Failed to create handle of the iStochastic indicator for the symbol %s/%s, error code %d",

                  m_symbol.Name(),

                  EnumToString(InpTimeframe),

                  GetLastError());

      //--- the indicator is stopped early 

      return(INIT_FAILED);

     }

//--- create handle of the indicator iRSI

   handle_iRSI=iRSI(m_symbol.Name(),InpTimeframe,Inp_RSI_ma_period,Inp_RSI_applied_price);

//--- if the handle is not created 

   if(handle_iRSI==INVALID_HANDLE)

     {

      //--- tell about the failure and output the error code 

      PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d",

                  m_symbol.Name(),

                  EnumToString(InpTimeframe),

                  GetLastError());

      //--- the indicator is stopped early 

      return(INIT_FAILED);

     }

//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

//---



  }

//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

  {

//--- we work only at the time of the birth of new bar

   static datetime PrevBars=0;

   datetime time_0=iTime(m_symbol.Name(),InpTimeframe,0);

   if(time_0==PrevBars)

      return;

   PrevBars=time_0;

   if(!RefreshRates())

     {

      PrevBars=0;

      return;

     }

//---

   int candle=f_candle();

   int macd=f_MACD();

   int sto=f_Stochastic();

   int rsi=f_RSI();

//---

   bool buy = f_long_signal(candle,macd,sto,rsi);

   bool sell= f_short_signal(candle,macd,sto,rsi);

//---

   for(int i=PositionsTotal()-1;i>=0;i--)

      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties

         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               if(sell)

                 {

                  m_trade.PositionClose(m_position.Ticket());

                  Sleep(30000);

                  OpenSell(InpLots,0.0,0.0);

                 }

              }



            if(m_position.PositionType()==POSITION_TYPE_SELL)

              {

               if(buy)

                 {

                  m_trade.PositionClose(m_position.Ticket());

                  Sleep(30000);

                  OpenBuy(InpLots,0.0,0.0);

                 }

              }

            return;

           }

//---

   if(buy)

      OpenBuy(InpLots,0.0,0.0);

   if(sell)

      OpenSell(InpLots,0.0,0.0);

  }

//+------------------------------------------------------------------+

//| TradeTransaction function                                        |

//+------------------------------------------------------------------+

void OnTradeTransaction(const MqlTradeTransaction &trans,

                        const MqlTradeRequest &request,

                        const MqlTradeResult &result)

  {

//---



  }

//+------------------------------------------------------------------+

//| Refreshes the symbol quotes data                                 |

//+------------------------------------------------------------------+

bool RefreshRates(void)

  {

//--- refresh rates

   if(!m_symbol.RefreshRates())

     {

      Print("RefreshRates error");

      return(false);

     }

//--- protection against the return value of "zero"

   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)

      return(false);

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Check the correctness of the position volume                     |

//+------------------------------------------------------------------+

bool CheckVolumeValue(double volume,string &error_description)

  {

//--- minimal allowed volume for trade operations

   double min_volume=m_symbol.LotsMin();

   if(volume<min_volume)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< <5=LH5 <8=8<0;L=> 4>?CAB8<>3> SYMBOL_VOLUME_MIN=%.2f",min_volume);

      else

         error_description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);

      return(false);

     }

//--- maximal allowed volume of trade operations

   double max_volume=m_symbol.LotsMax();

   if(volume>max_volume)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< 1>;LH5 <0:A8<0;L=> 4>?CAB8<>3> SYMBOL_VOLUME_MAX=%.2f",max_volume);

      else

         error_description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);

      return(false);

     }

//--- get minimal step of volume changing

   double volume_step=m_symbol.LotsStep();

   int ratio=(int)MathRound(volume/volume_step);

   if(MathAbs(ratio*volume_step-volume)>0.0000001)

     {

      if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian")

         error_description=StringFormat("1J5< =5 :@0B5= <8=8<0;L=><C H03C SYMBOL_VOLUME_STEP=%.2f, 1;8609H89 ?@028;L=K9 >1J5< %.2f",

                                        volume_step,ratio*volume_step);

      else

         error_description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",

                                        volume_step,ratio*volume_step);

      return(false);

     }

   error_description="Correct volume value";

   return(true);

  }

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

int f_candle()

  {

   int result=0;

   double open_array[];

   ArraySetAsSeries(open_array,true);

   if(CopyOpen(m_symbol.Name(),InpTimeframe,0,2,open_array)!=2)

      return(result);

   if(open_array[0]>open_array[1])

      result=1;

   else if(open_array[0]<open_array[1])

      result=-1;

//---

   return(result);

  }

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

int f_MACD()

  {

   int result=0;

   double main_array[];

   ArraySetAsSeries(main_array,true);

   if(!iGetArray(handle_iMACD,MAIN_LINE,0,2,main_array))

      return(result);

   if((main_array[0]-main_array[1])<0)

      result=1;

   else if((main_array[0]-main_array[1])>0)

      result=-1;

//---

   return(result);

  }

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

int f_Stochastic()

  {

   int result=0;

   double sto_array[];

   ArraySetAsSeries(sto_array,true);

   if(!iGetArray(handle_iStochastic,SIGNAL_LINE,0,2,sto_array))

      return(result);

   if(sto_array[0]-50.0<0)

      result=1;

   else if(sto_array[0]-50.0>0)

      result=-1;

//---

   return(result);

  }

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

int f_RSI()

  {

   int result=0;

   double rsi_array[];

   ArraySetAsSeries(rsi_array,true);

   if(!iGetArray(handle_iRSI,0,0,2,rsi_array))

      return(result);

   if(rsi_array[0]-50.0<0)

      result=1;

   else if(rsi_array[0]-50.0>0)

      result=-1;

//---

   return(result);

  }

//+------------------------------------------------------------------+

//| Get value of buffers                                             |

//+------------------------------------------------------------------+

double iGetArray(const int handle,const int buffer,const int start_pos,const int count,double &arr_buffer[])

  {

   bool result=true;

   if(!ArrayIsDynamic(arr_buffer))

     {

      Print("This a no dynamic array!");

      return(false);

     }

   ArrayFree(arr_buffer);

//--- reset error code 

   ResetLastError();

//--- fill a part of the iBands array with values from the indicator buffer

   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);

   if(copied!=count)

     {

      //--- if the copying fails, tell the error code 

      PrintFormat("Failed to copy data from the indicator, error code %d",GetLastError());

      //--- quit with zero result - it means that the indicator is considered as not calculated 

      return(false);

     }

   return(result);

  }

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

bool f_long_signal(const int candle,const int macd,const int sto,const int rsi)

  {

   if(candle<0)

      return(false);

   if(macd<0)

      return(false);

   if(sto<0)

      return(false);

   if(rsi<0)

      return(false);

//---

   return(true);

  }

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

bool f_short_signal(const int candle,const int macd,const int sto,const int rsi)

  {

   if(candle>0)

      return(false);

   if(macd>0)

      return(false);

   if(sto>0)

      return(false);

   if(rsi>0)

      return(false);

//---

   return(true);

  }

//+------------------------------------------------------------------+

//| Open Buy position                                                |

//+------------------------------------------------------------------+

void OpenBuy(double long_lot,double sl,double tp)

  {

   sl=m_symbol.NormalizePrice(sl);

   tp=m_symbol.NormalizePrice(tp);

//--- check volume before OrderSend to avoid "not enough money" error (CTrade)

   double free_margin_check=m_account.FreeMarginCheck(m_symbol.Name(),ORDER_TYPE_BUY,long_lot,m_symbol.Ask());

   if(free_margin_check>0.0)

     {

      if(m_trade.Buy(long_lot,m_symbol.Name(),m_symbol.Ask(),sl,tp))

        {

         if(m_trade.ResultDeal()==0)

           {

            Print("#1 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),

                  ", description of result: ",m_trade.ResultRetcodeDescription());

            PrintResultTrade(m_trade,m_symbol);

           }

         else

           {

            Print("#2 Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),

                  ", description of result: ",m_trade.ResultRetcodeDescription());

            PrintResultTrade(m_trade,m_symbol);

           }

        }

      else

        {

         Print("#3 Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),

               ", description of result: ",m_trade.ResultRetcodeDescription());

         PrintResultTrade(m_trade,m_symbol);

        }

     }

   else

     {

      Print(__FUNCTION__,", ERROR: method CAccountInfo::FreeMarginCheck returned the value ",DoubleToString(free_margin_check,2));

      return;

     }

//---

  }

//+------------------------------------------------------------------+

//| Open Sell position                                               |

//+------------------------------------------------------------------+

void OpenSell(double short_lot,double sl,double tp)

  {

   sl=m_symbol.NormalizePrice(sl);

   tp=m_symbol.NormalizePrice(tp);

//--- check volume before OrderSend to avoid "not enough money" error (CTrade)

   double free_margin_check=m_account.FreeMarginCheck(m_symbol.Name(),ORDER_TYPE_SELL,short_lot,m_symbol.Bid());

   if(free_margin_check>0.0)

     {

      if(m_trade.Sell(short_lot,NULL,m_symbol.Bid(),sl,tp))

        {

         if(m_trade.ResultDeal()==0)

           {

            Print("#1 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),

                  ", description of result: ",m_trade.ResultRetcodeDescription());

            PrintResultTrade(m_trade,m_symbol);

           }

         else

           {

            Print("#2 Sell -> true. Result Retcode: ",m_trade.ResultRetcode(),

                  ", description of result: ",m_trade.ResultRetcodeDescription());

            PrintResultTrade(m_trade,m_symbol);

           }

        }

      else

        {

         Print("#3 Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),

               ", description of result: ",m_trade.ResultRetcodeDescription());

         PrintResultTrade(m_trade,m_symbol);

        }

     }

   else

     {

      Print(__FUNCTION__,", ERROR: method CAccountInfo::FreeMarginCheck returned the value ",DoubleToString(free_margin_check,2));

      return;

     }

//---

  }

//+------------------------------------------------------------------+

//| Print CTrade result                                              |

//+------------------------------------------------------------------+

void PrintResultTrade(CTrade &trade,CSymbolInfo &symbol)

  {

   Print("File: ",__FILE__,", symbol: ",m_symbol.Name());

   Print("Code of request result: "+IntegerToString(trade.ResultRetcode()));

   Print("code of request result as a string: "+trade.ResultRetcodeDescription());

   Print("Deal ticket: "+IntegerToString(trade.ResultDeal()));

   Print("Order ticket: "+IntegerToString(trade.ResultOrder()));

   Print("Volume of deal or order: "+DoubleToString(trade.ResultVolume(),2));

   Print("Price, confirmed by broker: "+DoubleToString(trade.ResultPrice(),symbol.Digits()));

   Print("Current bid price: "+DoubleToString(symbol.Bid(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultBid(),symbol.Digits()));

   Print("Current ask price: "+DoubleToString(symbol.Ask(),symbol.Digits())+" (the requote): "+DoubleToString(trade.ResultAsk(),symbol.Digits()));

   Print("Broker comment: "+trade.ResultComment());

  }

//+------------------------------------------------------------------+

Comments