Exemple #1
0
        protected virtual void SetPricingVol(PricingResult result, IOption option, IMarketCondition market)
        {
            var vol = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                            exerciseDate: option.ExerciseDates.Last(), option: option, spot: market.SpotPrices.Value.Values.First());

            result.PricingVol = vol;
        }
Exemple #2
0
        //Precise TimeValue Optiong Pricing Mode:
        // if nightMarket,
        // T0,  <12:00, T = original T + 2/3
        // T0,  >12:00  && <15:00,  T = original T + 1/3
        // T0,  >=15:00 && <21:00,  T = original T
        // T0,  >=21:00,  T = original T (nightMarket)
        // if noNightMarket
        // T0,  <12:00,  T = orignal T + 1
        // T0,  >12:00 && <15:00,  T = original T +  1/2
        // T0,  >= 15:00,  T = original T

        /// <summary>
        /// 计算期权现值
        /// </summary>
        /// <param name="option">期权</param>
        /// <param name="markets">市场</param>
        /// <returns>计算结果</returns>
        public virtual double[] CalcPvs(IOption option, IMarketCondition[] markets)
        {
            var timeIncrement = AnalyticalOptionPricerUtil.optionTimeToMaturityIncrement(option);

            return(markets.Select(x => {
                if (x.ValuationDate == option.ExerciseDates.Last())
                {
                    return CalcIntrinsicValue(option, x);
                }
                else
                {
                    return CalcPv(option, x, timeIncrement);
                }
            }).ToArray());
        }
Exemple #3
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));
        }
        /// <summary>
        /// 计算期权现值
        /// </summary>
        /// <param name="option">期权</param>
        /// <param name="markets">市场</param>
        /// <returns>计算结果</returns>
        public override double[] CalcPvs(IOption option, IMarketCondition[] markets)
        {
            if (AnalyticalOptionPricerUtil.isForwardFuturesOption(option.UnderlyingProductType))
            {
                //market = market.UpdateCondition(new UpdateMktConditionPack<Dictionary<string, IYieldCurve>>(m => m.DividendCurves, new Dictionary<string, IYieldCurve> { { "", market.DiscountCurve.Value} }));
                markets = markets.Select(x =>
                                         x.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, IYieldCurve> >(m => m.DividendCurves, new Dictionary <string, IYieldCurve> {
                    { "", x.DiscountCurve.Value }
                }))
                                         ).ToArray();
            }
            var stochasticProcesses = CreateStochasticProcess1Ds(option, markets);
            var nProcess            = stochasticProcesses.Length;

            var partitioner    = Partitioner.Create(0, NumSimulations, NumSimulations / ParallelDegrees + 1);
            var partitionerPvs = Enumerable.Range(0, nProcess).Select(x => new List <double>()).ToArray();

            var parallelOption = new ParallelOptions()
            {
                MaxDegreeOfParallelism = ParallelDegrees
            };

            var size = option.ObservationDates.Length * 2 + 3;

            List <double>[] result = null;
            if (MonteCarloCollectPath)
            {
                result = new List <double> [NumSimulations + 1];
            }


            Parallel.ForEach(partitioner, parallelOption,
                             (range, loopState) =>
            {
                var pvs    = Enumerable.Range(0, nProcess).Select(x => new List <double>()).ToArray();
                var random = new MersenneTwister();

                for (var n = range.Item1; n < range.Item2; ++n)
                {
                    var paths = PathGenerator.GeneratePath(stochasticProcesses,
                                                           markets.Select(x => x.SpotPrices.Value.Values.First()).ToArray(),
                                                           markets.Select(x => x.ValuationDate.Value).ToArray(),
                                                           option.ObservationDates,
                                                           option.Calendar,
                                                           option.DayCount,
                                                           random);

                    for (var i = 0; i < nProcess; ++i)
                    {
                        pvs[i].Add(
                            option.GetPayoff(paths[i]).Sum(cf => cf.PaymentAmount * markets[i].DiscountCurve.Value.GetDf(markets[i].ValuationDate.Value, cf.PaymentDate))
                            );

                        //pvs[i].Add(option.GetPayoff(paths[i]).Sum(cf => cf.PaymentAmount * market.DiscountCurve.Value.GetDf(market.ValuationDate.Value, cf.PaymentDate)));
                    }


                    //antithetic path
                    for (var i = 0; i < nProcess; ++i)
                    {
                        pvs[i].Add(option.GetPayoff(paths[i + nProcess]).Sum(cf => cf.PaymentAmount * markets[i].DiscountCurve.Value.GetDf(markets[i].ValuationDate.Value, cf.PaymentDate)));
                        //pvs[i].Add(option.GetPayoff(paths[i + nProcess]).Sum(cf => cf.PaymentAmount * market.DiscountCurve.Value.GetDf(market.ValuationDate.Value, cf.PaymentDate)));
                    }

                    if (MonteCarloCollectPath)
                    {
                        var originalPathPrices = from e in paths[0].ToList() orderby e.Key select e.Value;

                        //original path price evolution
                        //result[n].AddRange(prices.ToList());
                        result[n] = originalPathPrices.ToList();
                        //pv
                        result[n].Add(pvs[0].First());

                        var antiPathPrices = from e in paths[1].ToList() orderby e.Key select e.Value;

                        //antipath  price evolution
                        result[n].AddRange(antiPathPrices);
                        //pv
                        result[n].Add(pvs[0].Last());

                        //expected pv
                        result[n].Add(pvs[0].Average());
                    }
                }

                lock (partitionerPvs)
                {
                    for (var i = 0; i < nProcess; ++i)
                    {
                        partitionerPvs[i].Add(pvs[i].Average());
                    }
                }

                //
            });
            if (MonteCarloCollectPath)
            {
                result[NumSimulations] = Enumerable.Repeat(0.0, 2 * (option.ObservationDates.Length + 1)).ToList();
                result[NumSimulations].Add(partitionerPvs[0].Average());
                var resultStr = result.Select(digits => string.Join(",", digits)).ToArray();
                var folder    = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                var filename  = folder + "/MonteCarlo.csv";
                File.WriteAllLines(filename, resultStr);
            }

            //return partitionerPvs[0].Average();
            return(partitionerPvs.Select(x => x.Average()).ToArray());
        }