public override void ApplyTo(StockSerie stockSerie)
        {
            Queue<float> resistanceQueue = new Queue<float>(new float[] { float.MinValue, float.MinValue });
            Queue<float> supportQueue = new Queue<float>(new float[] { float.MaxValue, float.MaxValue });

            FloatSerie lowSerie = stockSerie.GetSerie(StockDataType.LOW);
            FloatSerie highSerie = stockSerie.GetSerie(StockDataType.HIGH);
            FloatSerie closeSerie = stockSerie.GetSerie(StockDataType.CLOSE);
            int period = (int)this.Parameters[0];

            IStockTrailStop trailStop = stockSerie.GetTrailStop("TRAILHL(" + period + ")");

            FloatSerie longStopSerie = trailStop.Series[0];
            FloatSerie shortStopSerie = trailStop.Series[1];

            BoolSerie brokenUpSerie = trailStop.Events[2];
            BoolSerie brokenDownSerie = trailStop.Events[3];

            FloatSerie supportSerie = new FloatSerie(stockSerie.Count, "TRAILHL.S"); supportSerie.Reset(float.NaN);
            FloatSerie resistanceSerie = new FloatSerie(stockSerie.Count, "TRAILHL.R"); resistanceSerie.Reset(float.NaN);

            this.Series[0] = supportSerie;
            this.Series[1] = resistanceSerie;

            // Detecting events
            this.CreateEventSeries(stockSerie.Count);
            this.Events[0] = brokenUpSerie;
            this.Events[1] = brokenDownSerie;

            // Begin Sequence

            // Calculate Support/Resistance
            float extremum = lowSerie[0];
            bool waitingForEndOfTrend = false;
            int i = 0;
            for (; i < stockSerie.Count && (!brokenUpSerie[i] && !brokenDownSerie[i]); i++)
            {
                //if (float.IsNaN(longStopSerie[i]))
                //{
                //    this.UpDownState[i] = StockSerie.Trend.DownTrend; // Down trend
                //    supportSerie[i] = float.NaN;
                //    resistanceSerie[i] = highSerie.GetMax(0, i);
                //    resistanceQueue.Dequeue();
                //    resistanceQueue.Enqueue(resistanceSerie[i]);
                //    extremum = highSerie.GetMax(0, i);
                //}
                //else
                //{
                //    this.UpDownState[i] = StockSerie.Trend.UpTrend; // Up trend

                //    supportSerie[i] = lowSerie.GetMin(0, i);
                //    supportQueue.Dequeue();
                //    supportQueue.Enqueue(supportSerie[i]);
                //    resistanceSerie[i] = float.NaN;
                //    extremum = lowSerie.GetMin(0, i);
                //}
            }
            if (i < stockSerie.Count)
            {
                if (brokenUpSerie[i])
                {
                    this.UpDownState[i] = StockSerie.Trend.UpTrend;
                    extremum = lowSerie.GetMin(0, i);
                }
                if (brokenDownSerie[i])
                {
                    this.UpDownState[i] = StockSerie.Trend.DownTrend;
                    extremum = highSerie.GetMax(0, i);
                }
            }

            for (; i < stockSerie.Count; i++)
            {
                bool upSwing = float.IsNaN(shortStopSerie[i]);
                this.UpDownState[i] = StockUpDownIndicatorBase.BoolToTrend(upSwing);

                this.Events[8][i] = upSwing;
                this.Events[9][i] = !upSwing;

                if (brokenUpSerie[i])
                {
                    supportSerie[i] = extremum;
                    supportQueue.Dequeue();
                    supportQueue.Enqueue(extremum);
                    resistanceSerie[i] = float.NaN;

                    if (waitingForEndOfTrend)
                    {// Detect EndOfUptrend
                        waitingForEndOfTrend = false;
                        this.Events[3][i] = true;
                    }
                    else if (extremum > resistanceQueue.ElementAt(0))
                    {// Detect if pullback in uptrend
                        this.Events[2][i] = true;
                        waitingForEndOfTrend = true;
                    }

                    if (extremum > supportQueue.ElementAt(0))
                    {
                        // Higher Low detected
                        this.Events[4][i] = true;
                    }
                    else
                    {
                        // Lower Low
                        this.Events[11][i] = true;
                    }

                    extremum = highSerie[i];
                }
                else if (brokenDownSerie[i])
                {
                    supportSerie[i] = float.NaN;
                    resistanceSerie[i] = extremum;
                    resistanceQueue.Dequeue();
                    resistanceQueue.Enqueue(extremum);

                    if (waitingForEndOfTrend)
                    {// Detect EndOfUptrend
                        waitingForEndOfTrend = false;
                        this.Events[3][i] = true;
                    }
                    else if (extremum < supportQueue.ElementAt(0))
                    {// Detect if pullback in downTrend
                        this.Events[2][i] = true;
                        waitingForEndOfTrend = true;
                    }

                    if (extremum < resistanceQueue.ElementAt(0))
                    {
                        // Lower high detected
                        this.Events[5][i] = true;
                    }
                    else
                    {
                        // Higher high detected
                        this.Events[10][i] = true;
                    }

                    extremum = lowSerie[i];
                }
                else
                {
                    supportSerie[i] = supportSerie[i - 1];
                    resistanceSerie[i] = resistanceSerie[i - 1];
                    if (float.IsNaN(supportSerie[i])) // Down trend
                    {
                        extremum = Math.Min(extremum, lowSerie[i]);
                        if (closeSerie[i - 1] >= supportQueue.ElementAt(1) && closeSerie[i] < supportQueue.ElementAt(1))
                        {
                            // Previous support broken
                            this.Events[7][i] = true;
                        }
                    }
                    else
                    {
                        extremum = Math.Max(extremum, highSerie[i]);
                        if (closeSerie[i - 1] <= resistanceQueue.ElementAt(1) && closeSerie[i] > resistanceQueue.ElementAt(1))
                        {
                            // Previous resistance broken
                            this.Events[6][i] = true;
                        }
                    }
                }
            }
        }
        public override void ApplyTo(StockSerie stockSerie)
        {
            using (MethodLogger ml = new MethodLogger(this))
            {
                List<string> eventNames = this.EventNames.ToList();
                int ExhaustionTopIndex = eventNames.IndexOf("ExhaustionTop");
                int ExhaustionBottomIndex = eventNames.IndexOf("ExhaustionBottom");
                int BearishDivergenceIndex = eventNames.IndexOf("BearishDivergence");
                int BullishDivergenceIndex = eventNames.IndexOf("BullishDivergence");
                int ExhaustionTopOccuredIndex = eventNames.IndexOf("ExhaustionTopOccured");
                int ExhaustionBottomOccuredIndex = eventNames.IndexOf("ExhaustionBottomOccured");
                int PositiveIndex = eventNames.IndexOf("Positive");
                int NegativeIndex = eventNames.IndexOf("Negative");
                int BullishIndex = eventNames.IndexOf("Bullish");
                int BearishIndex = eventNames.IndexOf("Bearish");
                int BearFailureIndex = eventNames.IndexOf("BearFailure");
                int BullFailureIndex = eventNames.IndexOf("BullFailure");

                CreateEventSeries(stockSerie.Count);

                int smoothing = (int)this.parameters[0];
                float overbought = (float)this.parameters[1];
                float oversold = (float)this.parameters[2];
                int lookbackPeriod = (int)this.parameters[3];
                int signalSmoothing = (int)this.parameters[4];

                int countNegative = 0;
                int countPositive = 0;

                IStockIndicator indicator = stockSerie.GetIndicator(this.DecoratedItem);
                if (indicator != null && indicator.Series[0].Count > 0)
                {
                    FloatSerie indicatorToDecorate = indicator.Series[0].CalculateEMA(smoothing);
                    FloatSerie signalSerie = indicatorToDecorate.CalculateEMA(signalSmoothing);
                    FloatSerie upperLimit = new FloatSerie(indicatorToDecorate.Count); upperLimit.Reset(overbought);
                    FloatSerie lowerLimit = new FloatSerie(indicatorToDecorate.Count); lowerLimit.Reset(oversold);

                    if (smoothing <= 1) { this.SerieVisibility[0] = false; }
                    if (signalSmoothing <= 1) { this.SerieVisibility[3] = false; }

                    this.Series[0] = indicatorToDecorate;
                    this.Series[0].Name = this.SerieNames[0];
                    this.Series[1] = upperLimit;
                    this.Series[1].Name = this.SerieNames[1];
                    this.Series[2] = lowerLimit;
                    this.Series[2].Name = this.SerieNames[2];
                    this.Series[3] = signalSerie;
                    this.Series[3].Name = this.SerieNames[3];

                    if (indicator.DisplayTarget == IndicatorDisplayTarget.RangedIndicator && indicator is IRange)
                    {
                        IRange range = (IRange)indicator;
                        indicatorToDecorate = indicatorToDecorate.Sub((range.Max + range.Min) / 2.0f);
                    }
                    FloatSerie highSerie = stockSerie.GetSerie(StockDataType.HIGH);
                    FloatSerie lowSerie = stockSerie.GetSerie(StockDataType.LOW);

                    int lastExhaustionSellIndex = int.MinValue;
                    int lastExhaustionBuyIndex = int.MinValue;
                    float exhaustionBuyPrice = highSerie[0];
                    float exhaustionSellPrice = lowSerie[0];

                    float previousValue = indicatorToDecorate[0];
                    float currentValue;
                    int i = 0;
                    for (i = 1; i < indicatorToDecorate.Count - 1; i++)
                    {
                        if (indicatorToDecorate[i] > 0)
                        {
                            this.Events[PositiveIndex][i] = true;
                            countPositive++;
                            countNegative = 0;
                        }
                        else
                        {
                            this.Events[NegativeIndex][i] = true;
                            countPositive = 0;
                            countNegative++;
                        }
                        if (indicatorToDecorate[i] > signalSerie[i])
                        {
                            this.Events[BullishIndex][i] = true;
                        }
                        else
                        {
                            this.Events[BearishIndex][i] = true;
                        }
                        currentValue = indicatorToDecorate[i];
                        if (currentValue == previousValue)
                        {
                            if (indicatorToDecorate.IsBottomIsh(i))
                            {
                                if (currentValue <= oversold)
                                {
                                    // This is an exhaustion selling
                                    this.Events[ExhaustionBottomIndex][i + 1] = true;
                                    exhaustionSellPrice = lowSerie[i];
                                    lastExhaustionSellIndex = i + 1;
                                }
                                else
                                {
                                    // Check if divergence
                                    if (lowSerie[i] <= exhaustionSellPrice)
                                    {
                                        this.Events[BullishDivergenceIndex][i + 1] = true;
                                    }
                                }
                            }
                            else if (indicatorToDecorate.IsTopIsh(i))
                            {
                                if (currentValue >= overbought)
                                {
                                    // This is an exhaustion buying
                                    this.Events[ExhaustionTopIndex][i + 1] = true;
                                    exhaustionBuyPrice = highSerie[i];
                                    lastExhaustionBuyIndex = i + 1;
                                }
                                else
                                {
                                    // Check if divergence
                                    if (highSerie[i] >= exhaustionBuyPrice)
                                    {
                                        this.Events[BearishDivergenceIndex][i + 1] = true;
                                    }
                                }
                            }
                        }
                        else if (currentValue < previousValue)
                        {
                            if (indicatorToDecorate.IsBottom(i))
                            {
                                if (currentValue <= oversold)
                                {
                                    // This is an exhaustion selling
                                    this.Events[ExhaustionBottomIndex][i + 1] = true;
                                    exhaustionSellPrice = lowSerie[i];
                                    lastExhaustionSellIndex = i + 1;
                                }
                                else
                                {
                                    // Check if divergence
                                    if (lowSerie[i] <= exhaustionSellPrice)
                                    {
                                        this.Events[BullishDivergenceIndex][i + 1] = true;
                                    }
                                }
                            }
                        }
                        else if (currentValue > previousValue)
                        {
                            if (indicatorToDecorate.IsTop(i))
                            {
                                if (currentValue >= overbought)
                                {
                                    // This is an exhaustion selling
                                    this.Events[ExhaustionTopIndex][i + 1] = true;
                                    exhaustionBuyPrice = highSerie[i];
                                    lastExhaustionBuyIndex = i + 1;
                                }
                                else
                                {
                                    // Check if divergence
                                    if (highSerie[i] >= exhaustionBuyPrice)
                                    {
                                        this.Events[BearishDivergenceIndex][i + 1] = true;
                                    }
                                }
                            }
                        }
                        previousValue = currentValue;

                        // Exhaustion occured events
                        if (lookbackPeriod > 0)
                        {
                            if (i + 1 - lookbackPeriod < lastExhaustionBuyIndex)
                            {
                                this.Events[ExhaustionTopOccuredIndex][i + 1] = true;
                            }
                            if (i + 1 - lookbackPeriod < lastExhaustionSellIndex)
                            {
                                this.Events[ExhaustionBottomOccuredIndex][i + 1] = true;
                            }
                        }

                        this.Events[BearFailureIndex][i] = (this.Events[ExhaustionTopOccuredIndex][i] && countPositive == 1);
                        this.Events[BullFailureIndex][i] = (this.Events[ExhaustionBottomOccuredIndex][i] && countNegative == 1);
                    }
                }
                else
                {
                    for (int i = 0; i < this.EventNames.Length; i++)
                    {
                        this.Events[i] = new BoolSerie(0, this.EventNames[i]);
                    }
                }
            }
        }