Author: Copyright 2016, Kaleem Haider
tipu_renko

This script is designed to transform standard price charts into a "Renko" style visual, which focuses on price movement rather than the passage of time. Instead of traditional candlesticks that show every minor fluctuation, this logic identifies significant moves in price and represents them as consistent blocks or "bricks."

Core Logic and Functionality

Price Movement Detection The script continuously monitors the market to see if the price has moved a specific distance (defined by the user as a "Renko Size"). It operates based on two primary modes of calculation:

  • Close Price Mode: The script looks at whether the current price has moved far enough away from the previous brick's starting point to create a new move.
  • High/Low Mode: The script looks at the highest and lowest points reached during a period to determine if a new brick should be formed.

Visual Representation Once a significant price movement is detected, the script draws shapes on your chart to represent the trend:

  • Bricks: It creates rectangular boxes that show the direction of the trend. If the price moves up significantly, it draws an upward-colored box; if it moves down, it draws a downward-colored box.
  • Arrows: Depending on your settings, the script can also place visual markers (arrows) to highlight the exact moment a new trend or significant move begins.

Trend Tracking and Counting Beyond just drawing shapes, the logic performs internal "bookkeeping" to track the market's behavior:

  • It keeps track of the current trend direction (Up or Down).
  • It maintains a counter to see how many consecutive moves have occurred in the same direction.
  • It updates the "starting point" of each new brick based on the completion of the previous move, ensuring that every brick is of equal size regardless of how much time passed between those moves.

Alert System The script includes a notification system to keep you informed of trend changes in real-time. When a new "Buy" or "Sell" signal is triggered (meaning a price movement was large enough to form a new brick in the opposite direction), the script can:

  • Pop up an alert on your screen.
  • Send a notification to your mobile device.
  • Send an email notification.

Cleanup To ensure the chart remains organized, the script includes a cleanup routine that automatically removes the drawn bricks and marks when the indicator is removed from the chart, preventing "ghost" shapes from cluttering your view.

Miscellaneous
It issuies visual alerts to the screenIt sends emails
6 Views
0 Downloads
0 Favorites
tipu_renko
//+------------------------------------------------------------------+
//|                                                   Tipu Renko.mq4 |
//|                                    Copyright 2016, Kaleem Haider |
//|                      https://www.mql5.com/en/users/kaleem.haider |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Kaleem Haider"
#property link      "https://www.mql5.com/en/users/kaleem.haider"
#property version   "1.00"
#property strict
#property indicator_chart_window

#define PipsPoint Get_PipsPoint()
//Enumerations for Renko Mode
enum ENUM_RenkoMode
  {
   rClose = 0,       //Close
   rHighLow = 1,     //High/Low
  };
//Enumeration for type of marks
enum ENUM_RenkoMark
  {
   None=0,
   Brick=1,
   Arrows=2,
  };

input ENUM_RenkoMode eRenkoMode        =  0;              //Box Mode
input ENUM_RenkoMark eRenkoMark        =  1;              //Renko Mark
input int            iRenkoSize        =  20;             //Renko Size
input ENUM_LINE_STYLE eRenkoStyle      =  0;              //Line Style
input int            iRenkoWidth       =  1;              //Line Width
input color          cUpCandle         =  C'31,159,192';  //Up Color
input color          cDwnCandle        =  C'230,77,69';   //Down Color
input bool           bFill             =  true;           //Fill Candles
input bool           bAlertM           =  false;          //Alert Mobile
input bool           bAlertS           =  true;           //Alert Onscreen
input bool           bAlertE           =  false;          //Alert Email

string short_name="tp_Renko";
string indicator_name="Tipu Renko";
int iLastTrend;
double dLowR=0,dHighR=0,dOpenR=0,dCloseR=0;
datetime dtPrevTime=0;
static datetime prevTime;
double dBuyCounter=0.0,dSellCounter=0.0;

double dTrendBuffer[],dSignalBuffer[],dBuyCountBuffer[],dSellCountBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   int n=0;
//--- indicator buffers mapping
   IndicatorSetString(INDICATOR_SHORTNAME,indicator_name);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
   IndicatorBuffers(4);

