示例#1
0
        private OneTouchCalculator ConfigureCalculator(IOption option, IMarketCondition market, double timeIncrement = 0.0)
        {
            var trade = (BinaryOption)option;

            var exerciseDate = trade.ExerciseDates.Last();
            var maturityDate = trade.UnderlyingMaturityDate;

            var    riskFreeRate         = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var    riskfreeDfAtExercise = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var    spot  = market.SpotPrices.Value.Values.First();
            double sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                                 exerciseDate: exerciseDate, option: option, spot: spot);

            var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendInput      = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate,
                                                                                    option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount);
            var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskfreeDfAtExercise);

            var exerciseInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade) + timeIncrement;

            var calculator = new OneTouchCalculator(
                trade.BinaryRebateType,
                strike: option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike,
                spotPrice: spot,
                sigma: sigma,
                dividendRate: dividendRate,
                riskFreeRate: riskfreeDfAtExercise,
                cashOrNothingAmount: trade.CashOrNothingAmount,
                exerciseInYears: exerciseInYears,
                underlyingInstrumentType: trade.UnderlyingProductType,
                notional: trade.Notional);

            this._calculator = calculator;
            return(calculator);
        }
示例#2
0
            public OneTouchCalculator(
                BinaryRebateType binaryRebateType,
                double strike,
                double spotPrice,
                double sigma,
                double dividendRate,
                double riskFreeRate,
                double cashOrNothingAmount,
                double exerciseInYears,
                InstrumentType underlyingInstrumentType,
                double notional = 1.0)
            {
                _X                   = strike;
                _S                   = spotPrice;
                _notional            = notional;
                _cashOrNothingAmount = cashOrNothingAmount;
                _sigma               = sigma;
                _T                   = exerciseInYears;
                _binaryRebateType    = binaryRebateType;

                _r                 = riskFreeRate;
                _dividendRate      = dividendRate;
                _isOptionOnFutures = AnalyticalOptionPricerUtil.isFuturesOption(underlyingInstrumentType);
                _isOptionOnForward = AnalyticalOptionPricerUtil.isForwardOption(underlyingInstrumentType);
                _b                 = AnalyticalOptionPricerUtil.costOfCarry(_isOptionOnFutures || _isOptionOnForward, dividendRate, riskFreeRate);
            }
示例#3
0
        public BarrierOptionFourierPvPricer(BarrierOption barrierOption, IMarketCondition market, double timeIncrement = 0.0)
        {
            var exerciseDate    = barrierOption.ExerciseDates.Last();
            var riskFreeRate    = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var spotPrice       = market.SpotPrices.Value.Values.First();
            var vol             = market.VolSurfaces.Value.Values.First().GetValue(market.ValuationDate, barrierOption.Strike, spotPrice);
            var exerciseInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, barrierOption) + timeIncrement;

            _optionType = barrierOption.OptionType;
            _rebate     = barrierOption.Rebate;
            _coupon     = barrierOption.Coupon;
            _K          = barrierOption.Strike;
            _S          = spotPrice;
            _T          = exerciseInYears;
            _v          = vol;
            _r          = riskFreeRate;
            _B          = barrierOption.UpperBarrier;
            _A          = barrierOption.Barrier;

            b  = Math.Log(_B);
            a  = Math.Log(_A);
            x0 = Math.Log(_S);
            v2 = Math.Pow(_v, 2);
            u  = _r - v2 / 2;
            u2 = Math.Pow(u, 2);
        }
示例#4
0
        public Date ImpliedExpiryDate(IOption option, IMarketCondition market, double targetPremium)
        {
            var timeIncrement = AnalyticalOptionPricerUtil.optionTimeToMaturityIncrement(option);
            var calculator    = ConfigureCalculator(option, market, timeIncrement: timeIncrement);

            return(calculator.SolveExpiryDate(targetPremium));
        }
        public BjerksundAndStensland2002Calculator(OptionType optionType, double strike, double spotPrice,
                                                   double maturityInYears, double standardDeviation, double riskFreeRate, double dividendRate,
                                                   double notional, InstrumentType underlyingInstrumentType,
                                                   double riskfreeDfAtExercise, double riskfreeDfAtMaturity,
                                                   double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            _isOptionOnForward = AnalyticalOptionPricerUtil.isForwardOption(underlyingInstrumentType);
            _optionType        = optionType;
            _X = strike;
            _S = spotPrice;
            _T = maturityInYears + timeIncrement;
            if (!double.IsNaN(expiryDayRemainingLife))
            {
                _T = expiryDayRemainingLife;
            }
            _sigma    = standardDeviation;
            _r        = riskFreeRate;
            _dividend = dividendRate;
            _b        = riskFreeRate - dividendRate;
            _notional = notional;

            _riskfreeDfAtExercise   = riskfreeDfAtExercise;
            _riskfreeDfAtMaturity   = riskfreeDfAtMaturity;
            _expiryDayRemainingLife = expiryDayRemainingLife;
        }
示例#6
0
        public double ImpliedVolFromPremium(double targetPremium,
                                            VanillaOption option, MarketCondition market)
        {
            var timeIncrement = AnalyticalOptionPricerUtil.optionTimeToMaturityIncrement(option);
            var calculator    = ConfigureCalculator(option, market, timeIncrement: timeIncrement);

            return(calculator.SolveVol(targetPremium));
        }
