TRADERS’ TIPS

June 2009

Here is this month’s selection of Traders’ Tips, contributed by various developers of technical analysis software to help readers more easily implement some of the strategies presented in this and other issues.

Other code appearing in articles in this issue is posted in the Subscriber Area of our website at https://technical.traders.com/sub/sublogin.asp. Login requires your last name and subscription number (from mailing label). Once logged in, scroll down to beneath the “Optimized trading systems” area until you see “Code from articles.” From there, code can be copied and pasted into the appropriate technical analysis program so that no retyping of code is required for subscribers.

You can copy these formulas and programs for easy use in your spreadsheet or analysis software. Simply “select” the desired text by highlighting as you would in any word processing program, then use your standard key command for copy or choose “copy” from the browser menu. The copied text can then be “pasted” into any open spreadsheet or other software by selecting an insertion point and executing a paste command. By toggling back and forth between an application window and the open web page, data can be transferred with ease.

This month’s tips include formulas and programs for:


Return to Contents

TRADESTATION: Average True Range Trailing Stops

Sylvain Vervoort’s article in this issue, “Average True Range Trailing Stops,” describes a technique for generating trading signals with average true range calculations. Once the initial entry is made, any number of reversals may follow. The strategy’s first trade date and first trade direction are established by user inputs.

