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"); } } } }