/// <summary> /// Aggregate the valuation profile onto a set of result curves to support result partitioning. /// </summary> protected override void ProcessResults(ValuationResults valResults, DealPartitionAssociations assoc, PriceFactorList factors, BaseTimeGrid baseTimes, ValuationOptions options, int partition) { var pvProfiles = valResults.Results <PVProfiles>(); var addOnProfiles = valResults.Results <AddOnProfiles>(); var positiveMtmProfiles = valResults.Results <PositiveMtmProfiles>(); Debug.Assert(addOnProfiles != null, "No Add-On profiles. Cannot proceed with valuation."); Debug.Assert(positiveMtmProfiles != null, "No Positive mtM profiles. Cannot proceed with valuation."); fT = Deal.ValuationGrid(factors, baseTimes, Deal.EndDate()); var tgi = new TimeGridIterator(fT); var nettedExposure = new PVProfiles(factors.NumScenarios); var collateralExposure = new PVProfiles(factors.NumScenarios); var addOnsProfile = new PVProfiles(factors.NumScenarios); var mtmTermProfile = new PVProfiles(factors.NumScenarios); DealBaselNettingCollateralSet nettingSetDeal = Deal as DealBaselNettingCollateralSet; bool collateralised = nettingSetDeal.Collateralised == YesNo.Yes; using (var cache = Vector.Cache(factors.NumScenarios)) { Vector sumMtm = cache.Get(); Vector sumPositiveMtm = cache.Get(); Vector addOns = cache.Get(); Vector netGrossRatio = cache.Get(); Vector value = cache.Get(); Vector term1 = cache.Get(); Vector term2 = cache.Get(); // Collateral related vectors. Vector mtmTermStart = cache.Get(); Vector addOnHp = cache.Get(); // Loop to get the netting set exposure. while (tgi.Next()) { sumMtm.Clear(); sumPositiveMtm.Clear(); addOns.Clear(); value.Clear(); double date = tgi.Date; // For MtM Plus Add-On deals PV profiles represents the sum of the MtM profile and Add-On profile. // Subtract the Add-On profile to recover the MtM profile before flooring. sumMtm.Assign(VectorMath.Max(pvProfiles[date] - addOnProfiles[date], 0.0)); addOns.Assign(addOnProfiles[date]); sumPositiveMtm.Assign(positiveMtmProfiles[date]); netGrossRatio.AssignConditional(sumPositiveMtm > 0, sumMtm / sumPositiveMtm, 0.0); netGrossRatio.MultiplyBy(this.fNetGrossRatioCorrelation); netGrossRatio.Add(1 - this.fNetGrossRatioCorrelation); term2.AssignProduct(addOns, netGrossRatio); term1.Assign(VectorMath.Max(sumMtm, 0.0)); value.AssignSum(term1, term2); nettedExposure.AppendVector(date, value); if (collateralised) { mtmTermProfile.AppendVector(date, term1); addOnsProfile.AppendVector(date, term2); } } nettedExposure.Complete(this.fT); var exposureResults = valResults.Results <Exposure>(); if (exposureResults != null) { exposureResults.Assign(nettedExposure); } // Collateral cases. if (collateralised) { mtmTermProfile.Complete(this.fT); addOnsProfile.Complete(this.fT); double date = factors.BaseDate; mtmTermProfile.GetValue(mtmTermStart, date); addOnsProfile.GetValue(addOnHp, date + nettingSetDeal.Holding_Period); // Assume we have post haircut collateral. double collateral = nettingSetDeal.Balance; double threshold = nettingSetDeal.Threshold; tgi.Reset(); // Loop to get the netting set exposure. while (tgi.Next()) { bool inHoldingPeriod = tgi.T < CalcUtils.DaysToYears(nettingSetDeal.Holding_Period); CollateralBasel3(mtmTermStart, collateral, addOnHp, threshold, inHoldingPeriod, tgi.Date, nettedExposure, collateralExposure); } collateralExposure.Complete(this.fT); if (exposureResults != null) { exposureResults.Assign(collateralExposure); } } } if (options.PartitionCollateralMode != PartitionCollateralMode.Suppress_Collateral_And_Flooring || partition < options.NumTotalPartitions) { valResults.FloorResult(assoc.AggregationMode, options); } CollateralPlugIn.CollateralBalancesContainer coProfiles = valResults.Results <CollateralPlugIn.CollateralBalancesContainer>(); // Store collateral information according to diagnostic collection rules. if (coProfiles != null) { coProfiles.StoreInformation(this); } }