public override void setupArguments(IPricingEngineArguments args) { Swap.Arguments arguments = args as Swap.Arguments; Utils.QL_REQUIRE(arguments != null, () => "wrong argument type"); arguments.legs = legs_; arguments.payer = payer_; }
public override void setupArguments(IPricingEngineArguments args) { Swap.Arguments arguments = args as Swap.Arguments; if (arguments == null) { throw new ArgumentException("wrong argument type"); } arguments.legs = legs_; arguments.payer = payer_; }
public override void calculate() { /* both DTS, YTS ref dates and pricing date consistency * checks? settlement... */ Utils.QL_REQUIRE(!discountCurve_.empty(), () => "no discount term structure set"); Utils.QL_REQUIRE(!defaultTS_.empty(), () => "no ctpty default term structure set"); Utils.QL_REQUIRE(!swaptionletEngine_.empty(), () => "no swap option engine set"); Date priceDate = defaultTS_.link.referenceDate(); double cumOptVal = 0.0, cumPutVal = 0.0; // Vanilla swap so 0 leg is floater int index = 0; Date nextFD = arguments_.fixedPayDates[index]; Date swapletStart = priceDate; while (nextFD < priceDate) { index++; nextFD = arguments_.fixedPayDates[index]; } // Compute fair spread for strike value: // copy args into the non risky engine Swap.Arguments noCVAArgs = baseSwapEngine_.link.getArguments() as Swap.Arguments; noCVAArgs.legs = this.arguments_.legs; noCVAArgs.payer = this.arguments_.payer; baseSwapEngine_.link.calculate(); double baseSwapRate = ((FixedRateCoupon)arguments_.legs[0][0]).rate(); Swap.Results vSResults = baseSwapEngine_.link.getResults() as Swap.Results; double?baseSwapFairRate = -baseSwapRate * vSResults.legNPV[1] / vSResults.legNPV[0]; double?baseSwapNPV = vSResults.value; VanillaSwap.Type reversedType = arguments_.type == VanillaSwap.Type.Payer ? VanillaSwap.Type.Receiver : VanillaSwap.Type.Payer; // Swaplet options summatory: while (nextFD != arguments_.fixedPayDates.Last()) { // iFD coupon not fixed, create swaptionlet: IborIndex swapIndex = ((FloatingRateCoupon)arguments_.legs[1][0]).index() as IborIndex; // Alternatively one could cap this period to, say, 1M Period baseSwapsTenor = new Period(arguments_.fixedPayDates.Last().serialNumber() - swapletStart.serialNumber(), TimeUnit.Days); VanillaSwap swaplet = new MakeVanillaSwap(baseSwapsTenor, swapIndex, baseSwapFairRate) .withType(arguments_.type) .withNominal(arguments_.nominal) .withEffectiveDate(swapletStart) .withTerminationDate(arguments_.fixedPayDates.Last()).value(); VanillaSwap revSwaplet = new MakeVanillaSwap(baseSwapsTenor, swapIndex, baseSwapFairRate) .withType(reversedType) .withNominal(arguments_.nominal) .withEffectiveDate(swapletStart) .withTerminationDate(arguments_.fixedPayDates.Last()).value(); Swaption swaptionlet = new Swaption(swaplet, new EuropeanExercise(swapletStart)); Swaption putSwaplet = new Swaption(revSwaplet, new EuropeanExercise(swapletStart)); swaptionlet.setPricingEngine(swaptionletEngine_.currentLink()); putSwaplet.setPricingEngine(swaptionletEngine_.currentLink()); // atm underlying swap means that the value of put = value // call so this double pricing is not needed cumOptVal += swaptionlet.NPV() * defaultTS_.link.defaultProbability( swapletStart, nextFD); cumPutVal += putSwaplet.NPV() * invstDTS_.link.defaultProbability(swapletStart, nextFD); swapletStart = nextFD; index++; nextFD = arguments_.fixedPayDates[index]; } results_.value = baseSwapNPV - (1.0 - ctptyRecoveryRate_) * cumOptVal + (1.0 - invstRecoveryRate_) * cumPutVal; results_.fairRate = -baseSwapRate * (vSResults.legNPV[1] - (1.0 - ctptyRecoveryRate_) * cumOptVal + (1.0 - invstRecoveryRate_) * cumPutVal) / vSResults.legNPV[0]; }