示例#7
0
        private AsianOptionCalculator ConfigureCalculator(IOption option, IMarketCondition market,
                                                          double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var trade = (AsianOption)option;

            var exerciseDate       = trade.ExerciseDates.Last();
            var remainingObsDates  = trade.ObservationDates.Where(x => x >= market.ValuationDate).ToArray();
            var numOfObsDates      = trade.ObservationDates.Count();
            var numOfObservedDates = numOfObsDates - remainingObsDates.Count();
            var observedAverage    = trade.Fixings.Any() ? trade.Fixings.Average(x => x.Value) : market.SpotPrices.Value.Values.First();
            //if (trade.Fixings.Count != numOfObservedDates)
            //{
            //    throw new PricingLibraryException("AsianOption: number of fixings does not match!");
            //}

            var    spot  = market.SpotPrices.Value.Values.First();
            double sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                                 exerciseDate: exerciseDate, option: option, spot: spot);

            double t;

            if (!double.IsNaN(expiryDayRemainingLife))
            {
                t = expiryDayRemainingLife;
            }
            else
            {
                t = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade) + timeIncrement;
            }

            var t2 = AnalyticalOptionPricerUtil.timeToMaturityFraction(trade.ObservationDates[0], remainingObsDates.Last(), trade);
            var t1 = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, remainingObsDates[0], trade) + timeIncrement;

            var riskFreeRate       = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendInput      = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate,
                                                                                    option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount);
            var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskFreeRate);

            var calculator = new AsianOptionCalculator(trade.OptionType, trade.AsianType, trade.UnderlyingProductType,
                                                       trade.StrikeStyle,
                                                       strike: option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike,
                                                       spotPrice: spot,
                                                       realizedAveragePrice: observedAverage,
                                                       exerciseInYears: t,
                                                       originalAveragePeriod: t2,
                                                       timetoNextAveragePoint: t1,
                                                       sigma: sigma,
                                                       riskFreeRate: riskFreeRate,
                                                       dividendRate: dividendRate,
                                                       notional: trade.Notional,
                                                       numOfObsDates: numOfObsDates,
                                                       numOfObservedDates: numOfObservedDates);

            this._calculator = calculator;
            return(calculator);
        }
        private BarrierOptionCalculator configureCalculator(IOption option, IMarketCondition market,
                                                            double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var trade        = (BarrierOption)option;
            var exerciseDate = trade.ExerciseDates.Last();
            var maturityDate = trade.UnderlyingMaturityDate;
            var spot         = market.SpotPrices.Value.Values.First();

            double exerciseInYears;

            if (!double.IsNaN(expiryDayRemainingLife))
            {
                exerciseInYears = expiryDayRemainingLife;
            }
            else
            {
                exerciseInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade) + timeIncrement;
            }

            //barrier adjust
            var dt = trade.DayCount.CalcDayCountFraction(trade.ObservationDates.First(), trade.ObservationDates.Last()) /
                     trade.ObservationDates.Length;

            var riskFreeRate           = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var riskfreeRateAtMaturity = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, maturityDate);

            var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendInput      = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate,
                                                                                    option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount);
            var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskFreeRate);

            var vol = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                            exerciseDate: exerciseDate, option: option, spot: spot);

            var barrierCalculator = new BarrierOptionCalculator(
                trade.OptionType,
                trade.BarrierType,
                trade.Rebate,
                trade.IsDiscreteMonitored ? DiscreteAdjustedBarrier(trade.BarrierType, trade.Position, trade.Barrier, vol, dt, trade.BarrierShift) : trade.Barrier,
                trade.IsDiscreteMonitored ? DiscreteAdjustedBarrier(trade.BarrierType, trade.Position, trade.UpperBarrier, vol, dt, trade.BarrierShift) : trade.UpperBarrier,
                option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike,
                spot,
                exerciseInYears,
                vol,
                riskFreeRate,
                dividendRate,
                valuationDate: market.ValuationDate,
                exerciseDate: exerciseDate,
                underlyingMaturityDate: trade.UnderlyingMaturityDate,
                dayCount: trade.DayCount,
                underlyingInstrumentType: trade.UnderlyingProductType,
                notional: trade.Notional
                );

            this._calculator = barrierCalculator;
            return(barrierCalculator);
        }
示例#9
0
        private BlackScholeCalculator ConfigureCalculator(IOption option, IMarketCondition market,
                                                          double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var trade = (BinaryOption)option;

            var exerciseDate = trade.ExerciseDates.Last();
            var maturityDate = trade.UnderlyingMaturityDate;

            var    riskFreeRate         = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var    riskfreeDfAtMaturity = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, maturityDate);
            var    riskfreeDfAtExercise = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var    spot  = market.SpotPrices.Value.Values.First();
            double sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                                 exerciseDate: exerciseDate, option: option, spot: spot);

            var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendInput      = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate,
                                                                                    option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount);

            var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskfreeDfAtExercise);

            var exerciseInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade) + timeIncrement;

            var maturityInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, maturityDate, trade) + timeIncrement;

            var _isDelayedPay = exerciseInYears.AlmostEqual(maturityInYears);

            var calculator = new BlackScholeCalculator(trade.OptionType,
                                                       trade.BinaryOptionPayoffType,
                                                       strike: option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike,
                                                       spotPrice: spot,
                                                       sigma: sigma,
                                                       dividendRate: dividendRate,
                                                       riskfreeRateAtExercise: riskfreeDfAtExercise,
                                                       riskfreeRateAtMaturity: riskfreeDfAtMaturity,
                                                       curveDayCount: market.DiscountCurve.Value.DayCount,
                                                       cashOrNothingAmount: trade.CashOrNothingAmount,
                                                       exerciseDate: exerciseDate,
                                                       maturityDate: maturityDate,
                                                       valuationDate: market.ValuationDate,
                                                       trade: trade,
                                                       underlyingInstrumentType: trade.UnderlyingProductType,
                                                       notional: trade.Notional,
                                                       isDelayedPay: _isDelayedPay,
                                                       expiryDayRemainingLife: expiryDayRemainingLife,
                                                       timeIncrement: timeIncrement);

            this._calculator = calculator;
            return(calculator);
        }
