Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save snjage/33708d95861547467cdda11c7971ddbf to your computer and use it in GitHub Desktop.

Select an option

Save snjage/33708d95861547467cdda11c7971ddbf to your computer and use it in GitHub Desktop.
Plots automated trend lines and horizontal support and resistance lines on existing chart. This represents now version 3.0 of this script as it has had a rewrite on the level of swings, rather than limiting it to 3 levels through a series of multiple if-statements! This script will also form the basis for the automated trading aspect, so expect …
//+------------------------------------------------------------------+
//| CS Trend Line Breakout.mq4 |
//| Ryan Sheehy |
//| http://www.currencysecrets.com |
//| Version: 3.0 |
//| Released: 7 Jan 13 |
//+------------------------------------------------------------------+
#property copyright "Ryan Sheehy"
#property link "http://www.currencysecrets.com"
datetime now;
int globalTouches = 3; // number of touches needed to make interval a valid trend line
bool globalOpenBreaks = false; // are open prices considered a break in price?
int globalBreaks = 2; // how many breaks are needed until trend line is considered broken?
int globalLevel = 2; // how far do we search for swing points?
int globalHorizResColor = Red; // resistance colour for horizontal lines
int globalHorizSupColor = Blue; // support colour for horizontal lines
int globalSlopeResColor = LightCoral; // resistance colour for sloping trend lines
int globalSlopeSupColor = LightSkyBlue; // support colour for sloping trend lines
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
ObjectsDeleteAll();
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
ObjectsDeleteAll();
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
// only needs to be done at the change of every TF bar
if ( now != Time[0] ) {
int i;
int pkArr[];
int trArr[];
ObjectsDeleteAll();
for( i = Bars; i > 2; i-- ) {
if ( isPeak( i, i-1, i-2 ) ) {
addToArray( pkArr, i-1 );
}
if ( isTrough( i, i-1, i-2 ) ) {
addToArray( trArr, i-1 );
}
}
getSwingArray( pkArr, globalLevel, 1 ); // peaks
plotTrendLines( pkArr, 1 );
getSwingArray( trArr, globalLevel, -1); // troughs
plotTrendLines( trArr, -1 );
now = Time[0];
}
//----
return(0);
}
//+------------------------------------------------------------------+
/*
* getSwingArray
* This function further refines the initial peak & trough swing array. By
* using previous swing points to find stronger swing points.
* @param int& retArr initial array of bars
* @param int level 0 = minimal swing array
* @param int dir 1 = get peak swings, -1 = get trough swing
* @return int array of swing bars
*/
int getSwingArray( int& retArr[], int level, int dir ) {
int tempArr[];
int a, l, currBar, prevBar, nextBar, arrSize;
for ( l = 0; l <= level; l++ ) {
arrSize = ArraySize( retArr );
for ( a = 2; a < arrSize; a++ ) {
// identifying peaks
prevBar = retArr[a-2];
currBar = retArr[a-1];
nextBar = retArr[a];
if ( dir == 1 ) {
if ( isPeak( prevBar, currBar, nextBar ) ) {
addToArray( tempArr, currBar );
}
}
// identifying troughs
if ( dir == -1 ) {
if ( isTrough( prevBar, currBar, nextBar ) ) {
addToArray( tempArr, currBar );
}
}
}
clearArray( retArr, ArraySize( tempArr ) );
ArrayCopy( retArr, tempArr );
clearArray( tempArr );
}
return( retArr );
}
/*
* clearArray
* This function deletes all items in array and resizes array to size.
* @param int& theArray - passing the array by reference
* @param int size - size of the array (default = 1)
* @return int blank array of size
*/
int clearArray( int& theArray[], int size = 0 ) {
ArrayResize( theArray, size );
if ( size > 0 ) { ArrayInitialize( theArray, 0 ); }
return( theArray );
}
/*
* addToArray
* This function appends an integer value to an integer array.
* @param int& theArray - passing the array by reference
* @param int val - the item to be appended (no checks on val)
* @return int the array with appended value
*/
int addToArray( int& theArray[], int val ) {
ArrayResize( theArray, ArraySize( theArray ) + 1 );
theArray[ ArraySize( theArray ) - 1 ] = val;
return( theArray );
}
/*
* isPeak
* Checks if the bar being passed is a swing peak.
* @param int prevBar
* @param int currBar = cannot be 1 or 0 (active bar)
* @param int nextBar
* @return bool true = swing peak has been achieved
*/
bool isPeak( int prevBar, int currBar, int nextBar ) {
bool result = false;
if ( currBar <= 1 ) { result = false; }
if ( High[currBar] > High[nextBar] && High[currBar] >= High[prevBar] ) { result = true; }
return( result );
}
/*
* isTrough
* Checks if the bars passed form a swing trough.
* @param int prevBar
* @param int currBar = cannot be 1 or 0 (active bar)
* @param int nextBar
* @return bool true = swing trough has been achieved
*/
bool isTrough( int prevBar, int currBar, int nextBar ) {
bool result = false;
if ( currBar <= 1 ) { result = false; }
if ( Low[currBar] < Low[nextBar] && Low[currBar] <= Low[prevBar] ) { result = true; }
return( result );
}
/*
* plotTrendLines
* Loop through array of bars that have swing points and connect
* each point with an interval. Determine how close a bar needs to be
* for it to be a touch. And whether a trend line is broken.
* @param int arrayBars - array of bars holding swing points
* @param dir type of swing, 1 = peak swings; -1 = trough swings
*/
void plotTrendLines( int arrayBars[], int dir ) {
int a, b, t, barA, barB, horizColor, trendColor;
double plot1, plot2;
int lmt = ArraySize( arrayBars );
for( a = 0; a < lmt; a++ ) {
// checking horizontal lines
barA = arrayBars[a];
t = getTouchCount( barA, 0, dir, globalBreaks, globalOpenBreaks );
if ( t >= globalTouches ) {
if ( dir == 1 ) {
plot1 = High[barA];
horizColor = globalHorizResColor;
}
if ( dir == -1 ) {
plot1 = Low[barA];
horizColor = globalHorizSupColor;
}
ObjectCreate( "Bar " + barA, OBJ_TREND, 0, Time[barA], plot1, Time[0], plot1 );
ObjectSet( "Bar " + barA, OBJPROP_STYLE, STYLE_SOLID );
ObjectSet( "Bar " + barA, OBJPROP_COLOR, horizColor );
}
for( b = a + 1; b < lmt; b++ ) {
// checking sloping trend lines
barB = arrayBars[b];
t = getTouchCount( barA, barB, dir, globalBreaks, globalOpenBreaks );
if ( t >= globalTouches ) {
plot2 = getLastTLPrice( barA, barB, dir );
if ( dir == 1 ) {
plot1 = High[barA];
trendColor = globalSlopeResColor;
}
if ( dir == -1 ) {
plot1 = Low[barA];
trendColor = globalSlopeSupColor;
}
ObjectCreate( "Bar " + barA + "-" + barB, OBJ_TREND, 0, Time[barA], plot1, Time[0], plot2 );
ObjectSet( "Bar " + barA + "-" + barB, OBJPROP_STYLE, STYLE_SOLID );
ObjectSet( "Bar " + barA + "-" + barB, OBJPROP_COLOR, trendColor );
}
}
}
}
/*
* getTouchCount
* Returns the number of touches a trend line has had.
* @param int bar1 - first bar of point
* @param int bar2 - second bar of point (set to 0 if doing a horizontal line)
* @param int dir - if 1 = peaks; if -1 = troughs
* @param int brokenLimit how many breaks of the trend line are needed for the trend line to
* be nullified
* @param bool isOpenBreak - is the open considered a break
* @return int if -1 means the trend line has been broken, otherwise any other
* number returned is the count of how many touches the trend line
* has had
*/
int getTouchCount( int bar1, int bar2, int dir, int brokenLimit, bool isOpenBreak = false ) {
double slope, val;
int startBar;
bool flag;
int i, t = 0, x = 0;
// if bar2 == 0 we are dealing with a horizontal line
if ( bar2 == 0 ) {
startBar = bar1;
slope = 0;
} else {
startBar = MathMax( bar1, bar2 );
}
// get slope of interval if not horizontal line
if ( bar2 > 0 ) {
if ( dir == 1 ) {
slope = ((High[bar1] - High[bar2])/(bar1 - bar2));
}
if ( dir == -1 ) {
slope = ((Low[bar1] - Low[bar2])/(bar1 - bar2));
}
}
// start from the first bar and count how many touches
for ( i = startBar; i >= 0; i-- ) {
flag = true;
if ( dir == 1 ) {
val = (slope * (i - startBar)) + High[startBar];
if ( High[i] >= val ) {
t++;
}
if ( isOpenBreak == true && Open[i] > val ) {
flag = false; // need to make sure we don't double count if the close has broken above too!
x++;
}
if ( flag == true && Close[i] > val ) {
x++;
}
}
if ( dir == -1 ) {
val = (slope * (i - startBar)) + Low[startBar];
if ( Low[i] <= val ) {
t++;
}
if ( isOpenBreak == true && Open[i] < val ) {
flag = false;
x++;
}
if ( flag == true && Close[i] < val ) {
x++;
}
}
if ( x > brokenLimit && brokenLimit > 0 ) {
t = -1;
break;
}
} // end for-bars loop
return( t );
}
/*
* getLastTLPrice
* Get's the last trend line price.
* @param int bar1
* @param int bar2
* @param int dir if 1 = peaks, -1 = troughs
* @return double
*/
double getLastTLPrice( int bar1, int bar2, int dir ) {
double result, slope;
int startBar;
// if bar2 == 0 we are dealing with a horizontal line
if ( bar2 == 0 ) {
slope = 0;
startBar = bar1;
} else {
startBar = MathMin( bar1, bar2 );
}
int t = 0;
// get slope of interval
if ( dir == 1 ) {
if ( bar2 > 0 ) { slope = ((High[bar1] - High[bar2])/(bar1 - bar2)); }
result = (slope * (0 - startBar)) + High[startBar];
}
if ( dir == -1 ) {
if ( bar2 > 0 ) { slope = ((Low[bar1] - Low[bar2])/(bar1 - bar2)); }
result = (slope * (0 - startBar)) + Low[startBar];
}
return( result );
}
/*
* arrayToStr
* This function outputs a one-dimensional array to a string separated by concatWith variable.
* @param int theArray - the array of items you seek to print
* @param string concatWith - the string you wish to concatenate items with (default = ",")
* @return string the array concatenated to a string
*/
string arrayToStr( int theArray[], string concatWith = "," ) {
string s = "";
int a = ArraySize( theArray );
for( int i = 0; i < a; i++ ) {
s = StringConcatenate( s, theArray[i], concatWith );
}
s = StringSubstr( s, 0, StringLen(s) - StringLen( concatWith ) );
return ( s );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment