Traders' Tip text
The
Universal Oscillator from this month's Traders' Tip is an evolution of Mr. Ehlers' SuperSmoother filter (see January 2014 issue). The new indicator follows the swings in price without introducing extra delay. It is comfortably controlled through just a single input – the band edge – which basically is frequency. The smaller it is set, the less lag there is but the smoother the indicator's outline will be. Built-in automatic gain control normalizes the output to vary between the range of -1 to +1.
As an illustration of its application, Mr. Ehlers suggests a straightforward short-term, counter-trend system:
Since it is really a universal oscillator, the indicator can power up a trend-trading system as easily:
Included trading system code implements both approaches. To switch between trend- and counter-trend modes, drag the parameter slider named “Swing/Trend” at the bottom left part of the screen and Wealth-Lab will instantly rebuild the backtest.
But wouldn't it be interesting to adapt to different market conditions, distinguishing a trending market from a rangebound? Motivated traders can take it a step further and automate the switching from trending to mean reversion mode and vice versa. To achieve that, they can employ a dedicated trendiness oscillator like ADX,
Dreiss Choppiness Index, or McEwan's Volatility Switch (see
February 2013 issue of Stocks & Commodities).
Figure 1. A Wealth-Lab 6 chart illustrating the application of the system's rules on a Daily chart of Cisco Systems (CSCO).
To execute the example trading system, Wealth-Lab users need to install (or update) the latest version of TASCIndicators library (v.2014.12 or higher) 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 TASCIndicators;
namespace WealthLab.Strategies
{
public class UniversalOscSARStrategy : WealthScript
{
StrategyParameter be;
StrategyParameter mode;
public UniversalOscSARStrategy()
{
be = CreateParameter("Band edge", 20, 5, 200, 5);
mode = CreateParameter("Swing/Trend", 0, 0, 1, 1);
}
protected override void Execute()
{
bool swingTrade = mode.ValueInt == 0 ? true : false;
int period = be.ValueInt;
UniversalOscillator uo = UniversalOscillator.Series(Close,period );
ChartPane uPane = CreatePane(30,false,true); HideVolume();
PlotSeries(uPane,uo,Color.IndianRed,LineStyle.Solid,2);
DrawHorzLine(uPane,0,Color.Blue,LineStyle.Dashed,1);
for(int bar = GetTradingLoopStartBar(period); bar < Bars.Count; bar++)
{
// Detect crossover/crossunder and store state in variable
bool uXo = CrossOver(bar, uo, 0);
bool uXu = CrossUnder(bar, uo, 0);
if( swingTrade ) // Countertrend trading
{
// The first trade
if (Positions.Count == 0){
if ( uXu )
BuyAtMarket( bar + 1 );
else if( uXo )
ShortAtMarket( bar + 1 );
}
// Subsequent trades
else
{
Position p = LastPosition;
if ( p.PositionType == PositionType.Long )
{
if ( uXo )
{
SellAtMarket( bar + 1, p );
ShortAtMarket( bar + 1 );
}
}
else if ( uXu )
{
CoverAtMarket( bar + 1, p );
BuyAtMarket( bar + 1 );
}
}
}
else // Trend trading
{
if (IsLastPositionActive)
{
if ( uXu )
SellAtMarket( bar + 1, LastPosition );
}
else
{
if ( uXo )
BuyAtMarket( bar + 1 );
}
}
}
}
}
}
Eugene
Wealth-Lab team
www.wealth-lab.com