private static void DrawZigZagLine(List <ZigZagResult> results, List <Quote> historyList,
                                           ZigZagPoint lastPoint, ZigZagPoint nextPoint)
        {
            // initialize
            List <ZigZagResult> newResults = new List <ZigZagResult>();

            List <Quote> period = historyList
                                  .Where(x => x.Index > lastPoint.Index && x.Index <= nextPoint.Index)
                                  .ToList();

            decimal increment = (nextPoint.Value - lastPoint.Value) / (nextPoint.Index - lastPoint.Index);

            // add new line segment
            foreach (Quote h in period)
            {
                ZigZagResult result = new ZigZagResult
                {
                    Index  = (int)h.Index,
                    Date   = h.Date,
                    ZigZag = (lastPoint.Index != 1 || h.Index == nextPoint.Index) ?
                             lastPoint.Value + increment * (h.Index - lastPoint.Index) : null,
                    PointType = ((int)h.Index == nextPoint.Index) ? nextPoint.PointType : null
                };

                results.Add(result);
            }

            // reset lastpoint
            lastPoint.Index     = nextPoint.Index;
            lastPoint.Value     = nextPoint.Value;
            lastPoint.PointType = nextPoint.PointType;
        }
        private static void DrawZigZagLine <TQuote>(List <ZigZagResult> results, List <TQuote> historyList,
                                                    ZigZagPoint lastPoint, ZigZagPoint nextPoint) where TQuote : IQuote
        {
            decimal increment = (nextPoint.Value - lastPoint.Value) / (nextPoint.Index - lastPoint.Index);

            // add new line segment
            for (int i = lastPoint.Index; i < nextPoint.Index; i++)
            {
                TQuote h     = historyList[i];
                int    index = i + 1;

                ZigZagResult result = new ZigZagResult
                {
                    Date   = h.Date,
                    ZigZag = (lastPoint.Index != 1 || index == nextPoint.Index) ?
                             lastPoint.Value + increment * (index - lastPoint.Index) : null,
                    PointType = (index == nextPoint.Index) ? nextPoint.PointType : null
                };

                results.Add(result);
            }

            // reset lastpoint
            lastPoint.Index     = nextPoint.Index;
            lastPoint.Value     = nextPoint.Value;
            lastPoint.PointType = nextPoint.PointType;
        }
