public void testCachedValue() { //"Testing swaption value against cached value..."); CommonVars vars = new CommonVars(); vars.today = new Date(13, 3, 2002); vars.settlement = new Date(15, 3, 2002); Settings.setEvaluationDate(vars.today); vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, 0.05, new Actual365Fixed())); Date exerciseDate = vars.calendar.advance(vars.settlement, new Period(5, TimeUnit.Years)); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); VanillaSwap swap = new MakeVanillaSwap(new Period(10, TimeUnit.Years), vars.index, 0.06) .withEffectiveDate(startDate); Swaption swaption = vars.makeSwaption(swap, exerciseDate, 0.20); //#if QL_USE_INDEXED_COUPON double cachedNPV = 0.036418158579; //#else // double cachedNPV = 0.036421429684; //#endif // FLOATING_POINT_EXCEPTION if (Math.Abs(swaption.NPV() - cachedNPV) > 1.0e-12) { Assert.Fail("failed to reproduce cached swaption value:\n" + //QL_FIXED + std::setprecision(12) + "\ncalculated: " + swaption.NPV() + "\nexpected: " + cachedNPV); } }
// \warning Relinking the term structure underlying the index will not have effect on the returned swap. // recheck public VanillaSwap underlyingSwap(Date fixingDate) { Utils.QL_REQUIRE(fixingDate != null, () => "null fixing date"); // caching mechanism if (lastFixingDate_ != fixingDate) { double fixedRate = 0.0; if (exogenousDiscount_) { lastSwap_ = new MakeVanillaSwap(tenor_, iborIndex_, fixedRate) .withEffectiveDate(valueDate(fixingDate)) .withFixedLegCalendar(fixingCalendar()) .withFixedLegDayCount(dayCounter_) .withFixedLegTenor(fixedLegTenor_) .withFixedLegConvention(fixedLegConvention_) .withFixedLegTerminationDateConvention(fixedLegConvention_) .withDiscountingTermStructure(discount_) .value(); } else { lastSwap_ = new MakeVanillaSwap(tenor_, iborIndex_, fixedRate) .withEffectiveDate(valueDate(fixingDate)) .withFixedLegCalendar(fixingCalendar()) .withFixedLegDayCount(dayCounter_) .withFixedLegTenor(fixedLegTenor_) .withFixedLegConvention(fixedLegConvention_) .withFixedLegTerminationDateConvention(fixedLegConvention_) .value(); } lastFixingDate_ = fixingDate; } return(lastSwap_); }
protected override void initializeDates() { // do not pass the spread here, as it might be a Quote i.e. it can dinamically change // input discount curve Handle might be empty now but it could be assigned a curve later; // use a RelinkableHandle here swap_ = new MakeVanillaSwap(tenor_, iborIndex_, 0.0, fwdStart_) .withSettlementDays(settlementDays_.Value) .withDiscountingTermStructure(discountRelinkableHandle_) .withFixedLegDayCount(fixedDayCount_) .withFixedLegTenor(new Period(fixedFrequency_)) .withFixedLegConvention(fixedConvention_) .withFixedLegTerminationDateConvention(fixedConvention_) .withFixedLegCalendar(calendar_) .withFloatingLegCalendar(calendar_); earliestDate_ = swap_.startDate(); // Usually... maturityDate_ = latestRelevantDate_ = swap_.maturityDate(); // ...but due to adjustments, the last floating coupon might // need a later date for fixing #if QL_USE_INDEXED_COUPON FloatingRateCoupon lastCoupon = (FloatingRateCoupon)swap_.floatingLeg()[swap_.floatingLeg().Count - 1]; Date fixingValueDate = iborIndex_.valueDate(lastFloating.fixingDate()); Date endValueDate = iborIndex_.maturityDate(fixingValueDate); latestDate_ = Date.Max(latestDate_, endValueDate); #endif switch (pillarChoice_) { case Pillar.Choice.MaturityDate: pillarDate_ = maturityDate_; break; case Pillar.Choice.LastRelevantDate: pillarDate_ = latestRelevantDate_; break; case Pillar.Choice.CustomDate: // pillarDate_ already assigned at construction time Utils.QL_REQUIRE(pillarDate_ >= earliestDate_, () => "pillar date (" + pillarDate_ + ") must be later " + "than or equal to the instrument's earliest date (" + earliestDate_ + ")"); Utils.QL_REQUIRE(pillarDate_ <= latestRelevantDate_, () => "pillar date (" + pillarDate_ + ") must be before " + "or equal to the instrument's latest relevant date (" + latestRelevantDate_ + ")"); break; default: Utils.QL_FAIL("unknown Pillar::Choice(" + pillarChoice_ + ")"); break; } latestDate_ = pillarDate_; // backward compatibility }
public MakeVanillaSwap withFloatingLegNextToLastDate(Date d) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegNextToLastDate(swigCPtr, Date.getCPtr(d)), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withFloatingLegDayCount(DayCounter dc) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegDayCount(swigCPtr, DayCounter.getCPtr(dc)), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withFloatingLegSpread(double sp) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegSpread(swigCPtr, sp), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withNominal(double n) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withNominal(swigCPtr, n), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap receiveFixed() { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_receiveFixed__SWIG_1(swigCPtr), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withType(VanillaSwap.Type type) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withType(swigCPtr, (int)type), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withDiscountingTermStructure(YieldTermStructureHandle discountCurve) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withDiscountingTermStructure(swigCPtr, YieldTermStructureHandle.getCPtr(discountCurve)), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withPricingEngine(PricingEngine engine) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withPricingEngine(swigCPtr, PricingEngine.getCPtr(engine)), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withFloatingLegEndOfMonth() { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegEndOfMonth__SWIG_1(swigCPtr), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withTerminationDate(Date arg0) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withTerminationDate(swigCPtr, Date.getCPtr(arg0)), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withFloatingLegTerminationDateConvention(BusinessDayConvention bdc) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegTerminationDateConvention(swigCPtr, (int)bdc), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withFloatingLegRule(DateGeneration.Rule r) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegRule(swigCPtr, (int)r), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withFloatingLegCalendar(Calendar cal) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegCalendar(swigCPtr, Calendar.getCPtr(cal)), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withFloatingLegTenor(Period t) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withFloatingLegTenor(swigCPtr, Period.getCPtr(t)), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public MakeVanillaSwap withSettlementDays(uint settlementDays) { MakeVanillaSwap ret = new MakeVanillaSwap(NQuantLibcPINVOKE.MakeVanillaSwap_withSettlementDays(swigCPtr, settlementDays), false); if (NQuantLibcPINVOKE.SWIGPendingException.Pending) { throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
public Swaption value() { Date evaluationDate = Settings.evaluationDate(); Calendar fixingCalendar = swapIndex_.fixingCalendar(); fixingDate_ = fixingCalendar.advance(evaluationDate, optionTenor_, optionConvention_); if (exerciseDate_ == null) { exercise_ = new EuropeanExercise(fixingDate_); } else { Utils.QL_REQUIRE(exerciseDate_ <= fixingDate_, () => "exercise date (" + exerciseDate_ + ") must be less " + "than or equal to fixing date (" + fixingDate_ + ")"); exercise_ = new EuropeanExercise(exerciseDate_); } double usedStrike; if (strike_ == null) { // ATM on the forecasting curve Utils.QL_REQUIRE(!swapIndex_.forwardingTermStructure().empty(), () => "no forecasting term structure set to " + swapIndex_.name()); VanillaSwap temp = swapIndex_.underlyingSwap(fixingDate_); temp.setPricingEngine(new DiscountingSwapEngine(swapIndex_.forwardingTermStructure())); usedStrike = temp.fairRate(); } else { usedStrike = strike_.Value; } BusinessDayConvention bdc = swapIndex_.fixedLegConvention(); underlyingSwap_ = new MakeVanillaSwap(swapIndex_.tenor(), swapIndex_.iborIndex(), usedStrike) .withEffectiveDate(swapIndex_.valueDate(fixingDate_)) .withFixedLegCalendar(swapIndex_.fixingCalendar()) .withFixedLegDayCount(swapIndex_.dayCounter()) .withFixedLegConvention(bdc) .withFixedLegTerminationDateConvention(bdc) .withType(underlyingType_) .withNominal(nominal_); Swaption swaption = new Swaption(underlyingSwap_, exercise_, delivery_, settlementMethod_); swaption.setPricingEngine(engine_); return(swaption); }
public void testJpyLibor() { //"Testing bootstrap over JPY LIBOR swaps..."); CommonVars vars = new CommonVars(); vars.today = new Date(4, Month.October, 2007); Settings.setEvaluationDate(vars.today); vars.calendar = new Japan(); vars.settlement = vars.calendar.advance(vars.today, vars.settlementDays, TimeUnit.Days); // market elements vars.rates = new InitializedList <SimpleQuote>(vars.swaps); for (int i = 0; i < vars.swaps; i++) { vars.rates[i] = new SimpleQuote(vars.swapData[i].rate / 100); } // rate helpers vars.instruments = new InitializedList <RateHelper>(vars.swaps); IborIndex index = new JPYLibor(new Period(6, TimeUnit.Months)); for (int i = 0; i < vars.swaps; i++) { Handle <Quote> r = new Handle <Quote>(vars.rates[i]); vars.instruments[i] = new SwapRateHelper(r, new Period(vars.swapData[i].n, vars.swapData[i].units), vars.calendar, vars.fixedLegFrequency, vars.fixedLegConvention, vars.fixedLegDayCounter, index); } vars.termStructure = new PiecewiseYieldCurve <Discount, LogLinear>( vars.settlement, vars.instruments, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12); RelinkableHandle <YieldTermStructure> curveHandle = new RelinkableHandle <YieldTermStructure>(); curveHandle.linkTo(vars.termStructure); // check swaps IborIndex jpylibor6m = new JPYLibor(new Period(6, TimeUnit.Months), curveHandle); for (int i = 0; i < vars.swaps; i++) { Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units); VanillaSwap swap = new MakeVanillaSwap(tenor, jpylibor6m, 0.0) .withEffectiveDate(vars.settlement) .withFixedLegDayCount(vars.fixedLegDayCounter) .withFixedLegTenor(new Period(vars.fixedLegFrequency)) .withFixedLegConvention(vars.fixedLegConvention) .withFixedLegTerminationDateConvention(vars.fixedLegConvention) .withFixedLegCalendar(vars.calendar) .withFloatingLegCalendar(vars.calendar) .value(); double expectedRate = vars.swapData[i].rate / 100, estimatedRate = swap.fairRate(); double error = Math.Abs(expectedRate - estimatedRate); double tolerance = 1.0e-9; if (error > tolerance) { QAssert.Fail(vars.swapData[i].n + " year(s) swap:\n" + "\n estimated rate: " + (estimatedRate) + "\n expected rate: " + (expectedRate) + "\n error: " + (error) + "\n tolerance: " + (tolerance)); } } }
public void testSpreadDependency() { //"Testing swaption dependency on spread..."; CommonVars vars = new CommonVars(); double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { for (int k = 0; k < type.Length; k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); // store the results for different rates... List <double> values = new InitializedList <double>(spreads.Length); List <double> values_cash = new InitializedList <double>(spreads.Length); for (int l = 0; l < spreads.Length; l++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, 0.06) .withEffectiveDate(startDate) .withFloatingLegSpread(spreads[l]) .withType(type[k]); Swaption swaption = vars.makeSwaption(swap, exerciseDate, 0.20); // FLOATING_POINT_EXCEPTION values[l] = swaption.NPV(); Swaption swaption_cash = vars.makeSwaption(swap, exerciseDate, 0.20, Settlement.Type.Cash); values_cash[l] = swaption_cash.NPV(); } // and check that they go the right way if (type[k] == VanillaSwap.Type.Payer) { for (int n = 0; n < spreads.Length - 1; n++) { if (values[n] > values[n + 1]) { Assert.Fail("NPV is decreasing with the spread " + "in a payer swaption (physical delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values[n] + " for spread: " + spreads[n] + "\nvalue: " + values[n + 1] + " for spread: " + spreads[n + 1]); } if (values_cash[n] > values_cash[n + 1]) { Assert.Fail("NPV is decreasing with the spread " + "in a payer swaption (cash delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values_cash[n] + " for spread: " + spreads[n] + "\nvalue: " + values_cash[n + 1] + " for spread: " + spreads[n + 1]); } } } else { for (int n = 0; n < spreads.Length - 1; n++) { if (values[n] < values[n + 1]) { Assert.Fail("NPV is increasing with the spread " + "in a receiver swaption (physical delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values[n] + " for spread: " + spreads[n] + "\nvalue: " + values[n + 1] + " for spread: " + spreads[n + 1]); } if (values_cash[n] < values_cash[n + 1]) { Assert.Fail("NPV is increasing with the spread " + "in a receiver swaption (cash delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values_cash[n] + " for spread: " + spreads[n] + "\nvalue: " + values_cash[n + 1] + " for spread: " + spreads[n + 1]); } } } } } } }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(MakeVanillaSwap obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
public void testLiborFixing() { // "Testing use of today's LIBOR fixings in swap curve..."); CommonVars vars = new CommonVars(); var swapHelpers = new InitializedList <RateHelper>(); IborIndex euribor6m = new Euribor6M(); for (int i = 0; i < vars.swaps; i++) { Handle <Quote> r = new Handle <Quote>(vars.rates[i + vars.deposits]); swapHelpers.Add(new SwapRateHelper(r, new Period(vars.swapData[i].n, vars.swapData[i].units), vars.calendar, vars.fixedLegFrequency, vars.fixedLegConvention, vars.fixedLegDayCounter, euribor6m)); } vars.termStructure = new PiecewiseYieldCurve <Discount, LogLinear>(vars.settlement, swapHelpers, new Actual360()); Handle <YieldTermStructure> curveHandle = new Handle <YieldTermStructure>(vars.termStructure); IborIndex index = new Euribor6M(curveHandle); for (int i = 0; i < vars.swaps; i++) { Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units); VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0) .withEffectiveDate(vars.settlement) .withFixedLegDayCount(vars.fixedLegDayCounter) .withFixedLegTenor(new Period(vars.fixedLegFrequency)) .withFixedLegConvention(vars.fixedLegConvention) .withFixedLegTerminationDateConvention(vars.fixedLegConvention) .value(); double expectedRate = vars.swapData[i].rate / 100, estimatedRate = swap.fairRate(); double tolerance = 1.0e-9; if (Math.Abs(expectedRate - estimatedRate) > tolerance) { QAssert.Fail("before LIBOR fixing:\n" + vars.swapData[i].n + " year(s) swap:\n" + " estimated rate: " + (estimatedRate) + "\n" + " expected rate: " + (expectedRate)); } } Flag f = new Flag(); vars.termStructure.registerWith(f.update); f.lower(); index.addFixing(vars.today, 0.0425); if (!f.isUp()) { QAssert.Fail("Observer was not notified of rate fixing"); } for (int i = 0; i < vars.swaps; i++) { Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units); VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0) .withEffectiveDate(vars.settlement) .withFixedLegDayCount(vars.fixedLegDayCounter) .withFixedLegTenor(new Period(vars.fixedLegFrequency)) .withFixedLegConvention(vars.fixedLegConvention) .withFixedLegTerminationDateConvention(vars.fixedLegConvention) .value(); double expectedRate = vars.swapData[i].rate / 100, estimatedRate = swap.fairRate(); double tolerance = 1.0e-9; if (Math.Abs(expectedRate - estimatedRate) > tolerance) { QAssert.Fail("after LIBOR fixing:\n" + vars.swapData[i].n + " year(s) swap:\n" + " estimated rate: " + (estimatedRate) + "\n" + " expected rate: " + (expectedRate)); } } }
public void testImpliedVolatility() { //"Testing implied volatility for swaptions..."; CommonVars vars = new CommonVars(); int maxEvaluations = 100; double tolerance = 1.0e-08; Settlement.Type[] types = { Settlement.Type.Physical, Settlement.Type.Cash }; // test data double[] strikes = { 0.02, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.20, 0.30, 0.70, 0.90 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); Date maturity = vars.calendar.advance(startDate, lengths[j], vars.floatingConvention); for (int t = 0; t < strikes.Length; t++) { for (int k = 0; k < type.Length; k++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[t]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); for (int h = 0; h < types.Length; h++) { for (int u = 0; u < vols.Length; u++) { Swaption swaption = vars.makeSwaption(swap, exerciseDate, vols[u], types[h]); // Black price double value = swaption.NPV(); double implVol = 0.0; try { implVol = swaption.impliedVolatility(value, vars.termStructure, 0.10, tolerance, maxEvaluations); } catch (System.Exception e) { // couldn't bracket? swaption.setPricingEngine(vars.makeEngine(0.0)); double value2 = swaption.NPV(); if (Math.Abs(value - value2) < tolerance) { // ok, just skip: continue; } // otherwise, report error Assert.Fail("implied vol failure: " + exercises[i] + "x" + lengths[j] + " " + type[k] + "\nsettlement: " + types[h] + "\nstrike " + strikes[t] + "\natm level: " + swap.fairRate() + "\nvol: " + vols[u] + "\nprice: " + value + "\n" + e.Message.ToString()); } if (Math.Abs(implVol - vols[u]) > tolerance) { // the difference might not matter swaption.setPricingEngine(vars.makeEngine(implVol)); double value2 = swaption.NPV(); if (Math.Abs(value - value2) > tolerance) { Assert.Fail("implied vol failure: " + exercises[i] + "x" + lengths[j] + " " + type[k] + "\nsettlement: " + types[h] + "\nstrike " + strikes[t] + "\natm level: " + swap.fairRate() + "\nvol: " + vols[u] + "\nprice: " + value + "\nimplied vol: " + implVol + "\nimplied price: " + value2); } } } } } } } } }
public void testCurveConsistency <T, I, B>(CommonVars vars, I interpolator, double tolerance) where T : ITraits <YieldTermStructure>, new() where I : IInterpolationFactory, new() where B : IBootStrap <PiecewiseYieldCurve>, new() { vars.termStructure = new PiecewiseYieldCurve <T, I, B>(vars.settlement, vars.instruments, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12, interpolator); RelinkableHandle <YieldTermStructure> curveHandle = new RelinkableHandle <YieldTermStructure>(); curveHandle.linkTo(vars.termStructure); // check deposits for (int i = 0; i < vars.deposits; i++) { Euribor index = new Euribor(new Period(vars.depositData[i].n, vars.depositData[i].units), curveHandle); double expectedRate = vars.depositData[i].rate / 100, estimatedRate = index.fixing(vars.today); QAssert.IsTrue(Math.Abs(expectedRate - estimatedRate) < tolerance, vars.depositData[i].n + " " + (vars.depositData[i].units == TimeUnit.Weeks ? "week(s)" : "month(s)") + " deposit:" + "\n estimated rate: " + estimatedRate + "\n expected rate: " + expectedRate); } // check swaps IborIndex euribor6m = new Euribor6M(curveHandle); for (int i = 0; i < vars.swaps; i++) { Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units); VanillaSwap swap = new MakeVanillaSwap(tenor, euribor6m, 0.0) .withEffectiveDate(vars.settlement) .withFixedLegDayCount(vars.fixedLegDayCounter) .withFixedLegTenor(new Period(vars.fixedLegFrequency)) .withFixedLegConvention(vars.fixedLegConvention) .withFixedLegTerminationDateConvention(vars.fixedLegConvention); double expectedRate = vars.swapData[i].rate / 100, estimatedRate = swap.fairRate(); double error = Math.Abs(expectedRate - estimatedRate); QAssert.IsTrue(error < tolerance, vars.swapData[i].n + " year(s) swap:\n" + "\n estimated rate: " + estimatedRate + "\n expected rate: " + expectedRate + "\n error: " + error + "\n tolerance: " + tolerance); } // check bonds vars.termStructure = new PiecewiseYieldCurve <T, I, B>(vars.settlement, vars.bondHelpers, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12, interpolator); curveHandle.linkTo(vars.termStructure); for (int i = 0; i < vars.bonds; i++) { Date maturity = vars.calendar.advance(vars.today, vars.bondData[i].n, vars.bondData[i].units); Date issue = vars.calendar.advance(maturity, -vars.bondData[i].length, TimeUnit.Years); List <double> coupons = new List <double>() { vars.bondData[i].coupon / 100.0 }; FixedRateBond bond = new FixedRateBond(vars.bondSettlementDays, 100.0, vars.schedules[i], coupons, vars.bondDayCounter, vars.bondConvention, vars.bondRedemption, issue); IPricingEngine bondEngine = new DiscountingBondEngine(curveHandle); bond.setPricingEngine(bondEngine); double expectedPrice = vars.bondData[i].price, estimatedPrice = bond.cleanPrice(); QAssert.IsTrue(Math.Abs(expectedPrice - estimatedPrice) < tolerance, i + 1 + " bond failure:" + "\n estimated price: " + estimatedPrice + "\n expected price: " + expectedPrice); } // check FRA vars.termStructure = new PiecewiseYieldCurve <T, I, B>(vars.settlement, vars.fraHelpers, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12, interpolator); curveHandle.linkTo(vars.termStructure); IborIndex euribor3m = new Euribor3M(curveHandle); for (int i = 0; i < vars.fras; i++) { Date start = vars.calendar.advance(vars.settlement, vars.fraData[i].n, vars.fraData[i].units, euribor3m.businessDayConvention(), euribor3m.endOfMonth()); Date end = vars.calendar.advance(start, 3, TimeUnit.Months, euribor3m.businessDayConvention(), euribor3m.endOfMonth()); ForwardRateAgreement fra = new ForwardRateAgreement(start, end, Position.Type.Long, vars.fraData[i].rate / 100, 100.0, euribor3m, curveHandle); double expectedRate = vars.fraData[i].rate / 100, estimatedRate = fra.forwardRate().rate(); QAssert.IsTrue(Math.Abs(expectedRate - estimatedRate) < tolerance, i + 1 + " FRA failure:" + "\n estimated rate: " + estimatedRate + "\n expected rate: " + expectedRate); } }
public void testSpreadTreatment() { //"Testing swaption treatment of spread..."; CommonVars vars = new CommonVars(); double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { for (int k = 0; k < type.Length; k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); for (int l = 0; l < spreads.Length; l++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, 0.06) .withEffectiveDate(startDate) .withFloatingLegSpread(spreads[l]) .withType(type[k]); // FLOATING_POINT_EXCEPTION double correction = spreads[l] * swap.floatingLegBPS() / swap.fixedLegBPS(); VanillaSwap equivalentSwap = new MakeVanillaSwap(lengths[j], vars.index, 0.06 + correction) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); Swaption swaption1 = vars.makeSwaption(swap, exerciseDate, 0.20); Swaption swaption2 = vars.makeSwaption(equivalentSwap, exerciseDate, 0.20); Swaption swaption1_cash = vars.makeSwaption(swap, exerciseDate, 0.20, Settlement.Type.Cash); Swaption swaption2_cash = vars.makeSwaption(equivalentSwap, exerciseDate, 0.20, Settlement.Type.Cash); if (Math.Abs(swaption1.NPV() - swaption2.NPV()) > 1.0e-6) { Assert.Fail("wrong spread treatment:" + "\nexercise: " + exerciseDate + "\nlength: " + lengths[j] + "\ntype " + type[k] + "\nspread: " + spreads[l] + "\noriginal swaption value: " + swaption1.NPV() + "\nequivalent swaption value: " + swaption2.NPV()); } if (Math.Abs(swaption1_cash.NPV() - swaption2_cash.NPV()) > 1.0e-6) { Assert.Fail("wrong spread treatment:" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + //"\npay " + (type[k] ? "fixed" : "floating") + "\nspread: " + spreads[l] + "\nvalue of original swaption: " + swaption1_cash.NPV() + "\nvalue of equivalent swaption: " + swaption2_cash.NPV()); } } } } } }
public void testStrikeDependency() { //("Testing swaption dependency on strike......"); CommonVars vars = new CommonVars(); double[] strikes = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { for (int k = 0; k < type.Length; k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); // store the results for different rates... List <double> values = new InitializedList <double>(strikes.Length); List <double> values_cash = new InitializedList <double>(strikes.Length); double vol = 0.20; for (int l = 0; l < strikes.Length; l++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[l]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); Swaption swaption = vars.makeSwaption(swap, exerciseDate, vol); // FLOATING_POINT_EXCEPTION values[l] = swaption.NPV(); Swaption swaption_cash = vars.makeSwaption(swap, exerciseDate, vol, Settlement.Type.Cash); values_cash[l] = swaption_cash.NPV(); } // and check that they go the right way if (type[k] == VanillaSwap.Type.Payer) { for (int z = 0; z < values.Count - 1; z++) { if (values[z] < values[z + 1]) { Assert.Fail("NPV of Payer swaption with delivery settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values[z] + " at strike: " + strikes[z] + "\nvalue: " + values[z + 1] + " at strike: " + strikes[z + 1]); } } for (int z = 0; z < values_cash.Count - 1; z++) { if (values_cash[z] < values_cash[z + 1]) { Assert.Fail("NPV of Payer swaption with cash settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values_cash[z] + " at strike: " + strikes[z] + "\nvalue: " + values_cash[z + 1] + " at strike: " + strikes[z + 1]); } } } else { for (int z = 0; z < values.Count - 1; z++) { if (values[z] > values[z + 1]) { Assert.Fail("NPV of Receiver swaption with delivery settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values[z] + " at strike: " + strikes[z] + "\nvalue: " + values[z + 1] + " at strike: " + strikes[z + 1]); } } for (int z = 0; z < values_cash.Count - 1; z++) { if (values[z] > values[z + 1]) { Assert.Fail("NPV of Receiver swaption with cash settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values_cash[z] + " at strike: " + strikes[z] + "\nvalue: " + values_cash[z + 1] + " at strike: " + strikes[z + 1]); } } } } } } }
public void testVega() { //"Testing swaption vega..."; CommonVars vars = new CommonVars(); Settlement.Type[] types = { Settlement.Type.Physical, Settlement.Type.Cash }; double[] strikes = { 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.20, 0.30, 0.70, 0.90 }; double shift = 1e-8; for (int i = 0; i < exercises.Length; i++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); // A VERIFIER§§§§ Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); for (int j = 0; j < lengths.Length; j++) { for (int t = 0; t < strikes.Length; t++) { for (int h = 0; h < type.Length; h++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[t]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[h]); for (int u = 0; u < vols.Length; u++) { Swaption swaption = vars.makeSwaption(swap, exerciseDate, vols[u], types[h]); // FLOATING_POINT_EXCEPTION Swaption swaption1 = vars.makeSwaption(swap, exerciseDate, vols[u] - shift, types[h]); Swaption swaption2 = vars.makeSwaption(swap, exerciseDate, vols[u] + shift, types[h]); double swaptionNPV = swaption.NPV(); double numericalVegaPerPoint = (swaption2.NPV() - swaption1.NPV()) / (200.0 * shift); // check only relevant vega if (numericalVegaPerPoint / swaptionNPV > 1.0e-7) { double analyticalVegaPerPoint = (double)swaption.result("vega") / 100.0; double discrepancy = Math.Abs(analyticalVegaPerPoint - numericalVegaPerPoint); discrepancy /= numericalVegaPerPoint; double tolerance = 0.015; if (discrepancy > tolerance) { Assert.Fail("failed to compute swaption vega:" + "\n option tenor: " + exercises[i] + "\n volatility: " + vols[u] + "\n option type: " + swaption.type() + "\n swap tenor: " + lengths[j] + "\n strike: " + strikes[t] + "\n settlement: " + types[h] + "\n nominal: " + swaption.underlyingSwap().nominal + "\n npv: " + swaptionNPV + "\n calculated vega: " + analyticalVegaPerPoint + "\n expected vega: " + numericalVegaPerPoint + "\n discrepancy: " + discrepancy + "\n tolerance: " + tolerance); } } } } } } } }