TASC 2012-05 | Sentiment Zone Oscillator (SZO) (Khalil)

Modified on 2012/04/03 11:31 by Eugene — Categorized as: TASC Traders Tips

Traders' Tip text

Although one of Wealth-Lab's strongest points has been the ability to express your ideas in C# language, no programming is required for certain tasks like prototyping a trading idea. The Strategy Builder allows to combine building blocks known as Rules into a trading system.

After updating the TASC Magazine Indicators library to its most-recent version using the built-in Extension Manager, you will find Sentiment Zone Oscillator (SZO) organized under the TASC Magazine Indicators group. This allows to quickly use it in Rule-based Strategies as an entry or exit condition without having to program a line of code yourself.

Figure 1 shows the Strategy Builder’s Conditions tab with a group of rules for General Indicators. To attach a rule for SZO:

  1. Simply drag and drop one of the general conditions on an entry or exit (specifically, “Indicator crosses above/below a Value), and then
  2. Click where indicated to select the SZO from the Indicators dialog.

Image

Figure 1. Building a SZO crossover/crossunder Strategy from Rules as indicated in “SZO trading tactics” in Wealth-Lab 6.3.


In our example, the resulting system was a blend between the counter-trend entry based on reacting to SZO extremes as suggested by Walid Khalil, and a trend-following stop that trails a percentage below (above – for shorts) the highest high (or lowest low for shorts) achieved since the position was opened. It works like shown on Figure 2:

Image

Figure 2. Sample short trade: the stock's 14-period SZO crosses below the +7 threshold.


By extending the backtest range to most-recent 10 years, we examined how efficient were SZO signals on the same Dow 30 portfolio on a longer history. With 5% equity allocated to a position, some signals had to be skipped. Our preference is to err on the side of caution, so the trades with the most percentage gain were excluded, suggesting a conservative outcome. After subtracting trading costs (commissions and 0.05% slippage per trade), the system took 244 trades (and skipped 115), coming slightly short of Buy&Hold's net profit (64% vs 74%) with less downside risk (max drawdown -38% vs. -50%).

Image

Figure 3. The simplified rule-based strategy's equity virtually mirrored the Buy&Hold, the short side was a loser and was unable to support the long side during its weak times.


Overall, the SZO's turning points seem to highlight extremes in market sentiment, and they do it without repeating too often. If you're willing to experiment with the SZO trading system as presented by its author, the strategy code is also included:



WealthScript Code (C#)


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

namespace WealthLab.Strategies { public class SZOStrategy : WealthScript { private StrategyParameter paramPeriod; private StrategyParameter paramLongPeriod; private StrategyParameter paramBuy1; private StrategyParameter paramBuy2; private StrategyParameter paramBuy3; public SZOStrategy() { paramPeriod = CreateParameter("SZO Period", 14, 2, 300, 1); paramLongPeriod = CreateParameter("Long Period", 30, 20, 300, 1); paramBuy1 = CreateParameter("Buy1 On/Off", 1, 0, 1, 1); paramBuy2 = CreateParameter("Buy2 On/Off", 1, 0, 1, 1); paramBuy3 = CreateParameter("Buy3 On/Off", 1, 0, 1, 1); } protected override void Execute() { int period = paramPeriod.ValueInt; int LongPeriod = paramLongPeriod.ValueInt; double Percent=95; LineStyle ls = LineStyle.Solid; bool buy1 = paramBuy1.ValueInt > 0; bool buy2 = paramBuy2.ValueInt > 0; bool buy3 = paramBuy1.ValueInt > 0; SZO szo = SZO.Series( Close,period ); SMA ma = SMA.Series( szo,LongPeriod ); Highest HLP = Highest.Series(szo, LongPeriod); Lowest LLP = Lowest.Series(szo, LongPeriod); DataSeries Range = HLP - LLP; DataSeries Prange = Range *(Percent/100d); DataSeries OB = LLP + Prange; OB.Description = "O/B"; DataSeries OS = HLP - Prange; OS.Description = "O/S"; EMA ema = EMA.Series( Close,60,EMACalculation.Modern );

ChartPane szoPane = CreatePane( 30,true,true ); PlotSeriesOscillator( szoPane, szo, 7, -7, Color.Red, Color.Green, Color.Black, ls, 2 ); PlotSeries( szoPane, OB, Color.Red, ls, 1 ); PlotSeries( szoPane, OS, Color.Green, ls, 1 ); DrawHorzLine( szoPane, 7, Color.Red, LineStyle.Dashed, 2 ); DrawHorzLine( szoPane, -7, Color.Green, LineStyle.Dashed, 2 ); HideVolume();

for(int bar = GetTradingLoopStartBar(LongPeriod); bar < Bars.Count; bar++) { bool buyRule1 = CrossOver( bar, szo, 0 ) && (Close[bar] > ema[bar]) && buy1; bool buyRule2 = (Close[bar] > ema[bar]) && (szo[bar] < OS[bar]) && (ma[bar] > ma[bar - 1]) && buy2; bool buyRule3 = ( ma[bar] > 0 ) && CrossOver( bar, szo, -7 ) && (ema[bar] > ema[bar - 1]) && buy3; bool sellRule = CrossUnder( bar, szo, 0 ) || (CrossUnder( bar, szo, 7 ) && (ma[bar] < ma[bar - 1])); if (IsLastPositionActive) { Position p = LastPosition; if( sellRule ) SellAtMarket( bar+1,p ); } else { if( buyRule1 || buyRule2 || buyRule3 ) BuyAtMarket( bar+1 ); } } } } }