To download the EasyLanguage code for this study, go to the TradeStation and EasyLanguage Support Forum (https://www.tradestation.com/Discussions/forum.aspx?Forum_ID=213). Search for the file “Vervoort Atr Trail.eld.”

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.

Figure 1: TRADESTATION, ATR trailing stop strategy. Here is an example of the Vervoort ATR_Trail strategy on a chart of Google, Inc. (GOOG). The levels at which the strategy enters new long positions are displayed by the cyan lines. The short entry levels are displayed by the magenta lines. The chart on the left displays the levels based on the original ATR trail calculation. In the chart at right, the modified calculations are used.

Strategy: Vervoort ATR_Trail

{ Modified ATR Trailing Stop }
inputs:
	TrailType ( 1 ), { enter 1 for modified version, any
	 other number for unmodified version }
	ATR_Period( 5 ),
	ATR_Factor( 3.5 ),
	Quantity( 100 ),
	InitialMonth( 1 ),
	InitialDay( 1 ),
	InitialYear( 2009 ),
	FirstTrade( 1 ) ; { enter 1 for long, any other
	 number for short }

variables:
	Loss( 0 ),
	HiLo( 0 ),
	HRef( 0 ),
	LRef( 0 ),
	HiLoHRefMax( 0 ),
	HiLoHRefMaxLRefMax( 0 ),
	ATRMod( 0 ),
	WaitingForEntry( true ),
	Trail( 0 ),
	LineNum( 0 ),
	ReturnVal( 0 ) ;
 
if TrailType <> 1 then
	Loss = ATR_Factor * AvgTrueRange( ATR_Period )
else
	begin
	HiLo = iff( High - Low < 1.5 * Average( High - Low,
	 ATR_Period ), High - Low, 1.5 * Average( High -
	 Low, ATR_Period ) ) ;
	HRef = iff( Low <= High[1], High - Close[1],( High -
	 Close[1] ) - 0.5 * ( Low - High[1] ) ) ;
	LRef = iff( High >= Low[1], Close[1] - Low,
	 ( Close[1] - Low ) - 0.5 * ( Low[1] - High ) ) ;
	HiLoHRefMax = Maxlist( HiLo, HRef ) ;
	HiLoHRefMaxLRefMax = Maxlist( HiLoHRefMax, LRef ) ;
	ATRMod = XAverage( HiLoHRefMaxLRefMax, 2 *
	 ATR_Period - 1 ) ;
	Loss = ATR_Factor * ATRMod ;
	end ;

if WaitingForEntry 
	and Year( Date ) + 1900 >= InitialYear
	and Month( Date ) >= InitialMonth 
	and DayOfMonth( Date ) >= InitialDay 
then
	begin
	if FirstTrade = 1 then 
		begin
		Buy Quantity shares this bar Close ;
 	    WaitingForEntry = false ;
		Trail = Close - Loss ;
		end 
	else
		begin
		Sell short Quantity shares this bar at Close ; 
	 	WaitingForEntry = false ;
		Trail = Close + Loss ;
		end ;
	end 
else if WaitingForEntry[1] = false then
	begin
	if Close > Trail[1] and Close[1] > Trail[2] then
		{ continued long }		
		Trail = MaxList( Trail[1], Close - Loss )
	else if Close < Trail[1] and Close[1] < Trail[2]
	 then
		{ continued short }
		Trail = MinList( Trail[1], Close + Loss )
	else if Close > Trail[1] then  
		{ close is above trail }
		Trail = Close - Loss 
	else 
		Trail = Close + Loss ;

	if MarketPosition = -1 and Close > Trail and
	 Trail > 0 then
		begin
		Buy Quantity shares this bar Close ;
		LineNum = TL_New( Date[1], Time[1], Trail[1],
		 Date, Time, Trail[1] ) ;
		ReturnVal = TL_SetColor( LineNum, Cyan ) ;
		end 
	else if MarketPosition = 1 and Close < Trail then
		begin
		Sell short Quantity shares this bar at Close ;
		LineNum = TL_New( Date[1], Time[1], Trail[1],
		 Date, Time, Trail[1] ) ;
		ReturnVal = TL_SetColor( LineNum, Magenta ) ;
		end 
	else if Trail[1] > 0 then
		begin
		LineNum = TL_New( Date[1], Time[1], Trail[1],
		 Date, Time, Trail ) ;
		if Close > Trail then
			ReturnVal = TL_SetColor( LineNum, Magenta )
		else
			ReturnVal = TL_SetColor( LineNum, Cyan ) ;
		end ;
	end ;

—Mark Mills
TradeStation Securities, Inc.
A subsidiary of TradeStation Group, Inc.
www.TradeStation.com

BACK TO LIST

eSIGNAL: Average True Range Trailing Stops

For this month’s Traders’ Tip, we’ve provided the following three formulas: Atr_TrailingStop.efs, Modified_Atr.efs, and Modified_Atr_TrailingStop.efs based on the formula code from Sylvain Vervoort’s article in this issue, “Average True Range Trailing Stops.”

The Atr trailing stop formula is configured for backtesting only. This formula plots the trailing stop based on a five-period Atr with a multiple of 3.5. These parameters are configurable through the Edit Studies option of the Advanced Chart. In addition, the formula draws labels and arrows to highlight the trade signals, which may be disabled in Edit Studies. The strategy can be set to show long or short signals.

The modified Atr formula simply plots the indicator with a default of five periods. This parameter may be configured through the Edit Studies option of the Advanced Chart. The modified Atr trailing stop formula is similar to the Atr trailing stop except that it uses the modified Atr. This formula uses the same defaults, which are also configurable through the Edit Studies option of the Advanced Chart.

To discuss this study or download complete copies of the formula code, please visit the Efs Library Discussion Board forum under the Forums link at www.esignalcentral.com or visit our Efs KnowledgeBase at www.esignalcentral.com/support/kb/efs/. The eSignal formula scripts (Efs) are also available for copying and pasting from the Stocks & Commodities website at Traders.com.

Figure 2: eSIGNAL, AVERAGE TRUE RANGE TRAILING STOP. Here is a demonstration of the ATR trailing stop, the modified ATR, and the modified ATR trailing stop.

ATR_TrailingStop.efs

/*********************************
Provided By:  
    eSignal (Copyright c eSignal), a division of Interactive Data 
    Corporation. 2009. 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:        
    Average True Range Trailing Stops, by Sylvain Vervoort

Version:            1.0  04/09/2009

Formula Parameters:                     Default:
    ATR Period                          5
    ATR Multiplication                  3.5
    Long or Short                       Long
    Show Line Trailing Stop             True
    Show Labels                         True
    Show Arrows                         True
    Display Cursor Labels               True
    Line Color                          Red    

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("ATR Trailing Stops");
    setCursorLabelName("ATR Trailing Stop", 0);
    setShowTitleParameters(false);
    setDefaultBarFgColor(Color.red, 0);
    setPlotType(PLOTTYPE_LINE, 0); 
    setDefaultBarThickness(2, 0);

    askForInput();
    var x=0;
    fpArray[x] = new FunctionParameter("nATRPeriod", FunctionParameter.NUMBER);
    with(fpArray[x++]){
        setName("ATR Period");
        setLowerLimit(1);        
        setUpperLimit(100);        
        setDefault(5);
    }
    fpArray[x] = new FunctionParameter("nATRMultip", FunctionParameter.NUMBER);
    with(fpArray[x++]){
        setName("ATR Multiplication");
        setLowerLimit(1);        
        setUpperLimit(10);        
        setDefault(3.5);
    }
    fpArray[x] = new FunctionParameter("bShowTS", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Show Line Trailing Stop");
        addOption("true");
        addOption("false");        
        setDefault("true");
    }
    fpArray[x] = new FunctionParameter("bShowL", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Show Labels");
        addOption("true");
        addOption("false");        
        setDefault("true");
    }
    fpArray[x] = new FunctionParameter("bShowArrows", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Show Arrows");
        addOption("true");
        addOption("false");        
        setDefault("true");
    }    
    fpArray[x] = new FunctionParameter("ViewValue", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Display Cursor Labels");
        setDefault(true);
    }        
    fpArray[x] = new FunctionParameter("sStrategy", FunctionParameter.STRING);
    with(fpArray[x++]){
        setName("Long or Short");
        addOption("Long");
        addOption("Short");        
        setDefault("Long");
    }
    fpArray[x] = new FunctionParameter("cColor", FunctionParameter.COLOR);
    with(fpArray[x++]){
        setName("Line Color");
        setDefault(Color.red);
    }        
}

var bInit = false;
var bVersion = null;
var xATRTrailingStop = null;
var xClose = null;

function main(nATRPeriod, nATRMultip, sStrategy, bShowTS, bShowL, bShowArrows,
 ViewValue, cColor){
var nClose = 0;
var nClose1 = 0;
var nATRTS = 0;
var nATRTS1 = 0;

    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;   

    if(bInit==false){
        setShowCursorLabel(ViewValue);
        setDefaultBarFgColor(cColor, 0);        
        xClose = close();
        xATRTrailingStop = efsInternal("ATRTrailingStop", nATRPeriod,
         nATRMultip, xClose);
        bInit=true;
    }

    if(getCurrentBarIndex() == 0) return;
   
    nClose = xClose.getValue(0);
    nClose1 = xClose.getValue(-1);
    nATRTS = xATRTrailingStop.getValue(0);
    nATRTS1 = xATRTrailingStop.getValue(-1);
    if (nATRTS1 == null) return;

    if (nClose1 < nATRTS1 && nClose > nATRTS1) {
        if (bShowArrows) drawShape( Shape.UPARROW, BelowBar1, Color.green);
        if (sStrategy == "Long") {
            if (bShowL) drawTextRelative(0, BelowBar2, " LONG", Color.white,
             Color.green, Text.PRESET|Text.CENTER|Text.FRAME, "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            Strategy.doLong("Long", Strategy.MARKET, Strategy.NEXTBAR);
        } else {
            if (bShowL) drawTextRelative(0, BelowBar2,  " EXIT", Color.white,
             Color.green, Text.PRESET|Text.CENTER|Text.FRAME, "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            if (Strategy.isShort()) Strategy.doCover("Exit Short",
             Strategy.MARKET, Strategy.NEXTBAR);            
        }
    }
    if (nClose1 > nATRTS1 && nClose < nATRTS1) {
        if (bShowArrows) drawShape( Shape.DOWNARROW, AboveBar1, Color.red);
        if (sStrategy == "Long") {
            if (bShowL) drawTextRelative(0, AboveBar2,  " EXIT", Color.white,
             Color.red, Text.PRESET|Text.CENTER|Text.FRAME, "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            if (Strategy.isLong()) Strategy.doSell("Exit Long", Strategy.MARKET,
             Strategy.NEXTBAR);
        } else {
            if (bShowL) drawTextRelative(0, AboveBar2,  "SHORT", Color.white,
             Color.red, Text.PRESET|Text.CENTER|Text.FRAME , "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            Strategy.doShort("Short", Strategy.MARKET, Strategy.NEXTBAR);
        }    
    }

    if (bShowTS == false) return;
    return xATRTrailingStop.getValue(0);
}

var xATR = null;
var nRef = 0;
var bSecondInit = false;

function ATRTrailingStop(nATRPeriod, nATRMultip, xSClose){
var nClose = 0;
var nClose1 = 0;
var nLoss = 0;
var nRes = 0;
var nRef = ref(-1);

    if (bSecondInit == false) {
        xATR = atr(nATRPeriod);
        bSecondInit = true;
    }    
    nClose = xSClose.getValue(0);
    nClose1 = xSClose.getValue(-1);
    nLoss = nATRMultip * xATR.getValue(0);
    if (nLoss == null || nClose1 == null) return;
   
    if (nClose > nRef && nClose1 > nRef) {
        nRes = Math.max(nRef, nClose - nLoss);
    } else {
        if (nClose < nRef && nClose1 < nRef) {
            nRes = Math.min(nRef, nClose + nLoss);
        } else {
            if (nClose > nRef) {
                nRes = nClose - nLoss;
            } else {
                nRes = nClose + nLoss;
            }
        }
    }
    return nRes;
}

function verify() {
    var b = false;
    if (getBuildNumber() < 779) {
        drawTextAbsolute(5, 35, "This study requires version 8.0 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;
}


Modified_ATR_TrailingStop.efs

/*********************************
Provided By:  
    eSignal (Copyright c eSignal), a division of Interactive Data 
    Corporation. 2009. 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:        
    Modified Average True Range Trailing Stops, by Sylvain Vervoort

Version:            1.0  04/09/2009

Formula Parameters:                     Default:
    ATR Period                          5
    ATR Multiplication                  3.5
    Long or Short                       Long
    Show Line Trailing Stop             True
    Show Labels                         True
    Show Arrows                         True
    Display Cursor Labels               True
    Line Color                          Red

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("Modified ATR Trailing Stops");
    setCursorLabelName("Modified ATR TS", 0);
    setShowTitleParameters(false);

    setDefaultBarFgColor(Color.red, 0);
    setPlotType(PLOTTYPE_LINE, 0); 
    setDefaultBarThickness(2, 0);

    askForInput();
    var x=0;
    fpArray[x] = new FunctionParameter("nATRPeriod", FunctionParameter.NUMBER);
    with(fpArray[x++]){
        setName("ATR Period");
        setLowerLimit(1);        
        setUpperLimit(100);        
        setDefault(5);
    }
    fpArray[x] = new FunctionParameter("nATRMultip", FunctionParameter.NUMBER);
    with(fpArray[x++]){
        setName("ATR Multiplication");
        setLowerLimit(1);        
        setUpperLimit(10);        
        setDefault(3.5);
    }
    fpArray[x] = new FunctionParameter("bShowTS", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Show Line Trailing Stop");
        addOption("true");
        addOption("false");        
        setDefault("true");
    }
    fpArray[x] = new FunctionParameter("bShowL", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Show Labels");
        addOption("true");
        addOption("false");        
        setDefault("true");
    }
    fpArray[x] = new FunctionParameter("bShowArrows", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Show Arrows");
        addOption("true");
        addOption("false");        
        setDefault("true");
    }    
    fpArray[x] = new FunctionParameter("ViewValue", FunctionParameter.BOOLEAN);
    with(fpArray[x++]){
        setName("Display Cursor Labels");
        setDefault(true);
    }        
    fpArray[x] = new FunctionParameter("sStrategy", FunctionParameter.STRING);
    with(fpArray[x++]){
        setName("Long or Short");
        addOption("Long");
        addOption("Short");        
        setDefault("Long");
    }
    fpArray[x] = new FunctionParameter("cColor", FunctionParameter.COLOR);
    with(fpArray[x++]){
        setName("Line Color");
        setDefault(Color.red);
    }    
}

var bInit = false;
var bVersion = null;
var xATRTrailingStop = null;
var xClose = null;

function main(nATRPeriod, nATRMultip, sStrategy, bShowTS, bShowL, bShowArrows,
 ViewValue, cColor){
var nClose = 0;
var nClose1 = 0;
var nATRTS = 0;
var nATRTS1 = 0;

    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;   

    if(bInit==false){
        setShowCursorLabel(ViewValue);
        setDefaultBarFgColor(cColor, 0);
        xClose = close();        
        xATRTrailingStop = efsInternal("ModifiedATRTrailingStop", nATRPeriod,
         nATRMultip, xClose);
        bInit=true;
    }
    
    if(getCurrentBarIndex() == 0) return;
    
    nClose = xClose.getValue(0);
    nClose1 = xClose.getValue(-1);
    nATRTS = xATRTrailingStop.getValue(0);
    nATRTS1 = xATRTrailingStop.getValue(-1);
    if (nATRTS1 == null) return;

    if (nClose1 < nATRTS1 && nClose > nATRTS1) {
        if (bShowArrows) drawShape( Shape.UPARROW, BelowBar1, Color.green);
        if (sStrategy == "Long") {
            if (bShowL) drawTextRelative(0, BelowBar2, " LONG", Color.white,
             Color.green, Text.PRESET|Text.CENTER|Text.FRAME, "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            Strategy.doLong("Long", Strategy.MARKET, Strategy.NEXTBAR);
        } else {
            if (bShowL) drawTextRelative(0, BelowBar2,  " EXIT", Color.white,
             Color.green, Text.PRESET|Text.CENTER|Text.FRAME, "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            if (Strategy.isShort()) Strategy.doCover("Exit Short",
             Strategy.MARKET, Strategy.NEXTBAR);            
        }
    }
    if (nClose1 > nATRTS1 && nClose < nATRTS1) {
        if (bShowArrows) drawShape( Shape.DOWNARROW, AboveBar1, Color.red);
        if (sStrategy == "Long") {
            if (bShowL) drawTextRelative(0, AboveBar2,  " EXIT", Color.white,
             Color.red, Text.PRESET|Text.CENTER|Text.FRAME, "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            if (Strategy.isLong()) Strategy.doSell("Exit Long", Strategy.MARKET,
             Strategy.NEXTBAR);
        } else {
            if (bShowL) drawTextRelative(0, AboveBar2,  "SHORT", Color.white,
             Color.red, Text.PRESET|Text.CENTER|Text.FRAME , "Arial Black", 10,
              "b"+(getCurrentBarCount()), -5); 
            Strategy.doShort("Short", Strategy.MARKET, Strategy.NEXTBAR);
        }    
    }

    if (bShowTS == false) return;
    return xATRTrailingStop.getValue(0);
}

var xHigh_Low = null;
var xATR_Modif = null;
var nRef = 0;
var bSecondInit = false;

function ModifiedATRTrailingStop(nATRPeriod, nATRMultip, xSClose){
var nBarState = getBarState();
var nClose = 0;
var nClose1 = 0;
var nLoss = 0;
var nRes = 0;
var nRef = ref(-1);

    if (bSecondInit == false) {
        xHigh_Low = efsInternal("Calc_High_Low");
        xATR_Modif = efsInternal("Calc_ATRMod", nATRPeriod, nATRMultip,
         xSClose, xHigh_Low, sma(nATRPeriod, xHigh_Low))
        bSecondInit = true;
    }    
    nClose = xSClose.getValue(0);
    nClose1 = xSClose.getValue(-1);
    nLoss = nATRMultip * xATR_Modif.getValue(0);
    if (nLoss == null) return;
   
    if (nClose > nRef && nClose1 > nRef) {
        nRes = Math.max(nRef, nClose - nLoss);
    } else {
        if (nClose < nRef && nClose1 < nRef) {
            nRes = Math.min(nRef, nClose + nLoss);
        } else {
            if (nClose > nRef) {
                nRes = nClose - nLoss;
            } else {
                nRes = nClose + nLoss;
            }
        }
    }
    return nRes;
}

function Calc_High_Low() {
var nRes = high(0) - low(0);
    if (nRes == null) return;
    return nRes;
}

var bThirdInit = false;
var xHigh = null;
var xLow = null;

function Calc_ATRMod(nATRPeriod, nATRMultip, xTClose, xHigh_Low, xMA_High_Low) {
var nHiLo = 0;
var nHref = 0;
var nLref = 0;
var ndiff1 = 0;
var ndiff2 = 0;
var nHigh_Low = 0;
var nMA_High_Low = 0;
var nAtrMod = 0;

    if (bThirdInit == false) {
        xHigh = high();
        xLow = low();
        bThirdInit = true;
    }

    var nClose = xTClose.getValue(0);
    var nClose1 = xTClose.getValue(0);
    var nHigh = xHigh.getValue(0);
    var nHigh1 = xHigh.getValue(0);
    var nLow = xLow.getValue(0);
    var nLow1 = xLow.getValue(0);

    nHigh_Low = xHigh_Low.getValue(0);
    nMA_High_Low = xMA_High_Low.getValue(0) * 1.5;

    if (nHigh_Low == null || nMA_High_Low == null) return;
  
    if (nHigh_Low < nMA_High_Low) {
        nHiLo = nHigh_Low;
    } else {
        nHiLo = nMA_High_Low;
    }
 
     if (nLow <= nHigh1) {
        nHref = nHigh - nClose1;
    } else {
        nHref = (nHigh - nClose1) - (nLow - nHigh1) / 2;
    }
  
    if (nHigh >= nLow1) {
        nLref = nClose1 - nLow;
    } else {
        nLref = (nClose1 - nLow) - (nLow1 - nHigh) / 2;
    }

    ndiff1 = Math.max(nHiLo, nHref);
    ndiff2 = Math.max(ndiff1, nLref);
    nAtrMod = (ndiff2 + (nATRPeriod - 1) *  ref(-1)) / nATRPeriod;

    if (nAtrMod == null) return;
    return nAtrMod;
}

function verify() {
    var b = false;
    if (getBuildNumber() < 779) {
        drawTextAbsolute(5, 35, "This study requires version 8.0 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;
}


Modified/ATR.efs

/*********************************
Provided By:  
    eSignal (Copyright c eSignal), a division of Interactive Data 
    Corporation. 2009. 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:        
    Modified Average True Range, by Sylvain Vervoort

Version:            1.0  04/09/2009

Formula Parameters:                     Default:
    ATR Period                          5
    Line Color                          Red    

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(false);
    setStudyTitle("Modified ATR");
    setCursorLabelName("Modified ATR", 0);
    setShowTitleParameters(false);
    setDefaultBarFgColor(Color.red, 0);
    setPlotType(PLOTTYPE_LINE, 0); 
    setDefaultBarThickness(2, 0);
    askForInput();
    var x=0;
    fpArray[x] = new FunctionParameter("nATRPeriod", FunctionParameter.NUMBER);
    with(fpArray[x++]){
        setName("ATR Period");
        setLowerLimit(1);        
        setUpperLimit(100);        
        setDefault(5);
    }
    fpArray[x] = new FunctionParameter("cColor", FunctionParameter.COLOR);
    with(fpArray[x++]){
        setName("Line Color");
        setDefault(Color.red);
    }        
}

var bInit = false;
var bVersion = null;
var xATR_Modif = null;

function main(nATRPeriod, cColor){
var nATR_Modif = 0;

    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;   

    if(bInit==false){
        setDefaultBarFgColor(cColor, 0);
        xATR_Modif = efsInternal("Calc_ATRMod", nATRPeriod);
        bInit=true;
    }

    nATR_Modif = xATR_Modif.getValue(0);
    if (nATR_Modif == null) return;

    return nATR_Modif;
}

var xHigh_Low = null;
var xATR_ModifTmp = null;
var nRef = 0;
var bSecondInit = false;

function Calc_ATRMod(nATRPeriod, nATRMultip){
var nRes = 0;
    if (bSecondInit == false) {
        xHigh_Low = efsInternal("Calc_High_Low");
        xATR_ModifTmp = efsInternal("Calc_ATRModResult", nATRPeriod, xHigh_Low,
         sma(nATRPeriod, xHigh_Low))
        bSecondInit = true;
    }    
    nRes = xATR_ModifTmp.getValue(0);
    if (nRes == null) return;
    return nRes;
}

function Calc_High_Low() {
var nRes = high(0) - low(0);
    if (nRes == null) return;
    return nRes;
}

var bThirdInit = false;
var xClose = null;
var xHigh = null;
var xLow = null;

function Calc_ATRModResult(nATRPeriod, xHigh_Low, xMA_High_Low) {
var nHiLo = 0;
var nHref = 0;
var nLref = 0;
var ndiff1 = 0;
var ndiff2 = 0;
var nHigh_Low = 0;
var nMA_High_Low = 0;
var nAtrMod = 0;

    if (bThirdInit == false) {
        xClose = close();
        xHigh = high();
        xLow = low();
        bThirdInit = true;
    }

    var nClose = xClose.getValue(0);
    var nClose1 = xClose.getValue(0);
    var nHigh = xHigh.getValue(0);
    var nHigh1 = xHigh.getValue(0);
    var nLow = xLow.getValue(0);
    var nLow1 = xLow.getValue(0);

    nHigh_Low = xHigh_Low.getValue(0);
    nMA_High_Low = xMA_High_Low.getValue(0) * 1.5;

    if (nHigh_Low == null || nMA_High_Low == null) return;
  
    if (nHigh_Low < nMA_High_Low) {
        nHiLo = nHigh_Low;
    } else {
        nHiLo = nMA_High_Low;
    }

    if (nLow <= nHigh1) {
        nHref = nHigh - nClose1;
    } else {
        nHref = (nHigh - nClose1) - (nLow - nHigh1) / 2;
    }
  
    if (nHigh >= nLow1) {
        nLref = nClose1 - nLow;
    } else {
        nLref = (nClose1 - nLow) - (nLow1 - nHigh) / 2;
    }

    ndiff1 = Math.max(nHiLo, nHref);
    ndiff2 = Math.max(ndiff1, nLref);
    nAtrMod = (ndiff2 + (nATRPeriod - 1) *  ref(-1)) / nATRPeriod;

    if (nAtrMod == null) return;
    return nAtrMod;
}

function verify() {
    var b = false;
    if (getBuildNumber() < 779) {
        drawTextAbsolute(5, 35, "This study requires version 8.0 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;
}

—Jason Keck
eSignal, a division of Interactive Data Corp.
800 815-8256, www.esignalcentral.com

BACK TO LIST

WEALTH-LAB: Average True Range Trailing Stops

The modified Atr indicator presented by Sylvain Vervoort in “Average True Range Trailing Stops” in this issue is available in Wealth-Lab’s TascIndicator library version 1.0.7.0 and later.

Here, we’ll provide the WealthScript code to enter a discretionary position, long or short, on the open of a specified date given by the strategy parameters. Included is the AtrTrail class, which utilizes the modified Atr to calculate a trailing stop based on the most-recent close. You can use it with any of your strategies. Once you create an AtrTrail object, just pass the bar number to the AtrTrail.Price method. As with last month’s article, if you prefer to use touch stops, WealthScript’s built-in ExitAtTrailingStop method is convenient.

See Figure 3 for a sample chart.

Figure 3: WEALTH-LAB, modified average true range stop. INTC’s three black crows following a doji-island reversal made a nice setup to enter short with a relatively tight stop at the center of the pattern.

WealthScript Code (C#): 

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

namespace WealthLab.Strategies
{
   /* Class that encapsulates the ATR Trailing Stop, closing basis */
   public class ATRTrail
   {
      private WealthScript ws;
      private Bars bars;
      private double stopPrice;
      private bool longPosition;
      private DataSeries atrMod;
      
      public ATRTrail(WealthScript wL, Bars b, bool positionLong, double 
      initialStop, int period, double factor )
      {
         ws = wL;
         bars = b;
         longPosition = positionLong;
         stopPrice = initialStop;
         atrMod = factor * TASCIndicators.ATRModified.Series(bars, period);
      }
      
      // Call this method to update and return the stop price on each bar 
      after entry
      public double Price(int bar)
      {
         double prevPrice = stopPrice;
         double newPrice;         
         if (longPosition)
         {
            newPrice = bars.Close[bar] - atrMod[bar];
            stopPrice = newPrice > stopPrice ? newPrice : stopPrice;
         }
         else
         {
            newPrice = bars.Close[bar] + atrMod[bar];
            stopPrice = newPrice < stopPrice ? newPrice : stopPrice;
         }
         ws.DrawLine(ws.PricePane, bar-1, prevPrice, bar, stopPrice, Color.Blue,
          LineStyle.Solid, 1); 
         return stopPrice;
      }
   }
   
   public class SAC_ATRTrailingStops : WealthScript
   {
      private StrategyParameter _isLong = null;
      private StrategyParameter _initStop = null;
      private StrategyParameter _period = null;
      private StrategyParameter _atrMult = null; 
      private StrategyParameter _y = null;
      private StrategyParameter _m = null;
      private StrategyParameter _d = null;
      
      public SAC_ATRTrailingStops()
      {
         _isLong = CreateParameter("Long = 1", 1, 0, 1, 1); 
         _initStop = CreateParameter("Initial Stop", 1.0, 0.25, 50.0, 0.25); 
         _period = CreateParameter("ATR Period", 5, 2, 100, 1);
         _atrMult = CreateParameter("ATR Multiplier", 3.5, 1.0, 5.0, 0.1); 
         _m = CreateParameter("Month", 4, 1, 12, 1);
         _d = CreateParameter("Day", 13, 1, 31, 1);
         _y = CreateParameter("Year", 2009, 1990, 2012, 1); 
      }
      
      /* Execute a strategy - trade on a specified date */
      protected override void Execute()
      {      
         DateTime dt;         
         try {
            dt = new DateTime(_y.ValueInt, _m.ValueInt, _d.ValueInt); 
         }
         catch {
            DrawLabel(PricePane, "Invalid Date", Color.Red);
            return;
         }
         
         int b = Bars.ConvertDateToBar(dt, false);
         if (b < 1) {
            DrawLabel(PricePane, "Date does not exist on chart", Color.Red);
            return;
         }
         
         if(  _isLong.ValueInt == 1 )   
            BuyAtMarket(b, "Discretionary");
         else
            ShortAtMarket(b, "Discretionary");
         Position p = LastPosition;
         
         // After creating a position, initialize a stop object
         ATRTrail atrStop = new ATRTrail(this, Bars, p.PositionType ==
          PositionType.Long, _initStop.Value, _period.ValueInt, _atrMult.Value);
         
         for(int bar = b + 1; bar < Bars.Count; bar++)
         {            
            if (p.Active)
            {         
               if (p.PositionType == PositionType.Long)
               {
                  if( Close[bar] < atrStop.Price(bar) )
                     ExitAtMarket(bar + 1, p);
               }
               else if( Close[bar] > atrStop.Price(bar) )
                  ExitAtMarket(bar + 1, p); 
            } 
         } 
      }
   }
}

