TRADERS’ TIPS

January 2017

Tips Article Thumbnail

For this month’s Traders’ Tips, the focus is Ken Calhoun’s article in the December 2016 issue, “Mean-Reversion Swing Trading.” Here, we present the January 2017 Traders’ Tips code with possible implementations in various software.

The Traders’ Tips section is provided to help the reader implement a selected technique from an article in this issue or another recent issue. The entries here are contributed by software developers or programmers for software that is capable of customization.


logo

TRADESTATION: JANUARY 2017

In “Mean-Reversion Swing Trading,” which appeared in the December 2016 issue of STOCKS & COMMODITIES, author Ken Calhoun describes a trading methodology where the trader attempts to enter an existing trend after there has been a pullback. He suggests looking for 50% pullbacks in strong trends and waiting for price to move back in the direction of the trend before entering the trade.

Here, we are providing the TradeStation EasyLanguage code for a mean-revision strategy based on the author’s concepts. We have also included a companion indicator to help visualize the trade setups.

Strategy: MeanReversion
// TASC JAN 2017
// Mean-Reversion Swing Trading
// Ken Calhoun

inputs:
	ChanLength( 20 ),
	StopDollars( 1 ),
	MALength( 50 ) ; 
	
variables:
	UpperBand( 0 ),
	LowerBand( 0 ),
	MidBand( 0 ),
	LongOK( false ),
	ShortOK( false ),
	LowRef( 0 ),
	HighRef( 0 ),
	TriggerLine( 0 ),
	MAValue( 0 ) ;
	
UpperBand = Highest( High, ChanLength ) ;
LowerBand = Lowest( Low, ChanLength ) ;
MAValue = Average( Close, MALength ) ;

if Low = LowerBand then
	begin
	LowRef = Low ;
	LongOK = false ;
	ShortOK = true ;
	end ;
	
if High = UpperBand then
	begin
	HighRef = High ;
	LongOK = true ;
	ShortOK = false ;
	end ;		

// 50% Pull Back Level
TriggerLine = .5 * ( HighRef + LowRef ) ;

if LongOK[1] and LongOK 
	and Close crosses over TriggerLine 
	and Close > MAValue 
	and MarketPosition( 1 ) < 1 then
	begin
	Buy next bar at Market ;
	LongOK = false ;
	end
else if ShortOK[1] and ShortOK 
	and Close crosses under TriggerLine 
	and Close < MAValue 
	and MarketPosition( 1 ) > -1 then
	begin
	SellShort next bar at Market ;	
	ShortOK = false ;
	end ;

Sell next bar at Upperband Limit ;
Sell next bar at Lowerband Stop ;
Buy to Cover next bar at Lowerband Limit ;
Buy to Cover next bar at UpperBand Stop ;
	
SetStopShare ;
SetStopLoss( StopDollars ) ;	
	


Indicator: MeanReversion
// TASC JAN 2017
// Mean-Reversion Swing Trading
// Ken Calhoun

inputs:
	ChanLength( 20 ),
	MALength( 50 ) ;
	
variables:
	UpperBand( 0 ),
	LowerBand( 0 ),
	MidBand( 0 ),
	LongOK( false ),
	ShortOK( false ),
	LowRef( 0 ),
	HighRef( 0 ),
	TriggerLine( 0 ),
	MAValue( 0 ) ;
	
UpperBand = Highest( High, ChanLength ) ;
LowerBand = Lowest( Low, ChanLength ) ;
MAValue = Average( Close, MALength ) ;

if Low = LowerBand then
	begin
	LowRef = Low ;
	LongOK = false ;
	ShortOK = true ;
	end ;
	
if High = UpperBand then
	begin
	HighRef = High ;
	LongOK = true ;
	ShortOK = false ;
	end ;	

TriggerLine = .5 * ( HighRef + LowRef ) ;
	
Plot1( UpperBand, "UpperBand" ) ;
Plot2( LowerBand, "LowerBand" ) ;
Plot3( TriggerLine, "Trigger" ) ;
Plot4( MAValue, "Mov Avg" ) ;

if LongOK then
	begin
	SetPlotColor( 1, Green ) ;
	SetPlotColor( 2, Green ) ;
	end
else
	begin
	SetPlotColor( 1, Red ) ;
	SetPlotColor( 2, Red ) ;
	end ;	

To download the EasyLanguage code for the strategy in this article, please visit our TradeStation and EasyLanguage support forum. The code can be found at https://community.tradestation.com/Discussions/Topic.aspx?Topic_ID=147651. The ELD filename is “TASC_JAN2017.ELD.”

