/// <summary> /// Initializes a new instance of the <see cref="VanillaEuropeanFxOptionPricer"/> class. All the cashflows must be signed. /// </summary> /// <param name="paymentCalendar">The payment calendar</param> /// <param name="fxOptionLeg">The fxLeg.</param> /// <param name="baseParty">The the base party.</param> /// <param name="logger">The logger</param> /// <param name="cache">The cache</param> /// <param name="nameSpace">The namespace</param> /// <param name="fixingCalendar">The fixing calendar</param> public VanillaEuropeanFxOptionPricer(ILogger logger, ICoreCache cache, String nameSpace, IBusinessCalendar fixingCalendar, IBusinessCalendar paymentCalendar, FxOption fxOptionLeg, string baseParty) { OrderedPartyNames = new List <string>(); Multiplier = 1.0m; Id = fxOptionLeg.id; AnalyticsModel = new FxOptionLegAnalytic(); ProductType = ProductTypeSimpleEnum.FxOption; HybridValuation = true; BuyerPartyReference = fxOptionLeg.buyerPartyReference.href; SellerPartyReference = fxOptionLeg.sellerPartyReference.href; BasePartyBuyer = baseParty == BuyerPartyReference; FxOptionType = FxOptionType.Put; ProductType = ProductTypeSimpleEnum.FxOption; if (fxOptionLeg.spotRateSpecified) { SpotRate = fxOptionLeg.spotRate; } FpMLProductType = ProductTypeHelper.GetProductType(fxOptionLeg.Items, fxOptionLeg.ItemsElementName); //Temporary values used to build the fx and option trades. PutCurrencyAmount = fxOptionLeg.putCurrencyAmount.amount; PutCurrency = fxOptionLeg.callCurrencyAmount.currency.Value; CallCurrencyAmount = fxOptionLeg.callCurrencyAmount.amount; CallCurrency = fxOptionLeg.putCurrencyAmount.currency.Value; FxStrike = fxOptionLeg.strike.rate; StrikeQuoteBasis = fxOptionLeg.strike.strikeQuoteBasis; if (IsCall()) { FxOptionType = FxOptionType.Call; } SoldAs = fxOptionLeg.soldAs; if (fxOptionLeg.tenorPeriod != null) { QuotedTenor = fxOptionLeg.tenorPeriod.ToString(); } var vanillaOption = fxOptionLeg.Item as FxEuropeanExercise; if (vanillaOption != null) { ExpiryDate = vanillaOption.expiryDate; ExpiryTimeBusinessCenter = vanillaOption.expiryTime.businessCenter.Value; ExpiryTime = vanillaOption.expiryTime.hourMinuteTime; //TODO Not Implemented yet! CutName = vanillaOption.cutName; ValueDate = vanillaOption.valueDate; } var type = HasBeenExercised ? ProductTypeSimpleEnum.FxSpot : ProductTypeSimpleEnum.FxForward; //Create the fxleg. //TODO Currently this does not handle non-deliverable forwards or a third settlement currency. var fxLeg = FxOption.CreateFxSingleLeg(HasBeenExercised, BuyerPartyReference, SellerPartyReference, PutCurrencyAmount, PutCurrency, CallCurrencyAmount, CallCurrency, StrikeQuoteBasis, ValueDate, FxStrike); FxLeg = new FxSingleLegPricer(fxLeg, baseParty, type); VolatilitySurfaceName = fxOptionLeg.GetRequiredVolatilitySurfaces()[0]; //FxOptionType; //Get the currency. PaymentCurrencies = new List <string>(); PaymentCurrencies.AddRange(FxLeg.PaymentCurrencies); //Add the premia Premia = new List <PriceableFxOptionPremium>(); if (fxOptionLeg.premium != null) { foreach (var premium in fxOptionLeg.premium) { var priceablePayment = PriceableInstrumentsFactory.CreatePriceableFxOptionPremium(cache, nameSpace, null, baseParty, premium, fixingCalendar, paymentCalendar); Premia.Add(priceablePayment); PaymentCurrencies.AddRange(priceablePayment.PaymentCurrencies); } } PaymentCurrencies = PaymentCurrencies.Distinct().ToList(); if (fxOptionLeg.cashSettlement != null) { IsCashSettled = true; CashSettlementCurrency = fxOptionLeg.cashSettlement.settlementCurrency; //Only a single fixing date is currency implemented. if (fxOptionLeg.cashSettlement.fixing != null && fxOptionLeg.cashSettlement.fixing[0].fixingDateSpecified) { FixingDate = fxOptionLeg.cashSettlement.fixing[0].fixingDate; FixingQuotedCurrencyPair = fxOptionLeg.cashSettlement.fixing[0].quotedCurrencyPair; } } if (vanillaOption != null) { RiskMaturityDate = vanillaOption.valueDate; } logger.LogInfo("FxOption trade created :"); }
public override AssetValuation Calculate(IInstrumentControllerData modelData) { ModelData = modelData; AnalyticModelParameters = null; CalculationResults = null; UpdateBucketingInterval(ModelData.ValuationDate, PeriodHelper.Parse(CDefaultBucketingInterval)); // 1. First derive the analytics to be evaluated via the stream controller model // NOTE: These take precendence of the child model metrics if (AnalyticsModel == null) { AnalyticsModel = new FxOptionLegAnalytic(); } var marketEnvironment = modelData.MarketEnvironment as IFxLegEnvironment; AssetValuation streamValuation; //Check if risk calc are required. bool delta0PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta0PDH.ToString()) != null || AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta0PDH.ToString()) != null; bool delta1PDH = AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.LocalCurrencyDelta1PDH.ToString()) != null || AssetValuationHelper.GetQuotationByMeasureType(ModelData.AssetValuation, InstrumentMetrics.Delta1PDH.ToString()) != null; var streamControllerMetrics = ResolveModelMetrics(AnalyticsModel.Metrics); var childValuations = new List <AssetValuation>(); // 2. Now evaluate only the child specific metrics (if any) foreach (var payment in FxLeg.Payments) { payment.Multiplier = Multiplier; payment.PricingStructureEvolutionType = PricingStructureEvolutionType; payment.BucketedDates = BucketedDates; } foreach (var premium in Premia) { premium.Multiplier = 1.0m; premium.PricingStructureEvolutionType = PricingStructureEvolutionType; premium.BucketedDates = BucketedDates; } if (marketEnvironment != null) { //Modify the second market. var modelData1 = new InstrumentControllerData(modelData.AssetValuation, marketEnvironment.GetExchangeCurrencyPaymentEnvironment1(), modelData.ValuationDate, modelData.ReportingCurrency); var modelData2 = new InstrumentControllerData(modelData.AssetValuation, marketEnvironment.GetExchangeCurrencyPaymentEnvironment2(), modelData.ValuationDate, modelData.ReportingCurrency); childValuations.Add(Currency1Payment.Calculate(modelData1)); childValuations.Add(Currency2Payment.Calculate(modelData2)); childValuations.AddRange(Premia.Select(premium => premium.Calculate(modelData2))); } else if (modelData.MarketEnvironment.GetType() == typeof(MarketEnvironment)) { var market = (MarketEnvironment)modelData.MarketEnvironment; if (delta0PDH) { // //Force building of the risk curves. // market.SearchForPerturbedPricingStructures(FxIndexCurveName, "delta0PDH");//TODO Need to add this perturbation to fxCurve. } if (delta1PDH) { //Force building of the risk curves. market.SearchForPerturbedPricingStructures(FxLeg.Currency1DiscountCurveName, "delta1PDH"); market.SearchForPerturbedPricingStructures(FxLeg.Currency2DiscountCurveName, "delta1PDH"); } childValuations = EvaluateChildMetrics(GetChildren().ToList(), modelData, Metrics); //childValuations.Add(Currency1Payment.Calculate(modelData)); } var paymentValuation = AssetValuationHelper.AggregateMetrics(childValuations, new List <string>(Metrics), PaymentCurrencies);// modelData.ValuationDate); var childControllerValuations = new List <AssetValuation> { paymentValuation }; TimeToExpiry = GetPaymentYearFraction(ModelData.ValuationDate, ExpiryDate); var volatilityCurveNodeTime = GetPaymentYearFraction(ModelData.ValuationDate, ValueDate); // Child metrics have now been calculated so we can now evaluate the stream model metrics if (streamControllerMetrics.Count > 0) { if (modelData.MarketEnvironment is MarketEnvironment market) { var fxCurve = (IFxCurve)market.SearchForPricingStructureType(FxLeg.FxIndexCurveName); var indexSurface = (IVolatilitySurface)market.SearchForPricingStructureType(VolatilitySurfaceName); if (HybridValuation) { var curve1 = (IRateCurve)market.SearchForPricingStructureType(FxLeg.Currency1DiscountCurveName); var curve2 = (IRateCurve)market.SearchForPricingStructureType(FxLeg.Currency2DiscountCurveName); var flag = FxLeg.ExchangeRate.quotedCurrencyPair.quoteBasis == QuoteBasisEnum.Currency2PerCurrency1; AnalyticsModel = new FxOptionLegAnalytic(modelData.ValuationDate, RiskMaturityDate, fxCurve, curve1, curve2, flag, FxStrike, TimeToExpiry, volatilityCurveNodeTime, indexSurface, FxOptionType); } else { AnalyticsModel = new FxOptionLegAnalytic(modelData.ValuationDate, RiskMaturityDate, fxCurve, FxStrike, TimeToExpiry, volatilityCurveNodeTime, indexSurface, FxOptionType); } } decimal?premium = null; if (Premia.Count > 1) { premium = Premia[0].PaymentAmount.amount; // We assume only a single premium in the basic case. } IFxOptionLegParameters analyticModelParameters = new FxOptionLegParameters { Premium = premium, }; CalculationResults = AnalyticsModel.Calculate <IFxOptionLegInstrumentResults, FxOptionLegInstrumentResults>( analyticModelParameters, streamControllerMetrics.ToArray()); // Now merge back into the overall stream valuation var streamControllerValuation = GetValue(CalculationResults, modelData.ValuationDate); streamValuation = AssetValuationHelper.UpdateValuation(streamControllerValuation, childControllerValuations, ConvertMetrics(streamControllerMetrics), new List <string>(Metrics), PaymentCurrencies);// modelData.ValuationDate); } else { streamValuation = paymentValuation; } CalculationPerformedIndicator = true; streamValuation.id = Id; return(streamValuation); }
public VanillaEuropeanFxOptionPricer() { AnalyticsModel = new FxOptionLegAnalytic(); }