示例#10
0
            public BlackScholeCalculator(OptionType optionType,
                                         BinaryOptionPayoffType binaryOptionPayoffType,
                                         double strike,
                                         double spotPrice,
                                         double sigma,
                                         double dividendRate,
                                         double riskfreeRateAtExercise,
                                         double riskfreeRateAtMaturity,
                                         IDayCount curveDayCount,
                                         double cashOrNothingAmount,
                                         Date exerciseDate,
                                         Date maturityDate,
                                         Date valuationDate,
                                         IOption trade,
                                         InstrumentType underlyingInstrumentType,
                                         double notional               = 1.0,
                                         bool isDelayedPay             = false,
                                         double expiryDayRemainingLife = double.NaN,
                                         double timeIncrement          = 0.0)
            {
                _underlyingInstrumentType = underlyingInstrumentType;
                _isOptionOnFutures        = AnalyticalOptionPricerUtil.isFuturesOption(underlyingInstrumentType);
                _isOptionOnForward        = AnalyticalOptionPricerUtil.isForwardOption(underlyingInstrumentType);

                _optionType             = optionType;
                _binaryOptionPayoffType = binaryOptionPayoffType;
                _strike              = strike;
                _spotPrice           = spotPrice;
                _notional            = notional;
                _cashOrNothingAmount = cashOrNothingAmount;
                _sigma = sigma;

                _dividendRate           = dividendRate;
                _riskfreeRateAtExercise = riskfreeRateAtExercise;
                _riskfreeRateAtMaturity = riskfreeRateAtMaturity;

                _exerciseDate  = exerciseDate;
                _maturityDate  = maturityDate;
                _valuationDate = valuationDate;

                _trade = trade;

                _isDelayedPay           = isDelayedPay;
                _rfDfExerciseToMaturity = riskfreeRateAtMaturity / riskfreeRateAtExercise;

                _expiryDayRemainingLife = expiryDayRemainingLife;
                _timeIncrement          = timeIncrement;
                _curveDayCount          = curveDayCount;
            }
示例#11
0
        public BlackScholeCalculator(OptionType optionType,
                                     double strike,
                                     double spotPrice,
                                     double sigma,
                                     double riskfreeRateAtExercise,
                                     double riskfreeRateAtMaturity,
                                     IDayCount curveDayCount,
                                     double dividendRate,
                                     Date maturityDate,
                                     Date exerciseDate,
                                     Date valuationDate,
                                     IOption trade,
                                     InstrumentType underlyingInstrumentType,
                                     double notional,
                                     double expiryDayRemainingLife,
                                     double timeIncrement = 0.0)
        {
            _underlyingInstrumentType = underlyingInstrumentType;
            _isOptionOnFutures        = AnalyticalOptionPricerUtil.isFuturesOption(underlyingInstrumentType);
            _isOptionOnForward        = AnalyticalOptionPricerUtil.isForwardOption(underlyingInstrumentType);

            _optionType             = optionType;
            _strike                 = strike;
            _spotPrice              = spotPrice;
            _notional               = notional;
            _sigma                  = sigma;
            _riskfreeRateAtMaturity = riskfreeRateAtMaturity;
            _riskfreeRateAtExercise = riskfreeRateAtExercise;
            _dividendRate           = dividendRate;

            _trade         = trade;
            _maturityDate  = maturityDate;
            _exerciseDate  = exerciseDate;
            _valuationDate = valuationDate;

            _riskfreeDfAtExercise = CalcDfFromZeroRate(_riskfreeRateAtExercise, _exerciseDate, _valuationDate);
            _riskfreeDfAtMaturity = CalcDfFromZeroRate(_riskfreeRateAtMaturity, _maturityDate, _valuationDate);

            //just a internal indicator
            _isDelayedPay = maturityDate.CompareTo(_exerciseDate) > 0;

            _expiryDayRemainingLife = expiryDayRemainingLife;
            _timeIncrement          = timeIncrement;
            _curveDayCount          = curveDayCount;
        }
示例#12
0
        private LookbackOptionCalculator ConfigureCalculator(IOption option, IMarketCondition market,
                                                             double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var trade = (LookbackOption)option;

            var exerciseDate = trade.ExerciseDates.Last();
            var observedMax  = trade.Fixings.Any() ? trade.Fixings.Max(x => x.Value) : market.SpotPrices.Value.Values.First();
            var observedMin  = trade.Fixings.Any() ? trade.Fixings.Min(x => x.Value) : market.SpotPrices.Value.Values.First();

            var    spot  = market.SpotPrices.Value.Values.First();
            double sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                                 exerciseDate: exerciseDate, option: option, spot: spot);

            double t;

            if (!double.IsNaN(expiryDayRemainingLife))
            {
                t = expiryDayRemainingLife;
            }
            else
            {
                t = trade.DayCount.CalcDayCountFraction(market.ValuationDate, exerciseDate) + timeIncrement;
            }

            var riskFreeRate       = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendInput      = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate,
                                                                                    option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount);
            var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskFreeRate);

            var calculator = new LookbackOptionCalculator(trade.OptionType, trade.UnderlyingProductType,
                                                          trade.StrikeStyle,
                                                          strike: option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike,
                                                          spotPrice: spot,
                                                          exerciseInYears: t,
                                                          realizedMaxPrice: observedMax,
                                                          realizedMinPrice: observedMin,
                                                          sigma: sigma,
                                                          riskFreeRate: riskFreeRate,
                                                          dividendRate: dividendRate,
                                                          notional: trade.Notional);

            this._calculator = calculator;
            return(calculator);
        }
