TRADERS’ TIPS
For this month’s Traders’ Tips, we focus on Vitali Apirine’s June 2015 article, “The Slow Volume Strength Index,” as a followup to last month’s Traders’ Tips, which focused on Vitali Apirine’s April 2015 article, “The Slow Relative Strength Index.” Here, we present the August 2015 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 “The Slow Volume Strength Index,” which appeared in the June 2015 issue of STOCKS & COMMODITIES, author Vitali Apirine describes a momentum volume oscillator called the slow volume strength index (SVSI) that he characterizes as measuring the buying and selling pressure relative to a price exponential moving average. He then uses a method of smoothing based on techniques originally presented by J. Welles Wilder. Apirine presents a number of ways to use the oscillator, including combining it with his slow relative strength index (SRSI) oscillator, which he presented in his article “The Slow Relative Strength Index,” which appeared in the April 2015 issue of STOCKS & COMMODITIES.
For users’ convenience, we are providing the code for a TradeStation SVSI indicator as well as simple strategy based on the author’s work. A sample chart is shown in Figure 1.
{ TASC Jun 2015 The Slow Volume Strength Index Indicator Vitale Apirine } inputs: EMALength( 6 ), SmoothingLength( 14 ), OverBought( 80 ), OverSold( 20 ), MidLine( 50 ) ; variables: EMAValue( 0 ), PosVolume( 0 ), NegVolume( 0 ), AvgPosVol( 0 ), AvgNegVol( 0 ), SVS( 0 ), SVSI( 0 ), MyVolume( 0 ) ; if BarType >= 2 and BarType < 5 then MyVolume = Volume else MyVolume = Ticks ; EMAValue = XAverage( Close, EMALength ) ; if Close > EMAValue then begin PosVolume = MyVolume ; NegVolume = 0 ; end else if Close < EMAValue then begin PosVolume = 0 ; NegVolume = MyVolume ; end else begin PosVolume = 0 ; NegVolume = 0 ; end ; if CurrentBar = 1 then begin AvgPosVol = Average( PosVolume, SmoothingLength ) ; AvgNegVol = Average( NegVolume, SmoothingLength ) ; end else if CurrentBar > 1 then begin AvgPosVol = ( ( AvgPosVol * 13 ) + PosVolume ) / 14 ; AvgNegVol = ( ( AvgNegVol * 13 ) + NegVolume ) / 14 ; end ; SVS = iff( AvgNegVol <> 0, AvgPosVol / AvgNegVol, 100 ) ; if SVS <> 0 then SVSI = 100 - ( 100 / ( 1 + SVS ) ) ; Plot1( SVSI, "SVSI" ) ; Plot2( OverBought, "OB" ) ; Plot3( OverSold, "OS" ) ; Plot4( MidLine, "MidLine" ) ; Strategy SVSI { TASC Jun 2015 The Slow Volume Strength Index Strategy Vitale Apirine } inputs: EMALength( 6 ), SmoothingLength( 14 ), OverBought( 80 ), OverSold( 20 ), MidLine( 50 ) ; variables: EMAValue( 0 ), PosVolume( 0 ), NegVolume( 0 ), AvgPosVol( 0 ), AvgNegVol( 0 ), SVS( 0 ), SVSI( 0 ), MyVolume( 0 ) ; if BarType >= 2 and BarType < 5 then MyVolume = Volume else MyVolume = Ticks ; EMAValue = XAverage( Close, EMALength ) ; if Close > EMAValue then begin PosVolume = MyVolume ; NegVolume = 0 ; end else if Close < EMAValue then begin PosVolume = 0 ; NegVolume = MyVolume ; end else begin PosVolume = 0 ; NegVolume = 0 ; end ; if CurrentBar = 1 then begin AvgPosVol = Average( PosVolume, SmoothingLength ) ; AvgNegVol = Average( NegVolume, SmoothingLength ) ; end else if CurrentBar > 1 then begin AvgPosVol = ( ( AvgPosVol * 13 ) + PosVolume ) / 14 ; AvgNegVol = ( ( AvgNegVol * 13 ) + NegVolume ) / 14 ; end ; SVS = iff( AvgNegVol <> 0, AvgPosVol / AvgNegVol, 100 ) ; if SVS <> 0 then SVSI = 100 - ( 100 / ( 1 + SVS ) ) ; if SVSI crosses over MidLine then Buy next bar at Market else if SVSI crosses under MidLine then SellShort next bar at Market ;
FIGURE 1: TRADESTATION. Here is an example of the SVSI indicator and strategy applied to a daily chart of the Dow Jones Industrial Average (DJIA).
To download the EasyLanguage code, please visit our TradeStation and EasyLanguage support forum. The code for this article can be found here: https://www.tradestation.com/TASC-2015. The ELD filename is “TASC_AUG2015.ELD.” For more information about EasyLanguage in general, please see https://www.tradestation.com/EL-FAQ.
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.
For this month’s Traders’ Tip, we’ve provided the study SVSI.efs based on the formula described in Vitali Apirine’s article in the June 2015 issue of S&C, “The Slow Volume Strength Index.” In it, Apirine presents a volume oscillator based on J. Welles Wilder’s relative strength index (RSI). It also utilizes a price-based exponential moving average to determine overbought and oversold conditions, as well as divergences.
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 plotting the SVSI is shown in Figure 2.
FIGURE 2: eSIGNAL. Here is an example of the SVSI study plotted on a daily chart of AAPL.
/********************************* Provided By: Interactive Data Corporation (Copyright В© 2015) All rights reserved. This sample eSignal Formula Script (EFS) is for educational purposes only. Interactive Data Corporation reserves the right to modify and overwrite this EFS file with each new release. Description: The Slow Volume Strength Index by Vitali Apirine Formula Parameters: Default: Length EMA 6 Length Average Differences 14 Upper Bound 80 Lower Bound 20 Version: 1.00 06/05/2015 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(){ setStudyTitle("SVSI"); setCursorLabelName("Upper Bound", 0); setCursorLabelName("Lower Bound", 1); setCursorLabelName("Center Line", 2); setCursorLabelName("SVSI", 3); setDefaultBarFgColor(Color.grey, 0); setDefaultBarFgColor(Color.grey, 1); setDefaultBarFgColor(Color.grey, 2); setShowCursorLabel(false, 0); setShowCursorLabel(false, 1); setShowCursorLabel(false, 2); setShowCursorLabel(true, 3); setDefaultBarStyle(PS_SOLID, 0); setDefaultBarStyle(PS_SOLID, 1); setDefaultBarStyle(PS_DASHDOT, 2); setDefaultBarStyle(PS_SOLID, 3); var x = 0; fpArray[x] = new FunctionParameter("fpLengthEMA", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Length EMA"); setLowerLimit(1); setDefault(6); }; fpArray[x] = new FunctionParameter("fpLengthAvgDiff", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Length Average Differences"); setLowerLimit(1); setDefault(14); }; fpArray[x] = new FunctionParameter("fpSRSIHighBorder", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Upper Bound"); setLowerLimit(0); setUpperLimit(100); setDefault(80); }; fpArray[x] = new FunctionParameter("fpSRSILowBorder", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Lower Bound"); setLowerLimit(0); setUpperLimit(100); setDefault(20); }; } var bInit = false; var bVersion = null; var xDifferences = null; var xPositiveDiff = null; var xNegativeDiff = null; var xPositiveDiffAvg = null; var xNegativeDiffAvg = null; function main(fpLengthEMA, fpLengthAvgDiff, fpSRSIHighBorder, fpSRSILowBorder){ if (bVersion == null) bVersion = verify(); if (bVersion == false) return; if (!bInit){ xDifferences = efsInternal('Calc_Differences', fpLengthEMA); xPositiveDiff = getSeries(xDifferences, 0); xNegativeDiff = getSeries(xDifferences, 1); xPositiveDiffAvg = smma(fpLengthAvgDiff, xPositiveDiff); xNegativeDiffAvg = smma(fpLengthAvgDiff, xNegativeDiff); bInit = true; }; var nPositiveDiffAvg = xPositiveDiffAvg.getValue(0); var nNegativeDiffAvg = xNegativeDiffAvg.getValue(0); if (nPositiveDiffAvg == null || nNegativeDiffAvg == null) return; var nSVSI = (nNegativeDiffAvg == 0) ? 100 : 100 - (100 / (1 + (nPositiveDiffAvg / nNegativeDiffAvg))); return [fpSRSIHighBorder, fpSRSILowBorder, 50, nSVSI]; } var xClose = null; var xEMA = null; var xVol = null; function Calc_Differences(nLength){ if (getBarState() == BARSTATE_ALLBARS){ xClose = close(); xEMA = ema(nLength); xVol = volume(); } var nClose = xClose.getValue(0); var nEMA = xEMA.getValue(0); var nVol = xVol.getValue(0); if (nClose == null || nEMA == null || nVol == null) return; var nPositiveDiff = nClose > nEMA ? nVol : 0; var nNegativeDiff = nClose < nEMA ? nVol : 0; return [nPositiveDiff, nNegativeDiff]; } function verify(){ var b = false; if (getBuildNumber() < 3742){ drawTextAbsolute(5, 35, "This study requires version 12.1 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; }
In his June 2015 article “The Slow Volume Strength Index,” author Vitali Apirine expands on the slow relative strength index (SRSI) concept presented in his April 2015 article, but this time, changes the focus to volume.
Keeping in the same theme as his earlier article that “slow and steady wins the race,” he uses ideas from the SRSI concept but this time measures the relative strength of volume.
We have recreated his slow volume strength index (SVSI) as a thinkorswim study using our proprietary scripting language, thinkscript. We have made the loading process extremely easy—simply click on the link https://tos.mx/MEqL2n and choose save script to thinkorswim, then choose to rename your study to “SlowVSI.” You can adjust the parameters of these within the edit studies window to fine-tune your variables.
FIGURE 3: THINKORSWIM. The SlowVSI is plotted on a chart of GE over the past year.
In the example shown in Figure 3, you see the SlowVSI plotted on a chart of GE over the past year. For a more detailed description of the indicator, please see Apirine’s article in June 2015 issue.
The slow relative volume index (SVSI) introduced by Vitali Apirine in his June 2015 STOCKS & COMMODITIES article, “The Slow Volume Strength Index,” is a momentum volume oscillator similar to its sibling, the SRSI (slow relative strength index, described in Apirine’s April 2015 STOCKS & COMMODITIES article, “The Slow Relative Strength Index”) in application and interpretation. Oscillating between zero and 100, the SVSI becomes overbought after reaching 80 and oversold after dropping below 20. Signals can also be generated by looking for centerline crossovers and divergences.
As with the RSI (relative strength index) after which the SVSI is modeled, SVSI could be put to use to screen for dips in established trends. The following example trading system will focus on this ability. Here are its rules:
The trailing stop parameter (lowest low of N days) controls the trade duration: set it to a shorter period (five bars) to profit from small rallies, or to a longer period (for example, 20–50 bars) to catch larger trends (see Figure 4).
FIGURE 4: WEALTH-LAB, SVSI. Here is a characteristic trade on the ^DJIA when the SVSI dips below 50 in a strong uptrend.
You will find the SVSI indicator installed under the “TASC Magazine Indicators” group in Wealth-Lab after you update the TASCIndicators library to version 2015.07 or later, You can plot the indicator on a chart or use it as an entry or exit condition in a rule-based strategy without having to program any code yourself.
The code is shown below.
using System; using System.Collections.Generic; using System.Text; using System.Drawing; using WealthLab; using WealthLab.Indicators; using TASCIndicators; namespace WealthLab.Strategies { public class TASCTips201507 : WealthScript { private StrategyParameter paramSVSIPeriod; private StrategyParameter paramSVSIWMAPeriod; private StrategyParameter paramSVSIThreshold; private StrategyParameter paramSMAPeriod; private StrategyParameter paramExitChannel; public TASCTips201507() { paramSVSIPeriod = CreateParameter("SVSI Period",6,6,30,2); paramSVSIWMAPeriod = CreateParameter("SVSI WilderMA Period",14,8,52,4); paramSVSIThreshold = CreateParameter("SVSI Threshold",50,40,90,5); paramSMAPeriod = CreateParameter("SMA Period",40,10,100,10); paramExitChannel = CreateParameter("Trailing Exit",20,5,50,5); } protected override void Execute() { int svsiThreshold = paramSVSIThreshold.ValueInt; int smaPeriod = paramSMAPeriod.ValueInt; int trailingExit = paramExitChannel.ValueInt; SVSI svsi = SVSI.Series(Bars,paramSVSIPeriod.ValueInt, paramSVSIWMAPeriod.ValueInt); SMA sma = SMA.Series(Close,smaPeriod); ChartPane paneSVSI1 = CreatePane(40,true,true); PlotSeries(PricePane,sma,Color.MediumVioletRed,LineStyle.Solid,1); PlotSeries(paneSVSI1,svsi,Color.FromArgb(255,255,128,0),LineStyle.Solid,2); DrawHorzLine(paneSVSI1,50,Color.DodgerBlue,LineStyle.Dashed,2); for(int bar = GetTradingLoopStartBar(1); bar < Bars.Count; bar++) { if (IsLastPositionActive) { SellAtTrailingStop(bar+1,LastPosition, Lowest.Series(Low,trailingExit)[bar]); } else { if( Close[bar] > sma[bar] && svsi[bar] < svsiThreshold ) BuyAtMarket(bar+1); } } } } }
The slow volume strength index (SVSI) described by Vitali Apirine in his June 2015 article, “The Slow Volume Strength Index,” 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 set up the following indicators:
C1: ExpAvg(Close,6) V4: ExpAvg(IfThenElse(A>B(Close,C1),Volume,0),14) V5: ExpAvg(IfThenElse(A<B(Close,C1),Volume,0),14) RR: IfThenElse(A=B(V5,0),100,Sub(100,Divide(100,Add2(1,Divide(V4,V5)))))
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 5.
FIGURE 5: NEUROSHELL TRADER, SVSI. This sample NeuroShell Trader chart displays the SVSI on the DJIA.
The AIQ code based on Vitali Apirine’s June 2015 article in S&C, “The Slow Volume Strength Index,” is provided for download from the following website:
!THE SLOW VOLUME STRENGTH INDEX !Author: Vitali Aiprine, TASC April 2015 !Coded by: Richard Denning 6/10/2015 !www.TradersEdgeSystems.com !INPUTS FOR INDICATOR: emaLen is 6. wilderLen is 14. !INDICATOR FORMULAS: ema is expavg([close],emaLen). pDif is iff([close] - ema > 0,[volume],0). nDif is iff([close] - ema < 0,[volume],0). rsiLen is 2 * wilderLen - 1. AvgU is expavg(pDif,rsiLen). AvgD is expavg(nDif,rsiLen). svsi is 100-(100/(1+(AvgU/AvgD))). !PLOT
The code provided for the slow volume strength index (SVSI) may be plotted as an indicator, as shown in Figure 6.
FIGURE 6: AIQ. Here is the SVSI (6,14) indicator compared to the classic RSI (14).
The TradersStudio code based on Vitali Apirine’s June 2015 article in S&C, “The Slow Volume Strength Index,” is provided for download from the following website:
The following two code files are contained in the download:
FIGURE 7: TRADERSSTUDIO. Here is an example of the SVSI indicator on a chart of ESRX.
Figure 7 shows the indicator plotted on a chart of ESRX. The TradersStudio code is shown here:
'THE SLOW VOLUME STRENGTH INDEX 'Author: Vitali Aprine, TASC June 2015 'Coded by: Richard Denning 6/10/2015 'www.TradersEdgeSystems.com 'FUNCTION THAT RETURNS THE SVSI VALUES: function SlowVRSI(emaLen, wilderLen) 'emaLen = 6, wilderLen = 14 'INDICATOR FORMULAS: Dim ema,pDif,nDif,rsiLen,AvgU,AvgD Dim sVSI As BarArray ema = xaverage(C,emaLen) pDif = IIF(C - ema > 0,V,0) nDif = IIF(C - ema < 0,V,0) rsiLen = 2 * wilderLen - 1 AvgU = xaverage(pDif,rsiLen) AvgD = xaverage(nDif,rsiLen) if avgd <> 0 then sVSI = 100-(100/(1+(AvgU/AvgD))) SlowVRSI = sVSI End Function '-------------------------------------------------------- 'INDICATOR PLOT CODE: sub SlowVRSI_IND(emaLen, rsiLen) plot1(slowVRSI(emaLen, rsiLen)) plot2(70) plot3(30) End Sub '--------------------------------------------------------
We are providing a custom NinjaScript indicator based on Vitali Apirine’s June 2015 article, “The Slow Volume Strength Index.” This indicator, the slow volume strength index or SVSI, is available for download at www.ninjatrader.com/SC/August2015SC.zip.
Once you have it 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 or greater.
You can review the indicator source code by selecting the menu Tools → Edit NinjaScript → Indicator from within the NinjaTrader Control Center window and selecting the SVSI file.
NinjaScript uses compiled DLLs that run native, not interpreted, which provides you with the highest performance possible.
A sample chart implementing the indicator on a chart of the DJIA is shown in Figure 8.
FIGURE 8: NINJATRADER. This chart shows the indicator applied to the daily DJIA index in NinjaTrader with the SVSI (slow volume strength index) and SRSI (slow RSI) plotted together above the DJIA. Volume is plotted below the DJIA.
Our Traders’ Tip for this month is based on an article by Vitali Apirine that appeared in the June 2015 issue of STOCKS & COMMODITIES titled “The Slow Volume Strength Index.” In the article, Apirine delivers a variation of J. Welles Wilder’s classic relative strength index (RSI). Apirine substitutes the close-to-close difference input in the RSI with the difference between the close and moving average as the input for the SVSI in order to assign positive and negative values to volume. See Figure 9 for an example implementation of the SVSI on a chart in Updata.
FIGURE 9: UPDATA, SVSI. This chart shows the Dow Jones Industrial Average ETF (DIA) with the SVSI [14] shown in red and the standard RSI [14] for comparison.
The Updata code for this indicator is in the Updata Library and it may be downloaded by clicking the custom menu and then indicator library. Those who cannot access the library due to a firewall may paste the code shown here into the Updata custom editor and save it.
PARAMETER "Smooth Period" #SMOOTH=6 PARAMETER "SVSI Period" #PERIOD=14 NAME "SVSI[" #PERIOD "]" "" COLOUR RGB(200,0,0) @AVG=0 @POSVOL=0 @NEGVOL=0 @SVSI=0 FOR #CURDATE=#PERIOD TO #LASTDATE @AVG=SGNL(CLOSE,#SMOOTH,E) IF #CURDATE<#PERIOD-1 @POSVOL=SGNL(MAX(CLOSE>@AVG,0)*VOL,#PERIOD-1,M) @NEGVOL=SGNL(MAX(CLOSE<@AVG,0)*VOL,#PERIOD-1,M) ELSE @POSVOL=(MAX(CLOSE>@AVG,0)*VOL+(#PERIOD-1)*@POSVOL)/#PERIOD @NEGVOL=(MAX(CLOSE<@AVG,0)*VOL+(#PERIOD-1)*@NEGVOL)/#PERIOD @SVSI=100-(100/(1+(@POSVOL/@NEGVOL))) ENDIF @PLOT=@SVSI NEXT