private void AddJointOption( Dictionary <DateTime, Dictionary <DateTime, Dictionary <double, ISingleAssetOption> > > referenceDictionary, ISingleAssetOption referenceOption, ref List <ISingleAssetOption> listOfJointOption) { if (!referenceDictionary.ContainsKey(referenceOption.ValuationDate) || !referenceDictionary[referenceOption.ValuationDate].ContainsKey(referenceOption.Maturity) || !referenceDictionary[referenceOption.ValuationDate][referenceOption.Maturity] .ContainsKey(referenceOption.Strike)) { return; } SingleAssetOption optionDiffPremium; if (referenceOption.OptionType == eOptionType.C) { optionDiffPremium = new SingleAssetOption { StockPrice = referenceOption.StockPrice, Currency = referenceOption.Currency, DiscountFactor = referenceOption.DiscountFactor, DividendDiscountFactor = referenceOption.DividendDiscountFactor, Maturity = referenceOption.Maturity, Premium = referenceOption.Premium - referenceDictionary[referenceOption.ValuationDate][referenceOption.Maturity][ referenceOption.Strike].Premium, Strike = referenceOption.Strike } } ; else { optionDiffPremium = new SingleAssetOption { StockPrice = referenceOption.StockPrice, Currency = referenceOption.Currency, DiscountFactor = referenceOption.DiscountFactor, DividendDiscountFactor = referenceOption.DividendDiscountFactor, Maturity = referenceOption.Maturity, Premium = referenceDictionary[referenceOption.ValuationDate][referenceOption.Maturity][ referenceOption.Strike].Premium - referenceOption.Premium, Strike = referenceOption.Strike } }; listOfJointOption.Add(optionDiffPremium); }
public double NetPresentValue(DateTime valuationDate, ISingleAssetOption option, double underlyingPrice, double discountFactor = 1d, double dividendDiscountFactor = 1d) { var forwardPrice = underlyingPrice * dividendDiscountFactor / discountFactor; var strike = option.Strike; var tenor = (option.Maturity - option.ValuationDate).TotalDays / 365.0; var intrinsicValue = option.OptionType == eOptionType.C ? forwardPrice - strike : strike - forwardPrice; if (intrinsicValue <= 0.0 && option.OptionType == eOptionType.C) { return(discountFactor * NetOtmCallValueNormalized(option.ImpliedVolatility, forwardPrice, strike, tenor) * Math.Sqrt(forwardPrice * strike)); } if (intrinsicValue >= 0.0 && option.OptionType == eOptionType.P) { return(discountFactor * NetOtmPutValueNormalized(option.ImpliedVolatility, forwardPrice, strike, tenor) * Math.Sqrt(forwardPrice * strike)); } if (intrinsicValue > 0.0 && option.OptionType == eOptionType.C) { return(discountFactor * intrinsicValue + this.NetOtmPutValueNormalized(option.ImpliedVolatility, forwardPrice, strike, tenor)); } if (intrinsicValue < 0.0 && option.OptionType == eOptionType.P) { return(discountFactor * intrinsicValue + this.NetOtmCallValueNormalized(option.ImpliedVolatility, forwardPrice, strike, tenor)); } return(0.0); }
/// <summary> /// Determine the volatility underlying the option price. /// </summary> /// <param name="valuationTime">The valuation time.</param> /// <param name="optionPrice">Option price.</param> /// <param name="underlyingPrice">Underlying price.</param> /// <param name="volatilitySurface">The volatility surface.</param> /// <returns>System.Double.</returns> public double Volatility(DateTime valuationDate, ISingleAssetOption option, double underlyingPrice, double discountFactor = 1d, double dividendDiscountFactor = 1d) { var tenor = (option.Maturity - valuationDate).TotalDays / 365.0; //Get strike var strike = option.Strike; //Get option price var price = option.Premium; //Get forward price var forwardPrice = underlyingPrice * dividendDiscountFactor / discountFactor; //Get discounted strike var discountedStrike = dividendDiscountFactor * option.Strike; var discountedSpot = underlyingPrice * dividendDiscountFactor; //Get put call indicator int q; if (option.OptionType == eOptionType.C) { q = 1; } else { q = -1; } //Calculate intrinsic value var intrinsicValue = Math.Max(q < 0 ? strike - forwardPrice : forwardPrice - strike, 0.0); //Check if price is below intrinsic if (price <= intrinsicValue) { return(double.NaN); } //Check if price is above maximum price var maxPrice = q < 0 ? strike : forwardPrice; if (price >= maxPrice) { return(double.NaN); } //Get moneyness var moneyness = Math.Log(forwardPrice / strike); if (!(intrinsicValue > 0.0)) { return(UncheckedNormalizedImpliedVolatility(price / (Math.Sqrt(forwardPrice) * Math.Sqrt(strike)), moneyness, q, MaximumIterations) / Math.Sqrt(tenor)); } // Map in-the-money to out-of-the-money // price = Math.Max(price - intrinsicValue, 0.0); //** Original Code** price = q < 0 ? Math.Max(price + discountedSpot - discountedStrike, 0.0) : Math.Max(price - discountedSpot + discountedStrike, 0.0); //Check if price is above maximum price maxPrice = q > 0 ? strike : forwardPrice; if (price >= maxPrice) { return(double.NaN); } //Calculate intrinsic value intrinsicValue = Math.Max(q > 0 ? strike - forwardPrice : forwardPrice - strike, 0.0); //Check if price is below intrinsic if (price <= intrinsicValue) { return(double.NaN); } return(UncheckedNormalizedImpliedVolatility(price / (Math.Sqrt(forwardPrice) * Math.Sqrt(strike)), moneyness, -q, MaximumIterations) / Math.Sqrt(tenor)); }