/// <summary> /// Get options chain /// </summary> /// <param name="inputs"></param> /// <returns></returns> public override async Task <IList <IInstrumentOptionModel> > GetOptionChains(IDictionary <dynamic, dynamic> inputs) { var options = new List <IInstrumentOptionModel>(); var response = await GetResponse <InputOptionChainDataModel>($"/v1/markets/options/chains", inputs); foreach (var inputOption in response?.Chains?.Chain ?? new List <InputOptionModel>()) { var pointModel = new PointModel { Bid = inputOption.Bid, Ask = inputOption.Ask, Price = inputOption.Last, BidSize = inputOption.BidSize, AskSize = inputOption.AskSize }; var optionModel = new InstrumentOptionModel { Point = pointModel, Strike = inputOption.Strike, Volume = inputOption.Volume, AverageVolume = inputOption.AverageVolume, ContractSize = inputOption.ContractSize, OpenInterest = inputOption.OpenInterest, ExpirationDate = inputOption.ExpirationDate, Side = OptionTypeMap.Input(inputOption.OptionType), Variance = new InstrumentOptionVarianceModel { Vega = inputOption.Greeks.Vega, Delta = inputOption.Greeks.Delta, Gamma = inputOption.Greeks.Gamma, Theta = inputOption.Greeks.Theta, Interest = inputOption.Greeks.Rho, Distribution = inputOption.Greeks.Phi, AskIv = inputOption.Greeks.AskIv, BidIv = inputOption.Greeks.BidIv, Iv = inputOption.Greeks.Iv } }; options.Add(optionModel); } return(options); }
/// <summary> /// Get options chain /// </summary> /// <param name="inputs"></param> /// <returns></returns> protected async Task <IList <IInstrumentOptionModel> > GetOptionsChain(dynamic inputs) { var options = new List <IInstrumentOptionModel>(); var response = await GetResponse <InputOptionItemModel>($"/v1/markets/options/chains"); foreach (var inputOption in response.Options) { var optionModel = new InstrumentOptionModel { Bid = inputOption.Bid, Ask = inputOption.Ask, Price = inputOption.Last, Strike = inputOption.Strike }; options.Add(optionModel); } return(options); }
/// <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(); })); }