public InflectionPoint(SignalDataByTime signalValue, int indexOrigin, ExtremaType extremum) { this.x = signalValue.Time; this.y = signalValue.SignalValue; this.index = indexOrigin; this.extremumType = extremum; }
public InflectionPoint(EDASignal signalValue, int indexOrigin, ExtremaType extremum) { this.x = signalValue.time; this.y = signalValue.value; this.index = indexOrigin; this.extremumType = extremum; }
public static void Print(this IEnumerable <ExtremaGroup> extremaGroups, ExtremaType extremaType) { var list = extremaType == ExtremaType.Minimum ? extremaGroups.OrderByDescending(c => c.Average) : extremaGroups.OrderBy(c => c.Average); foreach (var extremaGroup in list) { extremaGroup.Print(); } }
public List <ExtremaGroup> GetSupportExtremaGroups(List <Price> prices, ExtremaType extremePoint, double offsetPercent) { // Get extrema points var extremePoints = GetExtremePoints(prices, extremePoint, offsetPercent); // Filter broken limits extremePoints = FilterBrokenLimits(extremePoints, ExtremaType.Minimum, offsetPercent); // Merge group var extremaGroups = MergeGroups(extremePoints, 1); return(extremaGroups); }
private static List <Extrema> GetExtremePoints(List <Price> prices, ExtremaType extremePoint, double offsetPercent) { var potentials = new List <Price>(); for (var i = 0; i < prices.Count - 1; i++) { if (i == 0) { continue; } var yesterday = prices[i - 1].Close; var today = prices[i].Close; var tomorrow = prices[i + 1].Close; switch (extremePoint) { case ExtremaType.Minimum: if (today.IsMinima(yesterday, tomorrow)) { potentials.Add(prices[i]); } break; case ExtremaType.Maximum: if (today.IsMaxima(yesterday, tomorrow)) { potentials.Add(prices[i]); } break; default: throw new ArgumentOutOfRangeException(nameof(extremePoint), extremePoint, null); } } var extremePoints = potentials.Select(p => new Extrema(p, offsetPercent)).ToList(); return(extremePoints); }
/// <summary> /// Constructor /// </summary> /// <param name="index">Data index of extrema.</param> /// <param name="extremaType">The type of extrema (maxima or minima).</param> public ExtremaPoint(int index, ExtremaType extremaType) { this.index = index; this.extremaType = extremaType; }
/// <summary> /// Looking for inflection points in a list of signal values. /// If we have a sequence of more than two signal values with the same value (points are collinear) /// we take for inflection points only the first and last. /// </summary> /// /// <param name="signalCoordinatePoints"> List of signal values. </param> /// /// <returns> /// List of founded inflection points. /// </returns> public List <InflectionPoint> GetInflectionPoints(List <SignalDataByTime> signalCoordinatePoints, string dataType) { List <InflectionPoint> inflectionPoints = new List <InflectionPoint>(); int candidateInflectionPoint = -1; //add the first and the last signal value double firstInflectionPoints = (("default").Equals(dataType)) ? signalCoordinatePoints[0].SignalValue : (("highPass").Equals(dataType)) ? signalCoordinatePoints[0].HighPassValue : signalCoordinatePoints[0].LowPassValue; double secondInflectionPoints = (("default").Equals(dataType)) ? signalCoordinatePoints[1].SignalValue : (("highPass").Equals(dataType)) ? signalCoordinatePoints[1].HighPassValue : signalCoordinatePoints[1].LowPassValue; inflectionPoints.Add(new InflectionPoint(signalCoordinatePoints[0], 0, GetExtremaType(null, firstInflectionPoints, secondInflectionPoints))); double penultimateInflectionPoint = (("default").Equals(dataType)) ? signalCoordinatePoints[signalCoordinatePoints.Count - 2].SignalValue : (("highPass").Equals(dataType)) ? signalCoordinatePoints[signalCoordinatePoints.Count - 2].HighPassValue : signalCoordinatePoints[signalCoordinatePoints.Count - 2].LowPassValue; double lastInflectionPoint = (("default").Equals(dataType)) ? signalCoordinatePoints[signalCoordinatePoints.Count - 1].SignalValue : (("highPass").Equals(dataType)) ? signalCoordinatePoints[signalCoordinatePoints.Count - 1].HighPassValue : signalCoordinatePoints[signalCoordinatePoints.Count - 1].LowPassValue; inflectionPoints.Add(new InflectionPoint(signalCoordinatePoints[signalCoordinatePoints.Count - 1], signalCoordinatePoints.Count - 1, GetExtremaType(penultimateInflectionPoint, lastInflectionPoint, null))); double currentFindLastInflectionPoint = firstInflectionPoints; for (int i = 1; i < (signalCoordinatePoints.Count - 1); i++) { double currentPointY = (("default").Equals(dataType)) ? signalCoordinatePoints[i].SignalValue : (("highPass").Equals(dataType)) ? signalCoordinatePoints[i].HighPassValue : signalCoordinatePoints[i].LowPassValue; double previousPointY = (("default").Equals(dataType)) ? signalCoordinatePoints[i - 1].SignalValue : (("highPass").Equals(dataType)) ? signalCoordinatePoints[i - 1].HighPassValue : signalCoordinatePoints[i - 1].LowPassValue; double nextPointY = (("default").Equals(dataType)) ? signalCoordinatePoints[i + 1].SignalValue : (("highPass").Equals(dataType)) ? signalCoordinatePoints[i + 1].HighPassValue : signalCoordinatePoints[i + 1].LowPassValue; ExtremaType extremumType = GetExtremaType(previousPointY, currentPointY, nextPointY); if (!extremumType.Equals(ExtremaType.None)) { if (currentPointY.CompareTo(currentFindLastInflectionPoint) != 0) { if (i > 0 && inflectionPoints.Count > 0) { if ((candidateInflectionPoint + 1) == i && inflectionPoints[inflectionPoints.Count - 1].CoordinateY.Equals(currentFindLastInflectionPoint)) { inflectionPoints.Add(new InflectionPoint(signalCoordinatePoints[candidateInflectionPoint], candidateInflectionPoint, extremumType)); } } inflectionPoints.Add(new InflectionPoint(signalCoordinatePoints[i], i, extremumType)); } else { candidateInflectionPoint = i; } currentFindLastInflectionPoint = currentPointY; } /*else * { * if (i > 0 && inflectionPoints.Count > 0) * { * if ((candidateInflectionPoint + 1) == i && inflectionPoints[inflectionPoints.Count - 1].CoordinateY.Equals(signalCoordinatePoints[i - 1].SignalValue)) * { * inflectionPoints.Add(new InflectionPoint(signalCoordinatePoints[candidateInflectionPoint], candidateInflectionPoint, extremumType)); * } * } * }*/ } return(inflectionPoints); }
private static bool IsInOffsetRange(double offsetPercent, float currentValue, float extremaValue, ExtremaType extremaType) { switch (extremaType) { case ExtremaType.Minimum: return(currentValue < (extremaValue + (extremaValue * offsetPercent) / 100)); case ExtremaType.Maximum: return(currentValue > (extremaValue - (extremaValue + offsetPercent) / 100)); default: throw new ArgumentOutOfRangeException(nameof(extremaType), extremaType, null); } }
private static List <Extrema> FilterBrokenLimits(List <Extrema> extremePoints, ExtremaType extremaType, double offsetPercent) { extremePoints.Reverse(); var mostExtrema = extremaType == ExtremaType.Minimum ? float.MaxValue : float.MinValue; var activePoints = new List <Extrema>(); foreach (var point in extremePoints) { var val = point.CurrentPrice.Close; if (!activePoints.Any()) { activePoints.Add(point); mostExtrema = val; } else { var shouldCheckOffset = false; switch (extremaType) { case ExtremaType.Minimum: { // Even if bigger, check if is in offset if (mostExtrema < val) { shouldCheckOffset = true; } break; } case ExtremaType.Maximum: { // Even if smaller, check if is in offset if (mostExtrema > val) { shouldCheckOffset = true; } break; } default: throw new ArgumentOutOfRangeException(nameof(extremaType), extremaType, null); } if (shouldCheckOffset) { if (IsInOffsetRange(offsetPercent, val, mostExtrema, extremaType)) { activePoints.Add(point); } continue; } mostExtrema = val; activePoints.Add(point); } } return(activePoints); }