For more information about EasyLanguage in general, please see https://www.tradestation.com/EL-FAQ.

A sample chart is shown in Figure 1.

Sample Chart

FIGURE 1: TRADESTATION. Here’s an example of the MeanReversion strategy and indicator applied to a 60-minute chart of Alphabet (GOOG).

This article is for informational purposes. No type of trading or investment recommendation, advice, or strategy is being made, given, or in any manner provided by TradeStation Securities or its affiliates.

—Doug McCrary
TradeStation Securities, Inc.
www.TradeStation.com

BACK TO LIST

logo

METASTOCK: JANUARY 2017

Ken Calhoun’s article in the December 2016 issue of STOCKS & COMMODITIES, “Mean-Reversion Swing Trading,” presented a visual trading system designed to take advantage of pullbacks in uptrends. The formula given here, used as a filter in the explorer, will find such trading opportunities. The first two lines of the formula allow the user to adjust the parameters of the scan:

The formula is presented using values of 10% minimum move and a 0.1% allowance on the difference at the reversion level.

Exploration filter:
z:= 10;
fudge:= 0.1; 
p1:= LastValue(TroughBars(1, C, z));
pv1:= Trough(1, C,z);
p2:= LastValue( HHVBars( C, p1 ));
pv2:= HHV( C, p1);
meanrev:= (pv1 + pv2) / 2;
pv3:= LLV(C, p2);

p1 < PeakBars(1, C, z) AND
pv2 >= pv1 * (1 + (z/100)) AND
Ref(Abs(pv3 - meanrev) <= pv3 * (fudge/100), -1) AND
C > Ref(C, -1) AND LLVBars(C, p2) = 1 AND
pv1 >= 20 AND pv2 <= 70

—William Golson
MetaStock Technical Support
www.metastock.com

BACK TO LIST

logo

eSIGNAL: JANUARY 2017

For this month’s Traders’ Tip, we’ve provided the study Mean_Reversion_Swing.efs based on the formula described in Ken Calhoun’s article in the December 2016 issue of S&C, “Mean-Reversion Swing Trading.” In the article, Calhoun presents a strategy of trading pullbacks during a trending market.

The study contains formula parameters that may be configured through the “edit chart” window (right-click on the chart and select edit chart). A sample chart is shown in Figure 2.

Sample Chart

FIGURE 2: eSIGNAL. Here is an example of the Mean_Reversion_Swing.efs study plotted on an intraday chart of APC.

To discuss this study or download a complete copy of the formula code, please visit the EFS Library Discussion Board forum under the forums link from the support menu at www.esignal.com or visit our EFS KnowledgeBase at https://www.esignal.com/support/kb/efs/. The eSignal formula script (EFS) is also available for copying & pasting below.

/*********************************
Provided By:  
eSignal (Copyright c eSignal), a division of Interactive Data 
Corporation. 2016. All rights reserved. This sample eSignal 
Formula Script (EFS) is for educational purposes only and may be 
modified and saved under a new file name.  eSignal is not responsible
for the functionality once modified.  eSignal reserves the right 
to modify and overwrite this EFS file with each new release.

Description:        
    Mean-Reversion Swing Trading by Ken Calhoun

Version:            1.00  11/09/2016

Formula Parameters:                     Default:
Slope                                   1
Trigger                                 0.5



Notes:
The related article is copyrighted material. If you are not a subscriber
of Stocks & Commodities, please visit www.traders.com.

**********************************/

var fpArray = new Array();

function preMain(){
    setPriceStudy(true);
    setStudyTitle("MR Swing");
    
    var x = 0;
    fpArray[x] = new FunctionParameter("Slope", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0.01);
        setUpperLimit(100);  
        setDefault(1);
        setName("Slope");
    }
    fpArray[x] = new FunctionParameter("Trigger", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0.000001);
        setDefault(0.5);
        setName("Trigger");
    }
}

var bInit = false;
var bVersion = null;
var xDHigh = null;
var xHigh = null;
var xDLow = null;
var xLow = null;
var xDDateTime = null;
var bInSwing = false;
var bSwFinished = false;
var nSwBarsBack = 0;
var nMeanRev = 0;
var nMeanHigh = 0;
var nSwHigh = 0;
var bMRFound = false;
var dMeanRevD = null;
var bFindBO = false;

