Exemplo n.º 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);
        }
Exemplo n.º 2
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);
        }
        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);
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
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);
        }
Exemplo n.º 8
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);
        }