/// <summary> /// Data updates /// </summary> private async Task OnData() { // Get price var instrument = (await DataService .GetInstruments(Chains.Select(o => o.Symbol).ToList())) .FirstOrDefault() .Value; if (instrument == null) { return; } // Get chains var optionQueries = Chains.Select(chain => { var inputs = new Dictionary <dynamic, dynamic> { ["greeks"] = Variance, ["symbol"] = chain.Symbol, ["expiration"] = chain.Expiration }; return(DataService.GetOptionChain(inputs)); }); var options = (await Task .WhenAll(optionQueries)) .SelectMany(o => o) .GroupBy(o => o.Strike) .ToDictionary(o => o.Key, o => o.Where(v => Where(v)).ToList()) .OrderBy(o => o.Key) .ToList(); // Find the current strike var closeIndex = -1; var closeDistance = double.MaxValue; for (var i = 0; i < options.Count; i++) { var distance = Math.Abs(instrument.Point.Price.Value - options[i].Key.Value); if (closeDistance > distance) { closeIndex = i; closeDistance = distance; } } if (closeIndex < 0) { return; } // Aggregate around the current strike var index = 0; var minSum = 0.0; var maxSum = 0.0; var currentPrice = instrument.Point.Price.Value; var summaries = new InstrumentOptionModel[options.Count]; var sources = new Dictionary <string, ISeriesModel>(); while (true) { var curMins = options.ElementAtOrDefault(closeIndex - index); var curMaxs = options.ElementAtOrDefault(closeIndex + index); if (curMins.Value == null && curMaxs.Value == null) { break; } if (curMins.Value != null) { minSum += SelectMany(curMins.Value, curMins.Key, currentPrice).Value; summaries[closeIndex - index] = new InstrumentOptionModel { Strike = curMins.Key, Side = OptionSideEnum.Put, Point = new Core.ModelSpace.PointModel { Price = minSum } }; } if (curMaxs.Value != null) { maxSum += SelectMany(curMaxs.Value, curMaxs.Key, currentPrice).Value; summaries[closeIndex + index] = new InstrumentOptionModel { Strike = curMaxs.Key, Side = OptionSideEnum.Call, Point = new Core.ModelSpace.PointModel { Price = maxSum } }; } index++; } // Create points with values for each expiration var points = summaries.Select(o => { var strike = o.Strike; var series = new Dictionary <string, ISeriesModel>(); var seriesColor = Brushes.Black.Color; var seriesName = "Aggregation"; switch (o.Side) { case OptionSideEnum.Put: seriesColor = Brushes.OrangeRed.Color; break; case OptionSideEnum.Call: seriesColor = Brushes.LimeGreen.Color; break; } sources[seriesName] = series[seriesName] = new SeriesModel { Name = seriesName, Shape = new BarSeries(), Model = new ExpandoModel { ["Color"] = seriesColor, ["Point"] = o.Point.Price } }; // Create point with all series var point = new Chart.ModelSpace.PointModel() { Areas = new Dictionary <string, IAreaModel> { [_name] = new AreaModel { Name = _name, Series = series } } }; point["Strike"] = strike; return(point as Chart.ModelSpace.IPointModel); }).ToList(); // Set appropriate number of series on the chart if (sources.Any()) { View.Composer.Group.Series = sources; } await Dispatcher.BeginInvoke(new Action(() => { var composer = View.Composer; composer.IndexDomain ??= new int[2]; composer.IndexDomain[0] = 0; composer.IndexDomain[1] = options.Count; composer.Items = _points = points.ToList(); composer.Update(); })); }
/// <summary> /// Data updates /// </summary> private async Task OnData() { // Get price var instrument = (await DataService .GetInstruments(Chains.Select(o => o.Symbol).ToList())) .FirstOrDefault() .Value; if (instrument == null) { return; } // Get chains var optionQueries = Chains.Select(chain => { var inputs = new Dictionary <dynamic, dynamic> { ["greeks"] = Variance, ["symbol"] = chain.Symbol, ["expiration"] = chain.Expiration }; return(DataService.GetOptionChain(inputs)); }); var options = (await Task .WhenAll(optionQueries)) .SelectMany(o => o) .GroupBy(o => o.Strike) .ToDictionary(o => o.Key, o => o.Where(v => Where(v)).ToList()) .OrderBy(o => o.Key) .ToList(); // Create points with values for each expiration var currentPrice = instrument.Point.Price.Value; var sources = new Dictionary <string, ISeriesModel>(); var points = options.Select(o => { var strike = o.Key; var strikeOptions = o.Value; var series = new Dictionary <string, ISeriesModel>(); // Create series based on option side and specified expirations foreach (var option in strikeOptions) { var seriesColor = Brushes.Black.Color; var seriesName = $"{option.Side} - {option.ExpirationDate:yyyy-MM-dd}"; switch (option.Side.Value) { case OptionSideEnum.Put: seriesColor = Brushes.OrangeRed.Color; break; case OptionSideEnum.Call: seriesColor = Brushes.LimeGreen.Color; break; } sources[seriesName] = series[seriesName] = new SeriesModel { Name = seriesName, Shape = new BarSeries(), Model = new ExpandoModel { ["Color"] = seriesColor, ["Point"] = Select(option, currentPrice) } }; } // Create point with all series var point = new Chart.ModelSpace.PointModel() { Areas = new Dictionary <string, IAreaModel> { [_name] = new AreaModel { Name = _name, Series = series } } }; point["Strike"] = strike; return(point as Chart.ModelSpace.IPointModel); }).ToList(); // Set appropriate number of series on the chart if (sources.Any()) { View.Composer.Group.Series = sources; } await Dispatcher.BeginInvoke(new Action(() => { var composer = View.Composer; composer.IndexDomain ??= new int[2]; composer.IndexDomain[0] = 0; composer.IndexDomain[1] = options.Count; composer.Items = _points = points.ToList(); composer.Update(); })); }