Indicators Used
Miscellaneous
1
Views
0
Downloads
0
Favorites
S_R_lines
///////////////////////////////////////////////////////
// George Egroeg (C) 2006 e-m: egro1egro at yahoo dot com
// aka "egro1egro"
//
// "Support/resistance lines" Version 3.0
//
///////////////////////////////////////////////////////
// The package contains two files:
// 1. S_R_lines.mq4 (script) should be placed into experts/indicators folder
// 2. S_R_lines.tpl (chart template) should be placed into templates folder
///////////////////////////////////////////////////////
// This indicator has only one parameter: lineIndex = 1,...,20
// In order to make it work you will have to place 20 indicators
// all with different parameter values. A chart template
// with 20 indicators of this type is included for
// your convenience.
//
// There are two global variable that you might want to set before running this script:
//
// "sr_last_screens" - number of last screens to start drawing s/r lines from
// One screen is assumed to have 150 bars/candles
// If you specify global value 2 it will mean that 300 candles back s/r lines
// can be started only. Using this parameter should improve performance significantly.
//
// "sr_spread_multiple" - number of (Bid-Ask) spreads to use as a delta when merging two s/r
// lines together. If you specify value 2 and current spread is 0.0003 then two lines within
// 6 pips will be merged into one. You might want to increase this parameter if you are
// planning to use bigger time-frames (for instance, for hourly charts you might need 5-10
// spreads to use as a delta in order to unclutter the screen). By default, it is set to 1.5 spreads.
//
// !!! After applying global variables or after recompiling this script it is necessary to
// de-select the chart template and then select it again to apply a new.
//
// Also, some parameters are defined as constants in the code
// and can be changed sensibly. These parameters cannot be made external
// because they need to be exactly the same on all instances of the indicator.
//
// MAX_NUM_LINES is a number of indicators on a chart
// If you think that 20 is overkill try to reduce this constant and
// accordingly delete some of the indicators from the chart template
// It might be enough to have 10, but if you notice that some lines are
// not drawn where they should be - increase the number (make it even bigger than 20)
// The point is - always maintain the same number of indicators
// on the chart al with different indices
//
// MAX_PERCENT_OUT is how far from the last price potential s/r lines
// should be maintained (I think 3% is quite enough for intraday, but...)
//
// DELTA_PERIODS a number of candles/bars after which s/r lines "expire"
// indicator script discards old line and stops drawing them to the right.
//
// DEFAULT_NUM_SCREENS how many screens back shell we start the first s/r line
// if the global variable "sr_last_screens" is not defined or invalid
///////////////////////////////////////////////////////
#property copyright "George Egroeg (egro1egro at yahoo dot com)"
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1 LimeGreen
#property indicator_color2 LimeGreen
#property indicator_color3 LimeGreen
#property indicator_color4 LimeGreen
#property indicator_color5 Red
#property indicator_color6 Red
#property indicator_color7 Red
#property indicator_color8 Red
// maximum number of support/resistance line pairs
#define MAX_NUM_LINES 5
#define MAX_NUM_LINES_REAL 20 // has to be exactly 4 times the previous number
// max deviation from current price
#define MAX_PERCENT_OUT 3.0
// 2 lines within (Bid-Ask)* DELTA_SPREAD_MULTIPLE are merged into one
#define DELTA_SPREAD_MULTIPLE 1.5
#define DELTA_PERIOD 600
// 10 screens back from now with 150 bars/canldes in each - the very first s/r/ line can possibly start
#define DEFAULT_NUM_SCREENS 10
//////////////////////////////////////////////////////////////////////////////
// the following constants are for internal use and should not be changed
//////////////////////////////////////////////////////////////////////////////
// number of bars left behind in a fractal
#define NUM_BARS_FRACTAL 2
// constants that denote empty values (i.e. don't draw if empty)
#define LINE_EMPTY_VALUE 0.0
#define FRACTAL_EMPTY_VALUE 0.0
#define DATE_EMPTY_VALUE 0 // 0 am 1 Jan 1970
#define NUM_BARS_SCREEN 150 // number of bars in a screen normally
// which one of s/r pair of lines to show (can be from 1 to 20)
extern int lineIndex = 1;
double lineDelta = 0.0005;
//---- buffers
double resLine1[];
double resLine2[];
double resLine3[];
double resLine4[];
double suppLine1[];
double suppLine2[];
double suppLine3[];
double suppLine4[];
// list of resistance lines
// we maintain the whole list of them but use only the requested one
double upper_f[MAX_NUM_LINES_REAL]; // f is for tracking previous fractal values (hi/lo of candles)
double upper_l[MAX_NUM_LINES_REAL]; // l is for tracking previous r/s lines levels (open/close of candles)
datetime upper_s[MAX_NUM_LINES_REAL]; // s is for tracking start time of s/r lines
// queue of support lines
double lower_f[MAX_NUM_LINES_REAL];
double lower_l[MAX_NUM_LINES_REAL];
datetime lower_s[MAX_NUM_LINES_REAL];
double valHigh = LINE_EMPTY_VALUE;
double valLow = LINE_EMPTY_VALUE;
datetime startTime = DATE_EMPTY_VALUE;
double deltaSpreadMultiple = DELTA_SPREAD_MULTIPLE;
// loop variable
int i;
int j;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void initRunningLists()
{
for(j = 0; j < MAX_NUM_LINES_REAL; j++)
{
upper_f[j] = LINE_EMPTY_VALUE;
upper_l[j] = LINE_EMPTY_VALUE;
upper_s[j] = DATE_EMPTY_VALUE;
lower_f[j] = LINE_EMPTY_VALUE;
lower_l[j] = LINE_EMPTY_VALUE;
lower_s[j] = DATE_EMPTY_VALUE;
}
}
int init()
{
// adjust input values
if ( lineIndex < 1 )
lineIndex = 1;
if ( lineIndex > MAX_NUM_LINES )
lineIndex = MAX_NUM_LINES;
j = (lineIndex-1)*4;
//----
SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 1, LimeGreen);
SetIndexEmptyValue(0, LINE_EMPTY_VALUE);
SetIndexDrawBegin(0, 1);
SetIndexBuffer(0, resLine1);
SetIndexLabel(0,"Resistance " + (j + 1));
SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 1, LimeGreen);
SetIndexEmptyValue(1, LINE_EMPTY_VALUE);
SetIndexDrawBegin(1, 1);
SetIndexBuffer(1, resLine2);
SetIndexLabel(1,"Resistance " + (j + 2));
SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 1, LimeGreen);
SetIndexEmptyValue(2, LINE_EMPTY_VALUE);
SetIndexDrawBegin(2, 1);
SetIndexBuffer(2, resLine3);
SetIndexLabel(2,"Resistance " + (j + 3));
SetIndexStyle(3, DRAW_LINE, STYLE_SOLID, 1, LimeGreen);
SetIndexEmptyValue(3, LINE_EMPTY_VALUE);
SetIndexDrawBegin(3, 1);
SetIndexBuffer(3, resLine4);
SetIndexLabel(3,"Resistance " + (j + 4));
//----
SetIndexStyle(4,DRAW_LINE, STYLE_SOLID,1, Red);
SetIndexEmptyValue(4, LINE_EMPTY_VALUE);
SetIndexDrawBegin(4,1);
SetIndexBuffer(4, suppLine1);
SetIndexLabel(4,"Support " + (j + 1));
SetIndexStyle(5,DRAW_LINE, STYLE_SOLID,1, Red);
SetIndexEmptyValue(5, LINE_EMPTY_VALUE);
SetIndexDrawBegin(5,1);
SetIndexBuffer(5, suppLine2);
SetIndexLabel(5,"Support " + (j + 2));
SetIndexStyle(6,DRAW_LINE, STYLE_SOLID,1, Red);
SetIndexEmptyValue(6, LINE_EMPTY_VALUE);
SetIndexDrawBegin(6,1);
SetIndexBuffer(6, suppLine3);
SetIndexLabel(6,"Support " + (j + 3));
SetIndexStyle(7,DRAW_LINE, STYLE_SOLID,1, Red);
SetIndexEmptyValue(7, LINE_EMPTY_VALUE);
SetIndexDrawBegin(7,1);
SetIndexBuffer(7, suppLine4);
SetIndexLabel(7,"Support " + (j + 4));
IndicatorShortName("S/R lines " + lineIndex);
if ( GlobalVariableCheck("sr_last_screens") )
{
double sn = GlobalVariableGet("sr_last_screens");
if ( sn > 0 )
{
startTime = TimeCurrent() - (Period() * 60 * sn * NUM_BARS_SCREEN);
}
else
{
startTime = TimeCurrent() - (Period() * 60 * DEFAULT_NUM_SCREENS * NUM_BARS_SCREEN);
}
}
else
startTime = TimeCurrent() - (Period() * 60 * DEFAULT_NUM_SCREENS * NUM_BARS_SCREEN);
if ( GlobalVariableCheck("sr_spread_multiple") )
{
double sm = GlobalVariableGet("sr_spread_multiple");
if ( sm > 0 )
deltaSpreadMultiple = sm;
else
deltaSpreadMultiple = DELTA_SPREAD_MULTIPLE;
}
initRunningLists();
//----
return(0);
}
double myFractal(int mode, int shift)
{
if ( (shift < 2) || (shift > (Bars - 2)) )
return (0.0);
if ( NUM_BARS_FRACTAL > 2 )
return (iFractals(NULL, 0, mode, shift));
// need to compare High of (shift-1, shift, shift+1)
if ( mode == MODE_UPPER )
{
if ( (High[shift] >= High[shift-1]) && (High[shift] >= High[shift+1]) )
return(High[shift]);
/*
// check right side
int k = shift - 1;
while( (k >= 0) && (High[k] == High[shift]) )
{
k--;
}
if ( k >= 0 && (High[k] > High[shift]) )
return (0.0);
// now check left side
k = shift + 1;
while( (k < Bars) && (High[k] == High[shift]) )
{
k++;
}
if ( (k < Bars) && (High[k] > High[shift]) )
return (0.0);
return (High[shift]);
*/
}
else
{
if ( (Low[shift] <= Low[shift-1]) && (Low[shift] <= Low[shift+1]) )
return(Low[shift]);
/*
// check right side
k = shift - 1;
while( (k >= 0) && (Low[k] == Low[shift]) )
{
k--;
}
if ( k >= 0 && (Low[k] < Low[shift]) )
return (0.0);
// now check left side
k = shift + 1;
while( (k < Bars) && (Low[k] == Low[shift]) )
{
k++;
}
if ( (k < Bars) && (Low[k] > Low[shift]) )
return (0.0);
return (Low[shift]);
*/
}
return (0.0);
}
double updateViewResistance(int li, double vhPrevious, double NewLow)
{
if ( upper_s[li] == DATE_EMPTY_VALUE )
{
// no line no picture
return (LINE_EMPTY_VALUE);
}
else
{
// new line can be cancelled if a candle has printed over it
if ( NewLow > (upper_l[li] + lineDelta) )
{
upper_f[li] = LINE_EMPTY_VALUE;
upper_l[li] = LINE_EMPTY_VALUE;
upper_s[li] = DATE_EMPTY_VALUE;
return (LINE_EMPTY_VALUE);
}
else
{
// we have a line but if we have an old line we will have to cancel it first
if ( vhPrevious != LINE_EMPTY_VALUE )
{
// we have a line already
if ( vhPrevious != upper_l[li] ) // got a new line instead now
return (LINE_EMPTY_VALUE); // cancel the old one
else
return (vhPrevious); // continue the same old one
}
else
{
return (upper_l[li]); // start a new one here
}
}
}
}
double updateViewSupport(int li, double vlPrevious, double NewHigh)
{
if ( lower_s[li] == DATE_EMPTY_VALUE )
{
// no line no picture
return (LINE_EMPTY_VALUE);
}
else
{
// new line can be cancelled if a candle has printed over it
if ( NewHigh < (lower_l[li] - lineDelta) )
{
lower_f[li] = LINE_EMPTY_VALUE;
lower_l[li] = LINE_EMPTY_VALUE;
lower_s[li] = DATE_EMPTY_VALUE;
return (LINE_EMPTY_VALUE);
}
else
{
// we have a line but if we have an old line we will have to cancel it first
if ( vlPrevious != LINE_EMPTY_VALUE )
{
// we have a line already
if ( vlPrevious != lower_l[li] ) // got a new line instead now
return (LINE_EMPTY_VALUE); // cancel the old one
else
return (vlPrevious); // continue the same old one
}
else
{
return(lower_l[li]); // start a new one here
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
initRunningLists();
lineDelta = MathAbs(Ask - Bid) * deltaSpreadMultiple;
int td1 = MathAbs(Time[Bars-1] - Time[Bars-2]); // number of seconds in one period
int td = td1 * DELTA_PERIOD;
i = Bars-1;
// skip old dates
while( (i >= 0) && (Time[i] < startTime) )
{
i--;
}
while( i >= 0 )
{
double rangeMax = Close[i] * ( 1.0 + (MAX_PERCENT_OUT/100.0) );
double rangeMin = Close[i] * ( 1.0 - (MAX_PERCENT_OUT/100.0) );
datetime t = Time[i];
// when fractal function returns non-zero value we get a new potential resistance line
valHigh = myFractal(MODE_UPPER, i);
double body_max = MathMax(Close[i], Open[i]);
if ( valHigh > FRACTAL_EMPTY_VALUE )
{
// fractal is getting reported only on the very last bar of it
// so we need to select the highest body top out of 5 bars
for(j = MathMin((i + NUM_BARS_FRACTAL - 1), Bars); j >= MathMax((i - NUM_BARS_FRACTAL + 1),0); j--)
{
if ( body_max < MathMax(Close[j], Open[j]) )
body_max = MathMax(Close[j], Open[j]);
}
j = MathMax((i - NUM_BARS_FRACTAL),0);
while( (j >= 0) && (MathMax(Close[j], Open[j]) < valHigh) && (MathMax(Close[j], Open[j]) > body_max) )
{
body_max = MathMax(Close[j], Open[j]);
j--;
}
}
valLow = myFractal(MODE_LOWER, i);
double body_min = MathMin(Close[i], Open[i]);
if ( valLow > FRACTAL_EMPTY_VALUE )
{
// fractal is getting reported only on the very last bar of it
// so we need to select the highest body top out of 5 bars
for(j = MathMin((i + NUM_BARS_FRACTAL - 1), Bars); j >= MathMax((i - NUM_BARS_FRACTAL + 1),0); j--)
{
if ( body_min > MathMin(Close[j], Open[j]) )
body_min = MathMin(Close[j], Open[j]);
}
j = MathMax((i - NUM_BARS_FRACTAL),0);
while( (j >= 0) && (MathMin(Close[j], Open[j]) > valLow) && (MathMin(Close[j], Open[j]) < body_min) )
{
body_min = MathMin(Close[j], Open[j]);
j--;
}
}
// First, cancel old resistance lines because of overlapping
for(j = 0; j < MAX_NUM_LINES_REAL; j++ )
{
if ( ((upper_l[j] /*+ lineDelta*/) < body_max)
|| (upper_l[j] > rangeMax)
|| ((upper_s[j] + td) < t)
)
{
upper_f[j] = LINE_EMPTY_VALUE; // cancel the item
upper_l[j] = LINE_EMPTY_VALUE;
upper_s[j] = DATE_EMPTY_VALUE;
}
}
if ( valHigh > FRACTAL_EMPTY_VALUE )
{
// Next, cancel old resistance lines because of new fractals
for(j = 0; j < MAX_NUM_LINES_REAL; j++ )
{
if (upper_f[j] < valHigh)
{
upper_f[j] = LINE_EMPTY_VALUE; // cancel the item
upper_l[j] = LINE_EMPTY_VALUE;
upper_s[j] = DATE_EMPTY_VALUE;
}
}
bool bExistsAlready = false;
for(j = 0; j < MAX_NUM_LINES_REAL; j++)
{
if ( upper_f[j] != LINE_EMPTY_VALUE )
{
if ( ((upper_l[j] - lineDelta) < body_max)
&& ((upper_l[j] + lineDelta) > body_max) )
{
bExistsAlready = true;
break;
}
}
}
// if we have a new fractal up - insert a new s/r line
if ( !bExistsAlready )
{
for(j = 0; j < MAX_NUM_LINES_REAL; j++)
{
if ( upper_f[j] == LINE_EMPTY_VALUE )
{
upper_f[j] = valHigh;
upper_l[j] = body_max;
upper_s[j] = t;
break;
}
}
}
}
// First, cancel old s/r lines because of candle-overlapping
for(j = 0; j < MAX_NUM_LINES_REAL; j++ )
{
if ( ((lower_l[j] /*- lineDelta*/) > body_min)
|| (lower_l[j] < rangeMin)
|| ((lower_s[j] + td) < t)
)
{
lower_f[j] = LINE_EMPTY_VALUE; // cancel the item
lower_l[j] = LINE_EMPTY_VALUE;
lower_s[j] = DATE_EMPTY_VALUE;
}
}
if ( valLow > FRACTAL_EMPTY_VALUE )
{
// First, cancel old resistance lines
for(j = 0; j < MAX_NUM_LINES_REAL; j++)
{
if (lower_f[j] > valLow)
{
lower_f[j] = LINE_EMPTY_VALUE; // cancel the item
lower_l[j] = LINE_EMPTY_VALUE;
lower_s[j] = DATE_EMPTY_VALUE;
}
}
bExistsAlready = false;
for(j = 0; j < MAX_NUM_LINES_REAL; j++)
{
if ( lower_f[j] != LINE_EMPTY_VALUE )
{
if ( ((lower_l[j] - lineDelta) < body_min)
&& ((lower_l[j] + lineDelta) > body_min) )
{
bExistsAlready = true;
break;
}
}
}
// if we have a new fractal down - insert a new s/r line
if ( !bExistsAlready )
{
for(j = 0; j < MAX_NUM_LINES_REAL; j++)
{
if ( lower_f[j] == LINE_EMPTY_VALUE )
{
lower_f[j] = valLow;
lower_l[j] = body_min;
lower_s[j] = t;
break;
}
}
}
}
j = (lineIndex-1)*4;
resLine1[i] = updateViewResistance(j, resLine1[i+1], Low[i]);
resLine2[i] = updateViewResistance(j+1, resLine2[i+1], Low[i]);
resLine3[i] = updateViewResistance(j+2, resLine3[i+1], Low[i]);
resLine4[i] = updateViewResistance(j+3, resLine4[i+1], Low[i]);
suppLine1[i] = updateViewSupport(j, suppLine1[i+1], High[i]);
suppLine2[i] = updateViewSupport(j+1, suppLine2[i+1], High[i]);
suppLine3[i] = updateViewSupport(j+2, suppLine3[i+1], High[i]);
suppLine4[i] = updateViewSupport(j+3, suppLine4[i+1], High[i]);
i--;
}
return(0);
}
//+------------------------------------------------------------------+
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---