TRADERS’ TIPS

November 2016

Tips Article Thumbnail

For this month’s Traders’ Tips, the focus is James Breen’s article in this issue, “Does Fully Automated Trading Software Work?” Here, we present the November 2016 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: NOVEMBER 2016

In “Does Fully Automated Trading Software Work?” in this issue, James Breen discusses the concepts involved in using a fully automated trading system. The author describes the processes that he uses and provides the basic outline of a strategy to help users get started. Here, we are providing the TradeStation EasyLanguage code for a strategy based on Breen’s outline.

TradeStation offers a number of advanced tools and capabilities to assist traders with the design and testing of their strategies as well as to fully automate the system for trading, if desired. The TradeStation walk-forward optimizer (WFO) is an advanced strategy optimization tool that automates the complex, multistep task of carrying out the statistical walk-forward testing of a trading strategy’s optimized inputs. TradeStation Portfolio Maestro is a backtesting tool that lets you evaluate the performance of a group of strategies applied to one or more symbols that make up your portfolio.

Strategy: Trend Following System

// TASC November 2016
// Does Fully Automated Trading
// Software Work?
// Author James Breen

inputs:
	MovingAverageLength( 10 ),
	PercentPriceChange( 1 ),
	MaximumDailyLoss( 500 ),
	InitialStopLossAmount( 200 ),
	TrailEnableAmount( 200 ),
	TrailPercent( 25 ),
	TradeWithTrend( true ) ;
	
variables:
	MovAvgValue( 0 ),
	MovAvgUpperBand( 0 ),
	MovAvgLowerBand( 0 ),
	MaxLossReached( false ), 
	StartingPL( 0 ),
	PL( 0 ),
	CS( 0 ) ;

once SetStopContract ;		
	
MovAvgValue = Average( Close, MovingAverageLength ) ;	
MovAvgUpperBand = MovAvgValue 
	+ MovAvgValue * PercentPriceChange * .01 ;
MovAvgLowerBand = MovAvgValue 
	- MovAvgValue * PercentPriceChange * .01 ;

CS = CurrentSession( 0 ) ;
PL = OpenPositionProfit + NetProfit ;

// Max Loss For Session
if CS <> CS[1] then
	begin
	StartingPL = PL[1] ;
	MaxLossReached = false ;
	end ;	
if  StartingPL - PL >= MaximumDailyLoss then
	MaxLossReached = true ;	

if MaxLossReached = true then
	begin
	Sell ( "MaxLoss LE" ) next bar at Market ;
	Buy To Cover ( "MaxLoss SE" ) next bar at Market ;
	end
else
	begin
	if TradeWithTrend then
		begin
		if Close < MovAvgUpperBand then
			Buy ( "MA Trend LE" ) next bar 
				at MovAvgUpperBand Stop ;	
		if Close > MovAvgLowerBand then
			Sell Short ( "MA Trend SE" ) next bar 
				at MovAvgLowerBand Stop ;
		end
	else
		begin
		if Close < MovAvgUpperBand then
			SellShort ( "MA Fade SE" ) next bar 
				at MovAvgUpperBand Limit ;	
		if Close > MovAvgLowerBand then
			Buy ( "MA Fade LE" ) next bar 
				at MovAvgLowerBand Limit ;
		end ;
	end ;

SetStopLoss( InitialStopLossAmount ) ;
SetPercentTrailing( TrailEnableAmount, TrailPercent ) ;
SetExitOnClose ;	

To download the EasyLanguage code for the strategy, please visit our TradeStation and EasyLanguage support forum. The code for this article can be found at https://community.tradestation.com/Discussions/Topic.aspx?Topic_ID=142776. The ELD filename is “TASC_NOV2016.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 a 10-minute S&P 500 emini TradeStation chart with the strategy applied.

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

eSIGNAL: NOVEMBER 2016