—Robert Sucher
www.wealth-lab.com

BACK TO LIST

AMIBROKER: Average True Range Trailing Stops

In “Average True Range Trailing Stops” in this issue, author Sylvain Vervoort continues his study of various trailing stop techniques. Implementing modified average true range stops is easy in AmiBroker Formula Language thanks to its built-in looping support, so we don’t need any external Dlls.

A ready-to-use AmiBroker formula for the Atr trailing stop technique is presented in Listing 1. This formula is an enhanced version of the one given in last month’s Traders’ Tips for Vervoort’s May 2009 Stocks & Commodities article. In addition to the fixed and standard Atr stop techniques given last month, the formula allows the user to select the modified Atr method from the “stop mode” list. Most of the code is unchanged, with only a calculation added for the modified Atr. To use it, enter the formula into the Editor, then press “Apply Indicator” (see Figure 4). To adjust the stop mode and its parameters, click on the chart with right mouse button and select “parameters” from the context menu.

Figure 4: AMIBROKER, modified average true range stop. Here is a daily chart of CRM showing the 3.5-multiple, modified ATR(5) trailing stop, with buy (green) and sell (red) arrows.

LISTING 1
Version(5.20); // requires v5.20  
SetBarsRequired(sbrAll);  
 
// get start date  
Start = Cross( DateNum(), ParamDate("Start date", "2005-10-30" ) );  
Started = Flip( Start, 0 );  
 
