TRADERS’ TIPS

November 2018

Tips Article Thumbnail

For this month’s Traders’ Tips, the focus is Markos Katsanos’ article in this issue, “The Stiffness Indicator.” Here, we present the November 2018 Traders’ Tips code with possible implementations in various software.

You can right-click on any chart to open it in a new tab or window and view it at it’s originally supplied size, often much larger than the version printed in the magazine.

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 2018

In “The Stiffness Indicator” in this issue, author Markos Katsanos introduces a new indicator to help the trader identify trading opportunities where strong trends have been established. The indicator evaluates the quality of the trend by counting the number of times price was above a moving average. In the article, Katsanos describes a trading strategy that incorporates the new indicator and provides an example of a backtest of the strategy on the basket of S&P 500 stocks. TradeStation provides a complete set of backtesting tools including TradeStation Portfolio Maestro, where you can backtest your strategies on a symbol list of your choice.

The TradeStation EasyLanguage code for both the indicators and strategy based on the author’s work is shown here.

Indicator: Stiffness Indicator
// The Stiffness Indicator
// Markos Katsanos
// TASC Nov 2018

inputs:
	MALength( 100 ),
	StiffnessLength( 60 ),
	Threshold( 90 ) ;
	
variables:
	MAValue( 0 ),
	MACorValue( 0 ),
	NumAboveMA( 0 ),
	Stiffness( 0 ),
	StiffnessEMA( 0 ) ;	

MAValue = Average( Close, MALength ) ;
MACorValue = MAValue - .2 * 
	StdDev( Close, MALength ) ;
NumAboveMA = CountIf( Close > 
	MACorValue, StiffnessLength ) ;
Stiffness = NumAboveMA * 
	MALength / StiffnessLength ;
StiffnessEMA = XAverage( Stiffness, 3 ) ;


Plot1( Threshold, "Threshold" ) ;
Plot2( StiffnessEMA, "Stiffness" ) ;


Indicator: Corrected Moving Average
// The Stiffness Indicator
// Markos Katsanos
// TASC Nov 2018

inputs:
	MALength( 100 ),
	StiffnessLength( 60 ),
	Threshold( 90 ) ;
	
variables:
	MAValue( 0 ),
	MACorValue( 0 ),
	NumAboveMA( 0 ),
	Stiffness( 0 ),
	StiffnessEMA( 0 ) ;	

MAValue = Average( Close, MALength ) ;
MACorValue = MAValue - .2 * 
	StdDev( Close, MALength ) ;

Plot1( MACorValue, "MA COR" ) ;
Plot2( MAValue, "MA" ) ;

Strategy: Stiffness Strategy
// The Stiffness Indicator
// Markos Katsanos
// TASC Nov 2018
// Requires Data2 Symbol for Market
// 
inputs:
	MALength( 100 ),
	StiffnessLength( 60 ),
	BuyThreshold( 90 ),
	SellThreshold( 50 ),
	ExitAfterBars( 84 ),
	MarketTrendEMALength( 100 ) ;
	
variables:
	MAValue( 0 ),
	MACorValue( 0 ),
	NumAboveMA( 0 ),
	Stiffness( 0 ),
	StiffnessEMA( 0 ),
	MarketTrendAvg( 0, Data2 ),
	MarketTrendOK( false, Data2 ) ;	

MAValue = Average( Close, MALength ) ;
MACorValue = MAValue - .2 * 
	StdDev( Close, MALength ) ;
NumAboveMA = CountIf( Close > 
	MACorValue, StiffnessLength ) ;
Stiffness = NumAboveMA * 
	MALength / StiffnessLength ;
StiffnessEMA = XAverage( Stiffness, 3 ) ;

MarketTrendAvg = XAverage( Close of Data2, 
	MarketTrendEMALength ) of Data2 ;
MarketTrendOK = MarketTrendAvg 
	>= MarketTrendAvg[2] ;

if StiffnessEMA crosses over BuyThreshold 
	and MarketTrendOK then
	Buy ( "X Over LE" ) next bar at Market ;
	
