Momentum-M15

Author: Copyright © 2011, Serg Deev
Price Data Components
Series array that contains open prices of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each barSeries array that contains close prices for each barSeries array that contains close prices for each bar
Indicators Used
Moving average indicatorMomentum indicator
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Momentum-M15
ÿþ//+------------------------------------------------------------------+

//|                        Momentum-M15(barabashkakvn's edition).mq5 |

//|                                      Copyright © 2011, Serg Deev |

//|                                            http://www.work2it.ru |

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

#property copyright "Copyright © 2011, Serg Deev"

#property link      "http://www.work2it.ru"

#property version   "1.000"

//---

#include <Trade\PositionInfo.mqh>

#include <Trade\Trade.mqh>

#include <Trade\SymbolInfo.mqh>  

CPositionInfo  m_position;                   // trade position object

CTrade         m_trade;                      // trading object

CSymbolInfo    m_symbol;                     // symbol info object

//--- input parameters

input double   InpLots                 = 0.1;         // Lots

input ushort   InpTrailingStop         = 0;           // Trailing Stop (in pips)

input int      InpMA_ma_period         = 26;          // MA: averaging period

input int      InpMA_ma_shift          = 8;           // MA: horizontal shift

input ENUM_MA_METHOD InpMA_ma_method   = MODE_SMMA;   // MA: smoothing type 

input ENUM_APPLIED_PRICE InpMA_ma_price= PRICE_LOW;   // MA: type of price

input double   MO_Min                  = 100.0;

input double   MO_Shift                = -0.2;

input int      InpMO_mom_period=23;          // Momentum: averaging period

input ENUM_APPLIED_PRICE InpMO_applied_price=PRICE_OPEN;  // Momentum: type of price

input int      MO_OpenTime             = 6;

input int      MO_CloseTime            = 10;

input ulong    m_magic=15489;                // magic number

//---

ulong          m_slippage=10;                // slippage



double         ExtTrailingStop=0.0;



int            handle_iMA;                   // variable for storing the handle of the iMA indicator 

int            handle_iMomentum;             // variable for storing the handle of the iMomentum indicator 



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



int            GAP_Level=30;

int            GAP_TimeOUT=100;

int            GAP_Timer=0;

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

//| Expert initialization function                                   |

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

int OnInit()

  {

//---

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

      return(INIT_FAILED);

   RefreshRates();



   string err_text="";

   if(!CheckVolumeValue(InpLots,err_text))

     {

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

      return(INIT_PARAMETERS_INCORRECT);

     }

//---

   m_trade.SetExpertMagicNumber(m_magic);

//---

   if(IsFillingTypeAllowed(SYMBOL_FILLING_FOK))

      m_trade.SetTypeFilling(ORDER_FILLING_FOK);

   else if(IsFillingTypeAllowed(SYMBOL_FILLING_IOC))

      m_trade.SetTypeFilling(ORDER_FILLING_IOC);

   else

      m_trade.SetTypeFilling(ORDER_FILLING_RETURN);

//---

   m_trade.SetDeviationInPoints(m_slippage);

//--- 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;



   ExtTrailingStop=InpTrailingStop*m_adjusted_point;

//--- create handle of the indicator iMA

   handle_iMA=iMA(m_symbol.Name(),Period(),InpMA_ma_period,InpMA_ma_shift,InpMA_ma_method,InpMA_ma_price);

//--- if the handle is not created 

   if(handle_iMA==INVALID_HANDLE)

     {

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

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

                  m_symbol.Name(),

                  EnumToString(Period()),

                  GetLastError());

      //--- the indicator is stopped early 

      return(INIT_FAILED);

     }

//--- create handle of the indicator iMomentum

   handle_iMomentum=iMomentum(m_symbol.Name(),Period(),InpMO_mom_period,InpMO_applied_price);

//--- if the handle is not created 

   if(handle_iMomentum==INVALID_HANDLE)

     {

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

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

                  m_symbol.Name(),

                  EnumToString(Period()),

                  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(0);

   if(time_0==PrevBars)

      return;

   PrevBars=time_0;

//---

   if(Bars(m_symbol.Name(),Period())<100 || !IsTradeAllowed())

      return;

   if(!RefreshRates())

     {

      PrevBars=iTime(1);

      return;

     }

//---

   if(!IsPositions())

      CheckForOpen();

   else

      CheckForClose();

//---



  }

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