StopMode = ParamList("Stop Mode", "Fixed|Chandelier|Modified ATR" );  
StopLevel = Param("Fixed perc %", 14, 0.1, 50, 0.1)/100;  
StopATRFactor = Param("ATR multiple", 4, 0.5, 10, 0.1 );  
StopATRPeriod = Param("ATR period", 14, 3, 50 );  
 
// calculate support and resistance levels  
if( StopMode == "Fixed" ) // fixed percent trailing stop  
{  
 sup = C * ( 1 - stoplevel );  
 res = C * ( 1 + stoplevel );  
}  
else // Chandelier ATR-based stop  
if( StopMode == "Chandelier" )  
{  
 sup = C - StopATRFactor * ATR( StopATRPeriod );  
 res = C + StopATRFactor * ATR( StopATRPeriod );  
}  
else  
{  
 HL = H - L;  
 MAHL =  1.5 * MA( HL, StopATRPeriod );  
 HiLo = IIf( HL < MAHL, HL, MAHL );  
 H1 = Ref( H, -1 );  
 L1 = Ref( L, -1 );  
 C1 = Ref( C, -1 );  
 Href = IIf( L <= H1, H - C1, ( H - C1 ) - ( L - H1 ) / 2 );  
 Lref = IIf( H >= L1, C1 - L, ( C1 - L ) - ( L1 - H ) / 2 );  
 
 diff1 = Max( HiLo, HRef );  
 diff2 = Max( diff1, LRef );  
 
 ATRmod = Wilders( diff2, StopATRPeriod );  
    
 sup = C - StopATRFactor * ATRmod ;  
 res = C + StopATRFactor * ATRmod ;  
}  
 
// calculate trailing stop line  
trailARRAY = Null;  
trailstop = 0;  
for( i = 1; i < BarCount; i++ )  
{  
 if( Started[ i ] == 0 ) continue;  
 
 if( C[ i ] > trailstop AND C[ i - 1 ] > trailstop )  
   trailstop = Max( trailstop, sup[ i ] );  
 else  
 if( C[ i ] < trailstop AND C[ i - 1 ] < trailstop )  
    trailstop = Min( trailstop, res[ i ] );  
 else  
   trailstop = IIf( C[ i ] > trailstop, sup[ i ], res[ i ] );        
 
 trailARRAY[ i ] = trailstop;  
}  
 
// generate buy/sell signals based on crossover with trail stop line  
Buy = Start OR Cross( C, trailArray );  
Sell = Cross( trailArray, C );  
 
PlotShapes(Buy*shapeUpArrow,colorGreen,0,trailarray);  
PlotShapes(Sell*shapeDownArrow,colorRed,0,trailarray);  
 
Plot( Close,"Price",colorBlack,styleBar);  
//SetBarFillColor( colorYellow );  
Plot( trailARRAY,"trailing stop level", colorRed, styleLine ); 

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

BACK TO LIST

NEUROSHELL TRADER: Average True Range Trailing Stops

The average true range trailing stop technique described by Sylvain Vervoort in his article in this issue, “Average True Range Trailing Stops,” can be implemented in NeuroShell Trader by combining a few of NeuroShell Trader’s built-in indicators plus the trading strategy wizard. First, to recreate J. Welles Wilder’s exponential average–based average true range indicator, select “New Indicator…” from the Insert menu and use the Indicator Wizard to create the following indicator:

Average true range (ATR) indicator:
ExpAvg( Subtract ( Max2(High, Lag(Close,1)), Min2( Low, Lag(Close,1))), 9 )

To recreate Sylvain Vervoort’s average true range trailing stop reversal system, select “New Trading Strategy…” from the Insert menu and enter the following in the appropriate locations of the Trading Strategy Wizard:

Long protective stop:
Subtract( MaxValueSinceEntryFilled(TradingStrategy, High, 1), 
Multiply2( 3.5, WilderAverageTrueRange))
 
Short protective stop:
Add2( MinValueSinceEntryFilled(TradingStrategy, Low, 1), 
Multiply2( 3.5, WilderAverageTrueRange))

If you wish to create an average true range trailing stop system using your own trading system’s entry rules, simply combine the trailing stops listed above with your own entry/exit conditions.

To recreate the modified average true range indicator, select “New Indicator…“ from the Insert menu and use the Indicator Wizard to create the following indicators:

HiLo 
Min2(Subtract(High,Low), MovAvg(Subtract(High,Low),5))
 
Href
Subtract(Subtract(High, Lag(Close,1)), IfThenElse( A<=B(Low, Lag(High,1)), 
0, Divide(Subtract(Low, Lag(High,1)), 2)))
 
Lref
Subtract(Subtract(Lag(Close,1), Low), IfThenElse ( A>=B(High, Lag(Low,1)), 
0, Divide(Subtract(Lag(Low,1), High), 2)))
 
Modified Average True Range
ExpAvg( Max3( HiLo, Href, Lref ), 9)

To recreate the modified average true range trailing stop reversal system, enter the following formula in the appropriate locations of the Trading Strategy Wizard:

