RenkoShade2_3
Download scriptOverview of RenkoShade2 Logic
This script is designed to transform the standard visual representation of a trading chart into a "Renko" style display. Unlike traditional charts that show price movement over specific periods of time (like 1-minute or 1-hour candles), Renko charts focus exclusively on price movement. This means the chart only creates a new "brick" or box when the price moves by a specific, pre-defined amount, effectively filtering out minor market noise to highlight the primary trend.
The script achieves this by overlaying custom visual elements on your existing main window without changing the underlying timeframe of the chart.
Core Functionality
1. Price Movement Tracking (Brick Generation) The logic monitors the live price of the asset. Instead of drawing a candle for every tick, it waits until the price reaches a specific threshold (the "Box Size").
- Upward Movement: When the price climbs high enough to meet the required distance from the previous high point, the script draws an upward-moving brick.
- Downward Movement: When the price drops far enough to meet the required distance from the previous low point, it draws a downward-moving brick.
- Neutral Movement: If the price fluctuates but does not hit either of these thresholds, the script continues to track the "high" and "low" points internally without drawing anything new.
2. Visual Representation The script creates distinct visual components for each price movement:
- Bodies: These represent the core move of the price. The colors are customizable (e.g., Dark Green for up, Maroon for down) to make trend identification immediate.
- Wicks (Tails/Heads): The script can optionally draw "wicks," which show the extreme highs or lows reached during a move that didn't quite result in a full brick change.
- Helper Lines: There is an optional feature that draws horizontal lines to assist in identifying key price levels and the boundaries of the current movement.
3. Automated Adjustments & Accuracy To ensure the script works correctly across different types of assets (like Forex, Indices, or Commodities), it includes automatic scaling logic. It detects how many decimal places your specific symbol uses and adjusts the "Box Size" calculations accordingly so that the bricks remain consistent regardless of the asset's unit value.
4. History Processing and Real-Time Syncing
- Historical Backfill: When you first load the script, it scans back through a user-defined number of historical bars to construct the Renko bricks chronologically. This ensures your chart looks complete from the past forward.
- Live Data Feed: Once the history is loaded, the script switches to "live mode," constantly comparing every new price tick against the last completed brick to determine if a new one should be drawn in real-time.
- Lag Correction: The logic includes a self-correction mechanism; if it detects that the historical data hasn't updated correctly or is lagging, it can reset its internal handles to ensure the visual bricks remain perfectly synced with the current market price.
Summary of User Experience
For the user, this means you can stay on your preferred timeframe (like an H1 chart) but view the market through a "smoothed" lens. The script strips away the horizontal "choppiness" of time and replaces it with a clean sequence of bricks that only change color and direction when significant price progress has actually occurred.
//+------------------------------------------------------------------+
//| RenkoShade2.mq4 |
//| Draws renko on normal tf main window |
//| main algo ripped from renkolivechart_v32 |
//| plus minor modification to make it work |
//| and make sense to the coder himself |
//| , Doztronics |
//| http://www.doztronics.com |
//| log |
//| v2_1 rip CompareDoubles from stdlib so no need to import |
//| v2_2 draws helper lines |
//| v2_3 re-init rs if its lag for more than 3 bar |
//| (less redraw issue) |
//| |
//+------------------------------------------------------------------+
#property copyright ""
#property link "http://www.doztronics.com"
// email: regfrea.k+renkoshade@gmail.com
#property indicator_chart_window
//+------------------------------------------------------------------+
extern color RenkoBodyUp=DarkGreen;
extern color RenkoBodyDn=Maroon;
extern color RenkoHead=PaleTurquoise;
extern color RenkoTail=Wheat;
extern bool DrawHelperLines=true;
int startTimeCurrent;
int rsBoxIdx=1;
bool rsBoxUp=true;
double p=0;
double RenkoSizeP=0;
double rso,rsc,rsh,rsl,rst,rsv;
//+------------------------------------------------------------------+
extern int RenkoBoxSize = 5;
extern int RenkoBoxOffset = 0;
extern bool ShowWicks = true;
extern int BarsCount=200;
extern int debugIdx=0;
//+------------------------------------------------------------------+
int HstHandle = -1, MT4InternalMsg = 0;
string SymbolName;
static double BoxPoints;
//+------------------------------------------------------------------+
int start() {
startTimeCurrent = TimeCurrent();
static double UpWick, DnWick;
static double PrevLow, PrevHigh, PrevOpen, PrevClose, CurVolume, CurLow, CurHigh, CurOpen, CurClose;
static datetime PrevTime;
//+------------------------------------------------------------------+
// This is only executed ones, then the first tick arives.
if(HstHandle < 0) {
// Init
HstHandle=0;
// Error checking
if(MathAbs(RenkoBoxOffset) >= RenkoBoxSize) {
Print("Error: |RenkoBoxOffset| should be less then RenkoBoxSize!");
return(-1);
}
//
int BoxSize = RenkoBoxSize;
int BoxOffset = RenkoBoxOffset;
if(Digits == 5 || (Digits == 3 && StringFind(Symbol(), "JPY") != -1)) {
BoxSize = BoxSize*10;
BoxOffset = BoxOffset*10;
}
if(Digits == 6 || (Digits == 4 && StringFind(Symbol(), "JPY") != -1)) {
BoxSize = BoxSize*100;
BoxOffset = BoxOffset*100;
}
cleanup();
SymbolName = Symbol();
BoxPoints = NormalizeDouble(BoxSize*Point, Digits);
// PrevLow = NormalizeDouble(BoxOffset*Point + MathFloor(Close[Bars-1]/BoxPoints)*BoxPoints, Digits);
PrevLow = NormalizeDouble(BoxOffset*Point + MathFloor(Close[BarsCount-1]/BoxPoints)*BoxPoints, Digits);
DnWick = PrevLow;
PrevHigh = PrevLow + BoxPoints;
UpWick = PrevHigh;
PrevOpen = PrevLow;
PrevClose = PrevHigh;
CurVolume = 1;
// PrevTime = Time[Bars-1];
PrevTime = Time[BarsCount-1];
//
// process historical data
//int i = Bars-2;
int i = BarsCount-2;
//Print(Symbol() + " " + High[i] + " " + Low[i] + " " + Open[i] + " " + Close[i]);
//---------------------------------------------------------------------------
while(i >= 0) {
CurVolume = CurVolume + Volume[i];
UpWick = MathMax(UpWick, High[i]);
DnWick = MathMin(DnWick, Low[i]);
// update low before high or the revers depending on is closest to prev. bar
bool UpTrend = High[i]+Low[i] > High[i+1]+Low[i+1];
while(UpTrend && (Low[i] < PrevLow-BoxPoints || CompareDoubles(Low[i], PrevLow-BoxPoints))) {
PrevHigh = PrevHigh - BoxPoints;
PrevLow = PrevLow - BoxPoints;
PrevOpen = PrevHigh;
PrevClose = PrevLow;
rst=PrevTime;
rso=PrevOpen;
rsl=PrevLow;
if(ShowWicks && UpWick > PrevHigh) rsh=UpWick;
else rsh=PrevHigh;
rsc=PrevClose;
rsv=CurVolume;
UpWick = 0;
DnWick = EMPTY_VALUE;
CurVolume = 0;
CurHigh = PrevLow;
CurLow = PrevLow;
if(PrevTime < Time[i]) PrevTime = Time[i];
else PrevTime=PrevTime+60*Period();
ObjectDelete("rsBox"+rsBoxIdx);
ObjectDelete("rsHead"+rsBoxIdx);
ObjectDelete("rsTail"+rsBoxIdx);
ObjectCreate("rsBox"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsc);
ObjectCreate("rsHead"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rsc,PrevTime,rsh);
ObjectCreate("rsTail"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsl);
ObjectSet("rsBox"+rsBoxIdx,OBJPROP_COLOR,RenkoBodyUp);
ObjectSet("rsHead"+rsBoxIdx,OBJPROP_COLOR,RenkoHead);
ObjectSet("rsTail"+rsBoxIdx,OBJPROP_COLOR,RenkoTail);
if(rsBoxIdx==debugIdx){
Print("2010.01.15 16:10 --**",rsBoxIdx);
Print(rso);
Print(rsh);
Print(rsl);
Print(rsc);
Print(rst);
}
rsBoxIdx++;
} // while(UpTrend && (Low[i] < PrevLow
while(High[i] > PrevHigh+BoxPoints || CompareDoubles(High[i], PrevHigh+BoxPoints)) {
PrevHigh = PrevHigh + BoxPoints;
PrevLow = PrevLow + BoxPoints;
PrevOpen = PrevLow;
PrevClose = PrevHigh;
rst=PrevTime;
rso=PrevOpen;
if(ShowWicks && DnWick < PrevLow) rsl=DnWick;
else rsl=PrevLow;
rsh=PrevHigh;
rsc=PrevClose;
rsv=CurVolume;
UpWick = High[i];
DnWick = EMPTY_VALUE;
CurVolume = 0;
CurHigh = PrevHigh;
CurLow = PrevHigh;
if(PrevTime < Time[i]) PrevTime = Time[i];
else PrevTime=PrevTime+60*Period();
ObjectDelete("rsBox"+rsBoxIdx);
ObjectDelete("rsHead"+rsBoxIdx);
ObjectDelete("rsTail"+rsBoxIdx);
ObjectCreate("rsBox"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsc);
ObjectCreate("rsHead"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rsc,PrevTime,rsh);
ObjectCreate("rsTail"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsl);
ObjectSet("rsBox"+rsBoxIdx,OBJPROP_COLOR,RenkoBodyUp);
ObjectSet("rsHead"+rsBoxIdx,OBJPROP_COLOR,RenkoHead);
ObjectSet("rsTail"+rsBoxIdx,OBJPROP_COLOR,RenkoTail);
if(rsBoxIdx==debugIdx){
Print("2010.01.15 16:10 --##",rsBoxIdx);
Print(rso);
Print(rsh);
Print(rsl);
Print(rsc);
Print(rst);
}
rsBoxIdx++;
} // while(High[i] > PrevHigh+BoxPoints || CompareDoubles
while(!UpTrend && (Low[i] < PrevLow-BoxPoints || CompareDoubles(Low[i], PrevLow-BoxPoints))) {
PrevHigh = PrevHigh - BoxPoints;
PrevLow = PrevLow - BoxPoints;
PrevOpen = PrevHigh;
PrevClose = PrevLow;
rst=PrevTime;
rso=PrevOpen;
rsl=PrevLow;
if(ShowWicks && UpWick > PrevHigh) rsh=UpWick;
else rsh=PrevHigh;
rsc=PrevClose;
rsv=CurVolume;
UpWick = 0;
// DnWick = EMPTY_VALUE;
DnWick = Low[i];
CurVolume = 0;
CurHigh = PrevLow;
CurLow = PrevLow;
if(PrevTime < Time[i]) PrevTime = Time[i];
else PrevTime=PrevTime+60*Period();
ObjectDelete("rsBox"+rsBoxIdx);
ObjectDelete("rsHead"+rsBoxIdx);
ObjectDelete("rsTail"+rsBoxIdx);
ObjectCreate("rsBox"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsc);
ObjectCreate("rsHead"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsh);
ObjectCreate("rsTail"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rsc,PrevTime,rsl);
ObjectSet("rsBox"+rsBoxIdx,OBJPROP_COLOR,RenkoBodyDn);
ObjectSet("rsHead"+rsBoxIdx,OBJPROP_COLOR,RenkoHead);
ObjectSet("rsTail"+rsBoxIdx,OBJPROP_COLOR,RenkoTail);
if(rsBoxIdx==debugIdx){
Print("2010.01.15 16:10 --$$",rsBoxIdx);
Print(rso);
Print(rsh);
Print(rsl);
Print(rsc);
Print(rst);
}
rsBoxIdx++;
}
i--;
}
//
DrawHelperLine(rso,rsc);
// Comment("RenkoLiveChart(" + RenkoBoxSize + "): Open Offline ", SymbolName, ",M", RenkoTimeFrame, " to view chart");
if(Close[0] > MathMax(PrevClose, PrevOpen)) CurOpen = MathMax(PrevClose, PrevOpen);
else if (Close[0] < MathMin(PrevClose, PrevOpen)) CurOpen = MathMin(PrevClose, PrevOpen);
else CurOpen = Close[0];
CurClose = Close[0];
if(UpWick > PrevHigh) CurHigh = UpWick;
if(DnWick < PrevLow) CurLow = DnWick;
rst=PrevTime;
rso=CurOpen;
rsl=CurLow;
rsh=CurHigh;
rsc=CurClose;
rsv=CurVolume;
//ZDO still in the making
if(rso<rsc) { // UP
ObjectDelete("rsBox"+rsBoxIdx);
ObjectDelete("rsHead"+rsBoxIdx);
ObjectDelete("rsTail"+rsBoxIdx);
ObjectCreate("rsBox"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsc);
ObjectCreate("rsHead"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rsc,PrevTime,rsh);
ObjectCreate("rsTail"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsl);
ObjectSet("rsBox"+rsBoxIdx,OBJPROP_COLOR,RenkoBodyUp);
ObjectSet("rsHead"+rsBoxIdx,OBJPROP_COLOR,RenkoHead);
ObjectSet("rsTail"+rsBoxIdx,OBJPROP_COLOR,RenkoTail);
// DrawHelperLine(rso,rsc);
} else { // DOWN
ObjectDelete("rsBox"+rsBoxIdx);
ObjectDelete("rsHead"+rsBoxIdx);
ObjectDelete("rsTail"+rsBoxIdx);
ObjectCreate("rsBox"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsc);
ObjectCreate("rsHead"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsh);
ObjectCreate("rsTail"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rsc,PrevTime,rsl);
ObjectSet("rsBox"+rsBoxIdx,OBJPROP_COLOR,RenkoBodyDn);
ObjectSet("rsHead"+rsBoxIdx,OBJPROP_COLOR,RenkoHead);
ObjectSet("rsTail"+rsBoxIdx,OBJPROP_COLOR,RenkoTail);
// DrawHelperLine(rso,rsc);
}
if(rsBoxIdx==debugIdx){
Print("2010.01.15 16:10 --^^",rsBoxIdx);
Print(rso);
Print(rsh);
Print(rsl);
Print(rsc);
Print(rst);
}
rsBoxIdx++;
return(0);
// End historical data / Init
}
//----------------------------------------------------------------------------
// HstHandle not < 0 so we always enter here after history done
// Begin live data feed
int counted_bars=IndicatorCounted();
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
int limit=Bars-counted_bars;
// v2_3 re-init rs if its lag more than 3 bars
if(limit>3) {
HstHandle=-2;
if(debugIdx==-2) Print("#### reset HstHandle");
}
UpWick = MathMax(UpWick, Bid);
DnWick = MathMin(DnWick, Bid);
CurVolume++;
//-------------------------------------------------------------------------
// up box
if(Bid > PrevHigh+BoxPoints || CompareDoubles(Bid, PrevHigh+BoxPoints)) {
PrevHigh = PrevHigh + BoxPoints;
PrevLow = PrevLow + BoxPoints;
PrevOpen = PrevLow;
PrevClose = PrevHigh;
rst=PrevTime;
rso=PrevOpen;
if (ShowWicks && DnWick < PrevLow) rsl=DnWick;
else rsl=PrevLow;
rsh=PrevHigh;
rsc=PrevClose;
rsv=CurVolume;
if(PrevTime < TimeCurrent()) PrevTime = TimeCurrent();
else PrevTime=PrevTime+60*Period();
ObjectDelete("rsBox"+rsBoxIdx);
ObjectDelete("rsHead"+rsBoxIdx);
ObjectDelete("rsTail"+rsBoxIdx);
ObjectCreate("rsBox"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsc);
ObjectCreate("rsHead"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rsc,PrevTime,rsh);
ObjectCreate("rsTail"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsl);
ObjectSet("rsBox"+rsBoxIdx,OBJPROP_COLOR,RenkoBodyUp);
ObjectSet("rsHead"+rsBoxIdx,OBJPROP_COLOR,RenkoHead);
ObjectSet("rsTail"+rsBoxIdx,OBJPROP_COLOR,RenkoTail);
//draw helper line
DrawHelperLine(rso,rsc);
if(rsBoxIdx==debugIdx){
Print("2010.01.15 16:10 --@@",rsBoxIdx);
Print(rso);
Print(rsh);
Print(rsl);
Print(rsc);
Print(rst);
}
rsBoxIdx++;
CurVolume = 0;
CurHigh = PrevHigh;
CurLow = PrevHigh;
UpWick = 0;
DnWick = EMPTY_VALUE;
}
//-------------------------------------------------------------------------
// down box
else if(Bid < PrevLow-BoxPoints || CompareDoubles(Bid,PrevLow-BoxPoints)) {
PrevHigh = PrevHigh - BoxPoints;
PrevLow = PrevLow - BoxPoints;
PrevOpen = PrevHigh;
PrevClose = PrevLow;
rst=PrevTime;
rso=PrevOpen;
rsl=PrevLow;
if(ShowWicks && UpWick > PrevHigh) rsh=UpWick;
else rsh=PrevHigh;
rsc=PrevClose;
rsv=CurVolume;
if(PrevTime < TimeCurrent()) PrevTime = TimeCurrent();
else PrevTime=PrevTime+60*Period();
ObjectDelete("rsBox"+rsBoxIdx);
ObjectDelete("rsHead"+rsBoxIdx);
ObjectDelete("rsTail"+rsBoxIdx);
ObjectCreate("rsBox"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsc);
ObjectCreate("rsHead"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rso,PrevTime,rsh);
ObjectCreate("rsTail"+rsBoxIdx,OBJ_RECTANGLE,0,rst,rsc,PrevTime,rsl);
ObjectSet("rsBox"+rsBoxIdx,OBJPROP_COLOR,RenkoBodyDn);
ObjectSet("rsHead"+rsBoxIdx,OBJPROP_COLOR,RenkoHead);
ObjectSet("rsTail"+rsBoxIdx,OBJPROP_COLOR,RenkoTail);
DrawHelperLine(rso,rsc);
if(rsBoxIdx==debugIdx){
Print("2010.01.15 16:10 --%%",rsBoxIdx);
Print(rso);
Print(rsh);
Print(rsl);
Print(rsc);
Print(rst);
}
rsBoxIdx++;
CurVolume = 0;
CurHigh = PrevLow;
CurLow = PrevLow;
UpWick = 0;
DnWick = EMPTY_VALUE;
}
//-------------------------------------------------------------------------
// no box - high/low not hit
else {
if(Bid > CurHigh) CurHigh = Bid;
if(Bid < CurLow) CurLow = Bid;
if(PrevHigh <= Bid) CurOpen = PrevHigh;
else if(PrevLow >= Bid) CurOpen = PrevLow;
else CurOpen = Bid;
CurClose = Bid;
/* FileWriteInteger(HstHandle, PrevTime, LONG_VALUE); // Time
FileWriteDouble(HstHandle, CurOpen, DOUBLE_VALUE); // Open
FileWriteDouble(HstHandle, CurLow, DOUBLE_VALUE); // Low
FileWriteDouble(HstHandle, CurHigh, DOUBLE_VALUE); // High
FileWriteDouble(HstHandle, CurClose, DOUBLE_VALUE); // Close
FileWriteDouble(HstHandle, CurVolume, DOUBLE_VALUE); // Volume
FileFlush(HstHandle);
UpdateChartWindow();
*/
}
return(0);
}
//+------------------------------------------------------------------+
int deinit() {
cleanup();
return(0);
}
//+------------------------------------------------------------------+
int init() {
cleanup();
return(0);
}
//+------------------------------------------------------------------+
int cleanup() {
int obj_total=ObjectsTotal();
string name;
for(int i=obj_total;i>=0;i--)
{
name=ObjectName(i);
if(StringSubstr(name,0,2)=="rs") {
ObjectDelete(name);
}
}
rsBoxIdx=1;
Comment("");
return(0);
}
//+------------------------------------------------------------------+
//| right comparison of 2 doubles |
//| taken from stdlib.mqh so no need to import external function |
//+------------------------------------------------------------------+
bool CompareDoubles(double number1,double number2)
{
if(NormalizeDouble(number1-number2,8)==0) return(true);
else return(false);
}
//+------------------------------------------------------------------+
int DrawHelperLine(double rso,double rsc)
{
if(DrawHelperLines) {
//draw helper line
ObjectDelete("rsP1");
ObjectDelete("rsP2");
ObjectDelete("rsP3");
ObjectDelete("rsP4");
ObjectCreate("rsP2",OBJ_HLINE,0,0,rso,-10,1);
ObjectCreate("rsP3",OBJ_HLINE,0,0,rsc,-10,1);
if(rso>rsc){
ObjectCreate("rsP1",OBJ_HLINE,0,0,rso+BoxPoints,-10,1);
ObjectCreate("rsP4",OBJ_HLINE,0,0,rsc-BoxPoints,-10,1);
} else {
ObjectCreate("rsP1",OBJ_HLINE,0,0,rso-BoxPoints,-10,1);
ObjectCreate("rsP4",OBJ_HLINE,0,0,rsc+BoxPoints,-10,1);
}
if(-1==debugIdx){
Print("2010.01.15 16:10 --%==",-1);
Print(rso);
Print(rsc);
}
}
return(0);
}
//+------------------------------------------------------------------+
Comments