//| 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 order volume                        |

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

bool CheckVolumeValue(double volume,string &error_description)

  {

//--- minimal allowed volume for trade operations

   double min_volume=m_symbol.LotsMin();

   if(volume<min_volume)

     {

      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)

     {

      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)

     {

      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);

  }

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

//| Checks if the specified filling mode is allowed                  | 

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

bool IsFillingTypeAllowed(int fill_type)

  {

//--- Obtain the value of the property that describes allowed filling modes 

   int filling=m_symbol.TradeFillFlags();

//--- Return true, if mode fill_type is allowed 

   return((filling & fill_type)==fill_type);

  }

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

//| Gets the information about permission to trade                   |

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

bool IsTradeAllowed()

  {

   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))

     {

      Alert("Check if automated trading is allowed in the terminal settings!");

      return(false);

     }

   else

     {

      if(!MQLInfoInteger(MQL_TRADE_ALLOWED))

        {

         Alert("Automated trading is forbidden in the program settings for ",__FILE__);

         return(false);

        }

     }

   if(!AccountInfoInteger(ACCOUNT_TRADE_EXPERT))

     {

      Alert("Automated trading is forbidden for the account ",AccountInfoInteger(ACCOUNT_LOGIN),

            " at the trade server side");

      return(false);

     }

   if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))

     {

      Comment("Trading is forbidden for the account ",AccountInfoInteger(ACCOUNT_LOGIN),

              ".\n Perhaps an investor password has been used to connect to the trading account.",

              "\n Check the terminal journal for the following entry:",

              "\n\'",AccountInfoInteger(ACCOUNT_LOGIN),"\': trading has been disabled - investor mode.");

      return(false);

     }

//---

   return(true);

  }

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

//| Get Open for specified bar index                                 | 

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

double iOpen(const int index,string symbol=NULL,ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT)

  {

   if(symbol==NULL)

      symbol=m_symbol.Name();

   if(timeframe==0)

      timeframe=Period();

   double Open[1];

   double open=0;

   int copied=CopyOpen(symbol,timeframe,index,1,Open);

   if(copied>0)

      open=Open[0];

   return(open);

  }

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

//| Get the High for specified bar index                             | 

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

double iHigh(const int index,string symbol=NULL,ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT)

  {

   if(symbol==NULL)

      symbol=m_symbol.Name();

   if(timeframe==0)

      timeframe=Period();

   double High[1];

   double high=0;

   int copied=CopyHigh(symbol,timeframe,index,1,High);

   if(copied>0)

      high=High[0];

   return(high);

  }

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

//| Get Low for specified bar index                                  | 

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

double iLow(const int index,string symbol=NULL,ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT)

  {

   if(symbol==NULL)

      symbol=m_symbol.Name();

   if(timeframe==0)

      timeframe=Period();

   double Low[1];

   double low=0;

   int copied=CopyLow(symbol,timeframe,index,1,Low);

   if(copied>0)

      low=Low[0];

   return(low);

  }

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

//| Get Close for specified bar index                                | 

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

double iClose(const int index,string symbol=NULL,ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT)

  {

   if(symbol==NULL)

      symbol=m_symbol.Name();

   if(timeframe==0)

      timeframe=Period();

   double Close[1];

   double close=0;

   int copied=CopyClose(symbol,timeframe,index,1,Close);

   if(copied>0)

      close=Close[0];

   return(close);

  }

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

//| Get Time for specified bar index                                 | 

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

datetime iTime(const int index,string symbol=NULL,ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT)

  {

   if(symbol==NULL)

      symbol=m_symbol.Name();

   if(timeframe==0)

      timeframe=Period();

   datetime Time[1];

   datetime time=0; // datetime "0" -> D'1970.01.01 00:00:00'

   int copied=CopyTime(symbol,timeframe,index,1,Time);

   if(copied>0)

      time=Time[0];

   return(time);

  }

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

//| Function looks for positions                                     |

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

bool IsPositions()

  {

   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)

            return(true);

//---

   return(false);

  }

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

//| Check for open                                                   |

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

