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]); } } } }