TRADERS’ TIPS
For this month’s Traders’ Tips, the focus is Vitali Apirine’s article in this issue, “Exponential Standard Deviation Bands.” Here, we present the February 2017 Traders’ Tips code with possible implementations in various software.
The Traders’ Tips section is provided to help the reader implement a selected technique from an article in this issue or another recent issue. The entries here are contributed by software developers or programmers for software that is capable of customization.
In “Exponential Standard Deviation Bands” in this issue, author Vitali Apirine presents a method intended to help traders see volatility while a stock is trending. These bands, while similar to Bollinger Bands, are calculated using exponential moving averages rather than simple moving averages. Like Bollinger Bands, they widen when volatility increases and narrow as volatility decreases. He suggests that the indicator can be used as a confirming indication along with other indicators such as the ADX.
Here, we are providing TradeStation EasyLanguage code for an exponential standard deviation bands indicator based on the author’s concepts. We have also included a function so that you can easily include the calculation in your own strategies or indicators.
Indicator: ESD Bands // TASC FEB 2017 // Exp Std Dev Bands // Vitali Apirine inputs: Price( Close ), Length( 20 ), NumDevs( 2 ) ; variables: ExpSDev( 0 ), MidLine( 0 ), UpperBand( 0 ), LowerBand( 0 ) ; MidLine = XAverage( Price, Length ) ; ExpSDev = ExpStdDev( Price, Length ) ; UpperBand = MidLine + ExpSDev * NumDevs ; LowerBand = MidLIne - ExpSDev * NumDevs ; Plot1( MidLine, "MidLine" ) ; Plot2( UpperBand, "UpperBand" ) ; Plot3( LowerBand, "LowerBand" ) ; Function: ExpStdDev inputs: Price( numericseries ), Length( numericsimple ) ; variables: XMean( 0 ), SumSqr( 0 ), Counter( 0 ), XVariance( 0 ) ; if Length > 0 then begin XMean = XAverage( Price, Length ) ; SumSqr = 0 ; for Counter = 0 to Length - 1 begin SumSqr = SumSqr + Square( Price[Counter] - XMean ) ; end ; XVariance = SumSqr / Length ; ExpStdDev = SquareRoot( XVariance ) ; end else ExpStdDev = -1 ;
To download the EasyLanguage code for the indicator and function presented here, please visit our TradeStation and EasyLanguage support forum. The code can be found here at https://community.tradestation.com/Discussions/Topic.aspx?Topic_ID=147651. The ELD filename is “TASC_FEB2017.ELD.”
For more information about EasyLanguage in general, please see https://www.tradestation.com/EL-FAQ.
A sample chart is shown in Figure 1.
FIGURE 1: TRADESTATION. Here is an example of the exponential standard deviation bands indicator applied to a daily S&P 500 index chart.
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.
Vitali Apirine’s article in this issue, “Exponential Standard Deviation Bands,” introduces an indicator of the same name. Here is the MetaStock formula for that indicator.
Exponential Standard Deviation Bands t1:= Input("time periods", 1, 50, 20); p1:= C; ma:= Mov(p1,t1,S); x:=Sum(Power(p1-LastValue(ma +(PREV*0)),2),t1); esd:= Sqrt(x/t1); ma + (esd * 2); ma; ma - (esd * 2)
For this month’s Traders’ Tip, we’ve provided the study ESDB.efs based on Vitali Apirine’s article in this issue, “Exponential Standard Deviation Bands.” In the article, Apirine presents a way of determining the volatility of a market.
The study contains formula parameters that may be configured through the edit chart window (right-click on the chart and select “edit chart”). A sample chart is shown in Figure 2.
FIGURE 2: eSIGNAL. Here is an example of the ESDB.efs study plotted on a daily chart of $SPX.
To discuss this study or download a complete copy of the formula code, please visit the EFS Library Discussion Board forum under the forums link from the support menu at www.esignal.com, or visit our EFS KnowledgeBase at https://www.esignal.com/support/kb/efs/. The eSignal formula script (EFS) is also available for copying & pasting below.
/********************************* Provided By: eSignal (Copyright c eSignal), a division of Interactive Data Corporation. 2016. All rights reserved. This sample eSignal Formula Script (EFS) is for educational purposes only and may be modified and saved under a new file name. eSignal is not responsible for the functionality once modified. eSignal reserves the right to modify and overwrite this EFS file with each new release. Description: Exponential Standard Deviation Bands by Vitali Apirine Version: 1.00 12/07/2016 Formula Parameters: Default: Length 20 # of EStdDev 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); setCursorLabelName("Upper", 0); setCursorLabelName("Middle", 1); setCursorLabelName("Lower", 2); setDefaultBarFgColor(Color.RGB(255,106,0),1); var x = 0; fpArray[x] = new FunctionParameter("Length", FunctionParameter.INTEGER) with(fpArray[x++]){ setLowerLimit(1); setDefault(20); setName("Length"); } fpArray[x] = new FunctionParameter("MFactor", FunctionParameter.NUMBER) with(fpArray[x++]){ setLowerLimit(1); setDefault(2); setName("# of EStdDev"); } } var bInit = false; var bVersion = null; var xClose = null; var xEMA = null; var xStdDev = null; var xUpBand = null; var xLwBand = null; var bUpFlag = false; var bLwFlag = true; function main(Length, MFactor){ if (bVersion == null) bVersion = verify(); if (bVersion == false) return; if (getBarState() == BARSTATE_ALLBARS) bInit = false; if (!bInit){ xClose = close(); xEMA = ema(Length, xClose); xStdDev = efsInternal("ExpStdDev", xClose, xEMA, Length); xUpBand = efsInternal("UpperLower", xEMA, xStdDev, MFactor, bUpFlag); xLwBand = efsInternal("UpperLower", xEMA, xStdDev, MFactor, bLwFlag); bInit = true; } nUpBand = xUpBand.getValue(0); nMidBand = xEMA.getValue(0); nLwBand = xLwBand.getValue(0); if ((!isNull(nUpBand)) && (!isNull(nMidBand)) && (!isNull(nLwBand))) return [nUpBand, nMidBand, nLwBand]; } function ExpStdDev(xClose, xEMA, len){ var nSum = 0; var nEMA = xEMA.getValue(0); for (var i = 0; i < len; i++){ var nClose = xClose.getValue(-i); if (!isNull(nClose) && !isNull(nEMA)){ nSum += Math.pow((nClose - nEMA), 2); } } return (Math.sqrt(nSum/len)); } function UpperLower(xEMA, xStdDev, MFactor, bFlag){ var nEMA = xEMA.getValue(0); var nStdDev = xStdDev.getValue(0); nStdDev *= MFactor; if (bFlag == bLwFlag) nStdDev = -nStdDev; return (nEMA + nStdDev); } 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; }
The ESD bands indicator, as discussed by Vitali Apirine in his article in this issue, “Exponential Standard Deviation Bands,” is available for download at the following links for NinjaTrader 8 and for NinjaTrader 7.
Once the file is downloaded, you can import the strategy in NinjaTader 8 from within the Control Center by selecting Tools → Import → NinjaScript Add-On and then selecting the downloaded file for NinjaTrader 8. To import in NinjaTrader 7 from within the Control Center window, select the menu File → Utilities → Import NinjaScript and select the downloaded file.
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 ESDBands 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 ESDBands file.
NinjaScript uses compiled DLLs that run native, not interpreted, which provides the highest performance possible.
A sample chart implementing the strategy is shown in Figure 3.
FIGURE 3: NINJATRADER. The ESDBands are displayed on an S&P 500 index daily chart in NinjaTrader 8.
In “Exponential Standard Deviation Bands” in this issue, author Vitali Apirine builds some price bands based on an exponential moving average. The idea behind this study is to have the ability to visualize price volatility and determine whether the current price volatility is extraordinary or not.
We built the following study using our proprietary scripting language, thinkscript. To allow greater customization, we added the ability to change variables. We have made the loading process extremely easy; simply click https://tos.mx/H02oFo then choose to “view thinkScript study.” Choose to rename your study “ESDBands.”
In Figure 4, you can see a daily chart of the S&P over the past year. You can see that at the end of October and beginning of November the price was below that lower band. This is a strong signal that a breakout is coming in the other direction, according to Apirine’s article. You can also see that the ADX made a short-term spike, which is seen as an indication that direction is changing. For more details on the approach, refer to Apirine’s article in this issue.
FIGURE 4: THINKORSWIM. This daily chart of the S&P for the past year shows the price bands and the ADX.
The exponential standard deviation bands (ESD bands) discussed by Vitali Apirine in his article in this issue follow the same interpretation guidelines as Bollinger Bands do, for example. The difference is in the usage of exponential standard deviation, which is believed to make the ESD bands more sensitive to market action. As to the optimal condition for applying them, Apirine suggests a flat trend.
To illustrate application of ESD bands, we’ve included a simple system that is based on a %b indicator that depicts how the price relates to the bands as well as to what degree it is above or below any of the bands. If the price is equal to the upper band, %b will be 100%; if it’s equal to the lower band, %b will be 0.0, and a %b value of 50% (0.5) means the price is in between, that is, equal to the EMA.
Here are the rules of the system:
A sample chart implementing the system is shown in Figure 5.
FIGURE 5: WEALTH-LAB. This example Wealth-Lab 6 chart illustrates the application of the system’s rules on a daily chart of PowerShares QQQ Trust ETF (QQQ).
To execute the example trading system, Wealth-Lab users should install (or update) the latest version of the TASCIndicators library from the Extensions section of our website if they haven’t already done so, and restart Wealth-Lab.
using System; using System.Collections.Generic; using System.Text; using System.Drawing; using WealthLab; using WealthLab.Indicators; using Community.Indicators; using TASCIndicators; namespace WealthLab.Strategies { public class PctB : WealthScript { private StrategyParameter esdbPeriod; private StrategyParameter esdbStdDev; public PctB() { esdbPeriod = CreateParameter("ESD Bands Period", 20, 5, 50, 5); esdbStdDev = CreateParameter("Std Dev", 2, 1, 5, 0.25); } protected override void Execute() { var period = esdbPeriod.ValueInt; var sd = esdbStdDev.Value; var esdbL = ESDBandLower.Series(Close,period,sd); var esdbU = ESDBandUpper.Series(Close,period,sd); DataSeries PctESDBW = ( Close - esdbL ) / ( esdbU - esdbL ); PctESDBW.Description = "% ESDB Width"; DataSeries pctESDBBelow = SeriesIsBelowValue.Series( PctESDBW, 0.2, 3 ); ChartPane xob_pane = CreatePane( 20, true, true ); PlotSeries( xob_pane, pctESDBBelow, Color.DarkRed, WealthLab.LineStyle.Solid, 1 ); ChartPane PctBBWPane = CreatePane( 20, true, true ); PlotSeries( PctBBWPane, PctESDBW, Color.Blue, WealthLab.LineStyle.Solid, 2 ); Color fillColor = Color.FromArgb(16, 0, 0, 255); PlotSeriesFillBand( PricePane, esdbU, esdbL, Color.Blue, fillColor, LineStyle.Solid, 1); HideVolume(); for(int bar = PctESDBW.FirstValidValue; bar < Bars.Count; bar++) { if (IsLastPositionActive) { if( PctESDBW[bar] >= 0.8 ) SellAtMarket( bar+1, LastPosition ); } else { if( bar >= pctESDBBelow[bar]+3 && pctESDBBelow[bar-3] > pctESDBBelow[bar-4] ) { SetBackgroundColor( bar, Color.FromArgb(231, 255, 231) ); if( BuyAtMarket( bar+1 ) != null ) LastPosition.Priority = -Close[bar]; } } } } } }
In “Exponential Standard Deviation Bands” in this issue, author Vitali Apirine presents a variation on classic Bollinger Bands. Instead of using a simple moving average, the exponential standard deviation bands use an exponential moving average as its base.
A ready-to-use AmiBroker formula that implements these bands is shown below. Use the parameters window to control the chart mode and switch between the bands and the indicator on a price chart. A sample chart is shown in Figure 6.
FIGURE 6: AMIBROKER. Here is an S&P 500 candlestick chart with exponential standard deviation bands based on Vitali Apirine’s article in this issue.
function ExpStandardDeviation( array, period ) { x = array - array[ BarCount - 1 ]; // dc removal ax = EMA( x, period ); sumd = 0; for( i = 0; i < period; i++ ) { d = Ref( x, -i ) - ax; sumd += d * d; } return sqrt( sumd / period ); } mode = ParamToggle("Mode", "Price&Bands|StdDev" ); period = Param("Period", 20 ); width = 2; if( mode == 0 ) { Plot( C, "Price", colorDefault, styleCandle ); center = EMA( C, period ); sd = ExpStandardDeviation( C, period ); Plot( center, "EMA"+_PARAM_VALUES(), colorRed ); upband = center + width * sd; dnband = center - width * sd; bandcolor = ColorBlend( colorLightBlue, GetChartBkColor(), 0.25 ); interior = ColorBlend( bandcolor, GetChartBkColor(), 0.7 ); Plot( upband, "UpperBand", bandcolor ); Plot( dnband, "LowerBand", bandcolor ); PlotOHLC( upband, upband, dnband, dnband, "", interior, styleCloud, Null, Null, 0, -1 ); } else { Plot( ExpStandardDeviation( Close, period ), "ExpStDev", colorRed ); Plot( StDev( Close, period ), "StDev", colorGreen ); }
The exponential standard deviation bands discussed by Vitali Apirine in his article in this issue can be easily implemented with a few of NeuroShell Trader’s 800+ indicators. Simply select new indicator from the insert menu and use the indicator wizard to create the following indicators:
ESD: SqrRt(Divide(Pow(Sub(Close,ExpAvg(Close,20)),2),20)) UpperBand: Add2( ExpAvg( Close,20 ), ESD) MiddleBand: ExpAvg( Close,20 ) LowerBand: Sub( ExpAvg( Close,20 ), ESD)
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 7.
FIGURE 7: NEUROSHELL TRADER. This NeuroShell Trader chart shows the exponential standard deviation bands on the S&P 500 index.
The AIQ code based on Vitali Apirine’s article in this issue, “Exponential Standard Deviation Bands,” can be found at www.TradersEdgeSystems.com/traderstips.htm.
To compare the exponential bands to Bollinger Bands, I created a trend-following trading system that trades long only according to the following rules:
Figure 8 shows the summary test results for taking all signals from the Bollinger Band system run on NASDAQ 100 stocks over the period 12/9/2000 to 12/09/2016. Figure 9 shows the summary test results for taking all signals from the exponential band system on NASDAQ 100 stocks over the same period. The exponential band system improved the average profit per trade while reducing the total number of trades.
FIGURE 8: AIQ. Here are summary test results for taking all signals from the Bollinger Band system run on NASDAQ 100 stocks over the period 12/9/2000 to 12/09/2016.
FIGURE 9: AIQ. Here are summary test results for taking all signals from the exponential band system run on NASDAQ 100 stocks over the period 12/9/2000 to 12/09/2016.
The code and EDS file can be downloaded from www.TradersEdgeSystems.com/traderstips.htm and is also shown here:
!Exponential Standard Deviation Bands !Author: Vitali Apirine, TASC February 2017 !Coded by: Richard Denning 12/11/2016 !www.TradersEdgeSystems.com !INPUT: xlen is 20. numSD is 2. !INDICATOR CODE: ExpAvg is expavg([close],xlen). Dev is [close] - ExpAvg. DevSqr is Dev*Dev. SumSqr is sum(DevSqr,xlen). AvgSumSqr is SumSqr / xlen. ExpSD is sqrt(AvgSumSqr). !UPPER EXPONENTIAL SD BAND: UpExpSD is ExpAvg + numSD*ExpSD. !PLOT ON CHART !LOWER EXPONENTIAL SD BAND: DnExpSD is ExpAvg - numSD*ExpSD. !PLOT ON CHART !MIDDLE EXPONENTIAL SD BAND: MidExpSD is ExpAvg. !BOLLINGER BANDS FOR COMPARISON: DnBB is [Lower BB]. !Lower Bollinger Band UpBB is [Upper BB]. !Upper Bollinger Band MidBB is simpleavg([close],xlen). !Middle Bollinger Band !REPORT RULE TO DISPLAY VALUES: ShowValures if 1. !TRADING SYSTEM USING EXPPONENTIAL SD BANDS: UpTrend if MidExpSD > valresult(MidExpSD,1). BreakUp if [close] > UpExpSD. BuyExpSD if UpTrend and BreakUp and valrule(Breakup=0,1). ExitExpSD if [Low] < DnExpSD. ! or UpTrend=0. !TRADING SYSTEM USING BOLLINGER BANDS: UpTrendBB if MidBB > valresult(MidBB,1). BreakUpBB if [close] > UpBB. BuyBB if UpTrendBB and BreakUpBB and valrule(BreakupBB=0,1). ExitBB if [Low] < DnBB. ! or UpTrend=0.
The TradersStudio code based on Vitali Apirine’s article in this issue, “Exponential Standard Deviation Bands,” can be found at www.TradersEdgeSystems.com/traderstips.htm.
The following code files are provided in the download:
In Figure 10, I show the EXSDB(20,2) indicator plotted on a chart of the S&P 500.
FIGURE 10: TRADERSSTUDIO. Here is the EXSDB(20,2) indicator plotted on a chart of the S&P 500.
The code is shown here:
'Exponential Standard Deviation Bands 'Author: Vitali Apirine, TASC February 2017 'Coded by: Richard Denning 12/11/16 'www TradersEdgeSystems.com Function EXPSD(xlen) 'INPUT: xlen = 20 Dim expAvg As BarArray Dim dev As BarArray Dim devSqr As BarArray Dim sumSqr As BarArray Dim avgSumSqr As BarArray 'INDICATOR CODE: expAvg = XAverage(Close,xlen) dev = Close - expAvg devSqr = dev*dev sumSqr = Summation(devSqr,xlen) avgSumSqr = sumSqr / xlen EXPSD = Sqr(avgSumSqr) End Function '-------------------------------------------------- Function EXPSDB(xlen,numSD,byref upSDB,byref dnSDB) 'Input: xlen = 20, numSD = 2 'INDICATOR CODE: Dim midSDB midSDB = XAverage(Close,xlen) upSDB = midSDB + numSD*EXPSD(xlen) dnSDB = midSDB - numSD*EXPSD(xlen) EXPSDB = midSDB End Function '-------------------------------------------------- sub EXPSDB_IND(xlen,numSD) Dim upSDB Dim dnSDB Dim midSDB midSDB = EXPSDB(xlen,numSD,upSDB,dnSDB) plot1(upSDB) plot2(dnSDB) plot3(midSDB) End Sub