Exemple #3
0
        private static void DrawRetraceLine(List <ZigZagResult> results, string lastDirection,
                                            ZigZagPoint lastLowPoint, ZigZagPoint lastHighPoint, ZigZagPoint nextPoint)
        {
            bool        isHighLine = (lastDirection == "L");
            ZigZagPoint priorPoint = new();

            // handle type and reset last point
            if (isHighLine)
            {
                priorPoint.Index = lastHighPoint.Index;
                priorPoint.Value = lastHighPoint.Value;

                lastHighPoint.Index = nextPoint.Index;
                lastHighPoint.Value = nextPoint.Value;
            }
            else
            {
                priorPoint.Index = lastLowPoint.Index;
                priorPoint.Value = lastLowPoint.Value;

                lastLowPoint.Index = nextPoint.Index;
                lastLowPoint.Value = nextPoint.Value;
            }

            // nothing to do if first line
            if (priorPoint.Index == 1)
            {
                return;
            }

            // handle error case
            if (nextPoint.Index == priorPoint.Index)
            {
                return;
            }

            // narrow to period
            decimal increment = (nextPoint.Value - priorPoint.Value) / (nextPoint.Index - priorPoint.Index);

            // add new line segment
            //foreach (ZigZagResult r in period)
            for (int i = priorPoint.Index - 1; i < nextPoint.Index; i++)
            {
                ZigZagResult r     = results[i];
                int          index = i + 1;

                if (isHighLine)
                {
                    r.RetraceHigh = priorPoint.Value + increment * (index - priorPoint.Index);
                }
                else
                {
                    r.RetraceLow = priorPoint.Value + increment * (index - priorPoint.Index);
                }
            }
        }
        private static void DrawRetraceLine(List <ZigZagResult> results, string lastDirection,
                                            ZigZagPoint lastLowPoint, ZigZagPoint lastHighPoint, ZigZagPoint nextPoint)
        {
            bool        isHighLine = (lastDirection == "L");
            ZigZagPoint priorPoint = new ZigZagPoint();

            // handle type and reset last point
            if (isHighLine)
            {
                priorPoint.Index = lastHighPoint.Index;
                priorPoint.Value = lastHighPoint.Value;

                lastHighPoint.Index = nextPoint.Index;
                lastHighPoint.Value = nextPoint.Value;
            }
            else
            {
                priorPoint.Index = lastLowPoint.Index;
                priorPoint.Value = lastLowPoint.Value;

                lastLowPoint.Index = nextPoint.Index;
                lastLowPoint.Value = nextPoint.Value;
            }

            // nothing to do if first line
            if (priorPoint.Index == 1)
            {
                return;
            }

            // narrow to period
            List <ZigZagResult> period = results
                                         .Where(x => x.Index >= priorPoint.Index && x.Index <= nextPoint.Index)
                                         .ToList();

            decimal increment = (nextPoint.Value - priorPoint.Value) / (nextPoint.Index - priorPoint.Index);

            // add new line segment
            foreach (ZigZagResult r in period)
            {
                if (isHighLine)
                {
                    r.RetraceHigh = priorPoint.Value + increment * (r.Index - priorPoint.Index);
                }
                else
                {
                    r.RetraceLow = priorPoint.Value + increment * (r.Index - priorPoint.Index);
                }
            }
        }
        // ZIG ZAG
        public static IEnumerable <ZigZagResult> GetZigZag <TQuote>(
            IEnumerable <TQuote> history,
            ZigZagType type       = ZigZagType.Close,
            decimal percentChange = 5)
            where TQuote : IQuote
        {
            // clean quotes
            List <TQuote> historyList = history.Sort();

            // check parameters
            ValidateZigZag(history, percentChange);

            // initialize
            List <ZigZagResult> results         = new List <ZigZagResult>(historyList.Count);
            decimal             changeThreshold = percentChange / 100m;
            TQuote     firstQuote = historyList[0];
            ZigZagEval eval       = GetZigZagEval(type, 1, firstQuote);

            ZigZagPoint lastPoint = new ZigZagPoint
            {
                Index     = eval.Index,
                Value     = firstQuote.Close,
                PointType = "U"
            };

            ZigZagPoint lastHighPoint = new ZigZagPoint
            {
                Index     = eval.Index,
                Value     = eval.High,
                PointType = "H"
            };

            ZigZagPoint lastLowPoint = new ZigZagPoint
            {
                Index     = eval.Index,
                Value     = eval.Low,
                PointType = "L"
            };

            int finalPointIndex = historyList.Count;

            // roll through history until to find initial trend
            for (int i = 0; i < historyList.Count; i++)
            {
                TQuote h     = historyList[i];
                int    index = i + 1;

                eval = GetZigZagEval(type, index, h);
                decimal changeUp = (eval.High - lastLowPoint.Value) / lastLowPoint.Value;
                decimal changeDn = (lastHighPoint.Value - eval.Low) / lastHighPoint.Value;

                if (changeUp >= changeThreshold && changeUp > changeDn)
                {
                    lastPoint.Index     = lastLowPoint.Index;
                    lastPoint.Value     = lastLowPoint.Value;
                    lastPoint.PointType = lastLowPoint.PointType;
                    break;
                }

                if (changeDn >= changeThreshold && changeDn > changeUp)
                {
                    lastPoint.Index     = lastHighPoint.Index;
                    lastPoint.Value     = lastHighPoint.Value;
                    lastPoint.PointType = lastHighPoint.PointType;
                    break;
                }
            }

            // add first point to results
            ZigZagResult firstResult = new ZigZagResult
            {
                Date = firstQuote.Date
            };

            results.Add(firstResult);

            // find and draw lines
            while (lastPoint.Index < finalPointIndex)
            {
                ZigZagPoint nextPoint     = EvaluateNextPoint(historyList, type, changeThreshold, lastPoint);
                string      lastDirection = lastPoint.PointType;

                // draw line (and reset last point)
                DrawZigZagLine(results, historyList, lastPoint, nextPoint);

                // draw retrace line (and reset last high/low point)
                DrawRetraceLine(results, lastDirection, lastLowPoint, lastHighPoint, nextPoint);
            }

            return(results);
        }
        private static ZigZagPoint EvaluateNextPoint <TQuote>(List <TQuote> historyList,
                                                              ZigZagType type, decimal changeThreshold, ZigZagPoint lastPoint) where TQuote : IQuote
        {
            // initialize
            bool    trendUp = (lastPoint.PointType == "L");
            decimal?change  = 0;

            ZigZagPoint extremePoint = new ZigZagPoint
            {
                Index     = lastPoint.Index,
                Value     = lastPoint.Value,
                PointType = trendUp ? "H" : "L"
            };

            // find extreme point before reversal point
            for (int i = lastPoint.Index; i < historyList.Count; i++)
            {
                TQuote h     = historyList[i];
                int    index = i + 1;

                ZigZagEval eval = GetZigZagEval(type, index, h);

                // reset extreme point
                switch (trendUp)
                {
                case true:

                    if (eval.High >= extremePoint.Value)
                    {
                        extremePoint.Index = eval.Index;
                        extremePoint.Value = eval.High;
                    }
                    else
                    {
                        change = (extremePoint.Value == 0) ? null
                                : (extremePoint.Value - eval.Low) / extremePoint.Value;
                    }

                    break;

                case false:

                    if (eval.Low <= extremePoint.Value)
                    {
                        extremePoint.Index = eval.Index;
                        extremePoint.Value = eval.Low;
                    }
                    else
                    {
                        change = (extremePoint.Value == 0) ? null
                                : (eval.High - extremePoint.Value) / extremePoint.Value;
                    }

                    break;
                }

                // return extreme point when deviation threshold met
                if (change >= changeThreshold)
                {
                    return(extremePoint);
                }
            }

            // handle last unconfirmed point
            int finalPointIndex = historyList.Count;

            if (extremePoint.Index == finalPointIndex && change < changeThreshold)
            {
                extremePoint.PointType = null;
            }

            return(extremePoint);
        }