//Holder for the signals, and trend
   SetIndexBuffer(n,dSignalBuffer,INDICATOR_CALCULATIONS); n++;
   SetIndexBuffer(n,dTrendBuffer,INDICATOR_CALCULATIONS);  n++;
   SetIndexBuffer(n,dBuyCountBuffer,INDICATOR_CALCULATIONS); n++;
   SetIndexBuffer(n,dSellCountBuffer,INDICATOR_CALCULATIONS); n++;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//Delete the Bricks
   DeleteBricks();
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int limit;
   string sMsg,sSubject;
   bool bBuy=false,bSell=false;

   ArraySetAsSeries(dTrendBuffer,true);
   ArraySetAsSeries(dSignalBuffer,true);
   ArraySetAsSeries(dBuyCountBuffer,true);
   ArraySetAsSeries(dSellCountBuffer,true);

   if(prev_calculated < 0)  return(0);

   if(prev_calculated>0) limit=rates_total-prev_calculated+1; //non-repainting should give -2 if prev_cal is 0, meaning two candles ahead
   else
     {
      limit=rates_total-1;
      dLowR  = low[limit];
      dOpenR = open[limit];
      dtPrevTime=time[limit];
     }

   for(int i=limit-1; i>=0; i--)
     {
      double dcheck=iRenkoSize*PipsPoint;
      switch(eRenkoMode)
        {
         case 0:
            bBuy=close[i]>=dOpenR+dcheck;
            bSell=close[i]<=dOpenR-dcheck;
            break;

         case 1:
            bBuy=high[i]>=dOpenR+dcheck;
            bSell=low[i]<=dOpenR-dcheck;
            break;
        }

      if(bBuy)
        {
         dCloseR=NormalizeDouble(dOpenR,_Digits)+dcheck;
         if(ObjectFind(0,short_name+(string)time[i])<0 && eRenkoMark==1)
            RectangleCreate(0,short_name+(string)time[i],0,dtPrevTime,dOpenR,time[i],dCloseR,cUpCandle,eRenkoStyle,iRenkoWidth,bFill,false,false,false,0);
         dOpenR=dCloseR;
         dtPrevTime=time[i];
         dSellCounter=0; dSellCountBuffer[i]=dSellCounter;
         if(dTrendBuffer[i+1]!=OP_BUY)
           {
            dSignalBuffer[i]=OP_BUY;
            dTrendBuffer[i]=dSignalBuffer[i];
            dBuyCounter=1;  dBuyCountBuffer[i]=dBuyCounter;
            if(ObjectFind(0,short_name+(string)time[i])<0 && eRenkoMark==2)
               ArrowCreate(0,short_name+(string)time[i],0,time[i],low[i],233,ANCHOR_TOP,cUpCandle,eRenkoStyle,iRenkoWidth,false,false,false);
           }
         else
           {dBuyCounter++;     dBuyCountBuffer[i]=dBuyCounter;}
        }
      if(bSell)
        {
         dCloseR=NormalizeDouble(dOpenR,_Digits)-dcheck;
         if(ObjectFind(0,short_name+(string)time[i])<0 && eRenkoMark==1)
            RectangleCreate(0,short_name+(string)time[i],0,dtPrevTime,dOpenR,time[i],dCloseR,cDwnCandle,eRenkoStyle,iRenkoWidth,bFill,false,false,false,0);
         dOpenR=dCloseR;
         dtPrevTime=time[i];
         dBuyCounter=0;  dBuyCountBuffer[i]=dBuyCounter;
         if(dTrendBuffer[i+1]!=OP_SELL)
           {
            dSignalBuffer[i]=OP_SELL;
            dTrendBuffer[i]=dSignalBuffer[i];
            dSellCounter=1; dSellCountBuffer[i]=dSellCounter;
            if(ObjectFind(0,short_name+(string)time[i])<0 && eRenkoMark==2)
               ArrowCreate(0,short_name+(string)time[i],0,time[i],high[i],234,ANCHOR_BOTTOM,cDwnCandle,eRenkoStyle,iRenkoWidth,false,false,false);
           }
         else
           {dSellCounter++;   dSellCountBuffer[i]=dSellCounter;}
        }

      if(dTrendBuffer[i]!=OP_BUY && dTrendBuffer[i]!=OP_SELL)
         dTrendBuffer[i]=dTrendBuffer[i+1];
      if(dBuyCountBuffer[i] == EMPTY_VALUE)
         dBuyCountBuffer[i] = dBuyCountBuffer[i+1];
      if(dSellCountBuffer[i] == EMPTY_VALUE)
         dSellCountBuffer[i] = dSellCountBuffer[i+1];
     }
//Alerts
   if(dSignalBuffer[0]==OP_BUY)
     {
      sMsg=indicator_name+" "+_Symbol+"\n "+"Buy Alert: "+
           "\n "+"Time: "+TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES);
      sSubject=indicator_name+" "+_Symbol+" "+"Buy Alert";
      SendAlert(bAlertM,bAlertS,bAlertE,sMsg,sSubject);
      dTrendBuffer[0]=OP_BUY;
     }
   if(dSignalBuffer[0]==OP_SELL)
     {
      sMsg=indicator_name+" "+_Symbol+"\n "+"Sell Alert: "
           +"\n "+"Time: "+TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES);
      sSubject=indicator_name+" "+_Symbol+" "+"Sell Alert";
      SendAlert(bAlertM,bAlertS,bAlertE,sMsg,sSubject);
      dTrendBuffer[0]=OP_SELL;
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

