Ticker Renko Box

Author: mandorr@gmail.com
Ticker Renko Box

This script is designed to create a specialized visual representation of market price movements known as a Renko chart. Unlike traditional charts that plot price based on time intervals (e.g., every minute or hour), this tool filters out "market noise" by focusing solely on price movement magnitude.

Core Logic Overview

The primary goal of the script is to convert standard price action into a series of uniform boxes (bricks). Each box represents a fixed price change. For a new brick to appear, the price must move a specific distance in one direction; if the price moves back within the range of the current brick, the chart remains unchanged.

Key Functionalities

  • Fixed Box Movement: The user can define a "Box Size." The script monitors the live market and only draws a new price level once the market has moved by that specific amount. This creates a clean, step-like visual where every movement is of equal significance.
  • Directional Recognition: The script tracks whether the current trend is bullish (upward) or bearish (downward).
    • If the price continues in the current direction, it extends the existing "brick."
    • If the price reverses and moves enough to surpass the previous brick's boundary, the script identifies a trend reversal.
  • Dynamic Reversal Handling: When a trend reversal occurs, the script automatically handles the transition by:
    1. Creating a new directional brick.
    2. Adjusting the history of the bricks to maintain a consistent sequence.
    3. Updating the visual colors (typically switching between Blue for up-movements and Red for down-movements) to clearly signal a change in market sentiment.
  • Real-Time Synchronization: The script is designed to stay updated with the live "Bid" price. It constantly recalculates the current position of the price relative to the last completed brick.
  • Visual Management:
    • Automatic Scaling: It manages the placement of objects on the chart, ensuring that as new bricks are formed, they appear in the correct chronological order.
    • Time Shifting: To ensure the boxes remain aligned with the price action, the script can shift existing visual elements to accommodate the passage of time on the main chart.
    • Reference Lines: It includes a silver horizontal line that tracks the current Bid price, allowing the user to see how close the current market action is to completing the next brick.

Summary for the User

Essentially, this script cleans up your view of the market. Instead of seeing every tiny fluctuation, it only shows you "meaningful" movements. It treats price action as a series of bricks: once a brick is finished, the next one begins in the new direction, providing a clear visual history of trend changes and momentum.

11 Views
0 Downloads
0 Favorites
Ticker Renko Box
// Ticker Renko Box.mq4
// Èíäèêàòîð

#property copyright "mandorr@gmail.com"
#property indicator_separate_window
#property indicator_buffers 2

extern int BoxSize=5;       // Ðàçìåð êèðïè÷à
extern int BarWidth=5;      // Øèðèíà ëèíèè áàðà

int    win_index;
int    box_size;
int    price_prev;
int    tickers;
int    bar_size;
int    bar_high[];
int    bar_low [];
int    bar_dir [];
double box_range;
double box_backlash; // çàçîð
double buffer0 [];
double buffer1 [];
datetime time0;


void init() {
   SetIndexBuffer(0,buffer0);
   SetIndexBuffer(1,buffer1);
   SetIndexStyle (0,DRAW_NONE);
   SetIndexStyle (1,DRAW_NONE);
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
   SetIndexLabel (0,"High");
   SetIndexLabel (1,"Low");
   SetIndexDrawBegin(0,0);
   SetIndexDrawBegin(1,0);
   IndicatorDigits(Digits);

   for (int i=0; i<=1000; i++) {
      buffer0[i]=0.0;
      buffer1[i]=0.0;
   }

   box_size=MathMax(1,BoxSize);
   box_range=box_size*Point;
   box_backlash=Point; // çàçîð

   time0=0;
   price_prev=0;
   tickers=0;
   bar_size=0;
}

void deinit() {
   ObjectsDeleteAll(win_index);
}