Long protective stop:
Subtract( MaxValueSinceEntryFilled(TradingStrategy #2, High, 1), 
Multiply2( 3.5, ModifiedAverageTrueRange))
 
Short protective stop:
Add2( MinValueSinceEntryFilled(TradingStrategy #2, Low, 1), 
Multiply2( 3.5, ModifiedAverageTrueRange))

If you wish to create a modified average true range trailing stop system using your own trading system’s entry rules, simply combine the modified average true range trailing stops listed above with your own entry/exit conditions.

Figure 5: NeuroShell TRADER, AVERAGE TRUE RANGE TRAILING STOP SYSTEM

If you have NeuroShell Trader Professional, you can also choose whether the system parameters should be optimized. After backtesting the trading strategies, use the “Detailed Analysis…” button to view the backtest and trade-by-trade statistics for each strategy.

For more information on NeuroShell Trader, visit www.NeuroShell.com.

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

BACK TO LIST

AIQ: Average True Range Trailing Stops

The Aiq code is shown here for the date-specific version of the average true range (Atr) trailing stop and the modified average true range (AtrM) trailing stop described by Sylvain Vervoort in his article in this issue, “Average True Range Trailing Stops.”

This Atr stop code can be pasted into any system of your choice and then used as the exit. The date-specific version (in which a start date is manually entered in the Eds code as an input, and then the stop starts trailing as of that date) has been coded and provided here as well. This stop can be plotted on a chart for the purposes of checking trades one at a time. Be sure to set all the inputs to match your objective.

!! AVERAGE TRUE RANGE TRAILING STOP (DATE SPECIFIC VERSION)
! Author: Sylvain Vervoort, TASC, June 2009
! Coded by: Richard Denning 4/12/09

! INPUTS:
mo 	is 	10.
da 	is 	2.
yr 	is 	2008.
isLong 	is 	1.          !  1 = for longs, 0 = for shorts
atrLen	is 	5.
atrMult	is 	3.5.

! ABBREVIATIONS:
C is [close].
C1 is valresult(C,1).
H is [high].
L is [low].

! AVERAGE TRUE RANGE
TR is Max(H - L,max(abs(C1 - L),abs(C1- H))). 
ATR is expAvg(TR,atrLen).

! ATR TRAILING STOP FROM DATE
startDate is makeDate(mo,da,yr).
daysSinceStart is scanany(ruledate() = startDate, 5040) 
	then offSetToDate(month(),day(),year()).
loss is ATR * atrMult.    
longStop is C-Loss.
shortStop is C+Loss.
maxVal is iff(reportdate() >= startDate,^highresult(longStop,^daysSinceStart+1),C). 
minVal is iff(reportdate() >= startDate,^lowresult(shortStop,^daysSinceStart+1),C).

! PLOT "TRAIL" AS CUSTOM INDICATOR TO SEE STOP ON CHART:
trail is iff(reportdate() >= startDate and  isLong = 1,maxVal,
	iff(reportdate() >= startDate and  isLong <> 1,minVal,C)).

Buy if reportdate() = startDate and isLong = 1.
Exit if C < trail.
SellShort if reportdate() = startDate and isLong <> 1.
Cover if C > trail.

!_____________The following code must go on a second EDS file_______________

!! MODIFIED AVERAGE TRUE RANGE TRAILING STOP (DATE SPECIFIC VERSION)
! Author: Sylvain Vervoort, TASC, June 2009
! Coded by: Richard Denning 4/12/09

! INPUTS:
mo 	is 	10.
da 	is 	2.
yr 	is 	2008.
isLong 	is 	1.          !  1 = for longs, 0 = for shorts
atrLen	is 	5.
atrMult	is 	3.5.

! ABBREVIATIONS:
C is [close].
C1 is valresult(C,1).
H is [high].
H1 is valresult(H,1).
L is [low].
L1 is lowresult(L,1).

! MODIFIED AVERAGE TRUE RANGE
AvgRng is simpleAvg(H - L, atrLen) .  
HiLo is iff(H - L < 1.5 * AvgRng, H - L, 1.5*AvgRng).
HLmax is (H - C1) - (L - H1) / 2.
Href is iff(L <= H1,H - C1,HLmax).
LHmax is (C1 - L) - (L1 - H) / 2.
Lref is iff(H >= L1, C1 - L, LHmax).
Diff1 is Max(HiLo,Href).
Diff2 is Max(Diff1,Lref).
ATRM is expAvg(Diff2,atrLen*2-1,0).

! ATR TRAILING STOP FROM DATE
startDate is makeDate(mo,da,yr).
daysSinceStart is scanany(ruledate() = startDate, 5040) 
	then offSetToDate(month(),day(),year()).
loss is ATRM * atrMult.    
longStop is C-Loss.
shortStop is C+Loss.
maxVal is iff(reportdate() >= startDate,^highresult(longStop,^daysSinceStart+1),C). 
minVal is iff(reportdate() >= startDate,^lowresult(shortStop,^daysSinceStart+1),C).

! PLOT "TRAIL" AS CUSTOM INDICATOR TO SEE STOP ON CHART:
trail is iff(reportdate() >= startDate and  isLong = 1,maxVal,
	iff(reportdate() >= startDate and  isLong <> 1,minVal,C)).

Buy if reportdate() = startDate and isLong = 1.
Exit if C < trail.
SellShort if reportdate() = startDate and isLong <> 1.
Cover if C > trail.

The code can be downloaded from the Aiq website at www.aiqsystems.com and also from www.TradersEdgeSystems.com/traderstips.htm. It can also copied and pasted from the Stocks & Commodities website at Traders.com.

—Richard Denning
for AIQ Systems
richard.denning@earthlink.net

BACK TO LIST

TradersStudio: Average True Range Trailing Stops

The TradersStudio implementation of the fixed-percentage trailing stop system and the date-specific version based on “Average True Range Trailing Stops” by Sylvain Vervoort is discussed here.

The average true range (Atr) trailing stop should have an advantage over the fixed-percentage trailing stop that was tested last month in my May 2009 Traders’ Tip, since the stop can adapt to the changing volatility of both the overall market as well as to each individual stock’s volatility and changes in volatility.

In my May 2009 Traders’ Tip, I modified Vervoort’s fixed-percentage trailing stop system by adding market timing and also by trading both the long and short sides. This system, if traded both long and short, would be always in, but since I added a market-timing filter based on a general-market trend-following filter, it will only trade long when the market trend is up or short when the market trend is down.

The coded version of Vervoort’s Atr trailing stop system that I am supplying here has the options of trading either long only, short only, or both long and short. It also has the option to apply a market-trend filter using the S&P 500 index (Spx) to determine whether to trade long or short. I decided to stick with the author’s list of stocks for the tests.

One advantage in testing stocks with TradersStudio over other programs is that both the unadjusted price series as well as the split-adjusted series are available in the tests. This can make a big difference in the computation of commissions when they are based on the number of shares traded. (Other programs compute commissions on a cents-per-share basis, and unless you know the actual price of the stock and the actual number of shares that would have been traded, commissions cannot be computed accurately.) In addition, with TradersStudio, we are able to correctly apply a minimum price rule to eliminate very low-priced stocks. When only split-adjusted data is available, we cannot accurately apply a price filter because we don’t know whether a stock is low-priced due to a split or was really trading at a low price in real time. TradersStudio also has the ability to compute the dividends that you would have been received or paid (if short).

Figure 6: TITLE.blurb

In Figure 6, I show a comparison of the equity curves: the left one represents trading both long and short using a trend filter on the Spx with optimized parameters using the fixed-percentage trailing stop system from the May 2009 issue, while the one on the right shows this issue’s modified Atr trailing stop (AtrM) system with optimized parameters. Just by looking at the two equity curves, it’s hard to tell which is preferable, although the AtrM (right curve) appears smoother with smaller drawdowns. Looking at the table in Figure 7, which shows some key metrics for the two trailing-stop methods, we see that the AtrM stops are preferable, since we obtain slightly more net profit with lower drawdown, better profit factor, and better profit-to-maximum drawdown ratios with fewer trades. I also found that there is a slight improvement (not shown) by using the AtrM system versus the Atr system.

Figure 7: TITLE.blurb

To measure the robustness of the parameter sets from the AtrM system optimization, in Figure 8 I show two three-dimensional models. The left model shows the two parameters compared to the net profit, and the right model shows the two parameters compared to the maximum drawdown. The Atr-length parameter is less sensitive to changes than the Atr multiple. The range of good parameters is five to 10 days for the Atr length, and 4.5 to 5.5 for the Atr multiple. All tests used 300 days for the moving average length on the Spx trend filter. I used a TradersStudio add-in to produce the three-dimensional models.

Figure 8: TITLE.blurb

The code can be downloaded from the TradersStudio website at www.TradersStudio.com ->Traders Resources->FreeCode as well as from www.TradersEdgeSystems.com/traderstips.htm. It can also be copied and pasted from the Stocks & Commodities website at www.traders.com.

' AVERAGE TRUE RANGE TRAILING STOPS (ATR and ATRM)
' Author: Sylvain Vervoort, TASC June 2009
' Coded by: Richard Denning 4/8/09
' www.tradersEdgeSystems.com

Sub ATR_TSSR(tsStartDate,WilderLenATR,multATR,longOnly,useMktTm,spxLen,useModATR)
'tsStartDate = date that trading is to start after bars back has been satisfied
'           use TradeStation date format of YYYMMDD example 1/20/2003 = 1030120
'WilderLenATR = 5, multATR = 3.5, unitSiz = 1, longOnly = 2 (both long and short)
'longOnly = 1 (trade long side only), longOnly = -1 (short side only)
'useMktTm = 1 will apply an SPX trend filter so that trades are taken only in
'           the direction of the trend of the SP500 index; any other value
'           and no market timing filter is applied
' spxLen = 250
' useModATR = 1 uses modified ATR; any other value uses standard ATR
Dim unitSiz
Dim trail As BarArray
Dim rsAIQst As BarArray
Dim size As BarArray
Dim SPXc As BarArray
Dim OKtoBuy, OKtoSell
unitSiz = 1
SPXc = C Of independent1
OKtoBuy = SPXc > Average(SPXc,spxLen,0) And SPXc[1] > Average(SPXc,spxLen,1)
OKtoSell = SPXc < Average(SPXc,spxLen,0) And SPXc[1] < Average(SPXc,spxLen,1)
If useModATR = 1 Then
    trail = ATRM_TRAIL_STOP(WilderLenATR, multATR)
Else
    trail = ATR_TRAIL_STOP(WilderLenATR, multATR)
End If

size = (1000 / TSCLose) / unitSiz

If Not CrossesOver(C,trail,0) And Not CrossesUnder(C,trail,0) Then size = size[1]
If useMktTm = 1 Then
    If Date >= MigrateDate(tsStartDate) Then
        If longOnly >= 1 And OKtoBuy Then
            If CrossesOver(C,trail,0) Then Buy("LE",size,0,CloseEntry,Day)
            If CrossesUnder(C,trail,0) Then ExitLong("LX","",size[1],0,
            CloseExit,Day)
        End If 
        If (longOnly <= 0 Or longOnly = 2) And OKtoSell Then
            If CrossesUnder(C,trail,0) Then Sell("SE",size,0,CloseEntry,Day)
            If CrossesOver(C,trail,0) Then ExitShort("SX","",size[1],0,
            CloseExit,Day)
        End If
    End If
Else
    If Date >= MigrateDate(tsStartDate) Then
        If longOnly >= 1 Then
            If CrossesOver(C,trail,0) Then Buy("LE",size,0,CloseEntry,Day)
            If CrossesUnder(C,trail,0) Then ExitLong("LX","",size[1],0,
            CloseExit,Day)
        End If 
        If (longOnly <= 0 Or longOnly = 2) Then
            If CrossesUnder(C,trail,0) Then Sell("SE",size,0,CloseEntry,Day)
            If CrossesOver(C,trail,0) Then ExitShort("SX","",size[1],0,
            CloseExit,Day)
        End If
    End If
End If
End Sub

'_____________________________________________

Function ATR_Wilder(WilderLen)
' computes average true range using Wells Wilder averaging method
    ATR_Wilder = XAverage(TrueRange,WilderLen*2-1,0)
End Function

'_____________________________________________

Function ATR_TRAIL_STOP(WilderLen,multATR)
' suggested default parameters: WilderLen = 5, multATR = 3.5
Dim loss
Dim longStop
Dim shortStop
Dim maxVal
Dim minVal
Dim ATRval As BarArray
Dim trail As BarArray
loss = ATR_Wilder(WilderLen)*multATR
longStop = C - loss
shortStop = C + loss
maxVal = Max(trail[1],longStop)
minVal = Min(trail[1],shortStop)
If C>trail[1] And C[1]>trail[2] Then
    trail = maxVal
Else If Ctrail[1] And C[1]trail[2] Then
    trail = shortStop
Else
    trail = C
End If
End If
End If
End If
    
ATR_TRAIL_STOP = trail

End Function

'_____________________________________________

Function ATRM_Wilder(WilderLen)
' computes average true range as modified using Wells Wilder averaging method
    Dim AvgRng As BarArray
    Dim HiLo As BarArray
    Dim Href As BarArray
    Dim Lref As BarArray
    Dim HLmax As BarArray
    Dim LHmax As BarArray
    Dim Diff1 As BarArray
    Dim Diff2 As BarArray
    
    AvgRng = Average(H - L, WilderLen)    
    HiLo = IIF(H - L < 1.5 * AvgRng, H - L, 1.5*AvgRng)
    HLmax = (H - C[1]) - (L - H[1]) / 2
    Href = IIF(L <= H[1],H - C[1],HLmax)
    LHmax = (C[1] - L) - (L[1] - H) / 2
    Lref = IIF(H >= L[1], C[1] - L, LHmax)
    Diff1 = Max(HiLo,Href)
    Diff2 = Max(Diff1,Lref)
    ATRM_Wilder = XAverage(Diff2,WilderLen*2-1,0)
End Function

'_____________________________________________

Function ATRM_TRAIL_STOP(WilderLen,multATR)
' coputes the modified ATR trailing stop
' suggested default parameters: WilderLen = 5, multATR = 3.5
Dim loss
Dim longStop
Dim shortStop
Dim maxVal
Dim minVal
Dim ATRval As BarArray
Dim trail As BarArray
loss = ATRM_Wilder(WilderLen)*multATR
longStop = C - loss
shortStop = C + loss
maxVal = Max(trail[1],longStop)
minVal = Min(trail[1],shortStop)
If C>trail[1] And C[1]>trail[2] Then
    trail = maxVal
Else If Ctrail[1] And C[1]trail[2] Then
    trail = shortStop
Else
    trail = C
End If
End If
End If
End If
  
ATRM_TRAIL_STOP = trail

End Function

'_____________________________________________

'ATR Trailing Stop Indicator
sub ATR_TRAIL_STOP_IND(WilderLen,multATR)
    plot1(ATR_TRAIL_STOP(WilderLen,multATR))
End Sub

'_____________________________________________

'ATR Modified Trailing Stop Indicator
Sub ATRM_TRAIL_STOP_IND(WilderLen,multATR)
    plot1(ATRM_TRAIL_STOP(WilderLen,multATR))
End Sub

'_____________________________________________

—Richard Denning
for TradersStudio
richard.denning@earthlink.net

BACK TO LIST

STRATASEARCH: Average True Range Trailing Stops

In the current series of articles by Sylvain Vervoort on stop methods, including the one in this issue, “Average True Range Trailing Stops,” Vervoort has provided some helpful methods for implementing trailing stops. Based on our tests, the strategy presented in this month’s article provides some performance increases over the methods discussed in his article last month (“Using Initial And Trailing Stops”).

In our tests, both the fixed-percentage trailing stop method and the modified Atr trailing stop method were run against the Nasdaq 100 components from 2004 to 2007 using a spread of 0.04 and commissions of $10.00 on either side. A range of variables was also added to test the percentage, period, and factor values. Surprisingly, every parameter set for both of the trailing stop approaches created profitable results. However, the modified Atr trailing stop clearly had the better performance, with higher returns and shorter holding periods.

Figure 9: STRATASEARCH, Modified ATR with trailing stops. One approach is to buy when the price rises above the modified ATR line, and sell when the price crosses below.

One issue, noted last month in this column as well, is that the percentage profitability never rose above 50% for either approach. Likewise, both approaches performed poorly when tested exclusively in 2008. Thus, these trailing stops may benefit greatly from the use of supporting indicators. The automated search in StrataSearch can help users find supporting indicators that improve either of these trailing-stop approaches.

As with all other StrataSearch Traders’ Tips, additional information, including plugins, can be found in the Shared Area of the StrataSearch user forum.

//****************************************************
// ATR Modified
//****************************************************
period = parameter("Period");
HiLo=If(H-L<1.5*Mov(H-L,period,S),H-L,
	1.5*Mov(H-L,period,S));
Href=If(L<=Ref(H,-1),H-Ref(C,-1),
	(H-Ref(C,-1))-(L-Ref(H,-1))/2);
Lref=If(H>=Ref(L,-1),Ref(C,-1)-L,
	(Ref(C,-1)-L)-(Ref(L,-1)-H)/2);
diff1=higher(HiLo,Href);
diff2=lower(diff1,Lref);
ATRMOD = wsm(diff2,period);

—Pete Rast
Avarin Systems Inc.
www.StrataSearch.com

BACK TO LIST

STOCKFINDER: Average True Range Trailing Stops

We’ve created a chart for StockFinder that shows plots for the fixed-percentage stop, average true range trailing stop (Atr TS), modified Atr TS, and a modified Atr, based on ’Average True Range Trailing Stops“ by Sylvain Vervoort. The standard average true range is already available in the indicator library.

To load the chart into any layout, click the Shared Items icon (envelope) at the top of the StockFinder screen then choose “Browse other users’ shared items” from the menu that appears. Click the Charts tab from the Shared Items window that appears and search for “June Traders’ Tips.” Open the chart by selecting it from the list and clicking the Open button. The chart will open in your current layout. You can save the chart by clicking the Save button at the top of the chart.

The red plot on price is the fixed-percentage stop from Vervoort’s article. Clicking it brings up its Edit window. From there, you can change the month, day, and year for the trade open, the stop, and the percentage. The blue plot on price is the Atr TS from the article. Clicking it brings up its Edit window. From there you can change the month, day, and year for the trade open, the stop, Atr period, and multiple. The yellow plot on price is the modified Atr TS from the article. Clicking it brings up its Edit window. From there you can change the month, day, and year for the trade open, the stop, Atr period, and multiple. The bottom pane shows the modified Atr plot, which can also be edited by clicking on it.

Rules to scan, sort, or color plots can be created for any plot by clicking on it and using the appropriate tab from the Edit window. If you have any questions about the chart or plots, visit the Worden support forums at www.Worden.com/Training.

For more information on the software or to start your free trial, visit www.StockFinder.com.

Figure 10: STOCKFINDER, ATR TRAILING STOP. This chart demonstrates the fixed-percentage stop, average true range trailing stop (ATR TS), modified ATR TS, and a modified ATR.

—Craig Shipman
Worden Brothers, Inc
www.Worden.com, www.StockFinder.com

BACK TO LIST

NeoTicker: Average True Range Trailing Stops

In the article “Average True Range Trailing Stops” in this issue, Sylvain Vervoort presents a modified version of the average true range indicator. This modified version, along with the trailing stop based on modified Atr, can be implemented in NeoTicker using formula language.

The indicator is named “Tasc modified average true range” (Listing 1) with three parameters: integer parameter Atr period; real number parameter Atr multiplication; and datetime parameter start date. Start date is a datetime setting parameter that determines which date the trailing stop will beginning plotting. This indicator has two plots: the first plot will return the modified Atr value, and the second plot is the trailing stop value. By default, only the trailing stop plot will show (Figure 11).

Figure 11: NEOTICKER, ATR TRAILING STOP

LISTING 1
$period := choose(param1 < 1, 1, param1 > 100, 100, param1);
$atrfact := choose(param2 < 1, 1, param2 > 10, 10, param2);
MidPrice := H-L;
$HiLo := if(MidPrice < 1.5*average(MidPrice, $period),
            MidPrice, 1.5*average(MidPrice, $period));
$Href := if (L <= H(1), H-C(1), ((H-C(1))-(L(1)-H))/2);
$Lref := if (H >= L(1), C(1)-L, ((C(1)-L)-(L(1)-H))/2);
diff1 := maxlist($HiLo, $Href);
diff2 := maxlist(diff1, $Lref);
$atrmod := 1/$period*diff2 + ($period-1)/$period*qc_xaverage(1,diff2,$period);
$loss := $atrfact*$atrmod;
plot1 := $atrmod;
plot2 := choose(C>plot2(1) and C(1)>plot2(1), maxlist(plot2(1),C-$loss),
                Cplot2(1), C-$loss, C+$loss);
success2 := date(0) > param3;

A downloadable version of the indicator will be available at the NeoTicker blog site (https://blog.neoticker.com).

—Kenneth Yuen, TickQuest Inc.
www.tickquest.com

BACK TO LIST

TRADECISION: Average True Range Trailing Stops

In his series of articles on stop methods, Sylvain Vervoort demonstrates the importance of considering a warning signal and setting stops at the right time to avoid getting stopped out by the normal noise of the market. This issue’s article, “Average True Range Trailing Stops,” describes a trailing-stop method based on the average true range (Atr) trailing stop.

Using the Function Builder in Tradecision, create the Stop_Trail_ATR_Mod function for a modified Atr trailing stop value as follows:

function (Period:numeric=5,atrfact:Numeric=3.5):Numeric;
var
 HiLo:=0;
 Href:=0;
 Lref:=0;
 diff1:=0;
 diff2:=0;
 atrmod:=0;
 loss:=0;
 result:=0;
end_var

   HiLo:=iff(H - L < 1.5 * Mov(H - L, period, S), H - L, 1.5 * Mov(H - L,
     period, S));
   Href:=iff(L <= Ref(H, -1), H - Ref(C, -1), (h - ref(C, -1)) - (L -
     Ref(H, -1)) / 2);
   Lref:=iff(H >= Ref(L, -1), Ref(C, -1) - L, (Ref(C, -1) - L) - (Ref(L, -1)
    - H) / 2);

   diff1:=Max(HiLo, Href);
   diff2:=Max(diff1, Lref);

   atrmod:=EMA(diff2,period);
   loss:=atrfact*atrmod;

if HISTORYSIZE <= period then result := C;
else
  begin
    if C > this\1\ AND C\1\ > this\1\  then result := Max(this\1\,C-loss);
    else
    begin
       if C < this\1\ then result := Min(this\1\,C+loss);
       else
       begin
          if C > this\1\ then result := C-loss;
          else result := C+loss;
       end;
    end;
  end;
return result;
 
Then you specify the strategy rules in Tradecision's Strategy Builder:
Entry Long:
if Date() = 080102 then return true;
return false;

Exit Long:
return CrossBelow(Stop_Trail_ATR_Mod(5,3.5),C);
Entry Short:
if Date() = 081201 then return true;
return false;

Exit Short:
return CrossAbove(Stop_Trail_ATR_Mod(5,3.5),C);

Figure 12: TRADECISION, MODIFIED AVERAGE TRUE RANGE TRAILING STOP. Here is a 3.5 times five-period modified ATR average plotted on a chart of DD.

As mentioned in Vervoort’s article, you’ll need to enter the starting date manually. To define Date(), use a numeric value in the Yymmdd format. Date returns “080102” if the day is January 2, 2008. See Figure 12.

To import the strategy into Tradecision, visit the area “Traders’ Tips from Tasc magazine” at https://tradecision.com/support/tasc_tips/tasc_traders_tips.htm or copy the code from the Stocks & Commodities website at www.traders.com.

—Yana Timofeeva
Alyuda Research, Inc.
510 931-7808, sales@tradecision.com
www.tradecision.com

BACK TO LIST

NINJATRADER: Average True Range Trailing Stops

The Atr trailing stop technique discussed by Sylvain Vervoort in his article in this issue, “Average True Range Trailing Stops,” has been implemented as an indicator available for download at www.ninjatrader.com/SC/June2009SC.zip.

Once it is downloaded, from within the NinjaTrader Control Center window, select the menu File > Utilities > Import NinjaScript and select the downloaded file. This indicator is for NinjaTrader version 6.5 or greater.

You can review the indicator’s source code by selecting the menu Tools > Edit NinjaScript > Indicator from within the NinjaTrader Control Center window and selecting “AtrTrailingStop.” A sample chart is shown in Figure 13.

NinjaScript indicators are compiled Dlls that run native, not interpreted, which provides you with the highest possible performance.

Figure 13: NINJATRADER, ATR TRAILING STOP. Here is an example of the ATR trailing stop indicator on a daily chart of AMD.

—Raymond Deux & Josh Peng
NinjaTrader, LLC
www.ninjatrader.com

BACK TO LIST

WAVE59: Average True Range Trailing Stops

In “Average True Range Trailing Stops” in this issue, Sylvain Vervoort implements an Atr stop algorithm that he uses as both a reversal system and as a way to apply a trailing stop to open positions entered using other methods.

We were interested to see how Vervoort’s trailing stop method handled recent action in the volatile stock indexes, so we applied it to the Dow Jones Industrial Average. You can see in Figure 14 that it stayed short for the latter half of 2008 and reversed to a long position in March 2009. According to this tool, the market looks ready to regain some of the losses posted last year. Just be wary if we cross back underneath the red line!

Figure 14: WAVE59, ATR TRAILING STOP. Here is Vervoort’s trailing stop method applied to the Dow Jones Industrial Average. It stayed short for the latter half of 2008 and reversed to a long position in March 2009.

We are offering four scripts that implement Vervoort’s approach in Wave59. As always, users of Wave59 can download these scripts directly using the QScript Library, found at https://www.wave59.com/library.

Indicator 1: ATR reversal system
#This script plots Sylvain Vervoort's ATR Stop Value
#as described in the June 2009 issue of Stocks&Commodities
#Period: period to get ATR value, using wilder's average function
#Multiplier: factor to multiply the ATR value by to calculate stop amount
#Act_as_System: if true, use as trading system, otherwise just lines
input:period(5),multiplier(3.5),act_as_system(false),color(red),thickness(1);

#initialize variables
if (barnum==barsback) {
   stopval=close;
   buysell=1;
}

#calculate atr values
atr=wilder_average(truerange(),period);
bigatr=atr*multiplier;

#calculate long stops
if (buysell>0) {
   stopval=close-bigatr;
   stopval=max(stopval,stopval[1]);
   if (close<stopval) {
      buysell=-1;
      stopval=close+bigatr;
      if (act_as_system==true) exitlong(0,close,"market","onebar");
   }
}

#calculate stort stops
else if (buysell<0) {
     stopval=close+bigatr;
     stopval=min(stopval,stopval[1]);
     if (close>stopval) {
        buysell=1;
        stopval=close-bigatr;
        if (act_as_system==true) buy(1,close,"market","onebar");
     }
}

#plot the lines
plot1=stopval;
color1=color;
thickness1=thickness;

 
Indicator 2: ATR system using a fixed date

#This script plots Sylvain Vervoort's ATR Stop Value
#as described in the June 2009 issue of Stocks&Commodities.
#Use this version to manage an actual trade based on a specific date.
#Period: period to get ATR value, using wilder's average function
#Multiplier: factor to multiply the ATR value by to calculate stop amount
#Startyear, Startmonth, Startday: Day to Begin plotting on
input:startyear(2009),startmonth(1),startday(1),longposition(true),
   period(5),multiplier(3.5),color(red),thickness(1);

#initialize variables
if (barnum==barsback) {
   startbar=date_to_bar(startyear,startmonth,startday,time);
   stopval=close;
   buysell=1;
   if (longposition==false) buysell=-1;
   txref=text(barnumber, close, "", color, tx_left, 8);
}

#calculate atr values
atr=wilder_average(truerange(),period);
bigatr=atr*multiplier;

if (barnum<startbar)
{
   if (buysell>0) stopval=close-bigatr;
   else stopval=close+bigatr;
}
else
{
    #calculate long stops
    if (buysell>0) {
       stopval=close-bigatr;
       stopval=max(stopval,stopval[1]);
       if (close<stopval) {
          buysell=-1;
          stopval=close+bigatr;
       }
    }

    #calculate stort stops
    else if (buysell<0) {
         stopval=close+bigatr;
         stopval=min(stopval,stopval[1]);
         if (close>stopval) {
            buysell=1;
            stopval=close-bigatr;
         }
    }

    #plot the lines
    plot1=stopval;
    color1=color;
    thickness1=thickness;

    #plot a label
    text_setbar(txref,barnum+5);
    text_setprice(txref,stopval);
    text_setstring(txref,to_string(stopval));
}
 
Indicator 3: This script uses Vervoort's Modified ATR calculation

#This script plots Sylvain Vervoort's Modified ATR Stop Value
#as described in the June 2009 issue of Stocks&Commodities
#Period: period to get modified ATR value
#Multiplier: factor to multiply the ATR value by to calculate stop amount
#Act_as_System: if true, use as trading system, otherwise just lines
input:period(5),multiplier(3.5),act_as_system(false),color(red),thickness(1);

#initialize variables
if (barnum==barsback) {
   stopval=close;
   buysell=1;
}

#calculate Vervoort's modified atr values
simplehilo=average(high-low,period);
if (high-low<1.5*simplehilo)
    hilo=high-low;
else
    hilo=simplehilo;
href=abs(high-close[1]);
if (low>high[1]) href-=(low-close[1])/2;
lref=abs(low-close[1]);
if (high<low[1]) lref-=(close[1]-high)/2;
modatr=max(lref,href,hilo);
bigatr=wilder_average(modatr,period);
bigatr*=multiplier;

#calculate long stops
if (buysell>0) {
   stopval=close-bigatr;
   stopval=max(stopval,stopval[1]);
   if (close<stopval) {
      buysell=-1;
      stopval=close+bigatr;
      if (act_as_system==true) exitlong(0,close,"market","onebar");
   }
}

#calculate stort stops
else if (buysell<0) {
     stopval=close+bigatr;
     stopval=min(stopval,stopval[1]);
     if (close>stopval) {
        buysell=1;
        stopval=close-bigatr;
        if (act_as_system==true) buy(1,close,"market","onebar");
     }
}

#plot the lines
plot1=stopval;
color1=color;
thickness1=thickness;
 
Indicator 4: This script uses Vervoort's Modified ATR calculation to
 manage a specific trade

#This script plots Sylvain Vervoort's ATR Stop Value
#as described in the June 2009 issue of Stocks&Commodities.
#Use this version to manage an actual trade based on a specific date.
#Period: period to get ATR value, using wilder's average function
#Multiplier: factor to multiply the ATR value by to calculate stop amount
#Startyear, Startmonth, Startday: Day to Begin plotting on
input:startyear(2009),startmonth(1),startday(1),longposition(true),
   period(5),multiplier(3.5),color(red),thickness(1);

#initialize variables
if (barnum==barsback) {
   startbar=date_to_bar(startyear,startmonth,startday,time);
   stopval=close;
   buysell=1;
   if (longposition==false) buysell=-1;
   txref=text(barnumber, close, "", color, tx_left, 8);
}

#calculate Vervoort's modified atr values
simplehilo=average(high-low,period);
if (high-low<1.5*simplehilo)
    hilo=high-low;
else
    hilo=simplehilo;
href=abs(high-close[1]);
if (low>high[1]) href-=(low-close[1])/2;
lref=abs(low-close[1]);
if (high<low[1]) lref-=(close[1]-high)/2;
modatr=max(lref,href,hilo);
bigatr=wilder_average(modatr,period);
bigatr*=multiplier;

if (barnum<startbar)
{
   if (buysell>0) stopval=close-bigatr;
   else stopval=close+bigatr;
}
else
{
    #calculate long stops
    if (buysell>0) {
       stopval=close-bigatr;
       stopval=max(stopval,stopval[1]);
       if (close<stopval) {
          buysell=-1;
          stopval=close+bigatr;
       }
    }

    #calculate stort stops
    else if (buysell<0) {
         stopval=close+bigatr;
         stopval=min(stopval,stopval[1]);
         if (close>stopval) {
            buysell=1;
            stopval=close-bigatr;
         }
    }

    #plot the lines
    plot1=stopval;
    color1=color;
    thickness1=thickness;

    #plot a label
    text_setbar(txref,barnum+5);
    text_setprice(txref,stopval);
    text_setstring(txref,to_string(stopval));
}


--------------------------------------------

—Earik Beann
Wave59 Technologies Int’l, Inc.
www.wave59.com

BACK TO LIST

VT TRADER: Average True Range Trailing Stops

This Traders’ Tip is based on the article “Average True Range Trailing Stops” by Sylvain Vervoort in this issue. We’ll be offering the Atr trailing stop reversal-level indicator for download in our online forums. The VT Trader code and instructions for setting up the indicator are as follows:

  1. Navigator Window>Tools>Indicator Builder>[New] button
  2. In the Indicator Bookmark, type the following text for each field:
    Name: TASC - 06/2009 - Trailing Stoploss Reversal Level (ATR)
    Short Name: tasc_TSRLATR
    Label Mask: TASC - 06/2009 - Trailing Stoploss Reversal Level
     (ATR) (%price%,%atrperiods%,%atrmult%) | %TSL%
    Placement: Price Frame
    Inspect Alias: tasc_TSRLATR

  3. In the Input Bookmark, create the following variables:
    [New] button... Name: price , Display Name: Price , Type: 
    price , Default: close
    [New] button... Name: atrperiods , Display Name: ATR Periods ,
     Type: integer , Default: 14
    [New] button... Name: atrmult , Display Name: ATR Multiplier ,
     Type: float , Default: 3.0000

  4. In the Output Bookmark, create the following variables:
    [New] button...
    Var Name: TSL	
    Name: (TSL)
    Line Color: red
    Line Width: thin
    Line Type: dashed

  5. In the Formula Bookmark, copy and paste the following formula:
    {Provided By: Capital Market Services, LLC & Visual Trading 
    Systems, LLC}
    {Copyright: 2009}
    {Description: TASC, June 2009 - "Average True Range Trailing Stops"
     by Sylvian Vervoort}
    {File: tasc_TSRLATR.vtsrc - Version 1.0}
    
    Loss:= ATR(atrperiods)*atrmult;
    
    TSL:= if(BarCount()>=atrperiods,
          if(ref(price,-1)>PREV(0) AND price>PREV(0),max(PREV(0),price-Loss),
          if(ref(price,-1)<PREV(0) AND price<PREV(0),min(PREV(0),price+Loss),
          if(Cross(price,PREV(0)),price-Loss,
          if(Cross(PREV(0),price),price+Loss,
          if(price=PREV(0),PREV(0),PREV(0)))))),
          NULL);

  6. Click the “Save” icon to finish building the ATR trailing stoploss reversal level indicator.

Figure 15: VT TRADER, ATR TRAILING STOP. Here is an example of the ATR trailing stop reversal-level indicator on a 30-minute candlestick chart of EUR/USD.

To attach the indicator to a chart (Figure 15), click the right mouse button within the chart window and then select “Add Indicator” -> “TASC - 06/2009 - Trailing Stoploss Reversal Level (Atr)” from the indicator list.

To learn more about VT Trader, visit www.cmsfx.com.

Forex trading involves a substantial risk of loss and may not be suitable for all investors.

—Chris Skidmore
Visual Trading Systems, LLC (courtesy of CMS Forex)
(866) 51-CMSFX, trading@cmsfx.com
www.cmsfx.com

BACK TO LIST

TRADE-IDEAS: Average True Range Trailing Stops

“Ideas are easy; it’s execution that’s hard.”—Jeff Bezos (Amazon.com)

In “Average True Range Trailing Stops” in this issue, Sylvain Vervoort creates a trailing stop based on the average true range value on a portfolio of 25 stocks and pursues the question of whether it’s a better stop than the fixed-percentage trailing stop method demonstrated in his May 2009 article. Subscribers to Trade-Ideas Pro who use our event-based backtesting tool, The OddsMaker, already understand the different premise these tools use to find high-probability winning trades. To recap briefly, The OddsMaker doesn’t just look at 25 stocks, à priori, to generate backtest results, it considers any stock that matched a desired pattern in the market, finds that stock, and applies the backtest’s rule set before summing up the results into a detailed set of totals: win rate, average winner, average loser, net winnings, and confidence factor. (See Figure 18.) As such, we provide an alternative stop method and another strategy for your consideration.

The wiggle
At Trade-Ideas we use a custom, dynamic stop that takes into account a stock’s 15-minute average volatility multiplied by the relative volume (an indexed ratio of what the current volume is over its historical volume of the stock at the time a trade is made). This measure is called the wiggle.

The wiggle can be further explained with an example. Nflx’s 15-minute average volatility is $0.3306/15 minutes. If the relative volume of Nflx at the time of an alert is 1.5 (that is, trading at 50% above what it normally trades at this time of the day of the alert based on accumulated volume of the day), then the wiggle is $0.50 (that is, $0.3306*1.5). Look up the volatility values of any stock at the Trade-Ideas.com Stock Research section. Imagine using a $0.50 stop and attempting to stay in a GS short or long; chances are, you will be correct about the trade but get stopped out, only to watch the stock do exactly what you thought it would, which we all know is painful. The wiggle creates a customized stop that takes into account the characteristics of each stock.

The wiggle is used in the strategy, “Modified Atr Volatility Stop” and is based on the Trade-Ideas inventory of alerts and filters found in our flagship product, Trade-Ideas Pro. The trading rules are modeled and backtested in its add-on tool, The OddsMaker.

Description: “Modified ATR Volatility Stop” 
Provided by:
Trade Ideas (copyright © Trade Ideas LLC 2009). All rights reserved. 
For educational purposes only. Remember these are sketches meant to 
give an idea how to model a trading plan. Trade-Ideas.com and all 
individuals affiliated with this site assume no responsibilities 
for trading and investment results.

Figure 16: TRADE-IDEAS, ALERTS CONFIGURATION. The combination of alerts and filters used to create Sylvain Vervoort’s modified ATR volatility stop strategy are shown here.

Type or copy/paste this shortened string directly into a browser then copy/paste the full length link into Trade-Ideas PRO using the “Collaborate” feature (right-click in any strategy window):

https://bit.ly/1WrpZ (case sensitive)

This strategy also appears on the Trade-Ideas blog, https://marketmovers.blogspot.com/, or you can build the strategy from Figure 16, which shows the configuration of this strategy, where one alert and nine filters are used with the following settings:

  • Running Up Now (in 1 minute or less), $0.75
  • Min Price Filter = 5 ($)
  • Max Price Filter = 50 ($)

The definitions of these indicators appear here: https://www.trade-ideas.com/Help.html.

That’s the strategy, but what about the trading rules? How should the opportunities that the strategy finds be traded? For the stop-loss, we used one of the more advanced options available in the OddsMaker. Instead of using a traditional stop-loss, we selected “Another alert” as the exit condition called “Trailing stop, volatility down.” This alert is triggered when a stock moves down an amount equal to the average 15-minute volatility multiplied by the number of 15-minute bars we decide on — in this case, 2. For example, if the average 15-minute volatility is 10 cents, this alert would not trigger until a stock moves down at least 20 cents.

Here is what The OddsMaker tested for the past three weeks ended 4/9/2009 given the following trade rules:

  • On each alert, sell short the symbol (price moves down to be a successful trade)
  • Schedule an exit for the stocks 30 minutes after entry
  • Start trading from the open and stop trading 30 minutes later
  • Set a stop using the alert, trailing stop, volatility down, with a setting of two bars

The OddsMaker summary provides evidence of how well this strategy and our trading rules did. The settings are shown in Figure 17.

Figure 17: TRADE-IDEAS, ODDSMAKER. Here is the backtesting configuration for the modified ATR volatility stop strategy.

The results (last backtested for the three-week period ended 4/9/2009) are shown in Figure 18. The summary reads as follows: This strategy generated 498 trades of which 339 were profitable for a win rate of 68.07%. The average winning trade generated $0.38 in profit and the average loser lost $0.18. The net winnings of using this strategy for 15 trading days generated $105.06 points. If you normally trade in 100-share lots, this strategy would have generated $10,506. The z-score or confidence factor that the next set of results will fall within this strategy’s average winner and loser is 100%.

Figure 18: TRADE-IDEAS, RESULTS. Here are sample results from The Oddsmaker for the modified ATR volatility stop strategy.

You can find an explanation of The OddsMaker backtest results in more detail from the online user manual at https://www.trade-ideas.com/OddsMaker/Help.html.

—Dan Mirkin & David Aferiat
Trade Ideas, LLC
david@trade-ideas.com, www.trade-ideas.com

BACK TO LIST

METASTOCK: Average True Range Trailing Stops (VERVOORT ARTICLE CODE)

The code for MetaStock to implement the average true-range trailing stop method, as described by author Sylvain Vervoort In “Average True Range Trailing Stops,” in this issue, is provided below.

MODIFIED ATR WITH TRAILING STOPS
{SVE_Stop_Trail_ATR_Mod}
period:=Input(“ATR period :”,1,100,5);
atrfact:=Input(“ATR multiplication :”,1,10,3.5);
HiLo:=If(H-L<1.5*Mov(H-L,period,S),H-L, 1.5*Mov
(H-L,period,S));
Href:=If(L<=Ref(H,-1),H-Ref(C,-1),(H-Ref(C,-1))-(L-Ref(H,-1))/2);
Lref:=If(H>=Ref(L,-1),Ref(C,-1)-L,(Ref(C,-1)-L)-(Ref(L,-1)-H)/2);
diff1:=Max(HiLo,Href);
diff2:=Max(diff1,Lref);
atrmod:=Wilders(diff2,period);
loss:=atrfact*atrmod;
trail:= 
If(C>PREV AND Ref(C,-1)>PREV,
Max(PREV,C-loss),
If(C<PREV AND Ref(C,-1)<PREV,
Min(PREV,C+loss),
If(C>PREV,C-loss,C+loss)));
Trail

—Sylvain Vervoort
sve.vervoort@scarlet.be
https://stocata.org

BACK TO LIST

Return to Contents