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);
        }
Exemplo n.º 3
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));
        }