using System; using System.Collections.Generic; using System.Text; using System.Drawing; using WealthLab; using WealthLab.Indicators; using WealthLab.Rules.Candlesticks; using TASCIndicators;namespace WealthLab.Strategies { public class IRSTS_StepPattern : WealthScript { private StrategyParameter paramPercent; private StrategyParameter paramLookbackForStepPattern; public IRSTS_StepPattern() { paramPercent = CreateParameter("Reversal %", 10.0, 1.0, 50.0, 1.0); paramLookbackForStepPattern = CreateParameter("Lookback", 3, 1, 20, 1); } bool isInsideBody( int bar, double price ) { return price <= Math.Max(Open[bar],Close[bar]) && price >= Math.Min(Open[bar],Close[bar]); } bool Upstep( int bar, int lookback ) { bool result = false; bool way1 = (Open[bar] > Close[bar] & Open[bar+1] < Close[bar+1]) && isInsideBody(bar, Open[bar+1]) && Close[bar+1] > Open[bar]; bool way2 = (Open[bar] < Close[bar] & Open[bar+1] < Close[bar+1]) && isInsideBody(bar, Open[bar+1]) && Close[bar+1] > Close[bar]; bool way3 = (Open[bar-1] > Close[bar-1]) && (Open[bar] < Close[bar]) && isInsideBody(bar, Open[bar+1]) && (Close[bar] > Open[bar-1]); bool way4 = (Open[bar-1] < Close[bar-1]) && (Open[bar] < Close[bar]) && isInsideBody(bar, Open[bar+1]) && (Close[bar] > Close[bar-1]); result = bar == LowestBar.Series( Low,lookback )[bar] && ( way1 | way2 | way3 | way4 ); return result; } bool Downstep( int bar, int lookback ) { bool result = false; bool way1 = (Open[bar] < Close[bar] & Open[bar+1] > Close[bar+1]) && isInsideBody(bar, Open[bar+1]) && Close[bar+1] < Open[bar]; bool way2 = (Open[bar] > Close[bar] & Open[bar+1] > Close[bar+1]) && isInsideBody(bar, Open[bar+1]) && Close[bar+1] < Close[bar]; bool way3 = (Open[bar-1] < Close[bar-1]) && (Open[bar] > Close[bar]) && isInsideBody(bar, Open[bar+1]) && (Close[bar] < Open[bar-1]); bool way4 = (Open[bar-1] > Close[bar-1]) && (Open[bar] > Close[bar]) && isInsideBody(bar, Open[bar+1]) && (Close[bar] < Close[bar-1]); result = bar == HighestBar.Series( High,lookback )[bar] && ( way1 | way2 | way3 | way4 ); return result; } protected override void Execute() { int lookback = paramLookbackForStepPattern.ValueInt; double percent = paramPercent.Value; const string t = "\t"; string s = string.Empty; ZZBuilder zz = new ZZBuilder( Bars, percent ); List<ZigZag> lst = zz.ZigZags; bool[] BearishEngulfing; CandlePattern.BearishEngulfingLines(this, s, false, out BearishEngulfing); bool[] BullishEngulfing; CandlePattern.BullishEngulfingLines(this, s, false, out BullishEngulfing); bool[] BearishHarami; CandlePattern.BearishHarami(this, s, false, out BearishHarami); bool[] BullishHarami; CandlePattern.BullishHarami(this, s, false, out BullishHarami); HideVolume(); SetBarColors(Color.Silver,Color.Silver); if( lst != null ) { DrawLabel(PricePane, string.Format( "Total {0}-percent zigzags: {1}", percent, lst.Count) ); foreach( ZigZag z in lst ) { if ( z.inPrice == 0.0 ) continue; DrawLine( PricePane, z.zigBar, z.inPrice, z.zagBar, z.outPrice, z.isMoveUp ? Color.Blue : Color.Red, LineStyle.Solid, 2 ); } } for(int bar = 2 + lookback; bar < Bars.Count; bar++) { if( lst != null ) { if( lst.Count > 0 ) { int idx = 0; foreach( ZigZag z in lst ) { if( z.barDetected == bar ) { //SetBackgroundColor( bar, !z.isMoveUp ? Color.FromArgb(30,Color.Green) : Color.FromArgb(30,Color.Red) ); if( Downstep( z.zagBar, lookback ) ) AnnotateBar( "D", z.zagBar, true, Color.Red ); if (BearishHarami[z.zagBar]) AnnotateBar( "H", z.zagBar, true, Color.Red ); if (BearishEngulfing[z.zagBar]) AnnotateBar( "E", z.zagBar, true, Color.Red ); if( Upstep( z.zagBar, lookback ) ) AnnotateBar( "U", z.zagBar, false, Color.Blue ); if (BullishHarami[z.zagBar]) AnnotateBar( "H", z.zagBar, false, Color.Blue ); if (BullishEngulfing[z.zagBar]) AnnotateBar( "E", z.zagBar, false, Color.Blue ); } } } } } } } public class XEvent { public int Bar {get; set; } public int Type {get; set; } public double Price {get; set; } public XEvent( int bar, int type ) { Bar = bar; Type = type; } public XEvent( int bar, int type, double price ) { Bar = bar; Type = type; Price = price; } } public enum Wave {W1, W2, W3} public class ZigZag { public int barDetected { get; set; } public bool isMoveUp { get; set; } public int zigBar { get; set; } public int zagBar { get; set; } public double inPrice { get; set; } public double outPrice { get; set; } public double magnitude { get; set; } public Wave wave { get; set; } public int leg3Count { get; set; } public ZigZag(int barDetected, bool isMoveUp, int zigBar, int zagBar, double inPrice, double outPrice, double magnitude) { this.barDetected = barDetected; this.isMoveUp = isMoveUp; this.zigBar = zigBar; this.zagBar = zagBar; this.inPrice = inPrice; this.outPrice = outPrice; this.magnitude = magnitude; this.leg3Count = 0; } } public class ZZBuilder { private bool Initialized = false; public Bars bars { get; private set; } public double percent { get; private set; } public List<ZigZag> ZigZags { get; private set; } public ZZBuilder( Bars b, double pct ) { this.bars = b; this.percent = pct; BuildZZHiLo(); //BuildZZ(); } private void BuildZZHiLo() { try { DataSeries zz = SVEHLZZperc.Series(bars,percent,14,3,SVEHLZZperc_Type.Percent); List<XEvent> lstX = new List<XEvent>(); lstX.Add( new XEvent( 0, 0 ) ); for(int bar = 1; bar < bars.Count; bar++) { if( bars.High[bar - 1] < zz[bar - 1] && bars.High[bar] > zz[bar] ) { lstX.Add( new XEvent(bar, 1) ); } if( bars.Low[bar - 1] > zz[bar - 1] && bars.Low[bar] < zz[bar] ) { lstX.Add( new XEvent(bar, -1) ); } } for(int bar = 0; bar < bars.Count; bar++) { for( int i = 0; i < lstX.Count; i++ ) { if( i == 0 ) continue; XEvent e = lstX[i]; if( e.Bar == bar ) { int prevEventBar = lstX[i - 1].Bar; int step = bar-prevEventBar; if( e.Type == 1 ) { double Trough = Lowest.Value( bar, bars.Low, step ); e.Price = Trough; e.Bar = (int)LowestBar.Value( bar, bars.Low, step ); } else if( e.Type == -1 ) { double Peak = Highest.Value( bar, bars.High, step ); e.Price = Peak; e.Bar = (int)HighestBar.Value( bar, bars.High, step ); } break; } } } List<ZigZag> lst = new List<ZigZag>(); double inPrice = 0, outPrice = 0, magnitude = 0; int barDetected = 0, zigBar = 0, zagBar = 0; bool detected = false; for(int bar = 1; bar < bars.Count; bar++) { detected = false; XEvent e = lstX[0]; XEvent prev = lstX[0]; for( int i = 0; i < lstX.Count; i++ ) { if( i == 0 ) continue; e = lstX[i]; prev = lstX[i - 1]; if( e.Bar == bar ) { detected = true; break; } } if( detected ) { bool isMoveUp = (e.Type == 1); if( isMoveUp ) { zigBar = prev.Bar; zagBar = e.Bar; inPrice = prev.Price; outPrice = e.Price; } else { zigBar = prev.Bar; zagBar = e.Bar; inPrice = prev.Price; outPrice = e.Price; } magnitude = Math.Abs( inPrice - outPrice ); lst.Add( new ZigZag( bar, isMoveUp, zigBar, zagBar, inPrice, outPrice, magnitude ) ); } } ZigZags = lst; Initialized = true; } catch { } } [Obsolete] private void BuildZZ() { try { PeakTroughMode mode = WealthLab.Indicators.PeakTroughMode.Percent; PeakBar pb = PeakBar.Series(bars.Close,percent,mode); TroughBar tb = TroughBar.Series(bars.Close,percent,mode); Trough tr = Trough.Series(bars.Close,percent,mode); Peak pk = Peak.Series(bars.Close,percent,mode); List<ZigZag> lst = new List<ZigZag>(); double t1 = 0, p1 = 0, inPrice, outPrice = 0, magnitude = 0; int tb1 = 0, pb1, barDetected = 0, zigBar = 0, zagBar = 0; bool detected = false; for(int bar = 1; bar < bars.Count; bar++) { detected = false; t1 = tr[bar]; tb1 = (int)tb[bar]; if (tb1 == -1) continue; p1 = pk[bar]; pb1 = (int)pb[bar]; if (pb1 == -1) continue; if( tb[bar] > tb[bar-1] && pb[bar] > -1){ detected = true; } if( pb[bar] > pb[bar-1] && tb[bar] > -1 ){ detected = true; } if( detected ) { bool isMoveUp = (tb1 < pb1); magnitude = Math.Abs( bars.High[pb1] - bars.Low[tb1] ); if( isMoveUp ) { zigBar = tb1; zagBar = pb1; inPrice = t1; outPrice = p1; } else { zigBar = pb1; zagBar = tb1; inPrice = p1; outPrice = t1; } lst.Add( new ZigZag( bar, isMoveUp, zigBar, zagBar, inPrice, outPrice, magnitude ) ); } } ZigZags = lst; Initialized = true; } catch { } } } }