double Get_PipsPoint()
  {
   double PP=(_Digits==5 || _Digits==3)?_Point*10:_Point;
   return (PP);
  }
//+------------------------------------------------------------------------------+
//| The following code is taken from:                                            |
//| https://docs.mql4.com/constants/objectconstants/enum_object/obj_rectangle    |
//+------------------------------------------------------------------------------+
bool RectangleCreate(const long            chart_ID=0,        // chart's ID
                     const string          name="Rectangle",  // rectangle name
                     const int             sub_window=0,      // subwindow index 
                     datetime              time1=0,           // first point time
                     double                price1=0,          // first point price
                     datetime              time2=0,           // second point time
                     double                price2=0,          // second point price
                     const color           clr=clrRed,        // rectangle color
                     const ENUM_LINE_STYLE style=STYLE_SOLID, // style of rectangle lines
                     const int             width=1,           // width of rectangle lines
                     const bool            fill=false,        // filling rectangle with color
                     const bool            back=false,        // in the background
                     const bool            selection=true,    // highlight to move
                     const bool            hidden=true,       // hidden in the object list
                     const long            z_order=0,         // priority for mouse click
                     const string          tooltip="Rectangle",// tooltip
                     const int             timeframes=OBJ_ALL_PERIODS) //show on timeframes)
  {

   ResetLastError();
//--- create a rectangle by the given coordinates
   if(!ObjectCreate(chart_ID,name,OBJ_RECTANGLE,sub_window,time1,price1,time2,price2))
     {
      Print(__FUNCTION__,
            ": failed to create a rectangle! Name: "+name+" Error code = ",GetLastError());
      return(false);
     }

   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
   ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
   ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
   ObjectSetInteger(chart_ID,name,OBJPROP_FILL,fill);
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
   ObjectSetString(chart_ID,name,OBJPROP_TOOLTIP,tooltip);
   ObjectSetInteger(chart_ID,name,OBJPROP_TIMEFRAMES,timeframes);

//--- successful execution
   return(true);
  }
//+------------------------------------------------------------------------------+
//| The following code is taken from:                                            |
//| https://docs.mql4.com/constants/objectconstants/enum_object/obj_arrow        |
//+------------------------------------------------------------------------------+
bool ArrowCreate(const long              chart_ID=0,           // chart's ID
                 const string            name="Arrow",         // arrow name
                 const int               sub_window=0,         // subwindow index
                 datetime                time=0,               // anchor point time
                 double                  price=0,              // anchor point price
                 const uchar             arrow_code=252,       // arrow code
                 const ENUM_ARROW_ANCHOR anchor=ANCHOR_BOTTOM, // anchor point position
                 const color             clr=clrRed,           // arrow color
                 const ENUM_LINE_STYLE   style=STYLE_SOLID,    // border line style
                 const int               width=3,              // arrow size
                 const bool              back=false,           // in the background
                 const bool              selection=true,       // highlight to move
                 const bool              hidden=true,          // hidden in the object list
                 const long              z_order=0,            // priority for mouse click
                 const string            tooltip="Rectangle",// tooltip
                 const int                timeframes=OBJ_ALL_PERIODS) //show on timeframes)                 
  {

//--- reset the error value
   ResetLastError();
//--- create an arrow
   if(!ObjectCreate(chart_ID,name,OBJ_ARROW,sub_window,time,price))
     {
      Print(__FUNCTION__,
            ": failed to create an arrow! Error code = ",GetLastError());
      return(false);
     }
   ObjectSetInteger(chart_ID,name,OBJPROP_ARROWCODE,arrow_code);
   ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
   ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
   ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width);
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
   ObjectSetString(chart_ID,name,OBJPROP_TOOLTIP,tooltip);
   ObjectSetInteger(chart_ID,name,OBJPROP_TIMEFRAMES,timeframes);
//--- successful execution
   return(true);
  }
//+------------------------------------------------------------------+
//|Delete Bricks                                                     |
//+------------------------------------------------------------------+
void DeleteBricks()
  {
   for(int i=ObjectsTotal()-1; i>=0; i--)
     {
      string name=ObjectName(i);
      if(StringFind(name,short_name,0)>=0) ObjectDelete(0,name);
     }

   return;
  }
//+------------------------------------------------------------------+
//| Send Alerts                                                      |
//+------------------------------------------------------------------+
void SendAlert(bool bMobile,bool bScreen,bool bEmail,string sMsg,string sSub)
  {
   if(bMobile || bScreen || bEmail)
     {
      if(sMsg!="")
        {
         if(prevTime<iTime(_Symbol,_Period,0))
           {
            prevTime=iTime(_Symbol,_Period,0);
            if(bMobile) SendNotification(sSub);
            if(bScreen) Alert(sSub);
            if(bEmail) SendMail(sSub,sMsg);
           }
        }
     }
  }
//+------------------------------------------------------------------+

Comments