AFL for Automatic Trend Lines

MarketSecrets - Learn To Trade Like a Pro

AFL for Automatic Trend Lines

This Amibroker script is designed to automate the process of drawing:
1. Trend lines (sloping)
2. Support & resistance lines (horizontal)
3. Channel lines (parallel lines to trend lines & horizontal lines)

Script:

// We only want to draw trend lines where they are within +/-X% of the last close
PctLmt = Param(“% from last Close to draw”, 3, 0, 100, 1, 0);

// Number of breaks allowed before NullBars area
BreaksLimit = Param(“Number of breaks allowed (before NullBars)”, 2, 0, 100, 1, 0);

// Do we deem a price body as a valid “break”? If just the close as a valid break leave No.
OpenBreak = ParamToggle(“Price body considered break?”, “No|Yes”, 0);

// What are the minimum numbers of touches to draw a trend line, being mindful
// that a sloping trend line already has two trend line touches, whereas horizontal
// and channel lines only have one.
TouchesLimit = Param(“Minimum trend line touches”, 2, 0, 10, 1, 0);

// Only look back over the last X number of bars from the right-most edge of
// the chart. By placing a value in here besides 0 it can help speed up the
// computation time spent with processing this script.
LastBars = Param(“Only use last X bars (0 = Use all)”, 0, 0, 10000, 100, 0);

// Ignore all trend line breaks and touches in the last X bars
NullBars = Param(“Ignore touches and breaks in last X bars”, 10, 0, 100, 1, 0);

// Swing level
SwingPoints = Param(“Swing points”, 2, 1, 3, 1, 0 );

// Do you wish to plot sloping trend lines?
PlotTL = ParamToggle(“Plot trend lines?”, “No|Yes”, 1);

// Do you wish to plot horizontal support and resistance lines?
PlotSR = ParamToggle(“Plot sup/res lines?”, “No|Yes”, 1);

// Do you wish to plot sloping channel lines?
PlotChannels = ParamToggle(“Plot channel lines?”, “No|Yes”, 1);

// What colour do you wish to plot for upper lines?
UpperColor = ParamColor(“Upper trend line colours”, ColorRGB( 17,199,251 ) );

// What colour do you wish to plot for lower lines?
LowerColor = ParamColor(“Lower trend line colours”, ColorRGB( 243,126,120 ) );

// Do you wish to plot upper lines?
PlotUpper = ParamToggle(“Plot upper lines?”, “No|Yes”, 1);

// Do you wish to plot lower lines?
PlotLower = ParamToggle(“Plot lower lines?”, “No|Yes”, 1);

/*
 * FUNCTIONS
 */

// Determine if the bars passed in form a swing high.
// @param {int} left bar
// @param {int} middle bar
// @param {int} right bar
// @return {boolean} if the three bars have created a swing high is True
function isSwingHigh( left, middle, right ) {
    result = False;
    if ( H[left] <= H[middle] && H[middle] > H[right] ) result = True;
    return result;
}

// Determines if the bars passed in form a swing low.
// @param {int} left bar
// @param {int} middle bar
// @param {int} right bar
// @return {boolean} if the three bars have created a swing low is True
function isSwingLow( left, middle, right ) {
    result = False;
    if ( L[left] >= L[middle] && L[middle] < L[right] ) result = True;
    return result;
}

// This function refines the swing array.
// @param {int[]} array of bar indexes
// @param {boolean} get swing high if True, otherwise get swing lows
// @return {int[]} array of bar indexes
function getSwingArray( swing, isHigh ) {
    z = 0;
    result = Null;
    for ( i = 2; i < BarCount; i += 1 ) {
        if ( IsNull( swing[i] ) ) break;
        if ( swing[i] < BarCount-LastBars && LastBars > 0 ) continue;
        if ( isHigh && isSwingHigh( swing[i-2], swing[i-1], swing[i] ) ) {
            result[z] = swing[i-1];
            z = z + 1;
        } else if ( !isHigh && isSwingLow( swing[i-2], swing[i-1], swing[i] ) ) {
            result[z] = swing[i-1];
            z = z + 1;
        }
    }
    return result;
}

