Example #1
0
        private double DoCalcPv(IOption option, IMarketCondition market, double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var valueDate     = market.ValuationDate;
            var dayCount      = market.DiscountCurve.Value.DayCount;
            var exerciseDates = option.ExerciseDates.Where(x => x >= market.ValuationDate).ToArray();
            var tExStart      = dayCount.CalcDayCountFraction(valueDate, exerciseDates[0]) + timeIncrement;
            var tExEnd        = dayCount.CalcDayCountFraction(valueDate, exerciseDates.Last()) + timeIncrement;

            if (!double.IsNaN(expiryDayRemainingLife))
            {
                tExEnd = expiryDayRemainingLife;
            }

            var spot = market.SpotPrices.Value.Values.First();

            Tuple <Date, double>[] dividends = (option.Dividends != null)? option.Dividends.Select(x => new Tuple <Date, double>(x.Key, x.Value)).ToArray(): null;
            if (dividends != null)
            {
                Array.Sort(dividends, (o1, o2) => o1.Item1.CompareTo(o2.Item1));
            }
            var sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                              exerciseDate: option.ExerciseDates.Last(), option: option, spot: spot);
            //Notional is been considered during simulation.
            var fa = BinomialDiscreteDividends(option, market,
                                               market.ValuationDate,
                                               dayCount: market.DiscountCurve.Value.DayCount,
                                               spotPrice: market.SpotPrices.Value.Values.First(),
                                               r: market.DiscountCurve.Value.ZeroRate(market.ValuationDate, option.ExerciseDates.Last()),
                                               v: sigma,
                                               dividends: dividends,
                                               steps: _steps,
                                               tStart: tExStart,
                                               tEnd: tExEnd);

            var option2   = option.Clone(OptionExercise.European);
            var bsmEngine = new AnalyticalVanillaEuropeanOptionEngine();

            //if cash dividends, then annualize it to equivalent dividend yield
            //var diviFraction = dayCount.CalcDayCountFraction(option.StartDate, option.ExerciseDates.Last());
            //var eqvDividendYield = (dividends ==null)? 0.0: dividends.Select(x => x.Item2).Sum() / spot / diviFraction;
            //var eqvDividendCurve = new YieldCurve(
            //    "dividend",
            //    valueDate,
            //    new[]
            //    {
            //        Tuple.Create((ITerm)new Term("1D"), eqvDividendYield),
            //        Tuple.Create((ITerm)new Term("1Y"), eqvDividendYield)
            //    },
            //    BusinessDayConvention.ModifiedFollowing,
            //    dayCount,
            //    market.DividendCurves.Value.First().Value.Calendar,
            //    CurrencyCode.CNY,
            //    Compound.Continuous,
            //    Interpolation.CubicHermiteMonotic,
            //    YieldCurveTrait.SpotCurve
            //    );

            //var eqvMarket = market.UpdateDividendCurve(eqvDividendCurve, market.DividendCurves.Value.First().Key);

            var fbsm = bsmEngine.Calculate(option2, market, PricingRequest.Pv).Pv;

            var fe = BinomialDiscreteDividends(option2, market,
                                               market.ValuationDate,
                                               dayCount: market.DiscountCurve.Value.DayCount,
                                               spotPrice: spot,
                                               r: market.DiscountCurve.Value.ZeroRate(market.ValuationDate, option.ExerciseDates.Last()),
                                               v: sigma,
                                               dividends: dividends,
                                               steps: _steps,
                                               tStart: tExStart,
                                               tEnd: tExEnd);

            //control variate
            //fa + ( fbsm - fe)
            return(fa + (fbsm - fe));
        }