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); }
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); }