For this month’s Traders’ Tip, we’ve provided the study Trend_Following.efs based on the formula described in James Breen’s article in this issue, “Does Fully Automated Trading Software Work?” In the article, Breen describes how to create an automated trading system.

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 Trend_Following.efs study plotted on a 15-minute chart of NAVB.

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 here:
/*********************************
Provided By:  
eSignal (Copyright © 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:        
    Does Fully Automated Trading Software Work? by James Breen

Version:            1.00  09/06/2016

Formula Parameters:                     Default:
MA Length                               10
Entry Trigger %                         3
Exit Trigger %                          4
Initial Stop Loss %                     2
Trailing Stop Trigger %                 6
Trailing Stop %                         2



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("MA");
    
    var x=0;
    fpArray[x] = new FunctionParameter("Length", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(1);
        setUpperLimit(1000);  
        setDefault(10);
        setName("MA Length");
    }

    fpArray[x] = new FunctionParameter("EntTrigger", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0.1);
        setUpperLimit(100);
        setDefault(3);
        setName("Entry Trigger %");
    }

    fpArray[x] = new FunctionParameter("ExtTrigger", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0.1);
        setUpperLimit(100);
        setDefault(4);
        setName("Exit Trigger %");
    }
    
    fpArray[x] = new FunctionParameter("InStopLoss", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0.1);
        setUpperLimit(100);
        setDefault(2);
        setName("Initial Stop Loss %");
    }

    fpArray[x] = new FunctionParameter("TrlStopTrigger", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0.1);
        setUpperLimit(100);
        setDefault(6);
        setName("Trailing Stop Trigger %");
    }

    fpArray[x] = new FunctionParameter("TrlStop", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0.1);
        setUpperLimit(100);
        setDefault(2);
        setName("Trailing Stop %");
    }

    fpArray[x] = new FunctionParameter("MaxLoss", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setLowerLimit(0);
        setDefault(500);
        setName("Max Daily Loss $");
    }
}

var bInit = false;
var bVersion = null;
var xSMA = null;
var xClose = null;
var xHigh = null;
var xLow = null;
var nInv = null;
var nShares = 0;
var nEntryPrice = 0;
var nTrlStop = null;
var nHighestHigh = null;
var nLowestLow = null;
var nCumProfit = 0;
var bMaxLost = false;

function main(Length, EntTrigger, ExtTrigger, InStopLoss, TrlStopTrigger, TrlStop, MaxLoss){
    
    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;
    
    if (getCurrentBarCount() <= Length) return;
    
    if (getBarState() == BARSTATE_ALLBARS){
        xSMA = null;
        xClose = null;
        xHigh = null;
        xLow = null;
        nInv = null;
        nShares = 0;
        nEntryPrice = 0;
        nTrlStop = null;
        nHighestHigh = null;
        nLowestLow = null;
        nCumProfit = 0;
        bMaxLost = false;
        bInit = false;
    }
    
    if (!bInit){
        xClose = close();
        xHigh = high();
        xLow = low();
        xSMA = sma(Length, xClose);
        nHighestHigh = xHigh.getValue(0);
        nLowestLow = xLow.getValue(0);
        bInit = true;
    }

    var nSMA = xSMA.getValue(0);
    var nClose = xClose.getValue(0);
    var nHigh = xHigh.getValue(0);
    var nLow = xLow.getValue(0);
    var nTradeProfit = 0;

    if (day(0) != day(-1) && !Strategy.isInTrade()){ 
        bMaxLost = false;
        nCumProfit = 0;
    }

    if (getCurrentBarIndex() != 0){
        if (Strategy.isLong())
            nTradeProfit = nClose * nShares - nInv;
        else if (Strategy.isShort())
            nTradeProfit = nInv - nClose * nShares;
        

        if ((nCumProfit + nTradeProfit) <= -MaxLoss){
            if (Strategy.isLong())
                Strategy.doSell("Loss Limit exceeded", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
            else 
                Strategy.doCover("Loss Limit exceeded", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
            nCumProfit = 0;
            bMaxLost = true;
        }
        
        if (nShares == 0)
            nShares = Strategy.getDefaultLotSize();
        
        if (Strategy.isLong()){
            if (nTrlStop == null && (nHigh * nShares) >= (nEntryPrice * nShares * (1 + TrlStopTrigger/100))){
                nTrlStop = nHigh * (1 - TrlStop/100);
                nHighestHigh = nHigh;
            }
            
            if (nTrlStop != null && nHigh > nHighestHigh){
                nHighestHigh = nHigh;
                nTrlStop = nHighestHigh * (1 - TrlStop/100);
            }

            if (nClose < (nSMA * (1 - ExtTrigger/100)))
                Strategy.doSell("Exit Long", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
            else if (nClose * nShares < (nInv * (1 - InStopLoss/100)))
                Strategy.doSell("Stop Loss Long", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
            else if (nTrlStop != null && nClose < nTrlStop)
                Strategy.doSell("Trl Stop Long", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
            
            if (!Strategy.isLong()){
                nCumProfit += nClose * nShares - nInv;
                nTrlStop = null;
            }
        

        }
        else if (Strategy.isShort()){
                if (nTrlStop == null && (nLow * nShares) <= (nEntryPrice * nShares * (1 - TrlStopTrigger/100))){
                nTrlStop = nLow * (1 + TrlStop/100);
                nLowestLow = nLow;
            }
            
            if (nTrlStop != null && nLow < nLowestLow){
                nLowestLow = nLow;
                nTrlStop = nLowestLow * (1 + TrlStop/100);
            }
           if (nClose > (nSMA * (1 + ExtTrigger/100))) 
                Strategy.doCover("Exit Short", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
           else if (nClose * nShares > (nInv * (1 + InStopLoss/100))){
                Strategy.doCover("Stop Loss Short", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
           }
           else if (nTrlStop != null && nClose > nTrlStop)
                Strategy.doCover("Trl Stop Short", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
           
           if (!Strategy.isShort()){
            nCumProfit += nInv - nClose * nShares;
               nTrlStop = null;
           }

       }
        
        if (!Strategy.isInTrade() && !bMaxLost){
            nTrlStop = null;
            if (nClose > (nSMA * (1 + EntTrigger/100))){
                Strategy.doLong("Long", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
            }
            else if (nClose < (nSMA * (1 - EntTrigger/100))){
                Strategy.doShort("Short", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
            }
        
            if (Strategy.isInTrade()){
                nEntryPrice = nClose;
                nInv = nShares * nEntryPrice;
            }
        }
        
        if (Strategy.isLong()) setBarBgColor(Color.RGB(0,60,0));
        else if (Strategy.isShort()) setBarBgColor(Color.RGB(170,46,46))
        
    }

    if (nSMA != null) return  nSMA;
}

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

WEALTHLAB: NOVEMBER 2016

The example daytrading system described by author James Breen in his article in this issue, “Does Fully Automated Trading Software Work?” is simple enough to avoid coding in Wealth-Lab entirely. You can simply compose it from building blocks known as rules in a drag-and-drop manner. In Figure 3, we provide an example of setting it all up. Note that the condition “price crosses X% above/below an indicator” is universal, that is, it can be used with different kinds of indicators such as moving averages, filters, price bands, and channels. In addition to author’s rules, a profit target exit is installed to capitalize on big intraday moves.

Sample Chart

FIGURE 3: WEALTH-LAB. This shows a guideline for setting up the example system in rules with drag & drop.

The red icon indicates that the parameter next to it is available as a parameter slider, enabling the user to change its value by dragging the slider on the bottom left of the screen. When you run the system on a chart of a single stock (as opposed to on a multisymbol portfolio), Wealth-Lab automatically and conveniently applies the changed parameters so you have a chance to see how entries & exits change interactively on the chart.

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

BACK TO LIST

logo

AMIBROKER: NOVEMBER 2016

In “Does Fully Automated Trading Software Work?” in this issue, author James Breen presents a very simple moving average crossover system. A ready-to-use AmiBroker formula implementing his system is provided here. Please be sure to test the system before trading, because my backtest of it showed poor performance on the S&P 500, at least.

LISTING 1.
// Very simple MA crossover with stops (as proposed in the article) 
Version( 6.10 ); 

upthresh = 1 + 0.01 * Optimize("Up MA cross threshold", 3, 0, 5, 0.5 ); 
dnthresh = 1 - 0.01 * Optimize("Down MA cross threshold", 4, 0, 5, 0.5 ); 

per = Optimize("MA period", 10, 5, 50, 1 ); 

mov = MA( C, per ); 
Buy = Close > upthresh * mov; // enter when close is 3% above moving average 
Sell = Close < dnthresh * mov; // exit when close is 4% below moving average 

// initial max loss stop 2% active for first 3 bars 
ApplyStop( stopTypeLoss, stopModePercent, 2, True, False, 0, 0, 3 ); 

// after 3 bars activate 2% trailing stop 
ApplyStop( stopTypeTrailing, stopModePercent, 2, True, False, 0, 3 ); 

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

BACK TO LIST

logo

NEUROSHELL TRADER: NOVEMBER 2016

The automated trading system described by James Breen in this article in this issue, “Does Fully Automated Trading Software Work?” can be easily implemented with a few of NeuroShell Trader’s 800+ indicators. 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]
     Avg Envelope High Breakout(Close,10,0.03)
     A>B(Sub(SystemEquity(Trading Strategy),DayOpen(Date,SystemEquity(Trading Strategy),0)),-500)

LONG TRAILING STOP PRICES:
     PriceFloor%(Trading Strategy,2)
     IfThenElse(A>=B(Divide(MaxValEntryAct(Trading Strategy,High,1),EntryPrice(Trading Strategy,0)),1.06),TrailPrice%(Trading Strategy,2),*)

SELL LONG CONDITIONS: [1 of which must be true]
     Avg Envelope Low Breakout(Close,10,0.04)
     A<=B(Sub(SystemEquity(Trading Strategy),DayOpen(Date,SystemEquity(Trading Strategy),0)),-500)

If you have NeuroShell Trader Professional, you can also choose whether the parameters should be optimized. 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 an S&P 500 emini automated trading system.

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

BACK TO LIST

logo

NINJATRADER: NOVEMBER 2016

The basic percentage risk strategy detailed in “Does Fully Automated Trading Software Work?” by James Breen in this issue is available for download at www.ninjatrader.com/SC/November2016SC.zip.

Once it has been downloaded, from within the NinjaTrader Control Center window, select the menu File → Utilities → Import NinjaScript and select the downloaded file. This file is for NinjaTrader Version 7.

You can review the indicator’s source code by selecting the menu Tools → Edit NinjaScript → Strategy from within the NinjaTrader Control Center window and selecting the BasicPercentageRisk file.

A sample chart implementing the strategy is shown in Figure 5.

Sample Chart

FIGURE 5: NINJATRADER. The basic percentage risk strategy’s results for an optimization on the AAPL instrument are displayed in the Strategy Analyzer of NinjaTrader 7.

—Raymond Deux & Alan Palmer
NinjaTrader, LLC
www.ninjatrader.com

BACK TO LIST

logo

UPDATA: NOVEMBER 2016

Our Traders’ Tip for this month is based on the article by James Breen in this issue, “Does Fully Automated Trading Software Work?” In the article, the author develops a fully automated trading system using rules for entries & exits based on the instrument being a given percentage from its simple moving average.

Within the Updata System Optimizer, all parameters are fully optimizable to help the user select the values that better account for ongoing changes in the market, to be able to work in bull and bear markets, and to limit losses/let winners run.

A sample chart is shown in Figure 6.

Sample Chart

FIGURE 6: UPDATA. Here is the example fully automated system applied to the ETF USO in daily resolution.

The Updata code for this article 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 a firewall may ask our helpdesk for a copy. The code is also shown below.

 'FullyAutomatedTradingIdea 
PARAMETER "Period" #PERIOD=10
PARAMETER "Entry %" @ENTRY=3 
PARAMETER "Exit %" @EXIT=4
PARAMETER "Loss %" @LOSS=2 
PARAMETER "Profit %" @PROFIT=6
PARAMETER "Trail %" @TRAIL=2
DISPLAYSTYLE 4LINES
INDICATORTYPE TOOL
COLOUR RGB(200,0,0) 
COLOUR2 RGB(0,0,200)
COLOUR3 RGB(100,100,100)
COLOUR4 RGB(190,190,190)
NAME "" "" 
@AVG=0
@TRIGGER=0 
@CUTLEVEL=0     
@PROFITTARGET=0
@SETSTOP=0
@STOP=0
FOR #CURDATE=#PERIOD TO #LASTDATE
    @AVG=MAVE(#PERIOD) 
    @TRIGGER=((@ENTRY/100)+1)*@AVG 
    @CUTLEVEL=(1-(@EXIT/100))*@AVG 
    'TRAILING STOP EXIT
    IF HASX(CLOSE,@STOP,DOWN)
       SELL @STOP
    ENDIF 
    'SETS TRAILING STOP AT 6% THRESHOLD
    IF @SETSTOP=1
       @STOP=MAX(@STOP,(1-(@TRAIL/100))*HIGH)
    ENDIF
    IF ORDERISOPEN=1 AND CLOSE>@PROFITTARGET AND @SETSTOP=0
       @SETSTOP=1
       @STOP=(1-(@TRAIL/100))*HIGH
    ENDIF  
    'CLOSES ORDERS BELOW X%
    IF ORDERISOPEN=1 AND CLOSE<@CUTLEVEL
       SELL CLOSE 
       @SETSTOP=0
    ENDIF  
    'ENTRIES ABOVE X %
    IF CLOSE>@TRIGGER AND ORDERISOPEN=0
       BUY CLOSE
       @PROFITTARGET=((@PROFIT/100)+1)*CLOSE 
       @SETSTOP=0
    ENDIF
    @PLOT=@AVG 
    IF ORDERISOPEN=0
       @PLOT2=@TRIGGER
       @PLOT3=-10000 
    ELSE
       @PLOT2=-10000 
       @PLOT3=@CUTLEVEL
    ENDIF 
    IF @SETSTOP=0 OR ORDERISOPEN=0
       @PLOT4=-10000
    ELSE
     @PLOT4=@STOP
    ENDIF
NEXT

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

BACK TO LIST

logo

THINKORSWIM: NOVEMBER 2016

In his article in this issue, James Breen poses the rhetorical question, “Does Fully Automated Trading Software Work?” This question could be answered by firing off orders on a fully automated system or by using thinkorswim to analyze results before making the trade.

We have recreated his strategy using our proprietary scripting language, thinkscript. We have made the loading process extremely easy—simply go to https://tos.mx/pYj2WJ and choose to view thinkscript strategy. Rename your study “TrendFollowingStratLE.” You can adjust the parameters of this strategy within the edit studies window to fine-tune your variables.

Sample Chart

FIGURE 7: THINKORSWIM. Here you see a chart of SPY with the TrendFollowingStratLE strategy added along with StopLossSX and ProfitTargetSX.

In Figure 7, you see a chart of SPY, which is the ETF designed to track the S&P 500, with the TrendFollowingStratLE strategy added. We have also added our StopLossSX and ProfitTargetSX in order to complete the idea outlined in Breen’s article.

—thinkorswim
A division of TD Ameritrade, Inc.
www.thinkorswim.com

BACK TO LIST

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