void CheckForOpen()

  {

   int gap=(int)((iOpen(0)-iClose(1))/m_symbol.Point());

   if(gap>GAP_Level)

      GAP_Timer=GAP_TimeOUT;

   if(GAP_Timer>0)

     {

      GAP_Timer--;

      if(GAP_Timer>0)

         return;

     }



   double ma=iMAGet(0);

   double mo=iMomentumGet(0);

   if(ma==0.0 || mo==0.0)

      return;



   if(mo<(MO_Min+MO_Shift))

     {

      if((iClose(1)<ma) && (iOpen(0)<ma))

        {

         if(CheckMO_Down(MO_OpenTime))

           {

            OpenBuy();

            return;

           }

        }

     }

   if(mo>(MO_Min-MO_Shift))

     {

      if((iClose(1)>ma) && (iOpen(0)>ma))

        {

         if(CheckMO_Up(MO_OpenTime))

           {

            OpenSell();

            return;

           }

        }

     }

  }

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

//| Check for close                                                  |

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

void CheckForClose()

  {

   double ma=iMAGet(0);

   if(ma==0.0)

      return;



   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of open positions

      if(m_position.SelectByIndex(i))

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

           {

            if(m_position.PositionType()==POSITION_TYPE_BUY)

              {

               if((CheckMO_Down(MO_CloseTime)) || (iClose(1)<ma))

                 {

                  m_trade.PositionClose(m_position.Ticket());

                  continue;

                 }

               else if(InpTrailingStop>0)

                 {

                  if(m_position.StopLoss()==0.0)

                    {

                     if(!m_trade.PositionModify(m_position.Ticket(),

                        m_symbol.NormalizePrice(iLow(0)-ExtTrailingStop),

                        m_position.TakeProfit()))

                        Print("Modify ",m_position.Ticket(),

                              " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

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

                    }

                  else

                    {

                     double SL=iLow(0)-ExtTrailingStop;

                     if(m_position.StopLoss()<SL && !CompareDoubles(m_position.StopLoss(),SL,m_symbol.Digits()))

                        if(!m_trade.PositionModify(m_position.Ticket(),

                           m_symbol.NormalizePrice(SL),

                           m_position.TakeProfit()))

                           Print("Modify ",m_position.Ticket(),

                                 " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

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

                    }

                 }

              }

            else

              {

               if((CheckMO_Up(MO_CloseTime) || (iClose(1)>ma)))

                 {

                  m_trade.PositionClose(m_position.Ticket());

                  continue;

                 }

               else if(InpTrailingStop>0)

                 {

                  if(m_position.StopLoss()==0.0)

                    {

                     if(!m_trade.PositionModify(m_position.Ticket(),

                        m_symbol.NormalizePrice(iHigh(0)-ExtTrailingStop),

                        m_position.TakeProfit()))

                        Print("Modify ",m_position.Ticket(),

                              " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

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

                    }

                  else

                    {

                     double SL=iHigh(0)+ExtTrailingStop;

                     if(m_position.StopLoss()>SL && !CompareDoubles(m_position.StopLoss(),SL,m_symbol.Digits()))

                        if(!m_trade.PositionModify(m_position.Ticket(),

                           m_symbol.NormalizePrice(SL),

                           m_position.TakeProfit()))

                           Print("Modify ",m_position.Ticket(),

                                 " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),

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

                    }

                 }

              }



           }

  }

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

//| Get value of buffers for the iMA                                 |

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

double iMAGet(const int index)

  {

   double MA[1];

//--- reset error code 

   ResetLastError();

//--- fill a part of the iMABuffer array with values from the indicator buffer that has 0 index 

   if(CopyBuffer(handle_iMA,0,index,1,MA)<0)

     {

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

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

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

      return(0.0);

     }

   return(MA[0]);

  }

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

//| Get value of buffers for the iMomentum                           |

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

double iMomentumGet(const int index)

  {

   double Momentum[];

//--- reset error code 

   ResetLastError();

//--- fill a part of the Momentum array with values from the indicator buffer that has 0 index 

   if(CopyBuffer(handle_iMomentum,0,0,index+1,Momentum)<0)

     {

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

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

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

      return(0.0);

     }

   return(Momentum[index]);

  }

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

//| Get value of buffers for the iMomentum                           |

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

bool iMomentumGetArray(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);

   int buffer_num=0;             // indicator buffer number 

//--- reset error code 

   ResetLastError();

//--- fill a part of the buffer array with values from the indicator buffer that has 0 index 

   int copied=CopyBuffer(handle_iMomentum,buffer_num,start_pos,count,arr_buffer);

   if(copied<0)

     {

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

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

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

      return(false);

     }

   else if(copied<count)

     {

      PrintFormat("Momentum indicator: %d elements from %d were copied",copied,count);

      DebugBreak();

      return(false);

     }

//---

   return(result);

  }

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

//| Check Momentum Up                                                |

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

bool CheckMO_Up(const int t)

  {

   if(t<=0)

      return(false);

   double y=0.0;

   double arr_momentum[];

   ArraySetAsSeries(arr_momentum,true);

   int start_pos=0;

   if(!iMomentumGetArray(start_pos,t,arr_momentum))

      return(false);

   double x=arr_momentum[t-1];

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

     {

      y=arr_momentum[i];

      if(y<x)

         return(false);

      else

         x=y;

     }

   return(true);

  }

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

//| Check Momentum Down                                              |

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

bool CheckMO_Down(const int t)

  {

   if(t<=0)

      return(false);

   double y=0.0;

   double arr_momentum[];

   ArraySetAsSeries(arr_momentum,true);

   int start_pos=0;

   if(!iMomentumGetArray(start_pos,t,arr_momentum))

      return(false);

   double x=arr_momentum[t-1];

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

     {

      y=arr_momentum[i];

      if(y>x)

         return(false);

      else

         x=y;

     }

   return(true);

  }

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

//| Open Buy position                                                |

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

void OpenBuy()

  {

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

   double check_volume_lot=m_trade.CheckVolume(m_symbol.Name(),InpLots,m_symbol.Ask(),ORDER_TYPE_BUY);



   if(check_volume_lot!=0.0)

     {

      if(check_volume_lot>=InpLots)

        {

         if(m_trade.Buy(InpLots,m_symbol.Name(),m_symbol.Ask()))

           {

            if(m_trade.ResultDeal()==0)

              {

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

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

               PrintResult(m_trade,m_symbol);

              }

            else

              {

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

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

               PrintResult(m_trade,m_symbol);

              }

           }

         else

           {

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

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

            PrintResult(m_trade,m_symbol);

           }

        }

      else

        {

         Print(__FUNCTION__,", ERROR: method CheckVolume (",DoubleToString(check_volume_lot,2),") ",

               "< Lots (",DoubleToString(InpLots,2),")");

         return;

        }

     }

   else

     {

      Print(__FUNCTION__,", ERROR: method CheckVolume returned the value of \"0.0\"");

      return;

     }

//---

  }

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

//| Open Sell position                                               |

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

void OpenSell()

  {

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

   double check_volume_lot=m_trade.CheckVolume(m_symbol.Name(),InpLots,m_symbol.Bid(),ORDER_TYPE_SELL);



   if(check_volume_lot!=0.0)

     {

      if(check_volume_lot>=InpLots)

        {

         if(m_trade.Sell(InpLots,m_symbol.Name(),m_symbol.Bid()))

           {

            if(m_trade.ResultDeal()==0)

              {

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

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

               PrintResult(m_trade,m_symbol);

              }

            else

              {

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

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

               PrintResult(m_trade,m_symbol);

              }

           }

         else

           {

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

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

            PrintResult(m_trade,m_symbol);

           }

        }

      else

        {

         Print(__FUNCTION__,", ERROR: method CheckVolume (",DoubleToString(check_volume_lot,2),") ",

               "< Lots (",DoubleToString(InpLots,2),")");

         return;

        }

     }

   else

     {

      Print(__FUNCTION__,", ERROR: method CheckVolume returned the value of \"0.0\"");

      return;

     }

//---

  }

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

//| Compare doubles                                                  |

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

bool CompareDoubles(double number1,double number2,int digits)

  {

   if(NormalizeDouble(number1-number2,digits)==0)

      return(true);

   else

      return(false);

  }

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

//| Print CTrade result                                              |

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

void PrintResult(CTrade &trade,CSymbolInfo &symbol)

  {

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

   Print("code of request result: "+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(trade.ResultBid(),symbol.Digits()));

   Print("current ask price: "+DoubleToString(trade.ResultAsk(),symbol.Digits()));

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

   int d=0;

  }

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

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---