Skip to content

Instantly share code, notes, and snippets.

@currencysecrets
Last active December 11, 2015 00:28
Show Gist options
  • Save currencysecrets/4516516 to your computer and use it in GitHub Desktop.
Save currencysecrets/4516516 to your computer and use it in GitHub Desktop.
This Expert Advisor plots the historical trend lines on the offline charts.
//+------------------------------------------------------------------+
//| 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