function main(Slope, Trigger){
    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;

    if (getBarState() == BARSTATE_ALLBARS){
        bInSwing = false;
        bSwFinished = false;
        nSwBarsBack = 0;
        nMeanRev = 0;
        nMeanHigh = 0;
        nSwHigh = 0;
        bMRFound = false;
        dMeanRevD = null;
        bFindBO = false;
        bInit = false;
    }
    
    if (!bInit){
        xDHigh = high(inv("D"));
        xDLow = low(inv("D"));
        xDDateTime = rawtime(inv("D"));
        xLow = low();
        xHigh = high();
    }

    nDHigh = xDHigh.getValue(0);
    var slopeFinished = false;
    var i = 0;
    var swingLen = 0;

    while (!slopeFinished){
        if (xDHigh.getValue(i) > xDHigh.getValue(i-1)){
            swingLen++;
            i--;
        }
        else slopeFinished = true;
    }

    if (bInSwing && swingLen == 0){
        nSwBarsBack = 0;
        bSwFinished = true;
        bInSwing = false;
    }

    if (bSwFinished && nMeanRev != 0){
        nSwBarsBack++;
        if (xDLow.getValue(-1) < nMeanRev && day(0) != day(-1)){
            drawLineRelative(-1, nMeanRev, -nSwBarsBack, nSwHigh, PS_SOLID, 3, Color.red, 
                            ("Mean rev. " + (rawtime(-nSwBarsBack))));
            dMeanRevD = xDDateTime.getValue(-1);
            nMeanHigh = nSwHigh;
            nSwBarsBack = 0;
            bSwFinished = false;
            bMRFound = false;
        }
    }

    if (!bSwFinished && !bInSwing && !bMRFound  && nMeanRev != 0 && xDDateTime.getValue(-1) == dMeanRevD){
        if (xHigh.getValue(0) >= nMeanRev + Trigger){
            drawTextRelative(0, BelowBar1, "\u00E9", Color.green, null, 
                            Text.PRESET|Text.CENTER, "Wingdings", 10, "Entry"+rawtime(0));
            drawTextRelative(0, BelowBar2, "MR", Color.green, null, 
                            Text.PRESET|Text.CENTER|Text.BOLD, "Arial", 8, "Entry text"+rawtime(0));
            bMRFound = true;
            bFindBO = true;
            nMeanRev = 0;
        }
    }

    if (bFindBO &&  xHigh.getValue(0) >= nMeanHigh){
        drawTextRelative(0, AboveBar1, "\u00E9", Color.green, null, 
                            Text.PRESET|Text.CENTER, "Wingdings", 10, "2nd Entry"+rawtime(0));
        drawTextRelative(0, AboveBar2, "BO", Color.green, null, 
                            Text.PRESET|Text.CENTER|Text.BOLD, "Arial", 8, "2nd Entry text"+rawtime(0));
        bFindBO = false;
    }
        
    if (swingLen >=4){
        var nSStart = getFirstBarIndexOfDay(xDDateTime.getValue(-(swingLen)));

        if(nSStart != null){
            if (((nDHigh - xDHigh.getValue(-(swingLen)))/(xDLow.getValue(0) - xDLow.getValue(-(swingLen)))) > Slope){
                nSwHigh = nDHigh;
                var nSwLow = xDLow.getValue(-(swingLen));
                nMeanRev = (nSwHigh + nSwLow)/2;
                drawLineRelative(0, nDHigh, (nSStart - getCurrentBarIndex()), xDLow.getValue(-(swingLen)), 
                                PS_SOLID, 3, Color.green, "Uptrend" + xDDateTime.getValue(-(swingLen)));
                bInSwing = true;
                bSwFinished = false;
                nSwBarsBack = 0;
            }
            else{
                bInSwing = false;
                bSwFinished = true;
            }
        }
    }    
}

function verify(){
    var b = false;
    if (getBuildNumber() < 779){
        
        drawTextAbsolute(5, 35, "This study requires version 10.6 or later.", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "error");
        drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=https://www.esignal.com/download/default.asp", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "upgrade");
        return b;
    } 
    else
        b = true;
    
    return b;
}

—Eric Lippert
eSignal, an Interactive Data company
800 779-6555, www.eSignal.com

BACK TO LIST

logo

WEALTH-LAB: JANUARY 2017

In his December 2016 article, “Mean-Reversion Swing Trading,” author Ken Calhoun shows clean and concise rules for entering in a trend continuation following a pullback after a breakout. This pattern (widely known as “1-2-3 pattern”) could be programmed to apply to intraday or daily charts alike. Our rendition targets daily charts.