示例#13
0
        public override IPricingResult Calculate(ResetStrikeOption trade, IMarketCondition market, PricingRequest request)
        {
            var result = new PricingResult(market.ValuationDate, request);

            var exerciseDate     = trade.ExerciseDates.Last();
            var strikefixingDate = trade.StrikeFixingDate;
            var spot             = market.SpotPrices.Value.Values.First();
            var sigma            = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                                         exerciseDate: exerciseDate, option: trade, spot: spot);
            var T = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade);
            var t = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, strikefixingDate, trade);

            var riskFreeRate      = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var dividendRateInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendRate      = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendRateInput, riskFreeRate);


            var calculator = new ResetStrikeOptionCalculator(trade.OptionType, trade.ResetStrikeType, trade.UnderlyingProductType,
                                                             trade.Strike,
                                                             market.SpotPrices.Value.Values.First(),
                                                             T,
                                                             t,
                                                             sigma,
                                                             riskFreeRate,
                                                             dividendRate,
                                                             trade.Notional);

            result.Pv         = calculator.Pv;
            result.Delta      = calculator.Delta;
            result.DeltaCash  = result.Delta * market.SpotPrices.Value.Values.First();
            result.Gamma      = calculator.Gamma;
            result.GammaCash  = result.Gamma * market.SpotPrices.Value.Values.First() * market.SpotPrices.Value.Values.First() / 100;
            result.Vega       = calculator.Vega;
            result.Rho        = calculator.Rho;
            result.Theta      = calculator.Theta;
            result.DDeltaDt   = calculator.DDeltaDt;
            result.DDeltaDvol = calculator.DDeltaDvol;
            result.DVegaDvol  = calculator.DDeltaDvol;
            result.DVegaDt    = calculator.DVegaDt;

            return(result);
        }
        private BAWCalculator ConfigureCalculator(IOption option, IMarketCondition market,
                                                  double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var trade = (VanillaOption)option;

            var exerciseDate    = trade.ExerciseDates.Last();
            var maturityDate    = trade.UnderlyingMaturityDate;
            var exerciseInYears = trade.DayCount.CalcDayCountFraction(market.ValuationDate, exerciseDate);
            var maturityInYears = trade.DayCount.CalcDayCountFraction(market.ValuationDate, maturityDate);

            var riskfreeRate         = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var riskfreeDfAtExercise = market.DiscountCurve.Value.GetDf(market.ValuationDate, exerciseDate);
            var riskfreeDfAtMaturity = market.DiscountCurve.Value.GetDf(market.ValuationDate, maturityDate);

            var dividendCurveInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendInput      = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskfreeRate,
                                                                                    option.Dividends, market.SpotPrices.Value.Values.First(), market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount);
            var dividendRate = AnalyticalOptionPricerUtil.dividendDf(trade.UnderlyingProductType, dividendInput, riskfreeRate);

            var    spot  = market.SpotPrices.Value.Values.First();
            double sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                                 exerciseDate: exerciseDate, option: option, spot: spot);

            var calculator = new BAWCalculator(trade.OptionType,
                                               option.IsMoneynessOption ? trade.Strike * trade.InitialSpotPrice : trade.Strike,
                                               spot,
                                               exerciseInYears,
                                               sigma,
                                               riskfreeRate,
                                               dividendRate,
                                               trade.Notional,
                                               trade.UnderlyingProductType,
                                               riskfreeDfAtExercise: riskfreeDfAtExercise,
                                               riskfreeDfAtMaturity: riskfreeDfAtMaturity,
                                               expiryDayRemainingLife: expiryDayRemainingLife,
                                               timeIncrement: timeIncrement);

            this._calculator = calculator;
            return(calculator);
        }
示例#15
0
        private BlackScholeCalculator ConfigureCalculator(IOption option, IMarketCondition market,
                                                          double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var trade        = (VanillaOption)option;
            var exerciseDate = trade.ExerciseDates.Last();
            var maturityDate = trade.UnderlyingMaturityDate;

            var    spot  = market.SpotPrices.Value.Values.First();
            double sigma = AnalyticalOptionPricerUtil.pricingVol(volSurf: market.VolSurfaces.Value.Values.First(),
                                                                 exerciseDate: exerciseDate, option: option, spot: spot);

            var riskfreeRateAtExercise = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var riskfreeRateAtMaturity = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, maturityDate);
            var riskFreeRate           = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var dividendCurveInput     = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendInput          = AnalyticalOptionPricerUtil.dividendYieldOutput(dividendCurveInput, riskFreeRate,
                                                                                        option.Dividends, spot, market.ValuationDate, trade.ExerciseDates.Last(), option.DayCount);

            var dividendRate = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendInput, riskFreeRate);

            var BSCalculator = new BlackScholeCalculator(trade.OptionType,
                                                         strike: option.IsMoneynessOption? trade.Strike * trade.InitialSpotPrice: trade.Strike,
                                                         spotPrice: spot,
                                                         sigma: sigma,
                                                         riskfreeRateAtExercise: riskfreeRateAtExercise,
                                                         riskfreeRateAtMaturity: riskfreeRateAtMaturity,
                                                         curveDayCount: market.DiscountCurve.Value.DayCount,
                                                         dividendRate: dividendRate,
                                                         maturityDate: trade.UnderlyingMaturityDate, //maturity of underlying, i.e. option on futures
                                                         exerciseDate: trade.ExerciseDates.Last(),
                                                         valuationDate: market.ValuationDate,
                                                         trade: trade,
                                                         underlyingInstrumentType: trade.UnderlyingProductType,
                                                         notional: trade.Notional,
                                                         expiryDayRemainingLife: expiryDayRemainingLife,
                                                         timeIncrement: timeIncrement);

            _calculator = BSCalculator;
            return(BSCalculator);
        }
        private BlackScholeCalculator configureBsCalculator(IOption option, IMarketCondition market,
                                                            double expiryDayRemainingLife = double.NaN, double timeIncrement = 0.0)
        {
            var trade        = (BarrierOption)option;
            var spot         = market.SpotPrices.Value.Values.First();
            var exerciseDate = trade.ExerciseDates.Last();
            var maturityDate = trade.UnderlyingMaturityDate;

            var vol = option.IsMoneynessOption ?
                      //moneyness option , strike i.e. 120% of initialSpot
                      market.VolSurfaces.Value.Values.First().GetValue(exerciseDate, trade.Strike * trade.InitialSpotPrice, spot) :
                      market.VolSurfaces.Value.Values.First().GetValue(exerciseDate, trade.Strike, spot);

            var riskFreeRate           = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var riskfreeRateAtMaturity = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, maturityDate);

            var dividendRateInput = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
            var dividendRate      = AnalyticalOptionPricerUtil.dividenRate(trade.UnderlyingProductType, dividendRateInput, riskFreeRate);

            return(new BlackScholeCalculator(
                       trade.OptionType,
                       strike: option.IsMoneynessOption?trade.Strike *trade.InitialSpotPrice: trade.Strike,
                       spotPrice: spot,
                       sigma: vol,
                       riskfreeRateAtExercise: riskFreeRate,
                       riskfreeRateAtMaturity: riskfreeRateAtMaturity,
                       curveDayCount: market.DiscountCurve.Value.DayCount,
                       dividendRate: dividendRate,
                       maturityDate: trade.UnderlyingMaturityDate,
                       exerciseDate: trade.ExerciseDates.Last(),
                       valuationDate: market.ValuationDate,
                       trade: trade,
                       underlyingInstrumentType: trade.UnderlyingProductType,
                       notional: trade.Notional,
                       expiryDayRemainingLife: expiryDayRemainingLife));
        }