// This function returns the highest or lowest bar between two bars.
// @param {int} bar1 – the leftmost bar
// @param {int} bar2 – the rightmost bar
// @param {boolean} isHigh – get highest bar if True, otherwise lowest bar
// @return {int} highest or lowest bar
function getBar( bar1, bar2, isHigh ) {
    result = bar1;
    for ( i = bar1; i <= bar2; i += 1 ) {
        if ( isHigh && H[i] >= H[result] ) result = i;
        if ( !isHigh && L[i] <= L[result] ) result = i;
    }
    return result;
}

// This function calculates the slope value.
// @param {int} bar1
// @param {int} bar2
// @param {boolean} isHigh
// @return {double} slope value
function getSlope( bar1, bar2, isHigh ) {
    result = -1;
    if ( bar1 – bar2 == 0 ) {
        result = 0;
    } else if ( isHigh ) {
        result = ( H[bar1] – H[bar2] ) / ( bar1 – bar2 );
    } else if ( !isHigh ) {
        result = ( L[bar1] – L[bar2] ) / ( bar1 – bar2 );
    }
    return result;
}

// This function plots the trend line. Don’t directly call from code,
// pass through the checkTrendline procedure first.
// @param {int} bar1
// @param {int} bar2
// @param {boolean} isHigh
// @param {double} slope
// @param {int} tlType  0 = horizontal; 1 = sloping; -1 = parallel (channel)
// @return {boolean} was trend line plotted?
function plotTrendLine( bar1, bar2, isHigh, slope, tlType ) {
    touches = 1; // being i == bar1
    breaks = 0;
    isPlotted = False;
    flag = 0;
    for ( i = bar1+1; i < BarCount-NullBars; i += 1 ) {
        if ( isHigh ) {
            trendlineValue = H[bar1] + ( slope * ( i – bar1 ) );
            if ( C[i] > trendlineValue ) {
                breaks = breaks + 1;
            } else if ( O[i] > trendlineValue && OpenBreak ) {
                breaks = breaks + 1;
            }
            // rather than just being a touch we’re checking that the touch
            // was a swing point as trendlines can go through a cluster of price
            // points and meet the touch trigger, here we’re refining what’s
            // classified as a legitimate “touch”
            if ( H[i] >= trendlineValue ) flag = i+1;
            if ( flag == i && isSwingHigh( i-2, i-1, i ) ) touches = touches + 1;
        } else {
            trendlineValue = L[bar1] + ( slope * ( i – bar1 ) );
            if ( C[i] < trendlineValue ) {
                breaks = breaks + 1;
            } else if ( O[i] < trendlineValue && OpenBreak ) {
                breaks = breaks + 1;
            }
            if ( L[i] <= trendlineValue ) flag = i+1;
            if ( flag == i && isSwingLow( i-2, i-1, i ) ) touches = touches + 1;
        }
        if ( breaks > BreaksLimit ) break;
    }
    if ( breaks <= BreaksLimit && touches >= TouchesLimit ) {
        // time to plot the trend line
        if ( isHigh ) {
            // Plot if parallel (channel) line
            if ( tlType == -1 ) {
                trendlineArray = LineArray( bar1, H[bar1], bar1+1, H[bar1]+slope, 1 );
                Plot( trendlineArray, “ch-up-“+bar1, LowerColor );
            }
            // Plot if horizontal line
            if ( tlType == 0 ) {
                trendlineArray = LineArray( bar1, H[bar1], BarCount, H[bar1], 1 );
                Plot( trendlineArray, “hz-“+bar1, UpperColor );
            }
            // Plot if sloping line
            if ( tlType == 1 ) {
                trendlineArray = LineArray( bar1, H[bar1], bar2, H[bar2], 1 );
                Plot( trendlineArray, “tl-up-“+bar1+”.”+bar2, UpperColor );
            }
            isPlotted = True;
        } else {
            if ( tlType == -1 ) {
                trendlineArray = LineArray( bar1, L[bar1], bar1+1, L[bar1]+slope, 1 );
                Plot( trendlineArray, “ch-dn-“+bar1, UpperColor );
            }
            if ( tlType == 0 ) {
                trendlineArray = LineArray( bar1, L[bar1], BarCount, L[bar1], 1 );
                Plot( trendlineArray, “hz-“+bar1, LowerColor );
            }
            if ( tlType == 1 ) {
                trendlineArray = LineArray( bar1, L[bar1], bar2, L[bar2], 1 );
                Plot( trendlineArray, “tl-dn-“+bar1+”.”+bar2, LowerColor );
            }
            isPlotted = True;
        }
    }
    return isPlotted;
}