Since the rules didn’t put much emphasis on exits, leaving this to the trader, we added a simple profit target. Here, you can find the complete trading system’s rules:

Entry:

  1. Wait for a five-day close-to-close uptrend.
  2. If the closing prices retrace 50% of the uptrend’s distance (±1 percentage point) over the next 10 bars, a valid pullback has formed.
  3. Look for the prices to rebound and buy on a stop 50 cents above the retracement price. If this condition hasn’t been met within 10 days, the setup is invalidated.
  4. A second entry is made if the first position has been established and the high price breaks through the 15-day highest high price.

Exit:

  1. Exit on a $1 stop-loss from the retracement price.
  2. Exit with a profit target at two times the retracement distance.

Motivated readers could make various improvements to the program’s logic. For instance, to help this technique work equally well on stocks outside the $20–70 price range, make the stop-loss and profit target adaptive by replacing the fixed-dollar distance with a unit of ATR. Another suggestion is to avoid trades when a stock is not really trending, as the 1-2-3 pattern seems to perform best in established trends.

Wealth-Lab strategy code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;

namespace WealthLab.Strategies
{
	public class MeanReversionSwingTrading : WealthScript
	{
		private StrategyParameter paramUptrendDays;
		private StrategyParameter paramReversionLasts;
		private StrategyParameter paramReversionExpiresAfter;
		private StrategyParameter paramSecondEntry;
		
		public MeanReversionSwingTrading()
		{
			paramUptrendDays = CreateParameter("Days in uptrend", 5, 2, 10, 1);
			paramReversionLasts = CreateParameter("Reversion lasts", 4, 2, 12, 2);
			paramReversionExpiresAfter = CreateParameter("Expires after", 10, 5, 20, 5);
			paramSecondEntry = CreateParameter("Second entry?", 1, 0, 1, 1);
		}
		
		protected override void Execute()
		{
			bool runup = false, reversion = false, pullback = false, secondEntry = paramSecondEntry.ValueInt == 1;
			int runupBar = -1, pBar = -1, reversionBar = -1, uptrendDays = paramUptrendDays.ValueInt;
			double runupStart = 0, runupHigh = 0, runupRange = 0, pivotPrice = 0, reversionThreshold = 1.0;
			
			Highest hi = Highest.Series(High,15);
			if( secondEntry )
				PlotSeries(PricePane, hi, Color.Blue, LineStyle.Dashed, 1);
			
			for(int bar = GetTradingLoopStartBar(15); bar < Bars.Count; bar++)
			{
				if( ActivePositions.Count > 0 )
				{					
					if(!SellAtStop(bar+1, Position.AllPositions, pivotPrice - 1.0, "$1 stop"))
						SellAtLimit(bar + 1, Position.AllPositions, pivotPrice + 2.0, "Profit Target");
				}
				
				if( ActivePositions.Count == 0 ) 	// First entry
				{
					if( !runup ) {
						if(CumUp.Series(Close,1)[bar] >= uptrendDays) {
							runup = true; runupBar = bar;
							runupStart = Low[bar-5]; runupHigh = High[runupBar];
							runupRange = runupHigh - runupStart;
							pivotPrice = runupStart + (runupRange / 2d);
							DrawLine(PricePane,runupBar,runupHigh,bar-5,runupStart,Color.Blue,LineStyle.Solid,2);
						}
					}
					if( !pullback ) {
						if( runup ) {
							if( bar >= runupBar + paramReversionExpiresAfter.ValueInt ) {
								runup = false;
								//AnnotateBar("Pullback timeout exceeded",bar,false,Color.Red);
							}
							else {
								double runupInPercent = runupRange / (double)runupStart * 100d;
								double closeToExact = (reversionThreshold / 100d);
								
								if( (Low[bar] <= (pivotPrice * 1.0+closeToExact)) &&
								(Low[bar] >= (pivotPrice * 1.0-closeToExact)) ) {
									pullback = true; pBar = bar;
									DrawLine(PricePane,runupBar,runupHigh,pBar,pivotPrice,Color.Red,LineStyle.Solid,2);
								}
							}
						}
					}
					
					// Buy at stop if price moves $0.50 the pivot price or above
					if( pullback ){
						double entryStop = pivotPrice + 0.50;
						if( BuyAtStop( bar + 1, entryStop, "1st" ) != null ) {
							DrawLine(PricePane,bar,entryStop,pBar,entryStop,Color.DarkGreen,LineStyle.Dotted,2);
							runup = false; pullback = false; 
							LastPosition.Tag = pivotPrice;
						}
						else
							// Invalidate entry if too many bars have passed since pullback
							if( bar >= pBar + paramReversionExpiresAfter.ValueInt ) {
							pullback = false;
							AnnotateBar("Rebound timeout exceeded",bar,true,Color.Orange);
						}
                    }
				}
				else
					//Second entry
					if( ActivePositions.Count == 1 && secondEntry )
						BuyAtStop(bar+1, hi[bar], "2nd");
			}
		}
	}
}