示例#17
0
        public override IPricingResult Calculate(BinaryOption trade, IMarketCondition market, PricingRequest request)
        {
            var result = new PricingResult(market.ValuationDate, request);

            if (trade.BinaryOptionPayoffType == BinaryOptionPayoffType.CashOrNothing)
            {
                var factor     = (double)BinaryOptionReplicationStrategy;
                var lowStrike  = trade.Strike + Offset * (factor - 1.0) / 2.0;
                var highStrike = trade.Strike + Offset * (factor + 1.0) / 2.0;

                //if call, replicate by call spreads,
                //if put, replicate by put spreads

                var lowStrikeOption  = new VanillaOption(trade.StartDate, trade.UnderlyingMaturityDate, trade.Exercise, trade.OptionType, lowStrike, trade.UnderlyingProductType, trade.Calendar, trade.DayCount, trade.PayoffCcy, trade.SettlementCcy, trade.ExerciseDates, trade.ObservationDates, trade.Notional);
                var highStrikeOption = new VanillaOption(trade.StartDate, trade.UnderlyingMaturityDate, trade.Exercise, trade.OptionType, highStrike, trade.UnderlyingProductType, trade.Calendar, trade.DayCount, trade.PayoffCcy, trade.SettlementCcy, trade.ExerciseDates, trade.ObservationDates, trade.Notional);
                var engine           = new AnalyticalVanillaEuropeanOptionEngine();
                var lowResult        = engine.Calculate(lowStrikeOption, market, request);
                var highResult       = engine.Calculate(highStrikeOption, market, request);

                var sign = trade.OptionType == OptionType.Call ? 1.0 : -1.0;
                factor = sign * trade.CashOrNothingAmount / Offset;

                //calc basic stuff
                if (result.IsRequested(PricingRequest.Pv))
                {
                    result.Pv = (lowResult.Pv - highResult.Pv) * factor;
                }
                if (AnalyticalOptionPricerUtil.isBasicPricing(result))
                {
                    result.Delta     = (lowResult.Delta - highResult.Delta) * factor;
                    result.DeltaCash = result.Delta * market.SpotPrices.Value.Values.First();
                    result.Gamma     = (lowResult.Gamma - highResult.Gamma) * factor;
                    result.GammaCash = result.Gamma * market.SpotPrices.Value.Values.First() * market.SpotPrices.Value.Values.First() / 100;
                    result.Vega      = (lowResult.Vega - highResult.Vega) * factor;
                    result.Rho       = (lowResult.Rho - highResult.Rho) * factor;
                    result.Theta     = (lowResult.Theta - highResult.Theta) * factor;
                }
                if (AnalyticalOptionPricerUtil.isHighOrderPricing(result))
                {
                    result.DDeltaDvol = (lowResult.DDeltaDvol - highResult.DDeltaDvol) * factor;
                    result.DVegaDvol  = (lowResult.DVegaDvol - highResult.DVegaDvol) * factor;
                    result.DVegaDt    = (lowResult.DVegaDt - highResult.DVegaDt) * factor;
                    result.DDeltaDt   = (lowResult.DDeltaDt - highResult.DDeltaDt) * factor;
                }
            }
            else if (trade.BinaryOptionPayoffType == BinaryOptionPayoffType.AssetOrNothing)
            {
                var binaryCfOption = new BinaryOption(trade.StartDate, trade.UnderlyingMaturityDate, trade.Exercise, trade.OptionType,
                                                      trade.Strike, trade.UnderlyingProductType, BinaryOptionPayoffType.CashOrNothing, 1.0, trade.Calendar,
                                                      trade.DayCount, trade.PayoffCcy,
                                                      trade.SettlementCcy, trade.ExerciseDates, trade.ObservationDates);
                var binaryResult  = Calculate(binaryCfOption, market, request);
                var vanillaOption = new VanillaOption(trade.StartDate, trade.UnderlyingMaturityDate, trade.Exercise, trade.OptionType,
                                                      trade.Strike, trade.UnderlyingProductType, trade.Calendar, trade.DayCount, trade.PayoffCcy,
                                                      trade.SettlementCcy, trade.ExerciseDates, trade.ObservationDates, trade.Notional);
                var engine        = new AnalyticalVanillaEuropeanOptionEngine();
                var vanillaResult = engine.Calculate(vanillaOption, market, request);
                var sign          = trade.OptionType == OptionType.Call ? 1.0 : -1.0;

                if (result.IsRequested(PricingRequest.Pv))
                {
                    result.Pv = sign * vanillaResult.Pv + trade.Strike * binaryResult.Pv;
                }

                if (AnalyticalOptionPricerUtil.isBasicPricing(result))
                {
                    result.Delta     = sign * vanillaResult.Delta + trade.Strike * binaryResult.Delta;
                    result.DeltaCash = result.Delta * market.SpotPrices.Value.Values.First();
                    result.Gamma     = sign * vanillaResult.Gamma + trade.Strike * binaryResult.Gamma;
                    result.GammaCash = result.Gamma * market.SpotPrices.Value.Values.First() * market.SpotPrices.Value.Values.First() / 100;
                    result.Vega      = sign * vanillaResult.Vega + trade.Strike * binaryResult.Vega;
                    result.Rho       = sign * vanillaResult.Rho + trade.Strike * binaryResult.Rho;
                    result.Theta     = sign * vanillaResult.Theta + trade.Strike * binaryResult.Theta;
                }

                if (AnalyticalOptionPricerUtil.isHighOrderPricing(result))
                {
                    result.DDeltaDvol = sign * vanillaResult.DDeltaDvol + trade.Strike * binaryResult.DDeltaDvol;
                    result.DVegaDvol  = sign * vanillaResult.DVegaDvol + trade.Strike * binaryResult.DVegaDvol;
                    result.DVegaDt    = sign * vanillaResult.DVegaDt + trade.Strike * binaryResult.DVegaDt;
                    result.DDeltaDt   = sign * vanillaResult.DDeltaDt + trade.Strike * binaryResult.DDeltaDt;
                }
            }
            return(result);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BarrierOptionCalculator"/> class.
        /// </summary>
        /// <param name="optionType">Type of the option, Call or Put.</param>
        /// <param name="barrierType">UpAndIn, DownAndOut etc.</param>
        /// <param name="payoff">Option payoff, coupon/rebate/paticipationrate included.</param>
        /// <param name="barrier">Barrier level</param>
        /// <param name="secondarybarrier">Secondary barrier, only effective for double barrier options</param>
        /// <param name="strike">The strike.</param>
        /// <param name="spotPrice">The spot price.</param>
        /// <param name="exerciseInYears">The maturity in years.</param>
        /// <param name="standardDeviation">Volatility, measured by the standard deviation of the underlying.</param>
        /// <param name="riskFreeRate">Risk free rate</param>
        /// <param name="dividendRate">Continuous dividend rate</param>
        public BarrierOptionCalculator(OptionType optionType,
                                       BarrierType barrierType,
                                       double rebate,
                                       double barrier,
                                       double secondarybarrier,
                                       double strike,
                                       double spotPrice,
                                       double exerciseInYears,
                                       double standardDeviation,
                                       double riskFreeRate,
                                       double dividendRate,
                                       Date valuationDate,
                                       Date exerciseDate,
                                       Date underlyingMaturityDate,
                                       IDayCount dayCount,
                                       InstrumentType underlyingInstrumentType,
                                       double notional)
        {
            _isOptionOnFutures = AnalyticalOptionPricerUtil.isFuturesOption(underlyingInstrumentType);
            _isOptionOnForward = AnalyticalOptionPricerUtil.isForwardOption(underlyingInstrumentType);

            _optionType  = optionType;
            _barrierType = barrierType;
            _rebate      = rebate;
            _H           = barrier;
            _H2          = secondarybarrier;
            _X           = strike;
            _S           = spotPrice;
            _T           = exerciseInYears;
            _K           = rebate;
            _sigma       = standardDeviation;
            _r           = riskFreeRate;
            _dividend    = dividendRate;
            _b           = AnalyticalOptionPricerUtil.costOfCarry(_isOptionOnFutures || _isOptionOnForward, dividendRate, riskFreeRate);
            _dayCount    = dayCount;
            _notional    = notional;

            var riskfreeDfAtMaturity = CalcDfFromZeroRate(riskFreeRate, underlyingMaturityDate, valuationDate);
            var riskfreeDfAtExercise = CalcDfFromZeroRate(riskFreeRate, exerciseDate, valuationDate);

            _dfExerciseToMaturity = (_isOptionOnForward) ? riskfreeDfAtMaturity / riskfreeDfAtExercise : 1.0;

            // factors calculation
            switch (barrierType)
            {
            case BarrierType.DownAndIn:
            case BarrierType.DownAndOut:
                _yita = 1.0;
                break;

            case BarrierType.UpAndIn:
            case BarrierType.UpAndOut:
                _yita = -1.0;
                break;

            case BarrierType.DoubleTouchOut:
            case BarrierType.DoubleTouchIn:
                throw new PricingLibraryException("Double barrier shall use AnalyticalDoubleBarrierOptionEngine to calculate!");
            }

            _phi = optionType.Equals(OptionType.Call) ? 1.0 : -1.0;
        }
示例#19
0
        public override IPricingResult Calculate(AsianOption trade, IMarketCondition market, PricingRequest request)
        {
            var result = new PricingResult(market.ValuationDate, request);

            var exerciseDate      = trade.ExerciseDates.Last();
            var remainingObsDates = trade.ObservationDates.Where(x => x > market.ValuationDate).ToArray();
            var n  = trade.ObservationDates.Count();
            var n2 = remainingObsDates.Count();
            var m  = n - n2;

            if (trade.Fixings.Count != m)
            {
                throw   new PricingLibraryException("AsianOption: number of fixings does not match!");
            }

            var fixingAverage = trade.Fixings.Any() ? trade.Fixings.Average(x => x.Value) : 0.0;


            if (!remainingObsDates.Any())
            {
                //already fix on all observation days
                var cfs = trade.GetPayoff(new[] { fixingAverage });
                result.Pv        = cfs.Sum(x => x.PaymentAmount * market.DiscountCurve.Value.GetDf(market.ValuationDate, x.PaymentDate));
                result.Delta     = 0.0;
                result.DeltaCash = 0.0;
                result.Gamma     = 0.0;
                result.GammaCash = 0.0;
                result.Vega      = 0.0;
                result.Theta     = 0.0;
                result.Rho       = 0.0;
                return(result);
            }

            //TODO: do it properly
            var newSpot = market.SpotPrices.Value.Values.First();

            var sigma = market.VolSurfaces.Value.Values.First().GetValue(exerciseDate, trade.Strike, newSpot);

            var    newSigma = market.VolSurfaces.Value.Values.First().GetValue(exerciseDate, trade.Strike, newSpot);
            double newStrike;
            var    factor = 1.0;

            if (remainingObsDates.Count() == 1)
            {
                newStrike = trade.ObservationDates.Count() * trade.Strike - (n - 1) * trade.Fixings.Average(x => x.Value);
                factor    = 1.0 / n;
            }
            else
            {
                var T  = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade);
                var T2 = AnalyticalOptionPricerUtil.timeToMaturityFraction(remainingObsDates[0], remainingObsDates.Last(), trade);
                var t1 = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, remainingObsDates[0], trade);

                var h            = T2 / (n2 - 1);
                var S            = market.SpotPrices.Value.Values.First();
                var riskFreeRate = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
                var dividendRate = market.DividendCurves.Value.Values.First().ZeroRate(market.ValuationDate, exerciseDate);
                var b            = riskFreeRate - dividendRate;
                var sigma2       = sigma * sigma;

                double eat, eat2;
                if (riskFreeRate.AlmostEqual(dividendRate))
                {
                    eat = market.SpotPrices.Value.Values.First();

                    eat2 = S * S * Math.Exp(sigma2 * t1) / n / n *
                           (
                        (1 - Math.Exp(sigma2 * h * n)) / (1 - Math.Exp(sigma2 * h)) +
                        2.0 / (1 - Math.Exp(sigma2 * h)) *
                        (n - (1 - Math.Exp(sigma2 * h * n)) / (1 - Math.Exp(sigma2 * h)))
                           );
                }
                else
                {
                    var o = 2 * b + sigma2;
                    eat  = S / n2 * Math.Exp(b * t1) * (1 - Math.Exp(b * h * n2)) / (1 - Math.Exp(b * h));
                    eat2 = S * S * Math.Exp(o * t1) / n / n *
                           (
                        (1 - Math.Exp(o * h * n)) / (1 - Math.Exp(o * h)) +
                        2.0 / (1 - Math.Exp((b + sigma2) * h)) *
                        ((1 - Math.Exp(b * h * n)) / (1 - Math.Exp(b * h)) - (1 - Math.Exp(o * h * n)) / (1 - Math.Exp(o * h)))
                           );
                }

                newSpot   = eat;
                newSigma  = Math.Sqrt(Math.Log(eat2 / eat / eat) / T);
                newStrike = (n * trade.Strike - m * fixingAverage) / (n - m) - m / (n - m);

                factor = 1.0 * (n - m) / n;
            }

            var newTrade = new VanillaOption(trade.StartDate,
                                             trade.UnderlyingMaturityDate,
                                             trade.Exercise,
                                             trade.OptionType,
                                             newStrike,
                                             trade.UnderlyingProductType,
                                             trade.Calendar,
                                             trade.DayCount,
                                             trade.PayoffCcy,
                                             trade.SettlementCcy,
                                             trade.ExerciseDates,
                                             trade.ObservationDates,
                                             trade.Notional,
                                             trade.SettlmentGap,
                                             trade.OptionPremiumPaymentDate,
                                             trade.OptionPremium);

            var newVol    = market.VolSurfaces.Value.Values.First().BumpVolSurf(newSigma - sigma);
            var newMarket = market.UpdateCondition(
                new UpdateMktConditionPack <Dictionary <string, double> >(x => x.SpotPrices, new Dictionary <string, double> {
                { "", newSpot }
            }),
                new UpdateMktConditionPack <Dictionary <string, IVolSurface> >(x => x.VolSurfaces, new Dictionary <string, IVolSurface> {
                { "", newVol }
            })
                );

            var bsEngine = new AnalyticalVanillaEuropeanOptionEngine();

            result        = (PricingResult)bsEngine.Calculate(newTrade, newMarket, request);
            result.Pv    *= factor;
            result.Delta *= factor;
            result.Gamma *= factor;
            result.Vega  *= factor;
            result.Theta *= factor;
            result.Rho   *= factor;

            return(result);
        }