// Here is the main procedure that plots trend lines, however, it’s
// operating as a gatekeeper to help determine whether values inserted
// into the parameters are valid. The types of trend lines passed through
// this function are:
// 1. Sloping trend lines (required = bar1, bar2, isHigh, slope)
// 2. Horizontal support & resistance lines (required = bar1, isHigh, slope)
// 3. Sloping channel lines (required = bar1, bar2, isHigh, slope)
// @param {int} bar1
// @param {int} bar2
// @param {boolean} isHigh
// @param {double} slope
// @param {int} tlType  0 = horizontal; 1 = sloping; -1 = parallel (channel)
procedure checkTrendline( bar1, bar2, isHigh, slope, tlType ) {
    if ( IsNull( bar2 ) ) bar2 = 0;
    if ( IsNull( slope ) && bar1 == bar2 ) slope = 0;
    if ( IsNull( slope ) ) slope = getSlope( bar1, bar2, isHigh );
    if ( isHigh ) trendlineEnd = H[bar1] + ( slope * ( BarCount-1 – bar1 ) );
    if ( !isHigh ) trendlineEnd = L[bar1] + ( slope * ( BarCount-1 – bar1 ) );
    if ( abs( 1 – ( trendlineEnd / LastValue( C ) ) ) * 100 <= PctLmt ) {
        if ( plotTrendline( bar1, bar2, isHigh, slope, tlType ) ) {
            // Check corresponding channel lines
            if ( PlotChannels ) {
                channelBar = getBar( bar1, bar2, !isHigh );
                plotTrendline( channelBar, channelBar, !isHigh, slope, -1 );
            }
        }
    }
}

/*
 * MAIN
 * Here is the beginning of the script.
 */

// 1. Initialise our swing points with all bars

swingHighs = BarIndex();
swingLows = BarIndex();

// 2. Recursively loop through the array by obtaining the SwingPoint level needed

for ( i = 0; i < SwingPoints; i += 1 ) {

    if ( PlotUpper ) swingHighs = getSwingArray( swingHighs, True );
    if ( PlotLower ) swingLows = getSwingArray( swingLows, False );

}

// 3. Count the number of elements in the array

swingHighCount = BarCount – NullCount( swingHighs, 0 );
swingLowCount = BarCount – NullCount( swingLows, 0 );

// 4a. Loop through the swing high array

for ( a = 0; a < swingHighCount; a += 1 ) {

    for ( b = a+1; b < swingHighCount; b += 1 ) {

        bar1 = swingHighs[a];
        bar2 = swingHighs[b];
        if ( !IsNull( bar1 ) && !IsNull( bar2 ) ) {
            slope = getSlope( bar1, bar2, True );
            // Check sloping trend lines
            if ( PlotTL ) checkTrendLine( bar1, bar2, True, slope, 1 );
            // Check horizontal resistance lines
            if ( PlotSR ) checkTrendLine( bar1, bar1, True, 0, 0 );
        }
    }
}

// 4b. Loop through the swing low array

for ( a = 0; a < swingLowCount; a += 1 ) {

    for ( b = a+1; b < swingLowCount; b += 1 ) {

        bar1 = swingLows[a];
        bar2 = swingLows[b];
        if ( !IsNull( bar1 ) && !IsNull( bar2 ) ) {
            slope = getSlope( bar1, bar2, False );
            // Check sloping trend lines
            if ( PlotTL ) checkTrendLine( bar1, bar2, False, slope, 1 );
            // Check horizontal resistance lines
            if ( PlotSR ) checkTrendLine( bar1, bar1, False, 0, 0 );
        }
    }
}

 

Download File

error: Content is protected !!