Traders' Tip text
The slow relative strength index (SRSI) indicator created by Vitali Apirine is a momentum price oscillator similar to RSI in its application and interpretation. Oscillating between 0 and 100, it becomes overbought after reaching 80 and oversold after dropping below 20. Signals can also be generated by looking for centerline crossovers and divergences. The latter trait is what our example trading system will zero in on.
There are several approaches that help identify divergences between price and oscillator. The one we're going to use is straightforward, detecting a divergence when the SRSI indicator fails to confirm a price extreme, that is, the highest high of 20 days for short trades or the 20-day lowest low for long trades. If we were to rely on finding retracements from a recent peak or trough, divergence detection would introduce a little delay compared to this technique.
As author suggests, bullish/bearish divergences generated by SRSI are not as effective during strong trends. To avoid fading an established trend, the system is used in conjunction with ADX indicator as trend confirmation tool. If the ADX is below its threshold for a trending market, the system would enter the trade.
Figure 1. Bearish divergence between the SRSI and price which formed in January 2014 triggered a short trade in KO (Coca Cola).After updating the TASCIndicators library to v2015.06 or later, the SRSI indicator can be found under the TASC Magazine Indicators group. You can plot it on a chart or use it as an entry or exit condition in a Rule-based Strategy without having to program a line of code yourself.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using TASCIndicators;
namespace WealthLab.Strategies
{
/*
SRSI divergence:
Price sets a lowest low but the indicator fails to confirm the new low and turns up
*/
public class SRSI_Divergence : WealthScript
{
private StrategyParameter paramHighest;
private StrategyParameter paramPeriod;
private StrategyParameter paramPeriodWMA;
private StrategyParameter paramThresholdForTrend;
private StrategyParameter paramExitDays;
public SRSI_Divergence()
{
paramPeriod = CreateParameter("SRSI period", 6, 1, 100, 1);
paramPeriodWMA = CreateParameter("WilderMA period", 14, 1, 100, 1);
paramThresholdForTrend = CreateParameter("ADX Threshold", 30, 10, 50, 10);
paramHighest = CreateParameter("Highest high of", 20, 5, 50, 1);
paramExitDays = CreateParameter("Exit after", 20, 1, 50, 1);
}
protected override void Execute()
{
bool peak = false; int peakBar = -1;
int high = paramHighest.ValueInt;
bool trough = false; int troughBar = -1;
int low = paramHighest.ValueInt;
int period = paramPeriod.ValueInt;
int periodWMA = paramPeriodWMA.ValueInt;
int days = paramExitDays.ValueInt;
int thresholdForTrend = paramThresholdForTrend.ValueInt;
ADX adx = ADX.Series(Bars,periodWMA);
SRSI srsi = SRSI.Series( Close, period, periodWMA );
Lowest indicatorLowest = Lowest.Series( srsi, low );
Lowest hLow = Lowest.Series( Low, low );
HideVolume(); LineStyle solid = LineStyle.Solid;
ChartPane srsiPane = CreatePane( 50, false, true );
PlotSeries( srsiPane, srsi, Color.Green, solid, 2 );
ChartPane adxPane = CreatePane( 25, true, true );
PlotSeries( adxPane, adx, Color.Red, solid, 2 );
DrawHorzLine(adxPane,thresholdForTrend,Color.Blue,LineStyle.Dashed,1);
for(int bar = GetTradingLoopStartBar(period); bar < Bars.Count; bar++)
{
if (!IsLastPositionActive)
{
/* 1st peak: both price and indicator */
if( peak == false )
{
if( ( Highbar-1 == Highest.Series( High, high )bar-1 )
& ( srsibar-1 == Highest.Series( srsi, high )bar-1 )
& TurnDown( bar, High ) & TurnDown( bar, srsi ) )
{
peak = true; peakBar = bar-1;
}
}
if( peak == true )
{
if( ( Highbar != Highest.Series( High, high )bar )
& ( srsibar == Highest.Series( srsi, high )bar ) )
peak = false;
}
/* 2nd peak: price high not confirmed by the indicator */
if( peak == true )
{
if( ( Highbar-1 == Highest.Series( High, high )bar-1 )
& ( Highbar-1 >= HighpeakBar )
& ( srsibar-1 != Highest.Series( srsi, high )bar-1 )
& ( srsibar-1 < srsipeakBar ) &
TurnDown( bar, High ) & TurnDown( bar, srsi ) )
{
peak = false;
/* Don't fade a strong trend */
if( adxbar < thresholdForTrend )
ShortAtMarket( bar+1 );
/* Highlight divergence */
for (int b = peakBar; b <= bar; b++)
SetPaneBackgroundColor( srsiPane, b, Color.FromArgb( 30, Color.LightCoral ) );
DrawLine( PricePane, peakBar, HighpeakBar, bar-1, Highbar-1, Color.Red, solid, 2 );
DrawLine( srsiPane, peakBar, srsipeakBar, bar-1, srsibar-1, Color.Blue, solid, 2 );
}
}
/* 1st trough: both price and indicator */
if( trough == false )
{
if( ( Lowbar-1 == Lowest.Series( Low, low )bar-1 )
& ( srsibar-1 == Lowest.Series( srsi, low )bar-1 )
& TurnUp( bar, Low ) & TurnUp( bar, srsi ) )
{
trough = true; troughBar = bar-1;
}
}
if( trough == true )
{
if( ( Lowbar != Lowest.Series( Low, low )bar )
& ( srsibar == Lowest.Series( srsi, low )bar ) )
trough = false;
}
/* 2nd trough: price low not confirmed by the indicator */
if( trough == true )
{
if( ( Lowbar-1 == Lowest.Series( Low, low )bar-1 )
& ( Lowbar-1 <= LowtroughBar )
& ( srsibar-1 != Lowest.Series( srsi, low )bar-1 )
& ( srsibar-1 > srsitroughBar ) &
TurnUp( bar, Low ) & TurnUp( bar, srsi ) )
{
trough = false;
/* Don't fade a strong trend */
if( adxbar < thresholdForTrend )
BuyAtMarket( bar+1 );
/* Highlight divergence */
for (int b = troughBar; b <= bar; b++)
SetPaneBackgroundColor( srsiPane, b,
Color.FromArgb( 30, Color.LightGreen ) );
DrawLine( PricePane, troughBar, LowtroughBar,
bar-1, Lowbar-1, Color.Blue, solid, 2 );
DrawLine( srsiPane, troughBar, srsitroughBar,
bar-1, srsibar-1, Color.Red, solid, 2 );
}
}
} else
{
/* Exit after N days */
Position p = LastPosition;
if ( bar+1 - p.EntryBar >= days )
ExitAtMarket( bar+1, p, "Timed" );
}
}
}
}
}
Eugene
Wealth-Lab team
www.wealth-lab.com