/// <summary> /// Checks if a given bar is a red candle. /// </summary> public static bool IsGreenCandle(BarData bar) { return(bar.Close > bar.Open); }
/// <summary> /// Check for a morning star pattern. /// </summary> public static bool CheckMorningStar(List <BarData> bars) { // what percent decrease would be considered as a downtrend? double downTrendPercent = 0.987; // get previous bars List <BarData> prevBars = new List <BarData>(); for (int i = 0; i < Settings.TREND_BAR_COUNT; i++) { prevBars.Add(bars[bars.Count - Settings.TREND_BAR_COUNT + i - 3]); } // get last bars BarData thirdLastBar = bars[bars.Count - 3]; BarData secondLastBar = bars[bars.Count - 2]; BarData lastBar = bars[bars.Count - 1]; // the pattern is marked by a red candle following either color and a green candle if (IsGreenCandle(thirdLastBar)) { return(false); } if (IsRedCandle(lastBar)) { return(false); } // what is the trend? double factor = GetWeightedPercentChange(prevBars); // are we in a downtrend? if (factor <= downTrendPercent) { // how short must the middle bar be? double middleShortPercent = 0.4; // what is the average bar size of the left and right candles? double averageTwinBody = (Math.Abs(thirdLastBar.Open - thirdLastBar.Close) + Math.Abs(lastBar.Open - lastBar.Close)) / 2; // do we fit the criteria? if (Math.Abs(secondLastBar.Open - secondLastBar.Close) / averageTwinBody <= middleShortPercent) { // what size relative to the previous bars would be considered long? double longPercent = 1.5; // what is the average bar length? double averageLength = prevBars.Average(x => Math.Abs(x.Open - x.Close)); // what are the bar lengths for the twins? double leftLength = Math.Abs(thirdLastBar.Open - thirdLastBar.Close); double rightLength = Math.Abs(lastBar.Open - lastBar.Close); // do we fit the criteria? if (leftLength / averageLength >= longPercent && rightLength / averageLength >= longPercent) { // what is the average bottom of the twins? double leftBot = thirdLastBar.Close; double rightBot = lastBar.Open; double averageBot = (rightBot + leftBot) / 2; // is the middle bar somewhat below them? if (Math.Min(secondLastBar.Close, secondLastBar.Open) <= averageBot) { return(true); } } } } return(false); }
/// <summary> /// Checks if a given bar is a red candle. /// </summary> public static bool IsRedCandle(BarData bar) { return(bar.Close <= bar.Open); }
/// <summary> /// Check for a piercing line pattern. /// </summary> public static bool CheckPiercingLine(List <BarData> bars) { // what percent decrease would be considered as a downtrend? double downTrendPercent = 0.987; // get previous bars List <BarData> prevBars = new List <BarData>(); for (int i = 0; i < Settings.TREND_BAR_COUNT; i++) { prevBars.Add(bars[bars.Count - Settings.TREND_BAR_COUNT + i - 2]); } // get last bars BarData secondLastBar = bars[bars.Count - 2]; BarData lastBar = bars[bars.Count - 1]; // the pattern is marked by a red candle followed by a green candle if (IsGreenCandle(secondLastBar)) { return(false); } if (IsRedCandle(lastBar)) { return(false); } // what is the trend? double factor = GetWeightedPercentChange(prevBars); // are we in a downtrend? if (factor <= downTrendPercent) { // is the last close greater than second to last midpoint? if (lastBar.Close <= ((secondLastBar.Open + secondLastBar.Close) / 2)) { return(false); } // is the last open less than second last close? if (lastBar.Open >= secondLastBar.Close) { return(false); } // is the last close less than the previous open? if (lastBar.Close >= secondLastBar.Open) { return(false); } // what is the max size difference between the bars? double maxPercent = 1.5; // what is the size difference? double diff = Math.Abs(secondLastBar.Open - secondLastBar.Close) / Math.Abs(secondLastBar.Open - secondLastBar.Close); if (diff < maxPercent && diff > Math.Pow(maxPercent, -1)) { return(true); } } return(false); }
/// <summary> /// Check for a bullish engulfing pattern. /// </summary> public static bool CheckBullishEngulfing(List <BarData> bars) { // what percent decrease would be considered as a downtrend? double downTrendPercent = 0.987; // get previous bars List <BarData> prevBars = new List <BarData>(); for (int i = 0; i < Settings.TREND_BAR_COUNT; i++) { prevBars.Add(bars[bars.Count - Settings.TREND_BAR_COUNT + i - 2]); } // get last bars BarData secondLastBar = bars[bars.Count - 2]; BarData lastBar = bars[bars.Count - 1]; // the pattern is marked by a red candle followed by a green candle if (IsGreenCandle(secondLastBar)) { return(false); } if (IsRedCandle(lastBar)) { return(false); } // what is the trend? double factor = GetWeightedPercentChange(prevBars); // are we in a downtrend? if (factor <= downTrendPercent) { // what percent less than the average open close difference is considered short? double shortPercent = 0.6; // what is the average open close different for the previous bars? double averageDiff = prevBars.Average(x => Math.Abs(x.Open - x.Close)); // if the average difference is so slim that it is equal to zero, // then there is no possible chance of us being smaller than it if (averageDiff == 0) { return(false); } // is our second to last bar shorter than this? if (Math.Abs(secondLastBar.Open - secondLastBar.Close) / averageDiff <= shortPercent) { // what percent longer than the short open close difference is considered long? double longPercent = 1.4; // what is the open close difference of the second to last bar? double secondLastDiff = Math.Abs(secondLastBar.Open - secondLastBar.Close); // are we sufficiently longer than this? if (Math.Abs(lastBar.Open - lastBar.Close) / secondLastDiff >= longPercent) { // is the last open below the second to last close? if (secondLastBar.Close - lastBar.Open < 0) { return(false); } // is the last bar close above second last bar open? if (lastBar.Close - secondLastBar.Open <= 0) { return(false); } return(true); } } } return(false); }
/// <summary> /// Check for an inverse hammer pattern. /// </summary> public static bool CheckInverseHammer(List <BarData> bars) { // what percent decrease would be considered as a downtrend? double downTrendPercent = 0.987; // get previous bars List <BarData> prevBars = new List <BarData>(); for (int i = 0; i < Settings.TREND_BAR_COUNT; i++) { prevBars.Add(bars[bars.Count - Settings.TREND_BAR_COUNT + i - 2]); } // get last bar BarData lastBar = bars[bars.Count - 1]; // the bar can be either color, but the most profitable form // of the hammer trend would include a green candle if (IsRedCandle(lastBar)) { return(false); } // what is the trend? double factor = GetWeightedPercentChange(prevBars); // are we in a downtrend? if (factor <= downTrendPercent) { // what percent less than the average open close difference is considered short? double shortPercent = 0.5; // what is the average open close different for the previous bars? double averageDiff = prevBars.Average(x => Math.Abs(x.Open - x.Close)); // if the average difference is so slim that it is equal to zero, // then there is no possible chance of us being smaller than it if (averageDiff == 0) { return(false); } // are we shorter than this? if (Math.Abs(lastBar.Open - lastBar.Close) / averageDiff <= shortPercent) { // what percent longer than the average nose is considered long? double noseLongPercent = 2.2; // what is the average tail length? double averageNose = GetAverageNoseLength(prevBars); // what is our tail length? double noseLength = GetNoseLength(lastBar); // in the case that the average tail is so slim that it is equal to zero, // then we assume we are long enough bool canContinue = false; if (averageNose == 0) { canContinue = true; } else { if (noseLength / averageNose >= noseLongPercent) { canContinue = true; } } if (canContinue) { // what percent shorter than our tail is considered short? double tailShortPercent = 0.4; // what is our nose length? double tailLength = GetTailLength(lastBar); // are we sufficiently shorter than the average? if (tailLength / noseLength <= tailShortPercent) { return(true); } } } } return(false); }
/// <summary> /// Get the nose length for a bar. /// </summary> public static double GetNoseLength(BarData bar) { return(bar.High - Math.Max(bar.Close, bar.Open)); }
/// <summary> /// Get the tail length for a bar. /// </summary> public static double GetTailLength(BarData bar) { return(Math.Min(bar.Close, bar.Open) - bar.Low); }