if StiffnessEMA crosses under SellThreshold then
	Sell ( "X Under LX" ) next bar at Market ;
	
if BarsSinceEntry >= ExitAfterBars then
	Sell ( "Num Days LX" ) next bar at Market ;	

To download this EasyLanguage code, please visit our TradeStation and EasyLanguage support forum. The files for this article can be found here: https://community.tradestation.com/Discussions/Topic.aspx?Topic_ID=152631. The filename is “TASC_NOV2018.ZIP.”

A sample chart is shown in Figure 1.

Sample Chart

FIGURE 1: TRADESTATION. The stiffness indicator and strategy are applied to a daily chart of ALGN.

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 2018

For this month’s Traders’ Tip, we’ve provided the StiffnessIndicator.efs study based on the article by Markos Katsanos in this issue, “The Stiffness Indicator.” This study attempts to determine if markets are in a strong price trend.

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 study plotted on a daily chart of ALGN.

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 www.esignal.com/support/kb/efs/. The eSignal formula script (EFS) is also available for copying & pasting below.

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

Description:        
    The Stiffness Indicator by Markos Katsanos
    

Version:            1.00  9/14/2018

Formula Parameters:                     Default:
Period                                  60
MA DAYS                                 100
STIFFNESS CRITICAl                      90

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("Stiffness Indicator");
    setCursorLabelName("STIFFNESS");
    setPlotType(PLOTTYPE_HISTOGRAM);
    
    var x = 0;
    fpArray[x] = new FunctionParameter("Period", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("STIFFNESS PERIOD");
        setLowerLimit(1);
        setDefault(60);
        
    }

    fpArray[x] = new FunctionParameter("MAB", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("MA DAYS");
        setLowerLimit(1);
        setDefault(100);
       
    }
    fpArray[x] = new FunctionParameter("STIFFCRIT", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("STIFFNESS CRITICAl");
        setLowerLimit(1);
        setDefault(90);
        
    }
}

var bInit = false;
var bVersion = null;
var xClose = null;
var xMA2 = null;
var nEntryPrice = null;
var xLow = null;
var xHigh = null;
var vStopPrice = null;
var bIsLong = null;
var xCloseSPY = null;
var xEMA = null;
var xStiffness = null;
var bWasLong = false;


function main(Period, MAB, STIFFCRIT){
    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;
        
    if (getBarState() == BARSTATE_ALLBARS){
        bInit = false;
        bIsLong = false;
    }

    if (getCurrentBarCount() < Period) return;
    
    if (!bInit){
        
        xCloseSPY = close("SPY");
        xClose = close();
        xHigh = high();
        xLow = low();
        bIsLong = false;
        bWasLong = false;
             
        xMA2 = efsInternal("Calc_MA2", xClose, MAB);
        xEMA = efsInternal("Calc_Ema", xCloseSPY, MAB);
        xStiffness = efsInternal("Calc_Stif", xClose, Period, xMA2);
        
        addBand(STIFFCRIT, PS_DASH, 1, Color.grey, 2);
        
        bInit = true;
    }

    
    if (getBarState() == BARSTATE_NEWBAR && xStiffness.getValue(-1) != null)  {    
         if ((xStiffness.getValue(0)<= STIFFCRIT) && bIsLong){      
             
            if (xStiffness.getValue(-1) > STIFFCRIT){
                drawTextRelative(0, TopRow1, "\u00EA", Color.red, null, Text.PRESET|Text.CENTER, "Wingdings", 10, "Exit"+rawtime(0));
                bIsLong = false;                    
            }
            else {
                removeText("Long"+rawtime(0));
                removeText("Text"+rawtime(0));
            } 
            bIsLong = false;
        }
    
        if (xEMA.getValue(0) >= xEMA.getValue(-2) && !bIsLong && (xStiffness.getValue(-1) < STIFFCRIT)){                  
            
            if ((xStiffness.getValue(1) > STIFFCRIT)){
                 
                drawTextRelative(0, TopRow1, "\u00E9", Color.green, null, Text.PRESET|Text.CENTER, "Wingdings", 10, "Long"+rawtime(0));
                bIsLong = true;
                bWasLong = true;
            }      
            else {
                removeText("Exit"+rawtime(0));
                removeText("TextExit"+rawtime(0));
                if (bWasLong) 
                    bIsLong = true;
                    
            }
        }
    }
    return (xStiffness.getValue(0))
}

