private void OnTimerTick(object sender, EventArgs e) { _yNext = _yNext + ((float)_random.NextDouble() - 0.5f); using (_xyDataSeries.SuspendUpdates()) { if (_index == 999) { // wrap around. Break the line with nan _xyDataSeries.Append(_index + 1, float.NaN); _index = 0; } _xyDataSeries.Update(_index++, _yNext); } }
// The First method of updating a real-time chart: Updating Data Values private void Method1_UpdatingDataValues() { var scatterData = new XyDataSeries <double, double>(); var lineData = new XyDataSeries <double, double>(); // Ensure that DataSeries are named for the legend scatterData.SeriesName = "Cos(x)"; lineData.SeriesName = "Sin(x)"; for (int i = 0; i < 1000; i++) { lineData.Append(i, Math.Sin(i * 0.1)); scatterData.Append(i, Math.Cos(i * 0.1)); } LineSeries.DataSeries = lineData; ScatterSeries.DataSeries = scatterData; // Start a timer to update our data double phase = 0.0; var timer = new DispatcherTimer(DispatcherPriority.Render); timer.Interval = TimeSpan.FromMilliseconds(10); timer.Tick += (s, e) => { // SuspendUpdates() ensures the chart is frozen // while you do updates. This ensures best performance using (lineData.SuspendUpdates()) using (scatterData.SuspendUpdates()) { for (int i = 0; i < 1000; i++) { // Updates the Y value at index i lineData.Update(i, Math.Sin(i * 0.1 + phase)); scatterData.Update(i, Math.Cos(i * 0.1 + phase)); } } phase += 0.01; }; timer.Start(); }
/// <summary> /// To analyze. /// </summary> protected override void OnAnalyze() { var chart = Chart; var grid = Grid; var chartSeries = new XyDataSeries<double, double>(); ThreadSafeObservableCollection<GridRow> gridSeries = null; chart.GuiSync(() => { // clear prev values chart.RenderableSeries.Clear(); grid.Columns.Clear(); chart.RenderableSeries.Add(new FastColumnRenderableSeries { ResamplingMode = ResamplingMode.None, DataPointWidth = 1, SeriesColor = Colors.Chocolate, DataSeries = chartSeries }); chart.XAxis = new NumericAxis { AxisTitle = LocalizedStrings.Price }; chart.YAxis = new NumericAxis { AxisTitle = LocalizedStrings.Volume, GrowBy = new DoubleRange(0, 0.1) }; grid.AddTextColumn("Price", LocalizedStrings.Price).Width = 150; var volumeColumn = grid.AddTextColumn("Volume", LocalizedStrings.Volume); volumeColumn.Width = 100; var gridSource = new ObservableCollectionEx<GridRow>(); grid.ItemsSource = gridSource; gridSeries = new ThreadSafeObservableCollection<GridRow>(gridSource); grid.SetSort(volumeColumn, ListSortDirection.Descending); }); // get candle storage var storage = StorateRegistry.GetCandleStorage(typeof(TimeFrameCandle), Security, TimeFrame, format: StorageFormat); // get available dates for the specified period var dates = storage.GetDates(From, To).ToArray(); var rows = new Dictionary<decimal, GridRow>(); foreach (var loadDate in dates) { // check if stopped if (ProcessState != ProcessStates.Started) break; // load candles var candles = storage.Load(loadDate); // groupping candles by candle's middle price var groupedCandles = candles.GroupBy(c => c.LowPrice + c.GetLength() / 2); foreach (var group in groupedCandles.OrderBy(g => g.Key)) { // check if stopped if (ProcessState != ProcessStates.Started) break; var price = group.Key; // calc total volume for the specified time frame var sumVol = group.Sum(c => c.TotalVolume); var row = rows.TryGetValue(price); if (row == null) { // new price level rows.Add(price, row = new GridRow { Price = price, Volume = sumVol }); // draw on chart chartSeries.Append((double)price, (double)sumVol); // draw on table gridSeries.Add(row); } else { // update existing price level row.Volume += sumVol; // update chart chartSeries.Update((double)price, (double)row.Volume); } } chart.GuiAsync(() => { // update grid sorting grid.RefreshSort(); // scale chart chart.ZoomExtents(); }); } // notify the script stopped Stop(); }
private void UsePointMarkers_OnLoaded(object sender, RoutedEventArgs e) { var dataSeries1 = new XyDataSeries <double, double>() { SeriesName = "Ellipse Marker" }; var dataSeries2 = new XyDataSeries <double, double>() { SeriesName = "Square Marker" }; var dataSeries3 = new XyDataSeries <double, double>() { SeriesName = "Triangle Marker" }; var dataSeries4 = new XyDataSeries <double, double>() { SeriesName = "Cross Marker" }; var dataSeries5 = new XyDataSeries <double, double>() { SeriesName = "Sprite Marker" }; const int dataSize = 30; var rnd = new Random(); for (int i = 0; i < dataSize; i++) { dataSeries1.Append(i, rnd.NextDouble()); } for (int i = 0; i < dataSize; i++) { dataSeries2.Append(i, 1 + rnd.NextDouble()); } for (int i = 0; i < dataSize; i++) { dataSeries3.Append(i, 1.8 + rnd.NextDouble()); } for (int i = 0; i < dataSize; i++) { dataSeries4.Append(i, 2.5 + rnd.NextDouble()); } for (int i = 0; i < dataSize; i++) { dataSeries5.Append(i, 3.5 + rnd.NextDouble()); } // insert a break into the line - we do this to test double.NaN for the point marker types dataSeries1.Update(dataSeries1.XValues[15], double.NaN); dataSeries2.Update(dataSeries1.XValues[15], double.NaN); dataSeries3.Update(dataSeries1.XValues[15], double.NaN); dataSeries4.Update(dataSeries1.XValues[15], double.NaN); dataSeries5.Update(dataSeries1.XValues[15], double.NaN); using (this.sciChart.SuspendUpdates()) { this.lineSeries1.DataSeries = dataSeries1; this.lineSeries2.DataSeries = dataSeries2; this.lineSeries3.DataSeries = dataSeries3; this.lineSeries4.DataSeries = dataSeries4; this.lineSeries5.DataSeries = dataSeries5; } this.sciChart.ZoomExtents(); }
/// <summary> /// To analyze. /// </summary> protected override void OnAnalyze() { var chart = Chart; var grid = Grid; var chartSeries = new XyDataSeries <double, double>(); ThreadSafeObservableCollection <GridRow> gridSeries = null; chart.GuiSync(() => { // clear prev values chart.RenderableSeries.Clear(); grid.Columns.Clear(); chart.RenderableSeries.Add(new FastColumnRenderableSeries { ResamplingMode = ResamplingMode.None, DataPointWidth = 1, SeriesColor = Colors.Chocolate, DataSeries = chartSeries }); chart.XAxis = new NumericAxis { AxisTitle = LocalizedStrings.Price }; chart.YAxis = new NumericAxis { AxisTitle = LocalizedStrings.Volume, GrowBy = new DoubleRange(0, 0.1) }; grid.AddTextColumn("Price", LocalizedStrings.Price).Width = 150; var volumeColumn = grid.AddTextColumn("Volume", LocalizedStrings.Volume); volumeColumn.Width = 100; var gridSource = new ObservableCollectionEx <GridRow>(); grid.ItemsSource = gridSource; gridSeries = new ThreadSafeObservableCollection <GridRow>(gridSource); grid.SetSort(volumeColumn, ListSortDirection.Descending); }); // get candle storage var storage = StorateRegistry.GetCandleStorage(typeof(TimeFrameCandle), Security, TimeFrame, format: StorageFormat); // get available dates for the specified period var dates = storage.GetDates(From, To).ToArray(); var rows = new Dictionary <decimal, GridRow>(); foreach (var loadDate in dates) { // check if stopped if (ProcessState != ProcessStates.Started) { break; } // load candles var candles = storage.Load(loadDate); // groupping candles by candle's middle price var groupedCandles = candles.GroupBy(c => c.LowPrice + c.GetLength() / 2); foreach (var group in groupedCandles.OrderBy(g => g.Key)) { // check if stopped if (ProcessState != ProcessStates.Started) { break; } var price = group.Key; // calc total volume for the specified time frame var sumVol = group.Sum(c => c.TotalVolume); var row = rows.TryGetValue(price); if (row == null) { // new price level rows.Add(price, row = new GridRow { Price = price, Volume = sumVol }); // draw on chart chartSeries.Append((double)price, (double)sumVol); // draw on table gridSeries.Add(row); } else { // update existing price level row.Volume += sumVol; // update chart chartSeries.Update((double)price, (double)row.Volume); } } chart.GuiAsync(() => { // update grid sorting grid.RefreshSort(); // scale chart chart.ZoomExtents(); }); } // notify the script stopped Stop(); }
/// <summary> /// Анализировать. /// </summary> protected override void OnAnalyze() { var chart = Chart; var grid = Grid; var chartSeries = new XyDataSeries <double, double>(); ThreadSafeObservableCollection <GridRow> gridSeries = null; chart.GuiSync(() => { // очищаем данные с предыдущего запуска скрипта chart.RenderableSeries.Clear(); grid.Columns.Clear(); chart.RenderableSeries.Add(new FastColumnRenderableSeries { ResamplingMode = ResamplingMode.None, DataPointWidth = 1, SeriesColor = Colors.Chocolate, DataSeries = chartSeries }); chart.XAxis = new NumericAxis { AxisTitle = LocalizedStrings.Str123 }; chart.YAxis = new NumericAxis { AxisTitle = LocalizedStrings.Str87, GrowBy = new DoubleRange(0, 0.1) }; grid.AddTextColumn("Price", LocalizedStrings.Str123).Width = 150; var volumeColumn = grid.AddTextColumn("Volume", LocalizedStrings.Str87); volumeColumn.Width = 100; var gridSource = new ObservableCollectionEx <GridRow>(); grid.ItemsSource = gridSource; gridSeries = new ThreadSafeObservableCollection <GridRow>(gridSource); grid.SetSort(volumeColumn, ListSortDirection.Descending); }); // получаем хранилище свечек var storage = StorateRegistry.GetCandleStorage(typeof(TimeFrameCandle), Security, TimeFrame, format: StorageFormat); // получаем набор доступных дат за указанный период var dates = storage.GetDates(From, To).ToArray(); var rows = new Dictionary <decimal, GridRow>(); foreach (var loadDate in dates) { // проверяем флаг остановки if (ProcessState != ProcessStates.Started) { break; } // загружаем свечки var candles = storage.Load(loadDate); // группируем свечки по цене (середина свечи) var groupedCandles = candles.GroupBy(c => c.LowPrice + c.GetLength() / 2); foreach (var group in groupedCandles.OrderBy(g => g.Key)) { // проверяем флаг остановки if (ProcessState != ProcessStates.Started) { break; } var price = group.Key; // получаем суммарный объем в пределах ценового уровня за день var sumVol = group.Sum(c => c.TotalVolume); var row = rows.TryGetValue(price); if (row == null) { // пришел новый уровень - добавляем новую запись rows.Add(price, row = new GridRow { Price = price, Volume = sumVol }); // выводим на график chartSeries.Append((double)price, (double)sumVol); // выводит в таблицу gridSeries.Add(row); } else { // увеличиваем суммарный объем row.Volume += sumVol; // обновляем график chartSeries.Update((double)price, (double)row.Volume); } } chart.GuiAsync(() => { // обновление сортировки в таблице grid.RefreshSort(); // автомасштабирование графика chart.ZoomExtents(); }); } // оповещаем программу об окончании выполнения скрипта base.Stop(); }
/// <summary> /// To analyze. /// </summary> protected override void OnAnalyze() { var chart = Chart; var grid = Grid; var chartSeries = new XyDataSeries<double, double>(); ThreadSafeObservableCollection<GridRow> gridSeries = null; chart.GuiSync(() => { // очищаем данные с предыдущего запуска скрипта chart.RenderableSeries.Clear(); grid.Columns.Clear(); chart.RenderableSeries.Add(new FastColumnRenderableSeries { ResamplingMode = ResamplingMode.None, DataPointWidth = 1, SeriesColor = Colors.Chocolate, DataSeries = chartSeries }); chart.XAxis = new NumericAxis { AxisTitle = LocalizedStrings.Price }; chart.YAxis = new NumericAxis { AxisTitle = LocalizedStrings.Volume, GrowBy = new DoubleRange(0, 0.1) }; grid.AddTextColumn("Price", LocalizedStrings.Price).Width = 150; var volumeColumn = grid.AddTextColumn("Volume", LocalizedStrings.Volume); volumeColumn.Width = 100; var gridSource = new ObservableCollectionEx<GridRow>(); grid.ItemsSource = gridSource; gridSeries = new ThreadSafeObservableCollection<GridRow>(gridSource); grid.SetSort(volumeColumn, ListSortDirection.Descending); }); // получаем хранилище свечек var storage = StorateRegistry.GetCandleStorage(typeof(TimeFrameCandle), Security, TimeFrame, format: StorageFormat); // получаем набор доступных дат за указанный период var dates = storage.GetDates(From, To).ToArray(); var rows = new Dictionary<decimal, GridRow>(); foreach (var loadDate in dates) { // проверяем флаг остановки if (ProcessState != ProcessStates.Started) break; // загружаем свечки var candles = storage.Load(loadDate); // группируем свечки по цене (середина свечи) var groupedCandles = candles.GroupBy(c => c.LowPrice + c.GetLength() / 2); foreach (var group in groupedCandles.OrderBy(g => g.Key)) { // проверяем флаг остановки if (ProcessState != ProcessStates.Started) break; var price = group.Key; // получаем суммарный объем в пределах ценового уровня за день var sumVol = group.Sum(c => c.TotalVolume); var row = rows.TryGetValue(price); if (row == null) { // пришел новый уровень - добавляем новую запись rows.Add(price, row = new GridRow { Price = price, Volume = sumVol }); // выводим на график chartSeries.Append((double)price, (double)sumVol); // выводит в таблицу gridSeries.Add(row); } else { // увеличиваем суммарный объем row.Volume += sumVol; // обновляем график chartSeries.Update((double)price, (double)row.Volume); } } chart.GuiAsync(() => { // обновление сортировки в таблице grid.RefreshSort(); // автомасштабирование графика chart.ZoomExtents(); }); } // оповещаем программу об окончании выполнения скрипта base.Stop(); }
private void HandleTicks(List <Tick> list) { List <Tick> ticks = new List <Tick>(); try { ticks = list.FindAll(i => i.Board == Board && i.Seccode == Seccode && DateTime.Parse(i.Tradetime) > _lastCandle.TradeTime); } catch { if (_lastCandle == null) { return; } } if (ticks.Count == 0) { return; } foreach (var tick in ticks) { var tickTime = DateTime.Parse(tick.Tradetime); try { if ((tickTime - _lastCandle.TradeTime).TotalMinutes >= _timeframe) { if (OhlcDataSeries == null) { OhlcDataSeries = new OhlcDataSeries <DateTime, double>(); } if (XyDataSeries == null) { XyDataSeries = new XyDataSeries <DateTime, int>(); } OhlcDataSeries.Append(tickTime, tick.Price, tick.Price, tick.Price, tick.Price); XyDataSeries.Append(tickTime, (int)tick.Price); _lastCandle = new Candle //init last candle { Time = tick.Tradetime, Open = tick.Price, High = tick.Price, Low = tick.Price, Close = tick.Price }; } else //else we update the last one { //if (_lastCandle.Close == tick.Price) //{ // continue; //} _lastCandle.Close = tick.Price; _lastCandle.High = _lastCandle.High < tick.Price ? tick.Price : _lastCandle.High; _lastCandle.Low = _lastCandle.Low > tick.Price ? tick.Price : _lastCandle.Low; if (Board == "FUT") { _lastCandle.Volume++; } else { _lastCandle.Volume += (int)tick.Price; } OhlcDataSeries?.Update(OhlcDataSeries.Count - 1, _lastCandle.Open, _lastCandle.High, _lastCandle.Low, _lastCandle.Close); XyDataSeries?.Update(XyDataSeries.Count - 1, _lastCandle.Volume); } } catch (Exception) { if (_lastCandle == null) { return; } throw; } } }