public DiscretizedSwap(VanillaSwap.Arguments args, Date referenceDate, DayCounter dayCounter) { arguments_ = args; fixedResetTimes_ = new InitializedList<double>(args.fixedResetDates.Count); for (int i = 0; i < fixedResetTimes_.Count; ++i) fixedResetTimes_[i] = dayCounter.yearFraction(referenceDate, args.fixedResetDates[i]); fixedPayTimes_ = new InitializedList<double>(args.fixedPayDates.Count); for (int i = 0; i < fixedPayTimes_.Count; ++i) fixedPayTimes_[i] = dayCounter.yearFraction(referenceDate, args.fixedPayDates[i]); floatingResetTimes_ = new InitializedList<double>(args.floatingResetDates.Count); for (int i = 0; i < floatingResetTimes_.Count; ++i) floatingResetTimes_[i] = dayCounter.yearFraction(referenceDate, args.floatingResetDates[i]); floatingPayTimes_ = new InitializedList<double>(args.floatingPayDates.Count); for (int i = 0; i < floatingPayTimes_.Count; ++i) floatingPayTimes_[i] = dayCounter.yearFraction(referenceDate, args.floatingPayDates[i]); }
public void testATMRate() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention); Schedule schedule = new Schedule(startDate, maturity, new Period(vars.frequency), vars.calendar, vars.convention, vars.convention, DateGeneration.Rule.Forward, false); for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < vols.Length; k++) { CapFloor cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]); CapFloor floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]); double capATMRate = cap.atmRate(vars.termStructure); double floorATMRate = floor.atmRate(vars.termStructure); if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10)) Assert.Fail( "Cap ATM Rate and floor ATM Rate should be equal :\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " strike: " + strikes[j] + "\n" + " cap ATM rate: " + capATMRate + "\n" + " floor ATM rate:" + floorATMRate + "\n" + " relative Error:" + Utilities.relativeError(capATMRate, floorATMRate, capATMRate) * 100 + "%"); VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], schedule, floorATMRate, vars.index.dayCounter(), schedule, vars.index, 0.0, vars.index.dayCounter()); swap.setPricingEngine((IPricingEngine)( new DiscountingSwapEngine(vars.termStructure))); double swapNPV = swap.NPV(); if (!checkAbsError(swapNPV, 0, 1.0e-10)) Assert.Fail( "the NPV of a Swap struck at ATM rate " + "should be equal to 0:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " ATM rate: " + floorATMRate + "\n" + " swap NPV: " + swapNPV); } } } }
public SwaptionHelper(Period maturity, Period length, Handle<Quote> volatility, IborIndex index, Period fixedLegTenor, DayCounter fixedLegDayCounter, DayCounter floatingLegDayCounter, Handle<YieldTermStructure> termStructure, bool calibrateVolatility /*= false*/) : base(volatility,termStructure, calibrateVolatility) { Calendar calendar = index.fixingCalendar(); Period indexTenor = index.tenor(); int fixingDays = index.fixingDays(); Date exerciseDate = calendar.advance(termStructure.link.referenceDate(), maturity, index.businessDayConvention()); Date startDate = calendar.advance(exerciseDate, fixingDays, TimeUnit.Days, index.businessDayConvention()); Date endDate = calendar.advance(startDate, length, index.businessDayConvention()); Schedule fixedSchedule=new Schedule(startDate, endDate, fixedLegTenor, calendar, index.businessDayConvention(), index.businessDayConvention(), DateGeneration.Rule.Forward, false); Schedule floatSchedule=new Schedule(startDate, endDate, index.tenor(), calendar, index.businessDayConvention(), index.businessDayConvention(), DateGeneration.Rule.Forward, false); IPricingEngine swapEngine=new DiscountingSwapEngine(termStructure); VanillaSwap temp=new VanillaSwap(VanillaSwap.Type.Receiver, 1.0, fixedSchedule, 0.0, fixedLegDayCounter, floatSchedule, index, 0.0, floatingLegDayCounter); temp.setPricingEngine(swapEngine); exerciseRate_ = temp.fairRate(); swap_ = new VanillaSwap(VanillaSwap.Type.Receiver, 1.0, fixedSchedule, exerciseRate_, fixedLegDayCounter, floatSchedule, index, 0.0, floatingLegDayCounter); swap_.setPricingEngine(swapEngine); Exercise exercise=new EuropeanExercise(exerciseDate); swaption_ = new Swaption(swap_, exercise); marketValue_ = blackPrice(volatility_.link.value()); }
public override void calculate() { Utils.QL_REQUIRE(arguments_.settlementType == Settlement.Type.Physical, () => "cash-settled swaptions not priced with Lfm engine"); double basisPoint = 1.0e-4; VanillaSwap swap = arguments_.swap; IPricingEngine pe = new DiscountingSwapEngine(discountCurve_); swap.setPricingEngine(pe); double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); double fixedRate = swap.fixedRate - correction; double fairRate = swap.fairRate() - correction; SwaptionVolatilityMatrix volatility = model_.link.getSwaptionVolatilityMatrix(); Date referenceDate = volatility.referenceDate(); DayCounter dayCounter = volatility.dayCounter(); double exercise = dayCounter.yearFraction(referenceDate, arguments_.exercise.date(0)); double swapLength = dayCounter.yearFraction(referenceDate, arguments_.fixedPayDates.Last()) - dayCounter.yearFraction(referenceDate, arguments_.fixedResetDates[0]); Option.Type w = arguments_.type == VanillaSwap.Type.Payer ? Option.Type.Call : Option.Type.Put; double vol = volatility.volatility(exercise, swapLength, fairRate, true); results_.value = (swap.fixedLegBPS() / basisPoint) * Utils.blackFormula(w, fixedRate, fairRate, vol * Math.Sqrt(exercise)); }
public CapFloor value() { VanillaSwap swap = makeVanillaSwap_; List <CashFlow> leg = swap.floatingLeg(); if (firstCapletExcluded_) { leg.RemoveAt(0); } // only leaves the last coupon if (asOptionlet_ && leg.Count > 1) { leg.RemoveRange(0, leg.Count - 2); // Sun Studio needs an lvalue } List <double> strikeVector; if (strike_ == null) { // temporary patch... // should be fixed for every CapFloor::Engine BlackCapFloorEngine temp = engine_ as BlackCapFloorEngine; Utils.QL_REQUIRE(temp != null, () => "cannot calculate ATM without a BlackCapFloorEngine"); Handle <YieldTermStructure> discountCurve = temp.termStructure(); strikeVector = new InitializedList <double>(1, CashFlows.atmRate(leg, discountCurve, false, discountCurve.link.referenceDate())); //strikeVector[0] = CashFlows.atmRate(leg,discountCurve,false,discountCurve.link.referenceDate()); } else { strikeVector = new InitializedList <double>(1, strike_.Value); } CapFloor capFloor = new CapFloor(capFloorType_, leg, strikeVector); capFloor.setPricingEngine(engine_); return(capFloor); }
public FdmAffineModelSwapInnerValue( ModelType disModel, ModelType fwdModel, VanillaSwap swap, Dictionary <double, Date> exerciseDates, FdmMesher mesher, int direction) { disModel_ = disModel; fwdModel_ = fwdModel; mesher_ = mesher; direction_ = direction; swap_ = new VanillaSwap(swap.swapType, swap.nominal, swap.fixedSchedule(), swap.fixedRate, swap.fixedDayCount(), swap.floatingSchedule(), swap.iborIndex().clone(fwdTs_), swap.spread, swap.floatingDayCount(), null); exerciseDates_ = exerciseDates; }
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 { if(exerciseDate_ <= fixingDate_) throw new ArgumentException( "exercise date (" + exerciseDate_ + ") must be less "+ "than or equal to fixing date (" + fixingDate_ + ")"); exercise_ = new EuropeanExercise(exerciseDate_); } double usedStrike = strike_; if (strike_ == null) { // ATM on the forecasting curve if (!swapIndex_.forwardingTermStructure().empty()) throw new ArgumentException( "no forecasting term structure set to "+swapIndex_.name()); VanillaSwap temp = swapIndex_.underlyingSwap(fixingDate_); temp.setPricingEngine(new DiscountingSwapEngine( swapIndex_.forwardingTermStructure())); usedStrike = temp.fairRate(); } 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); Swaption swaption=new Swaption(underlyingSwap_, exercise_, delivery_); swaption.setPricingEngine(engine_); return swaption; }
static void Main(string[] args) { DateTime timer = DateTime.Now; Date todaysDate = new Date(15, 2, 2002); Calendar calendar = new TARGET(); Date settlementDate = new Date(19, 2, 2002); Settings.setEvaluationDate(todaysDate); // flat yield term structure impling 1x5 swap at 5% Quote flatRate = new SimpleQuote(0.04875825); Handle<YieldTermStructure> rhTermStructure = new Handle<YieldTermStructure>( new FlatForward(settlementDate, new Handle<Quote>(flatRate), new Actual365Fixed())); // Define the ATM/OTM/ITM swaps Frequency fixedLegFrequency = Frequency.Annual; BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted; BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing; DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European); Frequency floatingLegFrequency = Frequency.Semiannual; VanillaSwap.Type type = VanillaSwap.Type.Payer; double dummyFixedRate = 0.03; IborIndex indexSixMonths = new Euribor6M(rhTermStructure); Date startDate = calendar.advance(settlementDate, 1, TimeUnit.Years, floatingLegConvention); Date maturity = calendar.advance(startDate, 5, TimeUnit.Years, floatingLegConvention); Schedule fixedSchedule = new Schedule(startDate, maturity, new Period(fixedLegFrequency), calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(startDate, maturity, new Period(floatingLegFrequency), calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap( type, 1000.0, fixedSchedule, dummyFixedRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); swap.setPricingEngine(new DiscountingSwapEngine(rhTermStructure)); double fixedAtmRate = swap.fairRate(); double fixedOtmRate = fixedAtmRate * 1.2; double fixedItmRate = fixedAtmRate * 0.8; VanillaSwap atmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedAtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap otmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedOtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap itmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedItmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); // defining the swaptions to be used in model calibration List<Period> swaptionMaturities = new List<Period>(5); swaptionMaturities.Add(new Period(1, TimeUnit.Years)); swaptionMaturities.Add(new Period(2, TimeUnit.Years)); swaptionMaturities.Add(new Period(3, TimeUnit.Years)); swaptionMaturities.Add(new Period(4, TimeUnit.Years)); swaptionMaturities.Add(new Period(5, TimeUnit.Years)); List<CalibrationHelper> swaptions = new List<CalibrationHelper>(); // List of times that have to be included in the timegrid List<double> times = new List<double>(); for (int i = 0; i < NumRows; i++) { int j = NumCols - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1 int k = i * NumCols + j; Quote vol = new SimpleQuote(SwaptionVols[k]); swaptions.Add(new SwaptionHelper(swaptionMaturities[i], new Period(SwapLenghts[j], TimeUnit.Years), new Handle<Quote>(vol), indexSixMonths, indexSixMonths.tenor(), indexSixMonths.dayCounter(), indexSixMonths.dayCounter(), rhTermStructure, false)); swaptions.Last().addTimesTo(times); } // Building time-grid TimeGrid grid = new TimeGrid(times, 30); // defining the models G2 modelG2 = new G2(rhTermStructure); HullWhite modelHw = new HullWhite(rhTermStructure); HullWhite modelHw2 = new HullWhite(rhTermStructure); BlackKarasinski modelBk = new BlackKarasinski(rhTermStructure); // model calibrations Console.WriteLine("G2 (analytic formulae) calibration"); for (int i = 0; i < swaptions.Count; i++) swaptions[i].setPricingEngine(new G2SwaptionEngine(modelG2, 6.0, 16)); CalibrateModel(modelG2, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n" + "b = {2:0.000000}, " + "eta = {3:0.0000000}\n" + "rho = {4:0.00000}\n", modelG2.parameters()[0], modelG2.parameters()[1], modelG2.parameters()[2], modelG2.parameters()[3], modelG2.parameters()[4]); Console.WriteLine("Hull-White (analytic formulae) calibration"); for (int i = 0; i < swaptions.Count; i++) swaptions[i].setPricingEngine(new JamshidianSwaptionEngine(modelHw)); CalibrateModel(modelHw, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n", modelHw.parameters()[0], modelHw.parameters()[1]); Console.WriteLine("Hull-White (numerical) calibration"); for (int i = 0; i < swaptions.Count(); i++) swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelHw2, grid)); CalibrateModel(modelHw2, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n", modelHw2.parameters()[0], modelHw2.parameters()[1]); Console.WriteLine("Black-Karasinski (numerical) calibration"); for (int i = 0; i < swaptions.Count; i++) swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelBk, grid)); CalibrateModel(modelBk, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.00000}\n", modelBk.parameters()[0], modelBk.parameters()[1]); // ATM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (ATM)", fixedAtmRate); List<Date> bermudanDates = new List<Date>(); List<CashFlow> leg = swap.fixedLeg(); for (int i = 0; i < leg.Count; i++) { Coupon coupon = (Coupon)leg[i]; bermudanDates.Add(coupon.accrualStartDate()); } Exercise bermudanExercise = new BermudanExercise(bermudanDates); Swaption bermudanSwaption = new Swaption(atmSwap, bermudanExercise); // Do the pricing for each model // G2 price the European swaption here, it should switch to bermudan bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.00}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.000}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.000}", bermudanSwaption.NPV()); // OTM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (OTM)", fixedOtmRate); Swaption otmBermudanSwaption = new Swaption(otmSwap, bermudanExercise); // Do the pricing for each model otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.0000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.0000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.0000}", otmBermudanSwaption.NPV()); // ITM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (ITM)", fixedItmRate); Swaption itmBermudanSwaption = new Swaption(itmSwap, bermudanExercise); // Do the pricing for each model itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.000}", itmBermudanSwaption.NPV()); Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.WriteLine(); Console.Write("Press any key to continue ..."); Console.ReadKey(); }
public override void calculate() { double basisPoint = 1.0e-4; Date exerciseDate = arguments_.exercise.date(0); // the part of the swap preceding exerciseDate should be truncated // to avoid taking into account unwanted cashflows // for the moment we add a check avoiding this situation VanillaSwap swap = arguments_.swap; double strike = swap.fixedRate; List <CashFlow> fixedLeg = swap.fixedLeg(); FixedRateCoupon firstCoupon = fixedLeg[0] as FixedRateCoupon; Utils.QL_REQUIRE(firstCoupon != null, () => "wrong coupon type"); Utils.QL_REQUIRE(firstCoupon.accrualStartDate() >= exerciseDate, () => "swap start (" + firstCoupon.accrualStartDate() + ") before exercise date (" + exerciseDate + ") not supported in Black swaption engine"); // using the forecasting curve swap.setPricingEngine(new DiscountingSwapEngine(swap.iborIndex().forwardingTermStructure())); double atmForward = swap.fairRate(); // Volatilities are quoted for zero-spreaded swaps. // Therefore, any spread on the floating leg must be removed // with a corresponding correction on the fixed leg. if (swap.spread.IsNotEqual(0.0)) { double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); strike -= correction; atmForward -= correction; results_.additionalResults["spreadCorrection"] = correction; } else { results_.additionalResults["spreadCorrection"] = 0.0; } results_.additionalResults["strike"] = strike; results_.additionalResults["atmForward"] = atmForward; // using the discounting curve swap.setPricingEngine(new DiscountingSwapEngine(discountCurve_, false)); double annuity = 0; switch (arguments_.settlementType) { case Settlement.Type.Physical: { annuity = Math.Abs(swap.fixedLegBPS()) / basisPoint; break; } case Settlement.Type.Cash: { DayCounter dayCount = firstCoupon.dayCounter(); // we assume that the cash settlement date is equal // to the swap start date Date discountDate = model_ == CashAnnuityModel.DiscountCurve ? firstCoupon.accrualStartDate() : discountCurve_.link.referenceDate(); double fixedLegCashBPS = CashFlows.bps(fixedLeg, new InterestRate(atmForward, dayCount, Compounding.Compounded, Frequency.Annual), false, discountDate); annuity = Math.Abs(fixedLegCashBPS / basisPoint) * discountCurve_.link.discount(discountDate); break; } default: Utils.QL_FAIL("unknown settlement type"); break; } results_.additionalResults["annuity"] = annuity; double swapLength = vol_.link.swapLength(swap.floatingSchedule().dates().First(), swap.floatingSchedule().dates().Last()); results_.additionalResults["swapLength"] = swapLength; double variance = vol_.link.blackVariance(exerciseDate, swapLength, strike); double displacement = displacement_ == null ? vol_.link.shift(exerciseDate, swapLength) : Convert.ToDouble(displacement_); double stdDev = Math.Sqrt(variance); results_.additionalResults["stdDev"] = stdDev; Option.Type w = (arguments_.type == VanillaSwap.Type.Payer) ? Option.Type.Call : Option.Type.Put; results_.value = new Spec().value(w, strike, atmForward, stdDev, annuity, displacement); double exerciseTime = vol_.link.timeFromReference(exerciseDate); results_.additionalResults["vega"] = new Spec().vega(strike, atmForward, stdDev, exerciseTime, annuity, displacement); }
public Swaption makeSwaption(VanillaSwap swap,Date exercise,double volatility) { Settlement.Type settlementType= Settlement.Type.Physical; Handle<Quote> vol=new Handle <Quote>(new SimpleQuote(volatility)); IPricingEngine engine=new BlackSwaptionEngine(termStructure, vol); Swaption result=new Swaption(swap,new EuropeanExercise(exercise),settlementType); result.setPricingEngine(engine); return result; }
// utilities public VanillaSwap makeSwap(double fixedRate) { Date start = calendar.advance(settlement, startYears, TimeUnit.Years); Date maturity = calendar.advance(start, length, TimeUnit.Years); Schedule fixedSchedule = new Schedule(start, maturity, new Period(fixedFrequency), calendar, fixedConvention, fixedConvention, DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(start, maturity, new Period(floatingFrequency), calendar, floatingConvention, floatingConvention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap(type, nominal, fixedSchedule, fixedRate, fixedDayCount, floatSchedule, index, 0.0, index.dayCounter()); swap.setPricingEngine((IPricingEngine)(new DiscountingSwapEngine(termStructure))); return swap; }
protected override void performCalculations() { Calendar calendar = index_.fixingCalendar(); int fixingDays = index_.fixingDays(); Date exerciseDate = exerciseDate_; if (exerciseDate == null) exerciseDate = calendar.advance(termStructure_.link.referenceDate(), maturity_, index_.businessDayConvention()); Date startDate = calendar.advance(exerciseDate, fixingDays, TimeUnit.Days, index_.businessDayConvention()); Date endDate = endDate_; if (endDate == null) endDate = calendar.advance(startDate, length_, index_.businessDayConvention()); Schedule fixedSchedule = new Schedule(startDate, endDate, fixedLegTenor_, calendar, index_.businessDayConvention(), index_.businessDayConvention(), DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(startDate, endDate, index_.tenor(), calendar, index_.businessDayConvention(), index_.businessDayConvention(), DateGeneration.Rule.Forward, false); IPricingEngine swapEngine = new DiscountingSwapEngine(termStructure_, false); VanillaSwap.Type type = VanillaSwap.Type.Receiver; VanillaSwap temp = new VanillaSwap(VanillaSwap.Type.Receiver, nominal_, fixedSchedule, 0.0, fixedLegDayCounter_, floatSchedule, index_, 0.0, floatingLegDayCounter_); temp.setPricingEngine(swapEngine); double forward = temp.fairRate(); if(! strike_.HasValue) { exerciseRate_ = forward; } else { exerciseRate_ = strike_.Value; type = strike_ <= forward ? VanillaSwap.Type.Receiver : VanillaSwap.Type.Payer; // ensure that calibration instrument is out of the money } swap_ = new VanillaSwap(type, nominal_, fixedSchedule, exerciseRate_, fixedLegDayCounter_, floatSchedule, index_, 0.0, floatingLegDayCounter_); swap_.setPricingEngine(swapEngine); Exercise exercise = new EuropeanExercise(exerciseDate); swaption_ = new Swaption(swap_, exercise); base.performCalculations(); }
public MakeVanillaSwap withType(VanillaSwap.Type type) { type_ = type; return this; }
public VanillaSwap value() { Date startDate; if (effectiveDate_ != null) startDate = effectiveDate_; else { int fixingDays = iborIndex_.fixingDays(); Date referenceDate = Settings.evaluationDate(); Date spotDate = floatCalendar_.advance(referenceDate, new Period(fixingDays, TimeUnit.Days)); startDate = spotDate + forwardStart_; } Date endDate; if (terminationDate_ != null) endDate = terminationDate_; else endDate = startDate + swapTenor_; Schedule fixedSchedule = new Schedule(startDate, endDate, fixedTenor_, fixedCalendar_, fixedConvention_, fixedTerminationDateConvention_, fixedRule_, fixedEndOfMonth_, fixedFirstDate_, fixedNextToLastDate_); Schedule floatSchedule = new Schedule(startDate, endDate, floatTenor_, floatCalendar_, floatConvention_, floatTerminationDateConvention_, floatRule_, floatEndOfMonth_, floatFirstDate_, floatNextToLastDate_); double? usedFixedRate = fixedRate_; if (fixedRate_ == null) { // calculate a fair fixed rate if no fixed rate is provided if (iborIndex_.forwardingTermStructure().empty()) throw new ArgumentException("no forecasting term structure set to " + iborIndex_.name()); VanillaSwap temp = new VanillaSwap(type_, nominal_, fixedSchedule, 0.0, fixedDayCount_, floatSchedule, iborIndex_, floatSpread_, floatDayCount_); temp.setPricingEngine(new DiscountingSwapEngine(iborIndex_.forwardingTermStructure())); usedFixedRate = temp.fairRate(); } VanillaSwap swap = new VanillaSwap(type_, nominal_, fixedSchedule, usedFixedRate.Value, fixedDayCount_, floatSchedule, iborIndex_, floatSpread_, floatDayCount_); swap.setPricingEngine(engine_); return swap; }
public VanillaSwap value() { Date startDate; if (effectiveDate_ != null) { startDate = effectiveDate_; } else { //int fixingDays = iborIndex_.fixingDays(); Date refDate = Settings.evaluationDate(); // if the evaluation date is not a business day // then move to the next business day refDate = floatCalendar_.adjust(refDate); Date spotDate = floatCalendar_.advance(refDate, new Period(settlementDays_, TimeUnit.Days)); startDate = spotDate + forwardStart_; if (forwardStart_.length() < 0) { startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Preceding); } else { startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Following); } } Date endDate = terminationDate_; if (endDate == null) { if (floatEndOfMonth_) { endDate = floatCalendar_.advance(startDate, swapTenor_, BusinessDayConvention.ModifiedFollowing, floatEndOfMonth_); } else { endDate = startDate + swapTenor_; } } Currency curr = iborIndex_.currency(); Period fixedTenor = null; if (fixedTenor_ != null) { fixedTenor = fixedTenor_; } else { if ((curr == new EURCurrency()) || (curr == new USDCurrency()) || (curr == new CHFCurrency()) || (curr == new SEKCurrency()) || (curr == new GBPCurrency() && swapTenor_ <= new Period(1, TimeUnit.Years))) { fixedTenor = new Period(1, TimeUnit.Years); } else if ((curr == new GBPCurrency() && swapTenor_ > new Period(1, TimeUnit.Years) || (curr == new JPYCurrency()) || (curr == new AUDCurrency() && swapTenor_ >= new Period(4, TimeUnit.Years)))) { fixedTenor = new Period(6, TimeUnit.Months); } else if ((curr == new HKDCurrency() || (curr == new AUDCurrency() && swapTenor_ < new Period(4, TimeUnit.Years)))) { fixedTenor = new Period(3, TimeUnit.Months); } else { Utils.QL_FAIL("unknown fixed leg default tenor for " + curr); } } Schedule fixedSchedule = new Schedule(startDate, endDate, fixedTenor, fixedCalendar_, fixedConvention_, fixedTerminationDateConvention_, fixedRule_, fixedEndOfMonth_, fixedFirstDate_, fixedNextToLastDate_); Schedule floatSchedule = new Schedule(startDate, endDate, floatTenor_, floatCalendar_, floatConvention_, floatTerminationDateConvention_, floatRule_, floatEndOfMonth_, floatFirstDate_, floatNextToLastDate_); DayCounter fixedDayCount = null; if (fixedDayCount_ != null) { fixedDayCount = fixedDayCount_; } else { if (curr == new USDCurrency()) { fixedDayCount = new Actual360(); } else if (curr == new EURCurrency() || curr == new CHFCurrency() || curr == new SEKCurrency()) { fixedDayCount = new Thirty360(Thirty360.Thirty360Convention.BondBasis); } else if (curr == new GBPCurrency() || curr == new JPYCurrency() || curr == new AUDCurrency() || curr == new HKDCurrency()) { fixedDayCount = new Actual365Fixed(); } else { Utils.QL_FAIL("unknown fixed leg day counter for " + curr); } } double?usedFixedRate = fixedRate_; if (fixedRate_ == null) { VanillaSwap temp = new VanillaSwap(type_, nominal_, fixedSchedule, 0.0, fixedDayCount, floatSchedule, iborIndex_, floatSpread_, floatDayCount_); if (engine_ == null) { Handle <YieldTermStructure> disc = iborIndex_.forwardingTermStructure(); Utils.QL_REQUIRE(!disc.empty(), () => "null term structure set to this instance of " + iborIndex_.name()); bool includeSettlementDateFlows = false; IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows); temp.setPricingEngine(engine); } else { temp.setPricingEngine(engine_); } usedFixedRate = temp.fairRate(); } VanillaSwap swap = new VanillaSwap(type_, nominal_, fixedSchedule, usedFixedRate.Value, fixedDayCount, floatSchedule, iborIndex_, floatSpread_, floatDayCount_); if (engine_ == null) { Handle <YieldTermStructure> disc = iborIndex_.forwardingTermStructure(); bool includeSettlementDateFlows = false; IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows); swap.setPricingEngine(engine); } else { swap.setPricingEngine(engine_); } return(swap); }
public void testFixing() { Date tradeDate = new Date( 17, Month.April, 2015 ); Calendar calendar = new UnitedKingdom(); Date settlementDate = calendar.advance( tradeDate, 2, TimeUnit.Days, BusinessDayConvention.Following ); Date maturityDate = calendar.advance( settlementDate, 5, TimeUnit.Years, BusinessDayConvention.Following ); Date valueDate = new Date( 20, Month.April, 2015 ); Settings.setEvaluationDate( valueDate ); List<Date> dates = new List<Date>(); dates.Add( valueDate ); dates.Add( valueDate + new Period( 1, TimeUnit.Years ) ); dates.Add( valueDate + new Period( 2, TimeUnit.Years ) ); dates.Add( valueDate + new Period( 5, TimeUnit.Years ) ); dates.Add( valueDate + new Period( 10, TimeUnit.Years ) ); dates.Add( valueDate + new Period( 20, TimeUnit.Years ) ); List<double> rates = new List<double>(); rates.Add( 0.01 ); rates.Add( 0.01 ); rates.Add( 0.01 ); rates.Add( 0.01 ); rates.Add( 0.01 ); rates.Add( 0.01 ); var discountCurveHandle = new RelinkableHandle<YieldTermStructure>(); var forecastCurveHandle = new RelinkableHandle<YieldTermStructure>(); GBPLibor index = new GBPLibor( new Period( 6, TimeUnit.Months ), forecastCurveHandle ); InterpolatedZeroCurve<Linear> zeroCurve = new InterpolatedZeroCurve<Linear>( dates, rates, new Actual360(), new Linear() ); var fixedSchedule = new Schedule( settlementDate, maturityDate, new Period( 1, TimeUnit.Years ), calendar, BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false ); var floatSchedule = new Schedule( settlementDate, maturityDate, index.tenor(), calendar, BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false ); VanillaSwap swap = new VanillaSwap( VanillaSwap.Type.Payer, 1000000, fixedSchedule, 0.01, new Actual360(), floatSchedule, index, 0, new Actual360() ); discountCurveHandle.linkTo( zeroCurve ); forecastCurveHandle.linkTo( zeroCurve ); var swapEngine = new DiscountingSwapEngine( discountCurveHandle, false, null ); swap.setPricingEngine( swapEngine ); try { double npv = swap.NPV(); } catch ( Exception ex ) { Assert.Fail( ex.Message ); Console.WriteLine( ex ); } }
protected override void performCalculations() { Calendar calendar = index_.fixingCalendar(); int fixingDays = index_.fixingDays(); Date exerciseDate = exerciseDate_; if (exerciseDate == null) { exerciseDate = calendar.advance(termStructure_.link.referenceDate(), maturity_, index_.businessDayConvention()); } Date startDate = calendar.advance(exerciseDate, fixingDays, TimeUnit.Days, index_.businessDayConvention()); Date endDate = endDate_; if (endDate == null) { endDate = calendar.advance(startDate, length_, index_.businessDayConvention()); } Schedule fixedSchedule = new Schedule(startDate, endDate, fixedLegTenor_, calendar, index_.businessDayConvention(), index_.businessDayConvention(), DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(startDate, endDate, index_.tenor(), calendar, index_.businessDayConvention(), index_.businessDayConvention(), DateGeneration.Rule.Forward, false); IPricingEngine swapEngine = new DiscountingSwapEngine(termStructure_, false); VanillaSwap.Type type = VanillaSwap.Type.Receiver; VanillaSwap temp = new VanillaSwap(VanillaSwap.Type.Receiver, nominal_, fixedSchedule, 0.0, fixedLegDayCounter_, floatSchedule, index_, 0.0, floatingLegDayCounter_); temp.setPricingEngine(swapEngine); double forward = temp.fairRate(); if (!strike_.HasValue) { exerciseRate_ = forward; } else { exerciseRate_ = strike_.Value; type = strike_ <= forward ? VanillaSwap.Type.Receiver : VanillaSwap.Type.Payer; // ensure that calibration instrument is out of the money } swap_ = new VanillaSwap(type, nominal_, fixedSchedule, exerciseRate_, fixedLegDayCounter_, floatSchedule, index_, 0.0, floatingLegDayCounter_); swap_.setPricingEngine(swapEngine); Exercise exercise = new EuropeanExercise(exerciseDate); swaption_ = new Swaption(swap_, exercise); base.performCalculations(); }
public override void calculate() { double basisPoint = 1.0e-4; Date exerciseDate = arguments_.exercise.date(0); // the part of the swap preceding exerciseDate should be truncated // to avoid taking into account unwanted cashflows VanillaSwap swap = arguments_.swap; double strike = swap.fixedRate; // using the forecasting curve swap.setPricingEngine(new DiscountingSwapEngine(swap.iborIndex().forwardingTermStructure())); double atmForward = swap.fairRate(); // Volatilities are quoted for zero-spreaded swaps. // Therefore, any spread on the floating leg must be removed // with a corresponding correction on the fixed leg. if (swap.spread != 0.0) { double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); strike -= correction; atmForward -= correction; results_.additionalResults["spreadCorrection"] = correction; } else { results_.additionalResults["spreadCorrection"] = 0.0; } results_.additionalResults["strike"] = strike; results_.additionalResults["atmForward"] = atmForward; // using the discounting curve swap.setPricingEngine(new DiscountingSwapEngine(termStructure_)); double annuity; switch (arguments_.settlementType) { case Settlement.Type.Physical: { annuity = Math.Abs(swap.fixedLegBPS()) / basisPoint; break; } case Settlement.Type.Cash: { List <CashFlow> fixedLeg = swap.fixedLeg(); FixedRateCoupon firstCoupon = (FixedRateCoupon)fixedLeg[0]; DayCounter dayCount = firstCoupon.dayCounter(); double fixedLegCashBPS = CashFlows.bps(fixedLeg, new InterestRate(atmForward, dayCount, QLNet.Compounding.Compounded, Frequency.Annual), false, termStructure_.link.referenceDate()); annuity = Math.Abs(fixedLegCashBPS / basisPoint); break; } default: throw new ApplicationException("unknown settlement type"); } results_.additionalResults["annuity"] = annuity; // the swap length calculation might be improved using the value date // of the exercise date double swapLength = volatility_.link.swapLength(exerciseDate, arguments_.floatingPayDates.Last()); results_.additionalResults["swapLength"] = swapLength; double variance = volatility_.link.blackVariance(exerciseDate, swapLength, strike); double stdDev = Math.Sqrt(variance); results_.additionalResults["stdDev"] = stdDev; Option.Type w = (arguments_.type == VanillaSwap.Type.Payer) ? Option.Type.Call : Option.Type.Put; results_.value = Utils.blackFormula(w, strike, atmForward, stdDev, annuity); double exerciseTime = volatility_.link.timeFromReference(exerciseDate); results_.additionalResults["vega"] = Math.Sqrt(exerciseTime) * Utils.blackFormulaStdDevDerivative(strike, atmForward, stdDev, annuity); }
protected override void initializeDates() { // dummy ibor index with curve/swap arguments IborIndex clonedIborIndex = iborIndex_.clone(termStructureHandle_); // do not pass the spread here, as it might be a Quote i.e. it can dinamically change swap_ = new MakeVanillaSwap(tenor_, clonedIborIndex, 0.0, fwdStart_) .withFixedLegDayCount(fixedDayCount_) .withFixedLegTenor(new Period(fixedFrequency_)) .withFixedLegConvention(fixedConvention_) .withFixedLegTerminationDateConvention(fixedConvention_) .withFixedLegCalendar(calendar_) .withFloatingLegCalendar(calendar_); earliestDate_ = swap_.startDate(); // Usually... latestDate_ = swap_.maturityDate(); // ...but due to adjustments, the last floating coupon might // need a later date for fixing #if QL_USE_INDEXED_COUPON FloatingRateCoupon lastFloating = (FloatingRateCoupon)swap_.floatingLeg()[swap_.floatingLeg().Count - 1]; Date fixingValueDate = iborIndex_.valueDate(lastFloating.fixingDate()); Date endValueDate = iborIndex_.maturityDate(fixingValueDate); latestDate_ = Date.Max(latestDate_, endValueDate); #endif }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as CmsCoupon; Utils.QL_REQUIRE(coupon_ != null, () => "CMS coupon needed"); gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); fixingDate_ = coupon_.fixingDate(); paymentDate_ = coupon_.date(); SwapIndex swapIndex = coupon_.swapIndex(); rateCurve_ = swapIndex.forwardingTermStructure().link; Date today = Settings.evaluationDate(); if (paymentDate_ > today) { discount_ = rateCurve_.discount(paymentDate_); } else { discount_ = 1.0; } spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_; if (fixingDate_ > today) { swapTenor_ = swapIndex.tenor(); VanillaSwap swap = swapIndex.underlyingSwap(fixingDate_); swapRateValue_ = swap.fairRate(); double bp = 1.0e-4; annuity_ = (swap.floatingLegBPS() / bp); int q = (int)swapIndex.fixedLegTenor().frequency(); Schedule schedule = swap.fixedSchedule(); DayCounter dc = swapIndex.dayCounter(); //DayCounter dc = coupon.dayCounter(); double startTime = dc.yearFraction(rateCurve_.referenceDate(), swap.startDate()); double swapFirstPaymentTime = dc.yearFraction(rateCurve_.referenceDate(), schedule.date(1)); double paymentTime = dc.yearFraction(rateCurve_.referenceDate(), paymentDate_); double delta = (paymentTime - startTime) / (swapFirstPaymentTime - startTime); switch (modelOfYieldCurve_) { case GFunctionFactory.YieldCurveModel.Standard: gFunction_ = GFunctionFactory.newGFunctionStandard(q, delta, swapTenor_.length()); break; case GFunctionFactory.YieldCurveModel.ExactYield: gFunction_ = GFunctionFactory.newGFunctionExactYield(coupon_); break; case GFunctionFactory.YieldCurveModel.ParallelShifts: { Handle <Quote> nullMeanReversionQuote = new Handle <Quote>(new SimpleQuote(0.0)); gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, nullMeanReversionQuote); } break; case GFunctionFactory.YieldCurveModel.NonParallelShifts: gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, meanReversion_); break; default: throw new ApplicationException("unknown/illegal gFunction type"); } vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link); } }
static void Main(string[] args) { DateTime timer = DateTime.Now; /********************* *** MARKET DATA *** *********************/ Calendar calendar = new TARGET(); Date settlementDate = new Date(22, Month.September, 2004); // must be a business day settlementDate = calendar.adjust(settlementDate); int fixingDays = 2; Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days); // nothing to do with Date::todaysDate Settings.setEvaluationDate(todaysDate); todaysDate = Settings.evaluationDate(); Console.WriteLine("Today: {0}, {1}", todaysDate.DayOfWeek, todaysDate); Console.WriteLine("Settlement date: {0}, {1}", settlementDate.DayOfWeek, settlementDate); // deposits double d1wQuote = 0.0382; double d1mQuote = 0.0372; double d3mQuote = 0.0363; double d6mQuote = 0.0353; double d9mQuote = 0.0348; double d1yQuote = 0.0345; // FRAs double fra3x6Quote = 0.037125; double fra6x9Quote = 0.037125; double fra6x12Quote = 0.037125; // futures double fut1Quote = 96.2875; double fut2Quote = 96.7875; double fut3Quote = 96.9875; double fut4Quote = 96.6875; double fut5Quote = 96.4875; double fut6Quote = 96.3875; double fut7Quote = 96.2875; double fut8Quote = 96.0875; // swaps double s2yQuote = 0.037125; double s3yQuote = 0.0398; double s5yQuote = 0.0443; double s10yQuote = 0.05165; double s15yQuote = 0.055175; /******************** *** QUOTES *** ********************/ // SimpleQuote stores a value which can be manually changed; // other Quote subclasses could read the value from a database // or some kind of data feed. // deposits Quote d1wRate = new SimpleQuote(d1wQuote); Quote d1mRate = new SimpleQuote(d1mQuote); Quote d3mRate = new SimpleQuote(d3mQuote); Quote d6mRate = new SimpleQuote(d6mQuote); Quote d9mRate = new SimpleQuote(d9mQuote); Quote d1yRate = new SimpleQuote(d1yQuote); // FRAs Quote fra3x6Rate = new SimpleQuote(fra3x6Quote); Quote fra6x9Rate = new SimpleQuote(fra6x9Quote); Quote fra6x12Rate = new SimpleQuote(fra6x12Quote); // futures Quote fut1Price = new SimpleQuote(fut1Quote); Quote fut2Price = new SimpleQuote(fut2Quote); Quote fut3Price = new SimpleQuote(fut3Quote); Quote fut4Price = new SimpleQuote(fut4Quote); Quote fut5Price = new SimpleQuote(fut5Quote); Quote fut6Price = new SimpleQuote(fut6Quote); Quote fut7Price = new SimpleQuote(fut7Quote); Quote fut8Price = new SimpleQuote(fut8Quote); // swaps Quote s2yRate = new SimpleQuote(s2yQuote); Quote s3yRate = new SimpleQuote(s3yQuote); Quote s5yRate = new SimpleQuote(s5yQuote); Quote s10yRate = new SimpleQuote(s10yQuote); Quote s15yRate = new SimpleQuote(s15yQuote); /********************* *** RATE HELPERS *** *********************/ // RateHelpers are built from the above quotes together with // other instrument dependant infos. Quotes are passed in // relinkable handles which could be relinked to some other // data source later. // deposits DayCounter depositDayCounter = new Actual360(); RateHelper d1w = new DepositRateHelper(new Handle<Quote>(d1wRate), new Period(1, TimeUnit.Weeks), fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); RateHelper d1m = new DepositRateHelper(new Handle<Quote>(d1mRate), new Period(1, TimeUnit.Months), fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); RateHelper d3m = new DepositRateHelper(new Handle<Quote>(d3mRate), new Period(3, TimeUnit.Months), fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); RateHelper d6m = new DepositRateHelper(new Handle<Quote>(d6mRate), new Period(6, TimeUnit.Months), fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); RateHelper d9m = new DepositRateHelper(new Handle<Quote>(d9mRate), new Period(9, TimeUnit.Months), fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); RateHelper d1y = new DepositRateHelper(new Handle<Quote>(d1yRate), new Period(1, TimeUnit.Years), fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); // setup FRAs RateHelper fra3x6 = new FraRateHelper(new Handle<Quote>(fra3x6Rate), 3, 6, fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); RateHelper fra6x9 = new FraRateHelper(new Handle<Quote>(fra6x9Rate), 6, 9, fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); RateHelper fra6x12 = new FraRateHelper(new Handle<Quote>(fra6x12Rate), 6, 12, fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); // setup futures // Handle<Quote> convexityAdjustment = new Handle<Quote>(new SimpleQuote(0.0)); int futMonths = 3; Date imm = IMM.nextDate(settlementDate); RateHelper fut1 = new FuturesRateHelper(new Handle<Quote>(fut1Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); imm = IMM.nextDate(imm + 1); RateHelper fut2 = new FuturesRateHelper(new Handle<Quote>(fut2Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); imm = IMM.nextDate(imm + 1); RateHelper fut3 = new FuturesRateHelper(new Handle<Quote>(fut3Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); imm = IMM.nextDate(imm + 1); RateHelper fut4 = new FuturesRateHelper(new Handle<Quote>(fut4Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); imm = IMM.nextDate(imm + 1); RateHelper fut5 = new FuturesRateHelper(new Handle<Quote>(fut5Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); imm = IMM.nextDate(imm + 1); RateHelper fut6 = new FuturesRateHelper(new Handle<Quote>(fut6Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); imm = IMM.nextDate(imm + 1); RateHelper fut7 = new FuturesRateHelper(new Handle<Quote>(fut7Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); imm = IMM.nextDate(imm + 1); RateHelper fut8 = new FuturesRateHelper(new Handle<Quote>(fut8Price), imm, futMonths, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter); // setup swaps Frequency swFixedLegFrequency = Frequency.Annual; BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted; DayCounter swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European); IborIndex swFloatingLegIndex = new Euribor6M(); RateHelper s2y = new SwapRateHelper(new Handle<Quote>(s2yRate), new Period(2, TimeUnit.Years), calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex); RateHelper s3y = new SwapRateHelper(new Handle<Quote>(s3yRate), new Period(3, TimeUnit.Years), calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex); RateHelper s5y = new SwapRateHelper(new Handle<Quote>(s5yRate), new Period(5, TimeUnit.Years), calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex); RateHelper s10y = new SwapRateHelper(new Handle<Quote>(s10yRate), new Period(10, TimeUnit.Years), calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex); RateHelper s15y = new SwapRateHelper(new Handle<Quote>(s15yRate), new Period(15, TimeUnit.Years), calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex); /********************* ** CURVE BUILDING ** *********************/ // Any DayCounter would be fine. // ActualActual::ISDA ensures that 30 years is 30.0 DayCounter termStructureDayCounter = new ActualActual(ActualActual.Convention.ISDA); double tolerance = 1.0e-15; // A depo-swap curve List<RateHelper> depoSwapInstruments = new List<RateHelper>(); depoSwapInstruments.Add(d1w); depoSwapInstruments.Add(d1m); depoSwapInstruments.Add(d3m); depoSwapInstruments.Add(d6m); depoSwapInstruments.Add(d9m); depoSwapInstruments.Add(d1y); depoSwapInstruments.Add(s2y); depoSwapInstruments.Add(s3y); depoSwapInstruments.Add(s5y); depoSwapInstruments.Add(s10y); depoSwapInstruments.Add(s15y); YieldTermStructure depoSwapTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>( settlementDate, depoSwapInstruments, termStructureDayCounter, new List<Handle<Quote>>(), new List<Date>(), tolerance); // A depo-futures-swap curve List<RateHelper> depoFutSwapInstruments = new List<RateHelper>(); depoFutSwapInstruments.Add(d1w); depoFutSwapInstruments.Add(d1m); depoFutSwapInstruments.Add(fut1); depoFutSwapInstruments.Add(fut2); depoFutSwapInstruments.Add(fut3); depoFutSwapInstruments.Add(fut4); depoFutSwapInstruments.Add(fut5); depoFutSwapInstruments.Add(fut6); depoFutSwapInstruments.Add(fut7); depoFutSwapInstruments.Add(fut8); depoFutSwapInstruments.Add(s3y); depoFutSwapInstruments.Add(s5y); depoFutSwapInstruments.Add(s10y); depoFutSwapInstruments.Add(s15y); YieldTermStructure depoFutSwapTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>( settlementDate, depoFutSwapInstruments, termStructureDayCounter, new List<Handle<Quote>>(), new List<Date>(), tolerance); // A depo-FRA-swap curve List<RateHelper> depoFRASwapInstruments = new List<RateHelper>(); depoFRASwapInstruments.Add(d1w); depoFRASwapInstruments.Add(d1m); depoFRASwapInstruments.Add(d3m); depoFRASwapInstruments.Add(fra3x6); depoFRASwapInstruments.Add(fra6x9); depoFRASwapInstruments.Add(fra6x12); depoFRASwapInstruments.Add(s2y); depoFRASwapInstruments.Add(s3y); depoFRASwapInstruments.Add(s5y); depoFRASwapInstruments.Add(s10y); depoFRASwapInstruments.Add(s15y); YieldTermStructure depoFRASwapTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>( settlementDate, depoFRASwapInstruments, termStructureDayCounter, new List<Handle<Quote>>(), new List<Date>(), tolerance); // Term structures that will be used for pricing: // the one used for discounting cash flows RelinkableHandle<YieldTermStructure> discountingTermStructure = new RelinkableHandle<YieldTermStructure>(); // the one used for forward rate forecasting RelinkableHandle<YieldTermStructure> forecastingTermStructure = new RelinkableHandle<YieldTermStructure>(); /********************* * SWAPS TO BE PRICED * **********************/ // constant nominal 1,000,000 Euro double nominal = 1000000.0; // fixed leg Frequency fixedLegFrequency = Frequency.Annual; BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted; BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing; DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European); double fixedRate = 0.04; DayCounter floatingLegDayCounter = new Actual360(); // floating leg Frequency floatingLegFrequency = Frequency.Semiannual; IborIndex euriborIndex = new Euribor6M(forecastingTermStructure); double spread = 0.0; int lenghtInYears = 5; VanillaSwap.Type swapType = VanillaSwap.Type.Payer; Date maturity = settlementDate + new Period(lenghtInYears, TimeUnit.Years); Schedule fixedSchedule = new Schedule(settlementDate, maturity, new Period(fixedLegFrequency), calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(settlementDate, maturity, new Period(floatingLegFrequency), calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false); VanillaSwap spot5YearSwap = new VanillaSwap(swapType, nominal, fixedSchedule, fixedRate, fixedLegDayCounter, floatSchedule, euriborIndex, spread, floatingLegDayCounter); Date fwdStart = calendar.advance(settlementDate, 1, TimeUnit.Years); Date fwdMaturity = fwdStart + new Period(lenghtInYears, TimeUnit.Years); Schedule fwdFixedSchedule = new Schedule(fwdStart, fwdMaturity, new Period(fixedLegFrequency), calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false); Schedule fwdFloatSchedule = new Schedule(fwdStart, fwdMaturity, new Period(floatingLegFrequency), calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false); VanillaSwap oneYearForward5YearSwap = new VanillaSwap(swapType, nominal, fwdFixedSchedule, fixedRate, fixedLegDayCounter, fwdFloatSchedule, euriborIndex, spread, floatingLegDayCounter); /*************** * SWAP PRICING * ****************/ // utilities for reporting List<string> headers = new List<string>(); headers.Add("term structure"); headers.Add("net present value"); headers.Add("fair spread"); headers.Add("fair fixed rate"); string separator = " | "; int width = headers[0].Length + separator.Length + headers[1].Length + separator.Length + headers[2].Length + separator.Length + headers[3].Length + separator.Length - 1; string rule = string.Format("").PadLeft(width, '-'), dblrule = string.Format("").PadLeft(width, '='); string tab = string.Format("").PadLeft(8, ' '); // calculations Console.WriteLine(dblrule); Console.WriteLine("5-year market swap-rate = {0:0.00%}", s5yRate.value()); Console.WriteLine(dblrule); Console.WriteLine(tab + "5-years swap paying {0:0.00%}", fixedRate); Console.WriteLine(headers[0] + separator + headers[1] + separator + headers[2] + separator + headers[3] + separator); Console.WriteLine(rule); double NPV; double fairRate; double fairSpread; IPricingEngine swapEngine = new DiscountingSwapEngine(discountingTermStructure); spot5YearSwap.setPricingEngine(swapEngine); oneYearForward5YearSwap.setPricingEngine(swapEngine); // Of course, you're not forced to really use different curves forecastingTermStructure.linkTo(depoSwapTermStructure); discountingTermStructure.linkTo(depoSwapTermStructure); NPV = spot5YearSwap.NPV(); fairSpread = spot5YearSwap.fairSpread(); fairRate = spot5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); // let's check that the 5 years swap has been correctly re-priced if (!(Math.Abs(fairRate-s5yQuote)<1e-8)) throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate-s5yQuote)); forecastingTermStructure.linkTo(depoFutSwapTermStructure); discountingTermStructure.linkTo(depoFutSwapTermStructure); NPV = spot5YearSwap.NPV(); fairSpread = spot5YearSwap.fairSpread(); fairRate = spot5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); if (!(Math.Abs(fairRate-s5yQuote)<1e-8)) throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate-s5yQuote)); forecastingTermStructure.linkTo(depoFRASwapTermStructure); discountingTermStructure.linkTo(depoFRASwapTermStructure); NPV = spot5YearSwap.NPV(); fairSpread = spot5YearSwap.fairSpread(); fairRate = spot5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); if (!(Math.Abs(fairRate-s5yQuote)<1e-8)) throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate-s5yQuote)); Console.WriteLine(rule); // now let's price the 1Y forward 5Y swap Console.WriteLine(tab + "5-years, 1-year forward swap paying {0:0.00%}", fixedRate); Console.WriteLine(headers[0] + separator + headers[1] + separator + headers[2] + separator + headers[3] + separator); Console.WriteLine(rule); forecastingTermStructure.linkTo(depoSwapTermStructure); discountingTermStructure.linkTo(depoSwapTermStructure); NPV = oneYearForward5YearSwap.NPV(); fairSpread = oneYearForward5YearSwap.fairSpread(); fairRate = oneYearForward5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); forecastingTermStructure.linkTo(depoFutSwapTermStructure); discountingTermStructure.linkTo(depoFutSwapTermStructure); NPV = oneYearForward5YearSwap.NPV(); fairSpread = oneYearForward5YearSwap.fairSpread(); fairRate = oneYearForward5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); forecastingTermStructure.linkTo(depoFRASwapTermStructure); discountingTermStructure.linkTo(depoFRASwapTermStructure); NPV = oneYearForward5YearSwap.NPV(); fairSpread = oneYearForward5YearSwap.fairSpread(); fairRate = oneYearForward5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); // now let's say that the 5-years swap rate goes up to 4.60%. // A smarter market element--say, connected to a data source-- would // notice the change itself. Since we're using SimpleQuotes, // we'll have to change the value manually--which forces us to // downcast the handle and use the SimpleQuote // interface. In any case, the point here is that a change in the // value contained in the Quote triggers a new bootstrapping // of the curve and a repricing of the swap. SimpleQuote fiveYearsRate = s5yRate as SimpleQuote; fiveYearsRate.setValue(0.0460); Console.WriteLine(dblrule); Console.WriteLine("5-year market swap-rate = {0:0.00%}", s5yRate.value()); Console.WriteLine(dblrule); Console.WriteLine(tab + "5-years swap paying {0:0.00%}", fixedRate); Console.WriteLine(headers[0] + separator + headers[1] + separator + headers[2] + separator + headers[3] + separator); Console.WriteLine(rule); // now get the updated results forecastingTermStructure.linkTo(depoSwapTermStructure); discountingTermStructure.linkTo(depoSwapTermStructure); NPV = spot5YearSwap.NPV(); fairSpread = spot5YearSwap.fairSpread(); fairRate = spot5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); if (!(Math.Abs(fairRate-s5yRate.value())<1e-8)) throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate-s5yRate.value())); forecastingTermStructure.linkTo(depoFutSwapTermStructure); discountingTermStructure.linkTo(depoFutSwapTermStructure); NPV = spot5YearSwap.NPV(); fairSpread = spot5YearSwap.fairSpread(); fairRate = spot5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); if (!(Math.Abs(fairRate-s5yRate.value())<1e-8)) throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate-s5yRate.value())); forecastingTermStructure.linkTo(depoFRASwapTermStructure); discountingTermStructure.linkTo(depoFRASwapTermStructure); NPV = spot5YearSwap.NPV(); fairSpread = spot5YearSwap.fairSpread(); fairRate = spot5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); if (!(Math.Abs(fairRate-s5yRate.value())<1e-8)) throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate-s5yRate.value())); Console.WriteLine(rule); // the 1Y forward 5Y swap changes as well Console.WriteLine(tab + "5-years, 1-year forward swap paying {0:0.00%}", fixedRate); Console.WriteLine(headers[0] + separator + headers[1] + separator + headers[2] + separator + headers[3] + separator); Console.WriteLine(rule); forecastingTermStructure.linkTo(depoSwapTermStructure); discountingTermStructure.linkTo(depoSwapTermStructure); NPV = oneYearForward5YearSwap.NPV(); fairSpread = oneYearForward5YearSwap.fairSpread(); fairRate = oneYearForward5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); forecastingTermStructure.linkTo(depoFutSwapTermStructure); discountingTermStructure.linkTo(depoFutSwapTermStructure); NPV = oneYearForward5YearSwap.NPV(); fairSpread = oneYearForward5YearSwap.fairSpread(); fairRate = oneYearForward5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); forecastingTermStructure.linkTo(depoFRASwapTermStructure); discountingTermStructure.linkTo(depoFRASwapTermStructure); NPV = oneYearForward5YearSwap.NPV(); fairSpread = oneYearForward5YearSwap.fairSpread(); fairRate = oneYearForward5YearSwap.fairRate(); Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap"); Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV); Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread); Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate); Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.Write("Press any key to continue ..."); Console.ReadKey(); }
public void testSwaptionPricing() { //"Testing forward swap and swaption pricing..."); //SavedSettings backup; const int size = 10; const int steps = 8*size; #if QL_USE_INDEXED_COUPON const double tolerance = 1e-6; #else const double tolerance = 1e-12; #endif List<Date> dates = new List<Date>(); List<double> rates = new List<double>(); dates.Add(new Date(4,9,2005)); dates.Add(new Date(4,9,2011)); rates.Add(0.04); rates.Add(0.08); IborIndex index = makeIndex(dates, rates); LiborForwardModelProcess process = new LiborForwardModelProcess(size, index); LmCorrelationModel corrModel = new LmExponentialCorrelationModel(size, 0.5); LmVolatilityModel volaModel = new LmLinearExponentialVolatilityModel(process.fixingTimes(), 0.291, 1.483, 0.116, 0.00001); // set-up pricing engine process.setCovarParam((LfmCovarianceParameterization) new LfmCovarianceProxy(volaModel, corrModel)); // set-up a small Monte-Carlo simulation to price swations List<double> tmp = process.fixingTimes(); TimeGrid grid=new TimeGrid(tmp ,steps); List<int> location=new List<int>(); for (int i=0; i < tmp.Count; ++i) { location.Add(grid.index(tmp[i])) ; } ulong seed=42; const int nrTrails = 5000; LowDiscrepancy.icInstance = new InverseCumulativeNormal(); IRNG rsg = (InverseCumulativeRsg<RandomSequenceGenerator<MersenneTwisterUniformRng> ,InverseCumulativeNormal>) new PseudoRandom().make_sequence_generator(process.factors()*(grid.size()-1),seed); MultiPathGenerator<IRNG> generator=new MultiPathGenerator<IRNG>(process, grid, rsg, false); LiborForwardModel liborModel = new LiborForwardModel(process, volaModel, corrModel); Calendar calendar = index.fixingCalendar(); DayCounter dayCounter = index.forwardingTermStructure().link.dayCounter(); BusinessDayConvention convention = index.businessDayConvention(); Date settlement = index.forwardingTermStructure().link.referenceDate(); SwaptionVolatilityMatrix m = liborModel.getSwaptionVolatilityMatrix(); for (int i=1; i < size; ++i) { for (int j=1; j <= size-i; ++j) { Date fwdStart = settlement + new Period(6*i, TimeUnit.Months); Date fwdMaturity = fwdStart + new Period(6*j, TimeUnit.Months); Schedule schedule =new Schedule(fwdStart, fwdMaturity, index.tenor(), calendar, convention, convention, DateGeneration.Rule.Forward, false); double swapRate = 0.0404; VanillaSwap forwardSwap = new VanillaSwap(VanillaSwap.Type.Receiver, 1.0, schedule, swapRate, dayCounter, schedule, index, 0.0, index.dayCounter()); forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure())); // check forward pricing first double expected = forwardSwap.fairRate(); double calculated = liborModel.S_0(i-1,i+j-1); if (Math.Abs(expected - calculated) > tolerance) Assert.Fail("Failed to reproduce fair forward swap rate" + "\n calculated: " + calculated + "\n expected: " + expected); swapRate = forwardSwap.fairRate(); forwardSwap = new VanillaSwap(VanillaSwap.Type.Receiver, 1.0, schedule, swapRate, dayCounter, schedule, index, 0.0, index.dayCounter()); forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure())); if (i == j && i<=size/2) { IPricingEngine engine = new LfmSwaptionEngine(liborModel, index.forwardingTermStructure()); Exercise exercise = new EuropeanExercise(process.fixingDates()[i]); Swaption swaption = new Swaption(forwardSwap, exercise); swaption.setPricingEngine(engine); GeneralStatistics stat = new GeneralStatistics(); for (int n=0; n<nrTrails; ++n) { Sample<MultiPath> path = (n%2!=0) ? generator.antithetic() : generator.next(); //Sample<MultiPath> path = generator.next(); List<double> rates_ = new InitializedList<double>(size); for (int k=0; k<process.size(); ++k) { rates_[k] = path.value[k][location[i]]; } List<double> dis = process.discountBond(rates_); double npv=0.0; for (int k=i; k < i+j; ++k) { npv += (swapRate - rates_[k]) * ( process.accrualEndTimes()[k] - process.accrualStartTimes()[k])*dis[k]; } stat.add(Math.Max(npv, 0.0)); } if (Math.Abs(swaption.NPV() - stat.mean()) > stat.errorEstimate()*2.35) Assert.Fail("Failed to reproduce swaption npv" + "\n calculated: " + stat.mean() + "\n expected: " + swaption.NPV()); } } } }
public void testSwaps() { //BOOST_MESSAGE("Testing Hull-White swap pricing against known values..."); Date today; //=Settings::instance().evaluationDate();; Calendar calendar = new TARGET(); today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); Date settlement = calendar.advance(today, 2, TimeUnit.Days); Date[] dates = { settlement, calendar.advance(settlement,1,TimeUnit.Weeks), calendar.advance(settlement,1,TimeUnit.Months), calendar.advance(settlement,3,TimeUnit.Months), calendar.advance(settlement,6,TimeUnit.Months), calendar.advance(settlement,9,TimeUnit.Months), calendar.advance(settlement,1,TimeUnit.Years), calendar.advance(settlement,2,TimeUnit.Years), calendar.advance(settlement,3,TimeUnit.Years), calendar.advance(settlement,5,TimeUnit.Years), calendar.advance(settlement,10,TimeUnit.Years), calendar.advance(settlement,15,TimeUnit.Years) }; double[] discounts = { 1.0, 0.999258, 0.996704, 0.990809, 0.981798, 0.972570, 0.963430, 0.929532, 0.889267, 0.803693, 0.596903, 0.433022 }; //for (int i = 0; i < dates.Length; i++) // dates[i] + dates.Length; LogLinear Interpolator = new LogLinear(); Handle<YieldTermStructure> termStructure = new Handle<YieldTermStructure>( new InterpolatedDiscountCurve<LogLinear>( dates.ToList<Date>(), discounts.ToList<double>(), new Actual365Fixed(),new Calendar(), null, null , Interpolator) ); HullWhite model = new HullWhite(termStructure); int[] start = { -3, 0, 3 }; int[] length = { 2, 5, 10 }; double[] rates = { 0.02, 0.04, 0.06 }; IborIndex euribor = new Euribor6M(termStructure); IPricingEngine engine = new TreeVanillaSwapEngine(model, 120, termStructure); #if QL_USE_INDEXED_COUPON double tolerance = 4.0e-3; #else double tolerance = 1.0e-8; #endif for (int i=0; i<start.Length; i++) { Date startDate = calendar.advance(settlement,start[i],TimeUnit.Months); if (startDate < today) { Date fixingDate = calendar.advance(startDate,-2,TimeUnit.Days); //TimeSeries<double> pastFixings; ObservableValue<TimeSeries<double>> pastFixings = new ObservableValue<TimeSeries<double>>(); pastFixings.value()[fixingDate] = 0.03; IndexManager.instance().setHistory(euribor.name(), pastFixings); } for (int j=0; j<length.Length; j++) { Date maturity = calendar.advance(startDate, length[i], TimeUnit.Years); Schedule fixedSchedule = new Schedule(startDate, maturity, new Period(Frequency.Annual), calendar, BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(startDate, maturity, new Period(Frequency.Semiannual), calendar, BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false); for (int k=0; k<rates.Length; k++) { VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, 1000000.0, fixedSchedule, rates[k], new Thirty360(), floatSchedule, euribor, 0.0, new Actual360()); swap.setPricingEngine(new DiscountingSwapEngine(termStructure)); double expected = swap.NPV(); swap.setPricingEngine(engine); double calculated = swap.NPV(); double error = Math.Abs((expected-calculated)/expected); if (error > tolerance) { Assert.Fail("Failed to reproduce swap NPV:" //+ QL_FIXED << std::setprecision(9) + "\n calculated: " + calculated + "\n expected: " + expected //+ QL_SCIENTIFIC + "\n rel. error: " + error); } } } } }
public void testParity() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < vols.Length; k++) { List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]); Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention); Schedule schedule = new Schedule(startDate, maturity, new Period(vars.frequency), vars.calendar, vars.convention, vars.convention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], schedule, strikes[j], vars.index.dayCounter(), schedule, vars.index, 0.0, vars.index.dayCounter()); swap.setPricingEngine((IPricingEngine)new DiscountingSwapEngine(vars.termStructure)); // FLOATING_POINT_EXCEPTION if (Math.Abs((cap.NPV() - floor.NPV()) - swap.NPV()) > 1.0e-10) { Assert.Fail( "put/call parity violated:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " strike: " + strikes[j] + "\n" + " cap value: " + cap.NPV() + "\n" + " floor value: " + floor.NPV() + "\n" + " swap value: " + swap.NPV()); } } } } }