示例#20
0
        public override IPricingResult Calculate(RainbowOption trade, IMarketCondition market, PricingRequest request)
        {
            var result = new PricingResult(market.ValuationDate, request);

            var exerciseDate = trade.ExerciseDates.Last();
            var maturityDate = trade.UnderlyingMaturityDate;

            //TODO:  support timeIncrement
            var exerciseInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, exerciseDate, trade);
            var maturityInYears = AnalyticalOptionPricerUtil.timeToMaturityFraction(market.ValuationDate, maturityDate, trade);

            var riskFreeRate = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, exerciseDate);
            var ticker1      = trade.UnderlyingTickers[0];
            var ticker2      = trade.UnderlyingTickers[1];

            double dividendRate1, dividendRate2;

            if (AnalyticalOptionPricerUtil.isForwardFuturesOption(trade.UnderlyingProductType))
            {
                dividendRate1 = riskFreeRate;
                dividendRate2 = riskFreeRate;
            }
            else
            {
                dividendRate1 = market.DividendCurves.Value[ticker1].ZeroRate(market.ValuationDate, exerciseDate);
                dividendRate2 = market.DividendCurves.Value[ticker2].ZeroRate(market.ValuationDate, exerciseDate);
            }

            var spot1 = market.SpotPrices.Value[ticker1];
            var spot2 = market.SpotPrices.Value[ticker2];

            var sigma1 = market.VolSurfaces.Value[ticker1].GetValue(exerciseDate, trade.Strikes[0], spot1);
            var sigma2 = market.VolSurfaces.Value[ticker2].GetValue(exerciseDate, trade.Strikes[0], spot2);

            var strike1 = trade.Strikes[0];

            var strike2 = 0.0;

            if (trade.Strikes.Length > 1)
            {
                strike2 = trade.Strikes[1];
            }

            //Note: correlation here is a scala number.  can be a grid for multi-asset option
            var rho = market.Correlations.Value[ticker1].GetValue(exerciseDate, strike1);

            var calculator = new RainbowOptionCalculator(trade.OptionType,
                                                         trade.RainbowType,
                                                         strike1, strike2, trade.CashAmount,
                                                         spot1, spot2, rho,
                                                         sigma1, sigma2,
                                                         exerciseInYears,
                                                         riskFreeRate,
                                                         dividendRate1, dividendRate2,
                                                         trade.Notional);

            bool isExpired         = trade.ExerciseDates.Last() < market.ValuationDate;
            bool isExpiredforTheta = trade.ExerciseDates.Last() <= market.ValuationDate;

            if (isExpired)
            {
                result.Pv                 = 0.0;
                result.Theta              = 0.0;
                result.asset1Delta        = 0.0;
                result.asset1DeltaCash    = 0.0;
                result.asset2Delta        = 0.0;
                result.asset2DeltaCash    = 0.0;
                result.asset1PartialDelta = 0.0;
                result.asset2PartialDelta = 0.0;
                result.asset1Gamma        = 0.0;
                result.asset1GammaCash    = 0.0;
                result.asset2Gamma        = 0.0;
                result.asset2GammaCash    = 0.0;
                result.asset1Vega         = 0.0;
                result.asset2Vega         = 0.0;
                result.Rho                = 0.0;
                result.Theta              = 0.0;
                result.asset1DDeltaDt     = 0.0;
                result.asset2DDeltaDt     = 0.0;
                result.asset1DVegaDvol    = 0.0;
                result.asset2DVegaDvol    = 0.0;
                result.asset1DDeltaDvol   = 0.0;
                result.asset2DDeltaDvol   = 0.0;
                result.asset1DVegaDt      = 0.0;
                result.asset2DVegaDt      = 0.0;
                result.crossGamma         = 0.0;
                result.crossVomma         = 0.0;
                result.crossVanna1        = 0.0;
                result.crossVanna2        = 0.0;
                result.correlationVega    = 0.0;
            }

            else
            {
                if (result.IsRequested(PricingRequest.Pv))
                {
                    result.Pv = calculator.Pv;
                }

                if (AnalyticalOptionPricerUtil.isBasicPricing(result))
                {
                    result.asset1Delta        = calculator.asset1Delta;
                    result.asset2Delta        = calculator.asset2Delta;
                    result.asset1DeltaCash    = calculator.asset1Delta * spot1;
                    result.asset2DeltaCash    = calculator.asset2Delta * spot2;
                    result.asset1PartialDelta = calculator.asset1PartialDelta;
                    result.asset2PartialDelta = calculator.asset2PartialDelta;
                    result.asset1Gamma        = calculator.asset1Gamma;
                    result.asset2Gamma        = calculator.asset2Gamma;
                    result.asset1GammaCash    = calculator.asset1Gamma * spot1 * spot1 / 100;
                    result.asset2GammaCash    = calculator.asset2Gamma * spot2 * spot2 / 100;
                    result.asset1Vega         = calculator.asset1Vega;
                    result.asset2Vega         = calculator.asset2Vega;
                    result.Rho = calculator.Rho;

                    result.Theta = (isExpiredforTheta) ? 0.0 : calculator.Theta;
                }

                if (AnalyticalOptionPricerUtil.isHighOrderPricing(result))
                {
                    result.asset1DVegaDvol  = calculator.asset1DVegaDvol;
                    result.asset2DVegaDvol  = calculator.asset2DVegaDvol;
                    result.asset1DDeltaDvol = calculator.asset1DDeltaDvol;
                    result.asset2DDeltaDvol = calculator.asset2DDeltaDvol;
                    result.crossGamma       = calculator.crossGamma;
                    result.crossVomma       = calculator.crossVomma;
                    result.crossVanna1      = calculator.crossVanna1;
                    result.crossVanna2      = calculator.crossVanna2;
                    result.correlationVega  = calculator.correlationVega;
                }


                if (isExpiredforTheta)
                {
                    result.asset1DDeltaDt = result.asset2DDeltaDt = 0.0;
                    result.asset1DVegaDt  = result.asset2DVegaDt = 0.0;
                }
                else
                {
                    result.asset1DDeltaDt = calculator.asset1DDeltaDt;
                    result.asset2DDeltaDt = calculator.asset2DDeltaDt;
                    result.asset1DVegaDt  = calculator.asset1DVegaDt;
                    result.asset2DVegaDt  = calculator.asset2DVegaDt;
                }
            }
            return(result);
        }
        public static void prepareBlackScholesInputs(
            double spotPrice,
            double riskfreeRateAtExerciseInput, double riskfreeRateAtMaturityInput, double dividendRateInput,
            double riskFreeCurveShiftInBp, double dividendCurveShiftInBp,
            Date maturityDate, Date exerciseDate, Date valuationDate,
            IOption trade,
            IDayCount curveDayCount,
            bool isOptionOnForward,
            bool isForwardFuturesOption,
            double strike,
            double sigma,
            out double nd1,  // P(x < d1)
            out double nd2,  // P(x < d2),
            out double riskfreeDfAtExercise,
            out double dfExerciseToMaturity,
            out double forwardPrice,
            double expiryDayRemainingLife = double.NaN,
            double timeIncrement          = 0.0
            )
        {
            double T = 0.0;

            if (!double.IsNaN(expiryDayRemainingLife))
            {
                T = expiryDayRemainingLife;
            }
            else
            {
                T = timeToMaturityFraction(valuationDate, exerciseDate, trade) + timeIncrement;
            }
            double riskfreeRateAtExercise, riskfreeRateAtMaturity;

            if (riskFreeCurveShiftInBp != 0.0)
            {
                riskfreeRateAtExercise = riskfreeRateAtExerciseInput + riskFreeCurveShiftInBp * 1e-4;
                riskfreeRateAtMaturity = riskfreeRateAtMaturityInput + riskFreeCurveShiftInBp * 1e-4;
            }
            else
            {
                riskfreeRateAtExercise = riskfreeRateAtExerciseInput;
                riskfreeRateAtMaturity = riskfreeRateAtMaturityInput;
            }
            var riskfreeDfAtMaturity = CalcDfFromZeroRate(riskfreeRateAtMaturity, maturityDate, valuationDate, curveDayCount);

            riskfreeDfAtExercise = CalcDfFromZeroRate(riskfreeRateAtExercise, exerciseDate, valuationDate, curveDayCount);

            double dividendRate;

            if (dividendCurveShiftInBp != 0.0)
            {
                dividendRate = dividendRateInput + dividendCurveShiftInBp / 1e4;
            }
            else
            {
                dividendRate = dividendRateInput;
            }

            //https://en.wikipedia.org/wiki/Black_model
            //if option on forward, discount to forward maturity day, and make sure maturity here is forward maturity, exercise is option exercise day
            //for other contracts,  pass maturity day = expiry day,  therefore _dfExerciseToMaturity = 1.0;
            dfExerciseToMaturity = (isOptionOnForward) ? riskfreeDfAtMaturity / riskfreeDfAtExercise : 1.0;

            var b = AnalyticalOptionPricerUtil.costOfCarry(isForwardFuturesOption, dividendRate, riskfreeRateAtExercise);

            forwardPrice = AnalyticalOptionPricerUtil.forwardPrice(
                isForwardFuturesOption,
                spotPrice,
                riskfreeDfAtExercise: riskfreeDfAtExercise,
                dividendRate: dividendRate,
                exerciseDate: exerciseDate,
                valuationDate: valuationDate,
                dayCount: trade.DayCount);

            var d1 = (Math.Log(spotPrice / strike) + (b + sigma * sigma / 2.0) * T) / (sigma * Math.Sqrt(T));
            var d2 = d1 - sigma * Math.Sqrt(T);

            nd1 = NormalCdf.NormalCdfHart(d1);  // P(x < d1)
            nd2 = NormalCdf.NormalCdfHart(d2);  // P(x < d2)

            //var nPrimceD1 = 1.0 / Math.Sqrt(2.0 * Math.PI) * Math.Exp(-d1 * d1 / 2.0); // derivative of N(d1)
            //var nPrimceD2 = 1.0 / Math.Sqrt(2.0 * Math.PI) * Math.Exp(-d2 * d2 / 2.0); // derivative of N(d2)
        }