예제 #1
0
        // PARABOLIC SAR
        public static IEnumerable <ParabolicSarResult> GetParabolicSar(
            IEnumerable <Quote> history,
            decimal accelerationStep      = (decimal)0.02,
            decimal maxAccelerationFactor = (decimal)0.2)
        {
            // clean quotes
            history = Cleaners.PrepareHistory(history);

            // initialize
            List <ParabolicSarResult> results = new List <ParabolicSarResult>();
            Quote first = history.Where(x => x.Index == 1).FirstOrDefault();

            decimal accelerationFactor = accelerationStep;
            decimal extremePoint       = first.High;
            decimal priorSar           = first.Low;
            bool    isRising           = true;

            // roll through history
            foreach (Quote h in history)
            {
                ParabolicSarResult result = new ParabolicSarResult
                {
                    Index = (int)h.Index,
                    Date  = h.Date
                };

                // skip first one
                if (h.Index == 1)
                {
                    results.Add(result);
                    continue;
                }


                // was rising
                if (isRising)
                {
                    decimal currentSar = priorSar + accelerationFactor * (extremePoint - priorSar);

                    // turn down
                    if (h.Low < currentSar)
                    {
                        result.IsReversal = true;
                        result.Sar        = extremePoint;

                        isRising           = false;
                        accelerationFactor = accelerationStep;
                        extremePoint       = h.Low;
                    }

                    // continue rising
                    else
                    {
                        result.IsReversal = false;
                        result.Sar        = currentSar;

                        // SAR cannot be higher than last two lows
                        decimal minLastTwo = history.Where(x => x.Index >= h.Index - 2 && x.Index < h.Index).Select(x => x.Low).Min();
                        result.Sar = Math.Min((decimal)result.Sar, minLastTwo);

                        if (h.High > extremePoint)
                        {
                            extremePoint       = h.High;
                            accelerationFactor = Math.Min(accelerationFactor += accelerationStep, maxAccelerationFactor);
                        }
                    }
                }

                // was falling
                else
                {
                    decimal currentSar = priorSar - accelerationFactor * (priorSar - extremePoint);

                    // turn up
                    if (h.High > currentSar)
                    {
                        result.IsReversal = true;
                        result.Sar        = extremePoint;

                        isRising           = true;
                        accelerationFactor = accelerationStep;
                        extremePoint       = h.High;
                    }

                    // continue falling
                    else
                    {
                        result.IsReversal = false;
                        result.Sar        = currentSar;

                        // SAR cannot be lower than last two highs
                        decimal maxLastTwo = history.Where(x => x.Index >= h.Index - 2 && x.Index < h.Index).Select(x => x.High).Max();
                        result.Sar = Math.Max((decimal)result.Sar, maxLastTwo);

                        if (h.Low < extremePoint)
                        {
                            extremePoint       = h.Low;
                            accelerationFactor = Math.Min(accelerationFactor += accelerationStep, maxAccelerationFactor);
                        }
                    }
                }

                result.IsRising = isRising;
                priorSar        = (decimal)result.Sar;

                results.Add(result);
            }

            return(results);
        }
예제 #2
0
        // PARABOLIC SAR
        public static IEnumerable <ParabolicSarResult> GetParabolicSar <TQuote>(
            IEnumerable <TQuote> history,
            decimal accelerationStep      = (decimal)0.02,
            decimal maxAccelerationFactor = (decimal)0.2)
            where TQuote : IQuote
        {
            // clean quotes
            List <TQuote> historyList = history.Sort();

            // check parameters
            ValidateParabolicSar(history, accelerationStep, maxAccelerationFactor);

            // initialize
            List <ParabolicSarResult> results = new List <ParabolicSarResult>(historyList.Count);
            TQuote first = historyList[0];

            decimal accelerationFactor = accelerationStep;
            decimal extremePoint       = first.High;
            decimal priorSar           = first.Low;
            bool    isRising           = true; // initial guess

            // roll through history
            for (int i = 0; i < historyList.Count; i++)
            {
                TQuote h = historyList[i];

                ParabolicSarResult result = new ParabolicSarResult
                {
                    Date = h.Date
                };

                // skip first one
                if (i == 0)
                {
                    results.Add(result);
                    continue;
                }

                // was rising
                if (isRising)
                {
                    decimal currentSar = priorSar + accelerationFactor * (extremePoint - priorSar);

                    // turn down
                    if (h.Low < currentSar)
                    {
                        result.IsReversal = true;
                        result.Sar        = extremePoint;

                        isRising           = false;
                        accelerationFactor = accelerationStep;
                        extremePoint       = h.Low;
                    }

                    // continue rising
                    else
                    {
                        result.IsReversal = false;
                        result.Sar        = currentSar;

                        // SAR cannot be higher than last two lows
                        if (i >= 2)
                        {
                            decimal minLastTwo = Math.Min(historyList[i - 1].Low, historyList[i - 2].Low);

                            result.Sar = Math.Min((decimal)result.Sar, minLastTwo);
                        }
                        else
                        {
                            result.Sar = (decimal)result.Sar;
                        }

                        if (h.High > extremePoint)
                        {
                            extremePoint       = h.High;
                            accelerationFactor = Math.Min(accelerationFactor += accelerationStep, maxAccelerationFactor);
                        }
                    }
                }

                // was falling
                else
                {
                    decimal currentSar = priorSar - accelerationFactor * (priorSar - extremePoint);

                    // turn up
                    if (h.High > currentSar)
                    {
                        result.IsReversal = true;
                        result.Sar        = extremePoint;

                        isRising           = true;
                        accelerationFactor = accelerationStep;
                        extremePoint       = h.High;
                    }

                    // continue falling
                    else
                    {
                        result.IsReversal = false;
                        result.Sar        = currentSar;

                        // SAR cannot be lower than last two highs
                        if (i >= 2)
                        {
                            decimal maxLastTwo = Math.Max(historyList[i - 1].High, historyList[i - 2].High);

                            result.Sar = Math.Max((decimal)result.Sar, maxLastTwo);
                        }
                        else
                        {
                            result.Sar = (decimal)result.Sar;
                        }

                        if (h.Low < extremePoint)
                        {
                            extremePoint       = h.Low;
                            accelerationFactor = Math.Min(accelerationFactor += accelerationStep, maxAccelerationFactor);
                        }
                    }
                }

                priorSar = (decimal)result.Sar;

                results.Add(result);
            }

            // remove first trend to reversal, since it is an invalid guess
            ParabolicSarResult firstReversal = results
                                               .Where(x => x.IsReversal == true)
                                               .OrderBy(x => x.Date)
                                               .FirstOrDefault();

            if (firstReversal != null)
            {
                int cutIndex = results.IndexOf(firstReversal);

                for (int d = 0; d <= cutIndex; d++)
                {
                    ParabolicSarResult r = results[d];
                    r.Sar        = null;
                    r.IsReversal = null;
                }
            }

            return(results);
        }