A sample chart is shown in Figure 3.

Sample Chart

FIGURE 3: WEALTH-LAB. This chart shows a potential trade in HeidelbergCement AG (ticker HEI.DE in Wealth-Data).

—Eugene, Wealth-Lab team
MS123, LLC
www.wealth-lab.com

BACK TO LIST

logo

NEUROSHELL TRADER: JANUARY 2017

An automated mean-reversion trading system as described by Ken Calhoun in his December 2016 article in STOCKS & COMMODITIES (“Mean-Reversion Swing Trading”) can be easily implemented using NeuroShell Trader’s Turning Points add-on indicators, which compute the relevant peak and valley statistics. Simply select new trading strategy from the insert menu and enter the following in the appropriate locations of the Trading Strategy Wizard:

BUY LONG CONDITIONS: [All of which must be true]
     A>=B(Add2(TPbars(High,Low,Close,3,2,1),1),5)
     A>=B(TPslope(High,Low,Close,3,2,1),45)
     CrossBelow(Close,FibRetr(High,Low,3,1,3,0))

   STOP PRICE: Add2(FibRetr(High,Low,3,1,3,0),0.5)

LONG TRAILING STOP PRICES:
     TrailPricePnts(Trading Strategy,1)

If you have NeuroShell Trader Professional, you can also choose whether the parameters should be optimized, including optimizing the retracement level to different Fibonacci retracements besides just 50%. After backtesting the trading strategy, use the detailed analysis button to view the backtest and trade-by-trade statistics for the strategy.

Users of NeuroShell Trader can go to the Stocks & Commodities section of the NeuroShell Trader free technical support website to download a copy of this or any previous Traders’ Tips.

A sample chart is shown in Figure 4.

Sample Chart

FIGURE 4: NEUROSHELL TRADER. This NeuroShell Trader chart shows the reversion trading system over the past 10 years for Anadarko Petroleum Corp (APC).

—Marge Sherald, Ward Systems Group, Inc.
301 662-7950, sales@wardsystems.com
www.neuroshell.com

BACK TO LIST

logo

NINJATRADER: JANUARY 2017

The concept discussed by Ken Calhoun in his December 2016 article in S&C, “Mean-Reversion Swing Trading,” is now available as a strategy named “MRST” for download at the following links for NinjaTrader 8 and for NinjaTrader 7:

Once the file is downloaded, you can import the strategy in NinjaTader 8 from within the Control Center by selecting Tools → Import → NinjaScript Add-On and then selecting the downloaded file for NinjaTrader 8. To import in NinjaTrader 7 from within the Control Center window, select the menu File → Utilities → Import NinjaScript and select the downloaded file. A sample chart implementing the strategy is shown in Figure 5.

Sample Chart

FIGURE 5: NINJATRADER. The MRST strategy is displayed on the APC daily chart in NinjaTrader 8.

You can review the strategy’s source code in NinjaTrader 8 by selecting the menu New → NinjaScript Editor → Strategies from within the Control Center window and selecting the MRST file. You can review the strategy’s source code in NinjaTrader 7 by selecting the menu Tools → Edit NinjaScript → Strategy from within the Control Center window and selecting the MRST file.

—Raymond Deux & Paul Hunt
NinjaTrader, LLC
www.ninjatrader.com

BACK TO LIST

logo

UPDATA: JANUARY 2017

Our Traders’ Tip for this month is based on the article by Ken Calhoun that appeared in the December 2016 issue of STOCKS & COMMODITIES, “Mean-Reversion Swing Trading.”

In the article, the author loosely defined a swing trading technique for entering long positions into uptrending instruments that have a 50% retracement, but that swing to make new highs. This can be easily realized with a point & figure–based system, since all the key signals for entry are simplified within this methodology.

Sample Chart

