using System; using System.Collections.Generic; using System.Text; using System.Drawing; using WealthLab; using WealthLab.Indicators; using Community.Components;namespace WealthLab.Strategies { internal struct PipInterval { public int X1; public int X2; } public class zzTOPAutoStudy : WealthScript { StrategyParameter _pct; StrategyParameter _thickness; List<int> _pipList; // list of PIP bar numbers public zzTOPAutoStudy() { _pct = CreateParameter("PIP Percent", 20, 2, 50, 1); _thickness = CreateParameter("Line Width", 2, 1, 3, 1); } int getPipBar(DataSeries ds, PipInterval pi, double minMove, bool useLog) { int pip = 0; double maxDiff = 0; double delta, y; for(int bar = pi.X1; bar <= pi.X2; bar++) { if (useLog) { y = LineExtendYLog( pi.X1, ds[pi.X1], pi.X2, ds[pi.X2], bar ); delta = Math.Abs(Math.Log(ds[bar] / y)); } else { y = LineExtendY( pi.X1, ds[pi.X1], pi.X2, ds[pi.X2], bar ); delta = Math.Abs(ds[bar] - y); } if( delta > maxDiff ) { maxDiff = delta; pip = bar; } } if (maxDiff < minMove) pip = -1; // invalid; no PIP in specified PipInterval if (pip > 0) _pipList.Add(pip); return pip; } /* Find the new PIP for each PipInterval in the List and return the new PipIntervals */ internal List<PipInterval> zzTopAuto(List<PipInterval> piList, DataSeries ds, double minmove, bool useLog) { List<PipInterval> nextList = new List<PipInterval>(); foreach (PipInterval pi in piList) { int bar = getPipBar(ds, pi, minmove, useLog); if (bar == -1) continue; else { PipInterval newinvl = new PipInterval(); newinvl.X1 = pi.X1; newinvl.X2 = bar; nextList.Add(newinvl); PipInterval newinvl2 = new PipInterval(); newinvl2.X1 = bar; newinvl2.X2 = pi.X2; nextList.Add(newinvl2); } } if (nextList.Count != 0) zzTopAuto(nextList, ds, minmove, useLog); return nextList; } void ZZTOP(DataSeries ds, ChartPane cp, double minPercent) { // Minimum vertical move for the arithmetic and log cases double minV = 0; if (cp.LogScale) minV = Math.Log(1 + minPercent/100d); else { int bc = Bars.Count; minV = minPercent / 100d * (Highest.Value(bc-1, ds, bc) - Lowest.Value(bc-1, ds, bc)); } // Initialize _pipList with the first and last bar numbers int nbars = Bars.Count - 1; _pipList = new List<int>(); _pipList.Add(0); _pipList.Add(nbars); // Initialize the first list to pass to zzTopAuto PipInterval interval = new PipInterval(); interval.X1 = 0; interval.X2 = nbars; List<PipInterval> aList = new List<PipInterval>(); aList.Add(interval); // Let the recursion begin! zzTopAuto(aList, ds, minV, cp.LogScale); // Sort the result to plot lines between the PIPs _pipList.Sort(); int lastpip = 0; foreach (int pip in _pipList) { if (pip == 0) continue; DrawLine(cp, lastpip, ds[lastpip], pip, ds[pip], Color.Blue, LineStyle.Solid, _thickness.ValueInt); lastpip = pip; } int segments = _pipList.Count - 1; DrawLabel(cp, "Log Scale: " + cp.LogScale.ToString()); DrawLabel(cp, "Segment Count: " + segments.ToString()); DrawLabel(cp, "PIP: " + minPercent + "%"); //DrawLabel(cp, "Press Go! after switch between Log and Arithmetic scales!", Color.Red); } protected override void Execute() { ZZTOP(Close, PricePane, _pct.Value); DataSeries rsi = RSI.Series(Close, 14); ChartPane rsiPane = CreatePane(40, true, true); PlotSeries(rsiPane, rsi, Color.Black, LineStyle.Solid, 1); ZZTOP(rsi, rsiPane, _pct.Value); } } }