public void CalculateImpliedVolatility(string ammOptionsFile, string underlyingsMarketDataFile, string optionsMarketDataFile, double daysToMaturity, double riskFreeRate, ref VolSurface volSurface) { double workingDaysInTheYear = 252; double timeToMaturity = daysToMaturity / workingDaysInTheYear; Dictionary <string, OptionInfo> allAvailableOptions = this.ListAllAvailableOptions(ammOptionsFile); Dictionary <string, OrderBook> underlyingsMarketData = this.GetMarketData(underlyingsMarketDataFile); Dictionary <string, OrderBook> optionsMarketData = this.GetMarketData(optionsMarketDataFile); foreach (var pair in optionsMarketData) { OrderBook optionOrderBook = pair.Value; OptionInfo option = null; if (allAvailableOptions.TryGetValue(optionOrderBook.Name, out option)) { OrderBook underlyingOrderBook = null; if (underlyingsMarketData.TryGetValue(option.Underlying, out underlyingOrderBook)) { double spot = underlyingOrderBook.GetPriceMid(); double bid = (optionOrderBook.Bid != null) ? optionOrderBook.Bid.Value : 0.00; double bidSize = (optionOrderBook.BidSize != null) ? optionOrderBook.BidSize.Value : 0.00;; double ask = (optionOrderBook.Ask != null) ? optionOrderBook.Ask.Value : 0.00;; double askSize = (optionOrderBook.AskSize != null) ? optionOrderBook.AskSize.Value : 0.00;; BlackScholes bs = new BlackScholes(); double bidImpliedVolatility = 0.00; double askImpliedVolatility = 0.00; if (bid > 0.00 && bidSize > 0.00) { bidImpliedVolatility = bs.GetImpliedVolatility(option.Type, bid, spot, option.Strike, riskFreeRate, timeToMaturity); } if (ask > 0.00 && askSize > 0.00) { askImpliedVolatility = bs.GetImpliedVolatility(option.Type, ask, spot, option.Strike, riskFreeRate, timeToMaturity); } if (!(bidImpliedVolatility > 0.0000)) { bidImpliedVolatility = 0.00; } if (!(askImpliedVolatility > 0.0000)) { askImpliedVolatility = 0.00; } VolQuote volQuote = new VolQuote(bidSize, askSize, bidImpliedVolatility, askImpliedVolatility); volSurface.Update(option.ExpiryDate, option.Strike, option.Type, volQuote); } } } }
private VolSurface GetVolSurface(SortedDictionary <DateTime, RiskFreeRate> riskFreeRates, OrderBook underlyingOrderBook, List <OptionMarketData> optionsMarketData) { double businessDaysInTheYear = 252; VolSurface volSurface = new VolSurface(); double spot = underlyingOrderBook.GetPriceMid(); foreach (OptionMarketData option in optionsMarketData) { RiskFreeRate riskFreeRate = null; riskFreeRates.TryGetValue(option.OptionInfo.ExpiryDate, out riskFreeRate); double timeToMaturity = riskFreeRate.BusinessDays / businessDaysInTheYear; double bid = (option.OrderBook.Bid != null) ? option.OrderBook.Bid.Value : 0.00; double bidSize = (option.OrderBook.BidSize != null) ? option.OrderBook.BidSize.Value : 0.00;; double ask = (option.OrderBook.Ask != null) ? option.OrderBook.Ask.Value : 0.00;; double askSize = (option.OrderBook.AskSize != null) ? option.OrderBook.AskSize.Value : 0.00;; BlackScholes bs = new BlackScholes(); double bidImpliedVolatility = 0.00; double askImpliedVolatility = 0.00; if (bid > 0.00 && bidSize > 0.00) { bidImpliedVolatility = bs.GetImpliedVolatility(option.OptionInfo.Type, bid, spot, option.OptionInfo.Strike, riskFreeRate.Rate, timeToMaturity); } if (ask > 0.00 && askSize > 0.00) { askImpliedVolatility = bs.GetImpliedVolatility(option.OptionInfo.Type, ask, spot, option.OptionInfo.Strike, riskFreeRate.Rate, timeToMaturity); } if (!(bidImpliedVolatility > 0.0000)) { bidImpliedVolatility = 0.00; } if (!(askImpliedVolatility > 0.0000)) { askImpliedVolatility = 0.00; } VolQuote volQuote = new VolQuote(bidSize, askSize, bidImpliedVolatility, askImpliedVolatility); volSurface.Update(option.OptionInfo.ExpiryDate, option.OptionInfo.Strike, option.OptionInfo.Type, volQuote); } return(volSurface); }
private void BuildChart(DateTime expiry) { VolExpiry volExpiry = null; double strikeMin = 9999.00; double strikeMax = 0.00; double volMin = 9999.00; double volMax = 0.00; if (this.VolSurface.VolExpiries.TryGetValue(expiry, out volExpiry)) { foreach (VolStrike volStrike in volExpiry.VolStrikes.Values) { if (volStrike.VolCallQuote != null) { VolQuote volCallQuote = volStrike.VolCallQuote; if (this.IsValid(volCallQuote.BidImpliedVolatility)) { double strike = volStrike.Strike; strikeMin = Math.Min(strikeMin, strike); strikeMax = Math.Max(strikeMax, strike); double vol = volCallQuote.BidImpliedVolatility * 100; volMin = Math.Min(volMin, vol); volMax = Math.Max(volMax, vol); chart1.Series["call_bid"].Points.AddXY(strike, vol); } if (this.IsValid(volCallQuote.AskImpliedVolatility)) { double strike = volStrike.Strike; strikeMin = Math.Min(strikeMin, strike); strikeMax = Math.Max(strikeMax, strike); double vol = volCallQuote.AskImpliedVolatility * 100; volMin = Math.Min(volMin, vol); volMax = Math.Max(volMax, vol); chart1.Series["call_ask"].Points.AddXY(strike, vol); } } if (volStrike.VolPutQuote != null) { VolQuote volPutQuote = volStrike.VolPutQuote; if (this.IsValid(volPutQuote.BidImpliedVolatility)) { double strike = volStrike.Strike; strikeMin = Math.Min(strikeMin, strike); strikeMax = Math.Max(strikeMax, strike); double vol = volPutQuote.BidImpliedVolatility * 100; volMin = Math.Min(volMin, vol); volMax = Math.Max(volMax, vol); chart1.Series["put_bid"].Points.AddXY(strike, vol); } if (this.IsValid(volPutQuote.AskImpliedVolatility)) { double strike = volStrike.Strike; strikeMin = Math.Min(strikeMin, strike); strikeMax = Math.Max(strikeMax, strike); double vol = volPutQuote.AskImpliedVolatility * 100; volMin = Math.Min(volMin, vol); volMax = Math.Max(volMax, vol); chart1.Series["put_ask"].Points.AddXY(strike, vol); } } } } chart1.ChartAreas[0].AxisX.Minimum = Math.Floor(strikeMin); chart1.ChartAreas[0].AxisX.Maximum = Math.Ceiling(strikeMax); chart1.ChartAreas[0].AxisX.Interval = 1; chart1.ChartAreas[0].AxisY.Minimum = Math.Floor(volMin); chart1.ChartAreas[0].AxisY.Maximum = Math.Ceiling(volMax); chart1.ChartAreas[0].AxisY.Interval = 5; }