Your search did not match any results.
Charts

SignalR Service

This example demonstrates real-time data update in a financial chart bound to a SignalR server. Note that data used in this demo is for demonstration purposes only.

@(Html.DevExtreme().Chart() .ID("chart") .Title("Stock Price") .Series(s => { s.Add() .Type(SeriesType.Candlestick) .ArgumentField("date") .Aggregation(a => a.Enabled(true) .Calculate((@<text> function(e){ var prices = e.data.map(function(i) { return i.price; }); if (prices.length) { return { date: e.intervalStart, open: prices[0], high: Math.max.apply(null, prices), low: Math.min.apply(null, prices), close: prices[prices.length - 1] }; } } </text>)) .Method(ChartSeriesAggregationMethod.Custom)); }) .ArgumentAxis(a => a.ArgumentType(ChartDataType.DateTime) .ValueMarginsEnabled(false) .VisualRange(v => v.Length(VizTimeInterval.Hour)) ) .Legend(l=>l.Visible(false)) .ValueAxis(v => v.Add().PlaceholderSize(50)) .Margin(m => m.Right(30)) .ScrollBar(s=>s.Visible(true)) .OnZoomEnd(@<text> function(e){ if (e.range.endValue - e.range.startValue < 1000 * 60 * 10) { e.cancel = true; } } </text>) .ZoomAndPan(z=>z.ArgumentAxis(ChartZoomAndPanMode.Both)) ) <script src="~/signalr/signalr-client.js"></script> <script> var connection = new signalR.HubConnectionBuilder() .withUrl("@Url.Content("~/stockTickDataHub")") .configureLogging(signalR.LogLevel.Information) .build(); $(function () { connection.start() .then(function () { var store = new DevExpress.data.CustomStore({ load: function () { return connection.invoke("getAllData"); }, key: "date" }); $("#chart").dxChart({ dataSource: store }); connection.on("updateStockPrice", function (data) { store.push([{ type: "insert", key: data.date, data: data }]); }); }); }); </script>
using DevExtreme.AspNet.Data; using DevExtreme.AspNet.Mvc; using DevExtreme.NETCore.Demos.Models; using DevExtreme.NETCore.Demos.Models.SampleData; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System; using System.Collections.Generic; namespace DevExtreme.NETCore.Demos.Controllers { public class ChartsController : Controller { public ActionResult SignalRService() { return View(); } } }
using System.Collections.Generic; using DevExtreme.NETCore.Demos.Models.SignalRTickData; using Microsoft.AspNetCore.SignalR; namespace DevExtreme.NETCore.Demos.Hubs { public class StockTickDataHub : Hub { private readonly TickDataService _service; public StockTickDataHub(TickDataService service) { _service = service; } public IEnumerable<TickItem> GetAllData() { return _service.GetAllData(); } } }
using DevExtreme.NETCore.Demos.Hubs; using Microsoft.AspNetCore.SignalR; using System; using System.Collections.Generic; using System.Threading; namespace DevExtreme.NETCore.Demos.Models.SignalRTickData { public class TickDataService { private IHubContext<StockTickDataHub> _hubContext { get; set; } private static int currentIndex = 0; private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(1000); private static readonly Random _updateOrNotRandom = new Random(); private readonly Timer _timer; private readonly object _updateStockPricesLock = new object(); static readonly Random random = new Random(); private static decimal[] _data = GeneratePrices(); public TickDataService(IHubContext<StockTickDataHub> hubContext) { _hubContext = hubContext; _timer = new Timer(Update, null, _updateInterval, _updateInterval); } public List<TickItem> GetAllData() { List<TickItem> data = new List<TickItem>(); lock(_updateStockPricesLock) { var time = DateTime.Now; for(var i = currentIndex; data.Count < 10000; i--) { time = time.AddSeconds(-5); data.Add(new TickItem("RND", _data[i], time)); if(i == 0) { i = _data.Length - 1; } } } return data; } private static decimal[] GeneratePrices() { decimal lastPrice = 140; decimal[] data = new decimal[60 * 60 * 20]; for(var i = 0; i < data.Length / 2; i++) { lastPrice = GetNextItem(lastPrice); data[data.Length - i - 1] = data[i] = lastPrice; } return data; } private static decimal GetNextItem(decimal lastPrice) { var volatility = 0.002; var change_percent = 2 * volatility * random.NextDouble(); if(change_percent > volatility) change_percent -= (2 * volatility); var change_amount = lastPrice * (decimal)change_percent; var price = lastPrice + change_amount; return price; } private void Update(object state) { lock(_updateStockPricesLock) { var price = _data[currentIndex]; var item = new TickItem("RND", price, DateTime.Now); BroadcastStockPrice(item); currentIndex++; if(currentIndex > _data.Length - 1) { currentIndex = 0; } } } private void BroadcastStockPrice(TickItem item) { _hubContext.Clients.All.SendAsync("updateStockPrice", item); } } }
using System; namespace DevExtreme.NETCore.Demos.Models.SignalRTickData { public class TickItem { public string Symbol { get; set; } public DateTime Date { get; set; } public decimal Price { get; set; } public TickItem(string symbol, decimal price) { Date = DateTime.Now; Symbol = symbol; Price = price; } public TickItem(string symbol, decimal price, DateTime date) { Symbol = symbol; Price = price; Date = date; } } }
#chart { height: 440px; }