Last active
May 13, 2017 19:32
-
-
Save currencysecrets/4475162 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 …
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //+------------------------------------------------------------------+ | |
| //| 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