Log in to see Cloud of Tags

Wealth-Lab Wiki

TASC 2017-01 | Mean-Reversion Swing Trading (Calhoun)

RSS

Traders' Tip text

This month, author Ken Calhoun shows clean and concise rules for entering in a trend continuation following a pullback after a breakout. This pattern (widely known as "1-2-3 pattern") could be programmed to apply to intraday or daily charts alike. Our rendition targets daily charts.

Since the rules didn't put much emphasis on exits, leaving this to the trader, we added a simple profit target. Below you can find the complete trading system's rules:

Entry:
  1. Wait for a 5-day close-to-close uptrend.
  2. If the closing prices retrace 50% of the uptrend's distance (±1 percentage point) over the next 10 bars, a valid pullback has formed.
  3. Look for the prices to rebound and buy on a stop 50 cents above the retracement price. If this condition hasn’t been met within 10 days, the setup is invalidated.
  4. A second entry is made if first position has been established and the high price breaks through the 15-day highest high price.

Exit:
  1. Exit on a $1 stop loss from the retracement price.
  2. Exit with a profit target at 2 times the retracement distance.

Motivated readers could make various improvements to the program's logic. For instance, to help this technique work equally well on stocks outside the $20-70 price range, make the stop loss and profit target adaptive by replacing the fixed dollar distance with a unit of ATR. Another suggestion is to avoid trades when a stock is not really trending as the 1-2-3 pattern seems to perform best in established trends.

Image

Figure 1 shows a potential trade in HeidelbergCement AG (ticker HEI.DE in Wealth-Data).

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

namespace WealthLab.Strategies { public class MeanReversionSwingTrading : WealthScript { private StrategyParameter paramUptrendDays; private StrategyParameter paramReversionLasts; private StrategyParameter paramReversionExpiresAfter; private StrategyParameter paramSecondEntry; public MeanReversionSwingTrading() { paramUptrendDays = CreateParameter("Days in uptrend", 5, 2, 10, 1); paramReversionLasts = CreateParameter("Reversion lasts", 4, 2, 12, 2); paramReversionExpiresAfter = CreateParameter("Expires after", 10, 5, 20, 5); paramSecondEntry = CreateParameter("Second entry?", 1, 0, 1, 1); } protected override void Execute() { bool runup = false, reversion = false, pullback = false, secondEntry = paramSecondEntry.ValueInt == 1; int runupBar = -1, pBar = -1, reversionBar = -1, uptrendDays = paramUptrendDays.ValueInt; double runupStart = 0, runupHigh = 0, runupRange = 0, pivotPrice = 0, reversionThreshold = 1.0; Highest hi = Highest.Series(High,15); if( secondEntry ) PlotSeries(PricePane, hi, Color.Blue, LineStyle.Dashed, 1); for(int bar = GetTradingLoopStartBar(15); bar < Bars.Count; bar++) { if( ActivePositions.Count > 0 ) { if(!SellAtStop(bar+1, Position.AllPositions, pivotPrice - 1.0, "$1 stop")) SellAtLimit(bar + 1, Position.AllPositions, pivotPrice + 2.0, "Profit Target"); } if( ActivePositions.Count == 0 ) // First entry { if( !runup ) { if(CumUp.Series(Close,1)[bar] >= uptrendDays) { runup = true; runupBar = bar; runupStart = Low[bar-5]; runupHigh = High[runupBar]; runupRange = runupHigh - runupStart; pivotPrice = runupStart + (runupRange / 2d); DrawLine(PricePane,runupBar,runupHigh,bar-5,runupStart,Color.Blue,LineStyle.Solid,2); } } if( !pullback ) { if( runup ) { if( bar >= runupBar + paramReversionExpiresAfter.ValueInt ) { runup = false; //AnnotateBar("Pullback timeout exceeded",bar,false,Color.Red); } else { double runupInPercent = runupRange / (double)runupStart * 100d; double closeToExact = (reversionThreshold / 100d); if( (Low[bar] <= (pivotPrice * 1.0+closeToExact)) && (Low[bar] >= (pivotPrice * 1.0-closeToExact)) ) { pullback = true; pBar = bar; DrawLine(PricePane,runupBar,runupHigh,pBar,pivotPrice,Color.Red,LineStyle.Solid,2); } } } } // Buy at stop if price moves $0.50 the pivot price or above if( pullback ){ double entryStop = pivotPrice + 0.50; if( BuyAtStop( bar + 1, entryStop, "1st" ) != null ) { DrawLine(PricePane,bar,entryStop,pBar,entryStop,Color.DarkGreen,LineStyle.Dotted,2); runup = false; pullback = false; LastPosition.Tag = pivotPrice; } else // Invalidate entry if too many bars have passed since pullback if( bar >= pBar + paramReversionExpiresAfter.ValueInt ) { pullback = false; AnnotateBar("Rebound timeout exceeded",bar,true,Color.Orange); } } } else //Second entry if( ActivePositions.Count == 1 && secondEntry ) BuyAtStop(bar+1, hi[bar], "2nd"); } } } }

Eugene
Wealth-Lab team
www.wealth-lab.com

Important Disclaimer: The information provided by Wealth-Lab is strictly for informational purposes and is not to be construed as advice or solicitation to buy or sell any security.  The owner of Wealth-Lab.com assumes no liability resulting from the use of the material contained herein for investment purposes. By using this web site, you agree to the terms of this disclaimer and our Terms of Use.


ScrewTurn Wiki. Some of the icons created by FamFamFam.