var P = null;

function Calc_Stif (xClose, Period, xMA2){
    if (xClose.getValue(-Period) == null || xMA2.getValue(-Period) == null) return;
    
    P = 0;
    for (var i = 0; i < Period; i++) {
        
        if (xClose.getValue(-i) > xMA2.getValue(-i)) P++;
    }
    return (P * 100 / Period); 
}

 function Calc_MA2(xClose, MAB){   
    if (xClose.getValue(-MAB) == null) return;
    return (sma(MAB) - 0.2 * stdDev(MAB));
}

function Calc_Ema(xCloseSPY, MAB){
    if (xCloseSPY.getValue(-MAB) == null) return;
    return ema(MAB, sym("SPY," + getInterval()));
}

function verify(){
    var b = false;
    if (getBuildNumber() < 3756){
        
        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

METASTOCK: NOVEMBER 2018

Markos Katsanos’ article in this issue, “The Stiffness Indicator,” introduces an indicator of the same name. He also includes an exploration and an optimized system test using this indicator. The formulas to put these into MetaStock are shown here:

Stiffness Indicator
tp:= Input("Stiffness Period", 2, 1000, 60);
MAB:= Input("Moving Average Period", 2, 1000, 100);
SM:= Input("Smooth Coeff.",1,20,3);
STIFFCRIT:= Input("STIFFCritical",70,100,90);
NSTD:= Input("Min SD",0,2,.2);

MA2:= Mov(C,MAB,S)-NSTD*Stdev(C,MAB);
PENS:= Sum(C>MA2, tp);
STIF:= PENS*100/ tp; 
Mov(STIF,SM, E);
STIFFCRIT

Stiffness Strategy
SYSTEM TEST NOTES
21 day inactivity stop suggested

4 optimization variables are used. Suggested values are:
Opt1 - Moving Average periods - suggested range: 50-120 with a step of 10
Opt2 - STIFF periods - suggested range of 40-80 with a step of 10
Opt3 - STIFFCRIT - suggested range of 90-95 with a step of 5
Opt4 - STIFFSELL - suggested range of 50-60 with a step of 10

Buy Order
MAB:= Opt1; {MA days: suggested range of 50-120 with a step of 10}
tp:= Opt2; {STIFF PERIOD: suggested range of 40-80 with a step of 10}
STIFFCRIT:= Opt3; {STIFFCRIT: suggested value of 90 or 95}

s1:= Security("ONLINE:SPY", C);

MA2:= Mov(C,MAB,S) - (0.2*StDev(C,MAB));
PENS:= Sum(C>MA2, tp);
STIF:= PENS*100/ tp; 
STIFFNESS:= Mov(STIF,3, E);

Mov(s1,100,E)>=Ref(Mov(s1,100,E),-2) AND
Cross(STIFFNESS,STIFFCRIT)

Sell Order
MAB:= Opt1; {MA days: suggested range of 50-120 with a step of 10}
tp:= Opt2; {STIFF PERIOD: suggested range of 40-80 with a step of 10}
STIFFSELL:= Opt4; {STIFFSELL: suggested value of 50 or 60}

MA2:= Mov(C,MAB,S) - (0.2*StDev(C,MAB));
PENS:= Sum(C>MA2, tp);
STIF:= PENS*100/ tp; 
STIFFNESS:= Mov(STIF,3, E);

Cross(STIFFSELL,STIFFNESS)

STOPS
Inactivity Minimum Change:
Positions: Longs
Method: Percent
Minimum Change: 100
Periods: 21

OPTIMIZATIONS
OPT1
Description: MA Periods
Minimum: 50
Maximum: 120
Step: 10

OPT2
Description: STIFF Periods
Minimum: 40
Maximum: 80
Step: 10

OPT3
Description: STIFF crit
Minimum: 90
Maximum: 95
Step: 5

OPT4
Description: STIFF sell
Minimum: 50
Maximum: 60
Step: 10

Stiffness Exploration
EXPLORATION NOTES
Columns reported are:
1- Current Price
2- Current Volume
3- Volume divided by Average Volume
4- RSI
5- Stiffness
6- Profit Target

COLUMN FORMULAS
Column A
Column Name: Price
Formula:
C

Column B
Column Name: Volume
Formula:
VOLUME

Column C
Column Name: V / AvgV
Formula:
ma1:= Mov(V,2,S);
ma2:= Mov(V,50,S);
denom:= If(ma2=0, -1, ma2);
If(denom=-1, 0, Mov(V,2,S)/denom)

Column D
Column Name: RSI
Formula:
RSI(6)

Column E
Column Name: Stiffness
Formula:
MAB:= 100; {Moving Average periods}
tp:= 60; {STIFFNESS PERIOD}
STIFFCRIT:= 90; {STIFFNESS CRITICAL}
MA2:= Mov(C,MAB,S) - (0.2*Stdev(C,MAB));
PENS:= Sum(C>MA2, tp);
STIF:= PENS*100/ tp;
Mov(STIF,3, E)

Column F
Column Name: target
Formula:
C + ( 8*ATR(50) )

EXPLORATION FILTER
Formula:
MAB:= 100; {Moving Average periods}
tp:= 60; {STIFFNESS PERIOD}
STIFFCRIT:= 90; {STIFFNESS CRITICAL}
s1:= Security("ONLINE:SPY", C);
MA2:= Mov(C,MAB,S) - (0.2*Stdev(C,MAB));
PENS:= Sum(C>MA2, tp);
STIF:= PENS*100/ tp;
STIFFNESS:= Mov(STIF,3, E);
Mov(s1,100,E)>=Ref(Mov(s1,100,E),-2) AND Cross(STIFFNESS,STIFFCRIT)

—William Golson
MetaStock Technical Support
www.metastock.com

BACK TO LIST

logo

THINKORSWIM: NOVEMBER 2018

We have put together a study for thinkorswim based on Markos Katsanos’ article in this issue, “The Stiffness Indicator.” The study is built using our proprietary scripting language, thinkscript. To ease the loading process, simply go to https://tos.mx/7WDQE0 and then click open shared item from within thinkorswim. Choose view thinkscript and name it “Stiffness.”

To add the strategy, go to https://tos.mx/cV8My6 and then open shared item from within thinkorswim. Choose view thinkscript and name it “StiffnessStrategy.” These can then be added to your chart from the edit study and strategies menu within thinkorswim.

Figure 3 shows the study added to the lower portion of a one-year daily chart of Apple with the strategy plotted in the upper subgraph. See Markos Katsanos’s article for more details on the interpretation of the study.

Sample Chart

FIGURE 3: THINKORSWIM. The study is shown in the lower panel of a one-year daily chart of Apple with the strategy plotted in the upper subgraph.

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

BACK TO LIST

logo

WEALTH-LAB: NOVEMBER 2018

The accompanying WealthScript C# code demonstrates how to implement a trading strategy based on the rules described by Markos Katsanos in his article in this issue, “The Stiffness Indicator.” Here they are:

To change the system’s behavior from “buy high” to “buy on pullback,” drag the synonymous slider at the bottom of Wealth-Lab’s main workspace. In accordance with Katsanos’ article, entering when the short-term RSI turns up from a pullback in an established trend is believed to be more efficient. Figure 4 shows a chart with example trades based on the stiffness indicator.

Sample Chart

FIGURE 4: WEALTH-LAB. This shows a set of typical trades using the strategy on a chart of Goodyear.

As the current abnormal bullish market has started nine years ago, we weren’t convinced by the author’s choice of using the 10 most recent years of data. Our backtest with 5% equity per position on a sample of historical Dow 30 stocks as of 1/1/2000 spans the 10-year range up until 1/1/2010. In addition to a vibrant recovery, this includes two bear markets. The buy-on-pullback version finished with the net profit beating buy & hold’s (49% vs. ≈17%, after commissions). And it did so with significantly lower risk (maximum drawdown -13% vs. -59.3%) and market exposure (39.2% vs. 100%) (Figure 5).

Sample Chart

FIGURE 5: WEALTH-LAB. This example equity curve highlights the system’s weakness: It can lose to buy & hold in strong bull markets.

On a closing note, make sure to load enough historical data to run this backtest. Indicators like the EMA (used as the broad market direction condition) require a fair amount of seed data (here, three times the 100-bar EMA period) to stabilize their calculation before they can be used reliably in a trading system.

Wealth-Lab strategy code (C#):

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

namespace WealthLab.Strategies
{
	// Dow 30 Y2K stocks included AA AXP BA C CAT CVX DIS GE GM GT HD HWP IBM INTC IP JNJ JPM KO KODK MCD MRK MSFT PG PM SHLD T UTX WMT XOM
	
	public class TASCNov2018 : WealthScript
	{
		private StrategyParameter slider1;
		private StrategyParameter slider2;
		private StrategyParameter slider3;
		private StrategyParameter slider4;
		private StrategyParameter slider5;
		private StrategyParameter slider6;

		public TASCNov2018()
		{
			slider6 = CreateParameter("Pullback?",1,0,1,1);
			slider1 = CreateParameter("Stiffness MA",100,2,100,10);
			slider2 = CreateParameter("Stiffness Period",60,2,100,10);
			slider3 = CreateParameter("Stiffness Devs",0.2,0.1,3,0.2);
			slider4 = CreateParameter("Bars since",84,10,200,2);
			slider5 = CreateParameter("RSI Period",3,3,6,1);
		}
		
		protected override void Execute()
		{
			int maPeriod = slider1.ValueInt, stiffPeriod = slider2.ValueInt, 
				exitAfter = slider4.ValueInt, rsiPeriod = slider5.ValueInt;
			var devs = slider3.Value;
			var stiffness = Stiffness.Series(Close,maPeriod,stiffPeriod,devs);
			var rsi = RSI.Series(Close, rsiPeriod);
			bool useRsiTurnup = slider6.ValueInt == 1 ? true : false;

			var spy = GetExternalSeries("SPY", Close);
			var spyEma = EMAModern.Series(spy, maPeriod);

			for(int bar = GetTradingLoopStartBar( 100 ); bar < Bars.Count; bar++)
			{
				if (IsLastPositionActive)
				{
					Position p = LastPosition;

					if ( bar+1 - p.EntryBar >= exitAfter )	//Bars since entry ? 84 (four months)
						SellAtMarket( bar+1, p, "Timed" );
					if( CrossUnder( bar, stiffness, 50) )	//Stiffness(100,60) crosses under 50
						SellAtMarket( bar+1, p, "Stiffness < 50" );
				}
				else
				{
					if( !useRsiTurnup )
					{
						if( CrossOver(bar, stiffness, 90) )	//Stiffness crosses over 90
							if( spyEma[bar] > spyEma[bar - 1] ) //EMA (SPY,100) > EMA (SPY,100)
									BuyAtMarket( bar+1);
					}
					else						
					{
						if( Close[bar] > SMA.Series(Close, maPeriod)[bar] )
							if( stiffness[bar] >= 90 )	//Stiffness is bullish
								if( spyEma[bar] > spyEma[bar - 1] ) //EMA (SPY,100) > EMA (SPY,100)
									if( rsi[bar - 1] < 40 &&  TurnUp( bar, rsi) ) //RSI is oversold and turns up
										BuyAtMarket( bar+1, "RSI TurnUp");					
					}
				}
			}

			ChartPane paneSpy = CreatePane(30,true,true);
			PlotSeries( paneSpy,spy,Color.Black,LineStyle.Solid,2);
			PlotSeries( paneSpy,spyEma,Color.Blue,LineStyle.Solid,1);
			ChartPane paneStiffness = CreatePane(30,false,true);
			PlotSeries( paneStiffness,stiffness,Color.Orange,LineStyle.Histogram,2);
			PlotSeries( PricePane, SMA.Series(Close, maPeriod),Color.Blue,LineStyle.Solid,1);
			PlotSeries( PricePane, SMA.Series(Close, maPeriod) - (devs * StdDev.Series(Close, maPeriod, StdDevCalculation.Sample)),
				Color.Red,LineStyle.Solid,1);
			ChartPane paneRsi = CreatePane(30,false,true); HideVolume();
			PlotSeries( paneRsi,rsi,Color.Violet,LineStyle.Solid,2);
		}
	}
}

—Eugene (Gene Geren), Wealth-Lab team
MS123, LLC
www.wealth-lab.com

BACK TO LIST

logo

NEUROSHELL TRADER: NOVEMBER 2018

The stiffness indicator and trading system described by Markos Katsanos in his article in this issue can be easily implemented in NeuroShell Trader by combining a few of NeuroShell Trader’s 800+ indicators. To implement the stiffness indicator, select “new indicator” from the insert menu and use the indicator wizard to set up the following indicator:

Stiffness indicator:

Mul2(Sum(A>B(Close,Sub(Avg(Close,100),Mul2(0.2,StndDev(Close,100)))),60),Divide(100,60))

To set up a trading system based on the stiffness indicator, 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]
     CrossAbove(Stiffness(Close,100,60),90)
     A>B(Momentum(ExpAvg(SPDRS Close,100),5),0)

SELL LONG CONDITIONS: [One of which must be true]
     CrossBelow(Stiffness(Close,100,60),50)
     BarsSinceFill>=X(Trading Strategy,84)

After entering the system conditions, 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 system.

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 6.

Sample Chart

FIGURE 6: NEUROSHELL TRADER. This NeuroShell Trader chart demonstrates the stiffness indicator and system.

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

BACK TO LIST

logo

AIQ: NOVEMBER 2018

The EDS file containing code for AIQ based on Markos Katsanos’ article in this issue, “The Stiffness Indicator,” can be obtained on request via email to info@TradersEdgeSystems.com. The code is also shown here:

! STIFFNESS INDICATOR 
! Copyright Markos Katsanos 2018 
! Coded by: Richard Denning, 9/13/18
! www.TradersEdgeSystems.com

!INPUTS:
C is [close].
PERIOD is 60. 
MAB is 100. !MA DAYS 
SM is 3. 
STIFFCRIT is 90.  !PLOT
NSTD is 2. ! Number of Standard Deviations 
TIMEEXIT is 4.
PD is {position days}.

! STIFFNESS: 
StDev is sqrt(variance(C,MAB)). 
MA2 is simpleavg(C,MAB)-NSTD*StDev. 
CLMA if C>MA2. 
PENS is countof(CLMA,PERIOD). 
STIF is PENS*100/PERIOD. 
STIFFNESS is expavg(STIF,SM). !PLOT

!STIFFNESS STRATEGY:
EMA is expavg(C,MAB).
EMAspy is tickerUDF("SPY",EMA).

BUY if EMAspy >= valresult(EMAspy,2)
         and STIFFNESS > STIFFCRIT
         and valrule(STIFFNESS <= STIFFCRIT,1).

SELL if (STIFFNESS < STIFFCRIT
         and valrule(STIFFNESS >= STIFFCRIT,1))
         or PD >= TIMEEXIT*21.

I tested the author’s system using his default parameters. Figure 7 shows the equity curve trading a list of the NASDAQ stocks as of 2015. The test showed an annual average return of 26% with a maximum drawdown of 53% on 9/22/2000.

Sample Chart

FIGURE 7: AIQ. Here is a sample equity curve (blue) for the strategy compared to the NDX index (red) using NASDAQ 100 stocks from 1/1/1999 to 9/13/2018.

—Richard Denning
info@TradersEdgeSystems.com
for AIQ Systems

BACK TO LIST

logo

NINJATRADER: NOVEMBER 2018

The stiffness indicator, as discussed in Markos Katsanos’ article in this issue, is available for download at the following links for NinjaTrader 8 and NinjaTrader 7:

Once the file is downloaded, you can import the indicator into NinjaTader 8 from within the control center by selecting Tools → Import → NinjaScript Add-On and then selecting the downloaded file for NinjaTrader 8. To import the indicator into NinjaTrader 7, from within the control center window, select the menu File → Utilities → Import NinjaScript and select the downloaded file.

You can review the indicator’s source code in NinjaTrader 8 by selecting the menu New → NinjaScript Editor → Indicators from within the control center window and selecting the stiffness file. You can review the indicator’s source code in NinjaTrader 7 by selecting the menu Tools → Edit NinjaScript → Indicator from within the control center window and selecting the stiffness file.

NinjaScript uses compiled DLLs that run native, not interpreted, which provides you with the highest performance possible.

A sample chart implementing the indicator and strategy is shown in Figure 8.

Sample Chart

FIGURE 8: NINJATRADER. The stiffness indicator and strategy are displayed on ALGN between June 2016 and June 2018 with default settings.

—Raymond Deux & Jim Dooms
NinjaTrader, LLC
www.ninjatrader.com

BACK TO LIST

logo

TRADERSSTUDIO: NOVEMBER 2018

The importable TradersStudio set of files for Markos Katsanos’ article in this issue, “The Stiffness Indicator,” can be obtained on request via email to info@TradersEdgeSystems.com. The code is also shown here:

' STIFFNESS INDICATOR 
' Copyright Markos Katsanos 2018 
' Coded by: Richard Denning, 9/13/18
' www.TradersEdgeSystems.com

'STIFFNESS FUNCTION:
Function STIFFNESS(PERIOD,MAB,SM,NSTD)
'INPUTS:
'PERIOD = 60  
'MAB = 100  'MA DAYS 
'SM = 3  
'STIFFCRIT = 90
'NSTD = 2  ' Number of Standard Deviations 
'TIMEEXIT = 4 
Dim StDev,MA2,CLMA,PENS,STIF
' STIFFNESS: 
StDev = StdDevSClose(PERIOD, 0)  
MA2 = Average(C,MAB)- NSTD*StDev  
CLMA = C > MA2  
PENS = COUNTOF(CLMA,PERIOD,0)  
STIF = PENS*100/PERIOD  
STIFFNESS = XAverage(STIF,SM)  

End Function
'----------------------------------------------
'COUNTOF FUNCTION:
Function COUNTOF(rule As BarArray, countLen As Integer, offset As Integer)
Dim count As Integer
Dim counter As Integer
    For counter = 0 + offset To countLen + offset - 1 
        If rule[counter] Then 
            count = count + 1
        End If
    Next
COUNTOF = count
End Function
'-----------------------------------------------
'PLOT FOR STIFFNESS INDICATOR:
sub STIFFNESS_IND(PERIOD,MAB,SM,NSTD,STIFFCRIT)
Dim theSTIFFNESS As BarArray
theSTIFFNESS = STIFFNESS(PERIOD,MAB,SM,NSTD)
plot1(theSTIFFNESS)
plot2(STIFFCRIT)
End Sub
'------------------------------------------------
'STIFFNESS SYSTEM:
Sub STIFFNESS_SYS(PERIOD,MAB,SM,STIFFCRIT,NSTD,TIMEEXIT)
'INPUTS:
'PERIOD = 60  
'MAB = 100  'MA DAYS 
'SM = 3  
'ST=FCRIT = 90   'PLOT
'NSTD = 0.2  ' Number of Standard Deviations 
'TIMEEXIT = 4 
Dim SPYc As BarArray
Dim theSTIFFNESS As BarArray
Dim EMAspy As BarArray
SPYc = C Of Independent1
EMAspy = XAverage(SPYc,MAB)
theSTIFFNESS = STIFFNESS(PERIOD,MAB,SM,NSTD)
If EMAspy >= EMAspy[2] And CrossesOver(theSTIFFNESS, STIFFCRIT) Then
    Buy("LE",1,0,Market,Day) 
End If

If CrossesUnder(theSTIFFNESS,STIFFCRIT) Or BarsSinceEntry >= TIMEEXIT*21 Then
    ExitLong("LX","",1,0,Market,Day)
End If
End Sub

Figure 9 shows the indicator on a chart of Apple, Inc. (AAPL).

Sample Chart

FIGURE 9: TRADERSSTUDIO. Here, the stiffness indicator is demonstrated on a chart of AAPL.

—Richard Denning
info@TradersEdgeSystems.com
for TradersStudio

BACK TO LIST

MICROSOFT EXCEL: NOVEMBER 2018

In “The Stiffness Indicator” in this issue, Markos Katsanos presents an indicator that can show us when a trend has demonstrated “legs”—a trend that is “strong and of high-quality,” as Katsanos puts it.

The stiffness indicator is designed to analyze and qualify uptrends. A few tweaks and you would have an indicator to provide similar analysis and qualification of downtrends.

If you are long or short a given stock or index, or using calls or puts against the underlying, this sort of information would be very useful for your trading decisions.

While validating this indicator, Katsanos set up a simple, four-rule trading system based on this indicator to use in backtesting. Using the optimizing facilities available in AmiBroker helped to arrive at the various default parameter settings used in the “Stiffness exploration” section of the AmiBroker code sidebar in the article and for this spreadsheet.

Figure 10 shows the stiffness indicator and several buy & sell signals. All of the sell points (red circles) shown here are due to the duration exit criteria. Notice that in several instances, a buy was initiated one bar later (the slightly off-center blue dot). Conditions were still correct for a buy.

Sample Chart

FIGURE 10: EXCEL, PRICE CHART WITH INDICATOR. The stiffness indicator is shown on a price chart with shading. The sell points (red circles) shown here are due to the duration exit criteria.

Figure 11 zooms in on one of the trades, as this spreadsheet allow you to adjust the time period displayed.

Sample Chart

FIGURE 11: EXCEL, EXAMINING THE TRADES. By adjusting cell A12, you can scroll the charting window back to the appropriate dates (see Figure 12) to see the pricing action leading into and out of these stiffness exit trades (days in trade: less than 84).

It would be interesting to alter the duration exit logic to something like: “Once we have exceeded the bars-in-trade criteria (and for each succeeding bar-in-trade), exit the trade only if conditions are no longer valid for entry.”

In the overall list of trades (Figure 12), older trades can be found that exited due to stiffness dropping below the suggested stiff exit threshold of 50.

Sample Chart

FIGURE 12: EXCEL, transaction summary tab. The transaction summary tab is built to accommodate at least 270 transactions but could be extended.

As Katsanos points out near the end of his article, the simple exit rules he used for testing do not constitute a robust system. He offers a couple of ideas that we might use to replace or augment the stiffness exit criteria.

To keep this spreadsheet to a manageable download size (it’s already over 4 MB), I reduced the capacity to 1,000 bars on the ComputationsAndCharts tab. A thousand bars translates to just under four years as opposed to the 10 years used for backtesting in the article.

Once you have the spreadsheet downloaded, if your Excel skills are up to it, you certainly can extend the ComputationsAndCharts tab row formulas beyond the initial 1,000. Making such an extension may not require any changes to the Transaction Summary tab (Figure 12), which is built to handle upwards of 270 transactions, but may also benefit from having the number of rows extended if you decide to extend the ComputationsAndCharts tab to accommodate 10 years.

The spreadsheet file for this Traders’ Tip can be downloaded here. To successfully download it, follow these steps:

—Ron McAllister
Excel and VBA programmer
rpmac_xltt@sprynet.com

BACK TO LIST

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