void start() {
   int i, j, price, box_count, obj_total;
   bool reverse;
   string obj_name, win_name;
   double high, low;
   double price1, price2;
   datetime time1, time2, time_shift;

   price=MathRound(Bid/Point);
   if (price==0) {return;}
   if (price==price_prev) {return;}
   tickers++;

   win_name="Renko ("+BoxSize+")"+" Ticker ("+tickers+")";
   IndicatorShortName(win_name);
   win_index=WindowFind(win_name);

   if (bar_size==0) {
      bar_size=1;
      time0=Time[0];
      ArrayResize(bar_high,1);
      ArrayResize(bar_low ,1);
      ArrayResize(bar_dir, 1);
      price_prev=10*(price/10); // ïðèâÿçêà ê öåíå, êðàòíîé 10 ïóíêòîâ
      bar_high[0]=price_prev+box_size;
      bar_low [0]=price_prev;
      bar_dir [0]=1;
   }

   price_prev=price;

   // Ïåðåìåùåíèå îáúåêòîâ îêíà íà 1 áàð âïðàâî, êîãäà ïîÿâëÿåòñÿ íîâûé áàð îñíîâíîãî ãðàôèêà
   if (time0!=Time[0]) {
      time0=Time[0];
      obj_total=ObjectsTotal();
      time_shift=Time[0]-Time[1];
      for (i=0; i<obj_total; i++) {
         obj_name=ObjectName(i);
         if (ObjectFind(obj_name)!=win_index) {continue;}
         if (obj_name=="Win"+win_index+"_Bid") {continue;}
         price1=ObjectGet(obj_name,OBJPROP_PRICE1);
         time1=ObjectGet(obj_name,OBJPROP_TIME1);
         ObjectMove(obj_name,0,time1+time_shift,price1);
         price2=ObjectGet(obj_name,OBJPROP_PRICE2);
         time2=ObjectGet(obj_name,OBJPROP_TIME2);
         ObjectMove(obj_name,1,time2+time_shift,price2);
      }
   }

   box_count=0;
   reverse=false;
   if ((price>bar_high[0]) && (bar_dir[0]>0)) {
      box_count=(price-bar_high[0])/box_size;
      bar_high[0]=bar_high[0]+box_count*box_size;
   }
   if ((price<bar_low[0]) && (bar_dir[0]<0)) {
      box_count=(bar_low[0]-price)/box_size;
      bar_low[0]=bar_low[0]-box_count*box_size;
   }
   if ((price>bar_low[0]) && (bar_dir[0]<0)) {
      box_count=(price-bar_low[0])/box_size;
      if (box_count>1) {reverse=true;}
   }
   if ((price<bar_high[0]) && (bar_dir[0]>0)) {
      box_count=(bar_high[0]-price)/box_size;
      if (box_count>1) {reverse=true;}
   }
   if (reverse) {
      bar_size++;
      ArrayResize(bar_high,bar_size);
      ArrayResize(bar_low ,bar_size);
      ArrayResize(bar_dir ,bar_size);
      for (i=bar_size-1; i>0; i--) {
         bar_high[i]=bar_high[i-1];
         bar_low [i]=bar_low [i-1];
         bar_dir [i]=bar_dir [i-1];
      }
      if (bar_dir[1]<0) {
         bar_high[0]=bar_low[1]+box_count*box_size;
         bar_low [0]=bar_low[1]+box_size;
         bar_dir [0]=1;
      }
      if (bar_dir[1]>0) {
         bar_high[0]=bar_high[1]-box_size;
         bar_low [0]=bar_high[1]-box_count*box_size;
         bar_dir [0]=-1;
      }
      // Ïåðåìåùåíèå îáúåêòîâ îêíà íà 1 áàð âëåâî
      obj_total=ObjectsTotal();
      time_shift=Time[0]-Time[1];
      for (i=0; i<obj_total; i++) {
         obj_name=ObjectName(i);
         if (ObjectFind(obj_name)!=win_index) {continue;}
         if (obj_name=="Win"+win_index+"_Bid") {continue;}
         price1=ObjectGet(obj_name,OBJPROP_PRICE1);
         time1=ObjectGet(obj_name,OBJPROP_TIME1);
         ObjectMove(obj_name,0,time1-time_shift,price1);
         price2=ObjectGet(obj_name,OBJPROP_PRICE2);
         time2=ObjectGet(obj_name,OBJPROP_TIME2);
         ObjectMove(obj_name,1,time2-time_shift,price2);
      }
   }

   for (i=0; i<bar_size; i++) {
      buffer0[i]=bar_high[i]*Point;
      buffer1[i]=bar_low [i]*Point;
   }
   buffer0[bar_size]=0.0;
   buffer1[bar_size]=0.0;

   high=bar_high[0]*Point;
   low =bar_low [0]*Point;
   time1=Time[0];
   time2=Time[0];
   box_count=(bar_high[0]-bar_low[0])/box_size;

   color bar_color;
   if (bar_dir[0]<0) {bar_color=Red;} else {bar_color=Blue;}

   for (i=0; i<box_count; i++) {
      price1=low+i*box_range;
      price2=low+(i+1)*box_range-box_backlash;
      if (i==box_count-1) {price2=low+(i+1)*box_range;} // ñàìûé âåðõíèé êèðïè÷ áåç çàçîðà
      obj_name="Win"+win_index+"_Bar"+(bar_size-1)+"_Box"+i;
      if (ObjectFind(obj_name)!=win_index) {
         ObjectCreate(obj_name,OBJ_TREND,win_index,time1,price1,time2,price2);
      }
      ObjectSet(obj_name,OBJPROP_TIME1,time1);
      ObjectSet(obj_name,OBJPROP_TIME2,time2);
      ObjectSet(obj_name,OBJPROP_PRICE1,price1);
      ObjectSet(obj_name,OBJPROP_PRICE2,price2);
      ObjectSet(obj_name,OBJPROP_STYLE,DRAW_LINE);
      ObjectSet(obj_name,OBJPROP_WIDTH,BarWidth);
      ObjectSet(obj_name,OBJPROP_RAY,false);
      ObjectSet(obj_name,OBJPROP_COLOR,bar_color);
   }

   obj_name="Win"+win_index+"_Bid";
   if (ObjectFind(obj_name)!=win_index) {
      ObjectCreate(obj_name,OBJ_HLINE,win_index,time1,Bid);
   }
   ObjectSet(obj_name,OBJPROP_PRICE1,Bid);
   ObjectSet(obj_name,OBJPROP_STYLE,DRAW_LINE);
   ObjectSet(obj_name,OBJPROP_WIDTH,1);
   ObjectSet(obj_name,OBJPROP_COLOR,Silver);
}

// End

Comments