Last active
December 11, 2015 00:28
-
-
Save currencysecrets/4516516 to your computer and use it in GitHub Desktop.
This Expert Advisor plots the historical trend lines on the offline charts.
This file contains 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 Auto Trend Lines (Offline).mq4 | | |
//| Ryan Sheehy | | |
//| http://www.currencysecrets.com | | |
//| Version: 1.0 | | |
//| Released: 12 Jan 13 | | |
//+------------------------------------------------------------------+ | |
#property copyright "Ryan Sheehy" | |
#property link "http://www.currencysecrets.com" | |
extern int globalTouches = 3; // number of touches needed to make interval a valid trend line | |
extern bool globalOpenBreaks = false; // are open prices considered a break in price? | |
extern int globalBreaks = 1; // how many breaks are needed until trend line is considered broken? | |
extern int globalLevel = 2; // how far do we search for swing points? | |
extern int globalHorizResColor = Red; // resistance colour for horizontal lines | |
extern int globalHorizSupColor = Blue; // support colour for horizontal lines | |
extern int globalSlopeResColor = LightCoral; // resistance colour for sloping trend lines | |
extern int globalSlopeSupColor = LightSkyBlue; // support colour for sloping trend lines | |
extern int globalPlotType = 2; // 0 = only plot horizontal lines; 1 = plot sloping trendlines; 2 = plot all | |
//+------------------------------------------------------------------+ | |
//| expert initialization function | | |
//+------------------------------------------------------------------+ | |
int init() | |
{ | |
//---- | |
ObjectsDeleteAll(0); | |
start(); | |
//---- | |
return(0); | |
} | |
//+------------------------------------------------------------------+ | |
//| expert deinitialization function | | |
//+------------------------------------------------------------------+ | |
int deinit() | |
{ | |
//---- | |
ObjectsDeleteAll(0); | |
//---- | |
return(0); | |
} | |
//+------------------------------------------------------------------+ | |
//| expert start function | | |
//+------------------------------------------------------------------+ | |
int start() | |
{ | |
//---- | |
int pkArr[]; | |
int trArr[]; | |
ObjectsDeleteAll(0); | |
for( int i = Bars-3; i > 0; i-- ) { | |
if ( isPeak( i, i+1, i+2 ) ) { | |
addToIntArray( pkArr, i+1 ); | |
} | |
if ( isTrough( i, i+1, i+2 ) ) { | |
addToIntArray( trArr, i+1 ); | |
} | |
} | |
getSwingArray( pkArr, globalLevel, 1 ); // peaks | |
plotTrendLines( pkArr, 1 ); | |
getSwingArray( trArr, globalLevel, -1); // troughs | |
plotTrendLines( trArr, -1 ); | |
//---- | |
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 ) ) { | |
addToIntArray( tempArr, currBar ); | |
} | |
} | |
// identifying troughs | |
if ( dir == -1 ) { | |
if ( isTrough( prevBar, currBar, nextBar ) ) { | |
addToIntArray( tempArr, currBar ); | |
} | |
} | |
} | |
clearIntArray( retArr ); | |
if ( ArraySize( tempArr ) > 0 ) { | |
ArrayCopy( retArr, tempArr, 0, 0, WHOLE_ARRAY ); | |
clearIntArray( tempArr ); | |
} else { | |
break; | |
} | |
} | |
return( retArr ); | |
} | |
/* | |
* clearIntArray | |
* 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 clearIntArray( int& theArray[], int size = 0 ) { | |
ArrayResize( theArray, size ); | |
if ( size > 0 ) { ArrayInitialize( theArray, 0 ); } | |
return( theArray ); | |
} | |
/* | |
* addToIntArray | |
* 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 addToIntArray( int& theArray[], int val ) { | |
ArrayResize( theArray, ArraySize( theArray ) + 1 ); | |
theArray[ ArraySize( theArray ) - 1 ] = val; | |
return( theArray ); | |
} | |
/* | |
* addToDoubleArray | |
* This function appends a double value to a double array. | |
* @param double& theArray - passing the array by reference | |
* @param double val - the item to be appended (no checks on val) | |
* @return double the array with appended value | |
*/ | |
int addToDoubleArray( double& theArray[], double 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 | |
if ( globalPlotType == 0 || globalPlotType == 2 ) { | |
barA = arrayBars[a]; | |
t = getTouchCount( barA, 0, dir, globalBreaks, globalOpenBreaks ); | |
if ( t >= 0 ) { | |
if ( dir == 1 ) { | |
plot1 = High[barA]; | |
horizColor = globalHorizResColor; | |
} | |
if ( dir == -1 ) { | |
plot1 = Low[barA]; | |
horizColor = globalHorizSupColor; | |
} | |
ObjectCreate( "HorizLine" + barA, OBJ_TREND, 0, Time[barA], plot1, Time[t], plot1 ); | |
ObjectSet( "HorizLine" + barA, OBJPROP_RAY, false ); | |
ObjectSet( "HorizLine" + barA, OBJPROP_STYLE, STYLE_SOLID ); | |
ObjectSet( "HorizLine" + barA, OBJPROP_COLOR, horizColor ); | |
} | |
} | |
if ( globalPlotType == 1 || globalPlotType == 2 ) { | |
for( b = a + 1; b < lmt; b++ ) { | |
// checking sloping trend lines | |
barB = arrayBars[b]; | |
t = getTouchCount( barA, barB, dir, globalBreaks, globalOpenBreaks ); | |
if ( t >= 0 ) { | |
plot2 = getLastTLPrice( barA, barB, dir, t ); | |
if ( dir == 1 ) { | |
plot1 = High[barA]; | |
trendColor = globalSlopeResColor; | |
} | |
if ( dir == -1 ) { | |
plot1 = Low[barA]; | |
trendColor = globalSlopeSupColor; | |
} | |
ObjectCreate( "SlopeLine" + barA + "-" + barB, OBJ_TREND, 0, Time[barA], plot1, Time[t], plot2 ); | |
ObjectSet( "SlopeLine" + barA + "-" + barB, OBJPROP_RAY, false ); | |
ObjectSet( "SlopeLine" + barA + "-" + barB, OBJPROP_STYLE, STYLE_SOLID ); | |
ObjectSet( "SlopeLine" + 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 -1 = not enough touches; 0 = trend line still active; else returns bar at which trend line broke | |
*/ | |
int getTouchCount( int bar1, int bar2, int dir, int brokenLimit, bool isOpenBreak = false ) { | |
double slope, val, entry, iniStop, lotSize; | |
int startBar, result = 0; | |
bool flag = false; | |
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-1; i > 1; i-- ) { | |
if ( dir == 1 ) { | |
val = (slope * (i+1 - startBar)) + High[startBar]; | |
if ( High[i+1] >= val && isPeak( i+2, i+1, i ) ) { | |
t++; | |
} | |
if ( isOpenBreak == true && Open[i+1] > val ) { | |
x++; | |
} else if ( Close[i+1] > val ) { | |
x++; | |
} | |
} | |
if ( dir == -1 ) { | |
val = (slope * (i+1 - startBar)) + Low[startBar]; | |
if ( Low[i+1] <= val && isTrough( i+2, i+1, i ) ) { // PEEKING FORWARD! | |
t++; | |
} | |
if ( isOpenBreak == true && Open[i+1] < val ) { | |
x++; | |
} else if ( Close[i+1] < val ) { | |
x++; | |
} | |
} | |
if ( x > brokenLimit ) { | |
if ( t >= globalTouches ) { | |
if ( bar2 == 0 ) { | |
return( i ); | |
} else if ( i < bar2 ) { | |
return( i ); | |
} else { | |
return( -1 ); | |
} | |
} else { | |
return( -1 ); | |
} | |
break; | |
} | |
} // end for-bars loop | |
if ( t >= globalTouches ) { | |
return( result ); | |
} else { | |
return( -1 ); | |
} | |
} | |
/* | |
* getLastTLPrice | |
* Get's the last trend line price up to "lastBar" (if defined, default = 0). | |
* @param int bar1 | |
* @param int bar2 | |
* @param int dir if 1 = peaks, -1 = troughs | |
* @return double | |
*/ | |
double getLastTLPrice( int bar1, int bar2, int dir, int lastBar = 0 ) { | |
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 * (lastBar - startBar)) + High[startBar]; | |
} | |
if ( dir == -1 ) { | |
if ( bar2 > 0 ) { slope = ((Low[bar1] - Low[bar2])/(bar1 - bar2)); } | |
result = (slope * (lastBar - startBar)) + Low[startBar]; | |
} | |
return( result ); | |
} | |
/* | |
* arrayIntToStr | |
* 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 arrayIntToStr( 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