FIGURE 6: UPDATA. Here is a point & figure (1x3) approach to mean-reversion swing trading as applied to Anadarko Petroleum Corp (APC).

The Updata code is in the Updata library and may be downloaded by clicking the custom menu and system library. Those who cannot access the library due to firewall issues may paste the code shown below into the Updata custom editor and save it.

PARAMETER "Box Size [%]" @Box=1
PARAMETER "Reversal" #Reversal=3
NAME "P&F Double Top Break" ""
DISPLAYSTYLE Custom
INDICATORTYPE Tool 
PANDFMODE @Box #Reversal PFLog PFClose
 
@PFHigh=0
@PFLow=0
@LnPFHigh=0
@LnPFLow=0
@LongEntry=0
@LongExit=0 
@PlusIncrement=0   
#DateBegin=0
#Count=0   
 
   
FOR #Curdate=0 To #LastDate 
   If PANDFCOLUMN(2)>0
      @PFHigh=PANDFHIGH(2)
   ElseIf PANDFCOLUMN(2)<0
      @PFLow=PANDFLOW(2)   
   EndIf  
      @LnPFHigh=Ln(@PFHigh)
      @LnPFLow=Ln(@PFLow)
      @PlusIncrement=Ln(1+(@BOX/100))  
      @LongEntry=Exp(@LnPFHigh+@PlusIncrement)
      @LongExit=Exp(@LnPFLow-@PlusIncrement)
   If HIST(Close>@LongEntry AND @LnPFHigh>0,1) AND PANDFLOW(1)<(PANDFHIGH(2)+PANDFLOW(2))
      Buy OPEN
   ElseIf HIST(Close<@LongExit AND @LnPFLow>0,1) 
      Sell OPEN
   EndIf 
NEXT 

—Updata support team
support@updata.co.uk, www.updata.co.uk

BACK TO LIST

logo

AMIBROKER: JANUARY 2017

The chart techniques based on after-the-fact determination of “waves” are highly subjective. In real-life trading, you don’t know that the wave has ended until the reversal is large enough.

A mechanical approach close to the one described by Ken Calhoun in his December 2016 column and in this issue on a mean-reversion technique was presented in the November 2003 STOCKS & COMMODITIES article “The Zigzag Trend Indicator” by Spyros Raftopoulos. In that article, a zigzag indicator that is appropriately delayed (to ensure its stability) was used to enter pullbacks. Users can find the AmiBroker code I had provided based on that article at the S&C website here:

https://traders.com/Documentation/FEEDbk_docs/2003/11/TradersTips/TradersTips.html#amibroker

The code is also shown here:

LISTING 1
array = Close;
amount = Param("Amount", 15.5, 1, 50, 0.5 );
zz0 = Zig( array, amount );
zz1 = Ref( zz0, -1 );
zz2 = Ref( zz0, -2 );
tr = ValueWhen(zz0 > zz1 AND zz1 < zz2, zz1);
pk = ValueWhen(zz0 < zz1 AND zz1 > zz2, zz1);
PU = tr + 0.01 * abs(tr)*amount;
PD = pk - 0.01 * abs(pk)*amount;
ZZT = IIf( array >= PU AND zz0 > zz1, 1,
IIf( array <= PD AND zz0 < zz1, -1, 0 ) );
ZZT = ValueWhen( ZZT != 0, ZZT );
// plot price bar chart
Plot( Close, "Price", colorBlack, styleBar );
// plot Zigzag and zigzag trend
Plot( ZZT, "ZigZagTrend", colorRed, styleOwnScale );
Plot( zz0, "ZigZag line", colorBlue, styleThick );
// Plot the ribbon
ribboncol= IIf( ZZT > 0, colorGreen, colorRed );
Plot( 2, "ZZT Ribbon", ribboncol, styleArea | styleOwnScale | styleNoLabel, 0, 100 );
GraphXSpace = 10;
Buy = Cover = Cross( ZZT, 0 );
Sell = Short = Cross( 0, ZZT );
// plot arrows
PlotShapes( Buy + 2 * Sell, ribboncol, 0, IIf( Buy, L, H ), -30 );

The code given there implements ideas similar to those described by Calhoun. The technique has the advantage of not relying on a strict “50%” pullback rule.

—Tomasz Janeczko, AmiBroker.com
www.amibroker.com

BACK TO LIST

Originally published in the January 2017 issue of
Technical Analysis of STOCKS & COMMODITIES magazine.
All rights reserved. © Copyright 2016, Technical Analysis, Inc.