Exemple #7
0
        // ZIG ZAG
        /// <include file='./info.xml' path='indicator/*' />
        ///
        public static IEnumerable <ZigZagResult> GetZigZag <TQuote>(
            IEnumerable <TQuote> history,
            ZigZagType type       = ZigZagType.Close,
            decimal percentChange = 5)
            where TQuote : IQuote
        {
            // sort history
            List <TQuote> historyList = history.Sort();

            // check parameter arguments
            ValidateZigZag(history, percentChange);

            // initialize
            List <ZigZagResult> results         = new(historyList.Count);
            decimal             changeThreshold = percentChange / 100m;
            TQuote     firstQuote = historyList[0];
            ZigZagEval eval       = GetZigZagEval(type, 1, firstQuote);

            ZigZagPoint lastPoint = new()
            {
                Index     = eval.Index,
                Value     = firstQuote.Close,
                PointType = "U"
            };

            ZigZagPoint lastHighPoint = new()
            {
                Index     = eval.Index,
                Value     = eval.High,
                PointType = "H"
            };

            ZigZagPoint lastLowPoint = new()
            {
                Index     = eval.Index,
                Value     = eval.Low,
                PointType = "L"
            };

            int finalPointIndex = historyList.Count;

            // roll through history, to find initial trend
            for (int i = 0; i < historyList.Count; i++)
            {
                TQuote h     = historyList[i];
                int    index = i + 1;

                eval = GetZigZagEval(type, index, h);

                decimal?changeUp = (lastLowPoint.Value == 0) ? null
                    : (eval.High - lastLowPoint.Value) / lastLowPoint.Value;

                decimal?changeDn = (lastHighPoint.Value == 0) ? null
                    : (lastHighPoint.Value - eval.Low) / lastHighPoint.Value;

                if (changeUp >= changeThreshold && changeUp > changeDn)
                {
                    lastPoint.Index     = lastLowPoint.Index;
                    lastPoint.Value     = lastLowPoint.Value;
                    lastPoint.PointType = lastLowPoint.PointType;
                    break;
                }

                if (changeDn >= changeThreshold && changeDn > changeUp)
                {
                    lastPoint.Index     = lastHighPoint.Index;
                    lastPoint.Value     = lastHighPoint.Value;
                    lastPoint.PointType = lastHighPoint.PointType;
                    break;
                }
            }

            // add first point to results
            ZigZagResult firstResult = new()
            {
                Date = firstQuote.Date
            };

            results.Add(firstResult);

            // find and draw lines
            while (lastPoint.Index < finalPointIndex)
            {
                ZigZagPoint nextPoint     = EvaluateNextPoint(historyList, type, changeThreshold, lastPoint);
                string      lastDirection = lastPoint.PointType;

                // draw line (and reset last point)
                DrawZigZagLine(results, historyList, lastPoint, nextPoint);

                // draw retrace line (and reset last high/low point)
                DrawRetraceLine(results, lastDirection, lastLowPoint, lastHighPoint, nextPoint);
            }

            return(results);
        }

        private static ZigZagPoint EvaluateNextPoint <TQuote>(
            List <TQuote> historyList,
            ZigZagType type, decimal changeThreshold, ZigZagPoint lastPoint) where TQuote : IQuote
        {
            // initialize
            bool    trendUp = (lastPoint.PointType == "L");
            decimal?change  = 0;

            ZigZagPoint extremePoint = new()
            {
                Index     = lastPoint.Index,
                Value     = lastPoint.Value,
                PointType = trendUp ? "H" : "L"
            };

            // find extreme point before reversal point
            for (int i = lastPoint.Index; i < historyList.Count; i++)
            {
                TQuote h     = historyList[i];
                int    index = i + 1;

                ZigZagEval eval = GetZigZagEval(type, index, h);

                // reset extreme point
                if (trendUp)
                {
                    if (eval.High >= extremePoint.Value)
                    {
                        extremePoint.Index = eval.Index;
                        extremePoint.Value = eval.High;
                    }
                    else
                    {
                        change = (extremePoint.Value == 0) ? null
                            : (extremePoint.Value - eval.Low) / extremePoint.Value;
                    }
                }
                else
                {
                    if (eval.Low <= extremePoint.Value)
                    {
                        extremePoint.Index = eval.Index;
                        extremePoint.Value = eval.Low;
                    }
                    else
                    {
                        change = (extremePoint.Value == 0) ? null
                            : (eval.High - extremePoint.Value) / extremePoint.Value;
                    }
                }

                // return extreme point when deviation threshold met
                if (change >= changeThreshold)
                {
                    return(extremePoint);
                }
            }

            // handle last unconfirmed point
            int finalPointIndex = historyList.Count;

            if (extremePoint.Index == finalPointIndex && change < changeThreshold)
            {
                extremePoint.PointType = null;
            }

            return(extremePoint);
        }

        private static void DrawZigZagLine <TQuote>(List <ZigZagResult> results, List <TQuote> historyList,
        private static ZigZagPoint EvaluateNextPoint(List <Quote> historyList,
                                                     ZigZagType type, decimal changeThreshold, ZigZagPoint lastPoint)
        {
            // initialize
            bool       trendUp = (lastPoint.PointType == "L");
            decimal    change  = 0;
            ZigZagEval eval    = new ZigZagEval();

            ZigZagPoint extremePoint = new ZigZagPoint
            {
                Index     = lastPoint.Index,
                Value     = lastPoint.Value,
                PointType = trendUp ? "H" : "L"
            };

            List <Quote> period = historyList
                                  .Where(x => x.Index > lastPoint.Index)
                                  .ToList();

            // find extreme point before reversal point
            foreach (Quote h in period)
            {
                eval = GetZigZagEval(type, h);

                // reset extreme point
                switch (trendUp)
                {
                case true:

                    if (eval.High >= extremePoint.Value)
                    {
                        extremePoint.Index = eval.Index;
                        extremePoint.Value = eval.High;
                    }
                    else
                    {
                        change = (extremePoint.Value - eval.Low) / extremePoint.Value;
                    }

                    break;

                case false:

                    if (eval.Low <= extremePoint.Value)
                    {
                        extremePoint.Index = eval.Index;
                        extremePoint.Value = eval.Low;
                    }
                    else
                    {
                        change = (eval.High - extremePoint.Value) / extremePoint.Value;
                    }

                    break;
                }

                // return extreme point when deviation threshold met
                if (change >= changeThreshold)
                {
                    return(extremePoint);
                }
            }

            // handle last unconfirmed point
            int finalPointIndex = historyList.Select(x => (int)x.Index).Max();

            if (extremePoint.Index == finalPointIndex && change < changeThreshold)
            {
                extremePoint.PointType = null;
            }

            return(extremePoint);
        }