private LiveChartSeries BuildSeries(QuantChartSeries qSeries) { LiveChartSeries series; switch (qSeries.SeriesType) { case SeriesType.Line: series = new GLineSeries(); break; case SeriesType.Bar: series = new GColumnSeries(); break; case SeriesType.Candle: series = new GOhlcSeries(); break; default: throw new NotSupportedException(); } series.Configuration = ChartPointMapper; series.Title = qSeries.Name; series.PointGeometry = GetPointGeometry(qSeries.ScatterMarkerSymbol); series.Fill = Brushes.Transparent; return(series); }
private void UpdateSeries(ISeriesView series, QuantChartSeries qSeries) { var detectedResolution = DetectResolution(qSeries); if (Resolution > detectedResolution) { Resolution = detectedResolution; } // QuantChart series are unix timestamp switch (qSeries.SeriesType) { case SeriesType.Line: var existingLineValues = (GearedValues <TimeStampChartPoint>)(series.Values ?? (series.Values = new GearedValues <TimeStampChartPoint>())); existingLineValues.AddRange(qSeries.Values.Select(cp => cp.ToTimeStampChartPoint())); // Update range break; case SeriesType.Bar: var existingBarValues = (GearedValues <TimeStampChartPoint>)(series.Values ?? (series.Values = new GearedValues <TimeStampChartPoint>())); existingBarValues.AddRange(qSeries.Values.Select(cp => cp.ToTimeStampChartPoint())); break; case SeriesType.Candle: // Build daily candles // TODO: Candle allows for custom resolution var existingCandleValues = (GearedValues <TimeStampOhlcChartPoint>)(series.Values ?? (series.Values = new GearedValues <TimeStampOhlcChartPoint>())); var newValues = qSeries.Values.Select(cp => cp.ToTimeStampChartPoint()).GroupBy(cp => cp.X).Select( g => { return(new TimeStampOhlcChartPoint { X = g.First().X, Open = (double)g.First().Y, Close = (double)g.Last().Y, Low = (double)g.Min(z => z.Y), High = (double)g.Max(z => z.Y) }); }); existingCandleValues.AddRange(newValues); break; } }
public static ChartResolution DetectResolution(QuantChartSeries series) { if (series.SeriesType == SeriesType.Candle) { // Candle data is supposed to be grouped. // Currently we group candle data by day. return(ChartResolution.Day); } var chartPoints = series.Values.Select(cp => cp.ToTimeStampChartPoint()).ToList(); // Check whether we have duplicates in day mode var dayDuplicates = chartPoints.GroupBy(cp => cp.X.ElapsedDays).Any(g => g.Count() > 1); if (!dayDuplicates) { return(ChartResolution.Day); } var hourDuplicates = chartPoints.GroupBy(cp => cp.X.ElapsedHours).Any(g => g.Count() > 1); if (!hourDuplicates) { return(ChartResolution.Hour); } var minuteDuplicates = chartPoints.GroupBy(cp => cp.X.ElapsedMinutes).Any(g => g.Count() > 1); if (!minuteDuplicates) { return(ChartResolution.Minute); } var secondDuplicates = chartPoints.GroupBy(cp => cp.X.ElapsedSeconds).Any(g => g.Count() > 1); if (!secondDuplicates) { return(ChartResolution.Second); } throw new Exception("Resolution is below second which is not supported."); }