// other instrument dependant infos. Quotes are passed in
// relinkable handles which could be relinked to some other
// data source later.
// deposits
final DayCounter depositDayCounter = new Actual360();
final RateHelper d1w = new DepositRateHelper(
new Handle<Quote>(d1wRate),
new Period(1, TimeUnit.Weeks),
fixingDays, calendar,
BusinessDayConvention.ModifiedFollowing,
true, depositDayCounter);
final RateHelper d1m = new DepositRateHelper(
new Handle<Quote>(d1mRate),
new Period(1, TimeUnit.Months),
fixingDays, calendar,
BusinessDayConvention.ModifiedFollowing,
true, depositDayCounter);
final RateHelper d3m = new DepositRateHelper(
new Handle<Quote>(d3mRate),
new Period(3, TimeUnit.Months),
fixingDays, calendar,
BusinessDayConvention.ModifiedFollowing,
true, depositDayCounter);
final RateHelper d6m = new DepositRateHelper(
new Handle<Quote>(d6mRate),
new Period(6, TimeUnit.Months),
fixingDays, calendar,
BusinessDayConvention.ModifiedFollowing,
true, depositDayCounter);
final RateHelper d9m = new DepositRateHelper(
new Handle<Quote>(d9mRate),
new Period(9, TimeUnit.Months),
fixingDays, calendar,
BusinessDayConvention.ModifiedFollowing,
true, depositDayCounter);
final RateHelper d1y = new DepositRateHelper(
new Handle<Quote>(d1yRate),
new Period(1, TimeUnit.Years),
fixingDays, calendar,
BusinessDayConvention.ModifiedFollowing,
true, depositDayCounter);
// setup swaps
final Frequency swFixedLegFrequency = Frequency.Annual;
final BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
final DayCounter swFixedLegDayCounter = new Thirty360(Convention.European);
final IborIndex swFloatingLegIndex = new Euribor6M(new Handle<YieldTermStructure>());
// TODO and FIXME: not sure whether the class stuff works properly
// final IborIndex swFloatingLegIndex = Euribor.getEuribor6M(new Handle<YieldTermStructure>(YieldTermStructure.class)); //FIXME::RG::Handle
// final YieldTermStructure nullYieldTermStructure = new AbstractYieldTermStructure() {
// @Override
// protected double discountImpl(final double t) {
// throw new UnsupportedOperationException();
// }
// @Override
// public Date maxDate() {
// throw new UnsupportedOperationException();
// }
// };
// final IborIndex swFloatingLegIndex = new Euribor6M(new Handle<YieldTermStructure>(nullYieldTermStructure));
final Period forwardStart = new Period(1, TimeUnit.Days);
final RateHelper s2y = new SwapRateHelper(
new Handle<Quote>(s2yRate),
new Period(2, TimeUnit.Years),
calendar,
swFixedLegFrequency,
swFixedLegConvention,
swFixedLegDayCounter,
swFloatingLegIndex,
new Handle<Quote>(),
forwardStart);
final RateHelper s3y = new SwapRateHelper(
new Handle<Quote>(s3yRate),
new Period(3, TimeUnit.Years),
calendar,
swFixedLegFrequency,
swFixedLegConvention,
swFixedLegDayCounter,
swFloatingLegIndex,
new Handle<Quote>(),
forwardStart);
final RateHelper s5y = new SwapRateHelper(
new Handle<Quote>(s5yRate),
new Period(5, TimeUnit.Years),
calendar,
swFixedLegFrequency,
swFixedLegConvention,
swFixedLegDayCounter,
swFloatingLegIndex,
new Handle<Quote>(),
forwardStart);
final RateHelper s10y = new SwapRateHelper(
new Handle<Quote>(s10yRate),
new Period(10, TimeUnit.Years),
calendar,
swFixedLegFrequency,
swFixedLegConvention,
swFixedLegDayCounter,
swFloatingLegIndex,
new Handle<Quote>(),
forwardStart);
final RateHelper s15y = new SwapRateHelper(
new Handle<Quote>(s15yRate),
new Period(15, TimeUnit.Years),
calendar,
swFixedLegFrequency,
swFixedLegConvention,
swFixedLegDayCounter,
swFloatingLegIndex,
new Handle<Quote>(),
forwardStart);
/*********************
** CURVE BUILDING **
*********************/
// Any DayCounter would be fine.
// ActualActual::ISDA ensures that 30 years is 30.0
// A depo-swap curve
final List<RateHelper> depoSwapInstruments = new ArrayList<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);
final RateHelper[] instruments = new RateHelper[depoSwapInstruments.size()];
depoSwapInstruments.toArray(instruments);
final Handle[] jumps= new Handle[0];//]<Quote>[]) new ArrayList<Handle<Quote>>().toArray();
final Date[] jumpDates = new Date[0];// new ArrayList<Date>().toArray();
final YieldTermStructure depoSwapTermStructure =
new PiecewiseYieldCurve<Discount,LogLinear,IterativeBootstrap>(
Discount.class, LogLinear.class, IterativeBootstrap.class,
settlementDate,
instruments,
termStructureDayCounter,
jumps,
jumpDates,
tolerance,
interpolator,/*Hack*/
bootstrap /*Hack*/){/* anonymous */};
// Term structures that will be used for pricing:
// the one used for discounting cash flows
final RelinkableHandle<YieldTermStructure> discountingTermStructure = new RelinkableHandle<YieldTermStructure>();
// the one used for forward rate forecasting
final RelinkableHandle<YieldTermStructure> forecastingTermStructure = new RelinkableHandle<YieldTermStructure>();
/*********************
* BONDS TO BE PRICED *
**********************/
// Common data
final double faceAmount = 100;
// Pricing engine
final PricingEngine bondEngine = new DiscountingBondEngine(discountingTermStructure);
// Zero coupon bond
final ZeroCouponBond zeroCouponBond = new ZeroCouponBond(
settlementDays,
new UnitedStates(UnitedStates.Market.GOVERNMENTBOND),
faceAmount,
new Date(15,Month.August,2013),
BusinessDayConvention.Following,
116.92,
new Date(15,Month.August,2003));
zeroCouponBond.setPricingEngine(bondEngine);
// Fixed 4.5% US Treasury Note
final Schedule fixedBondSchedule = new Schedule(
new Date(15, Month.May, 2007),
new Date(15,Month.May,2017),
new Period(Frequency.Semiannual),
new UnitedStates(UnitedStates.Market.GOVERNMENTBOND),
BusinessDayConvention.Unadjusted,
BusinessDayConvention.Unadjusted,
DateGeneration.Rule.Backward, false);
final FixedRateBond fixedRateBond = new FixedRateBond(
settlementDays,
faceAmount,
fixedBondSchedule,
new double[]{0.045},
new ActualActual(ActualActual.Convention.Bond),
BusinessDayConvention.ModifiedFollowing,
100.0,
new Date(15, Month.May, 2007));
fixedRateBond.setPricingEngine(bondEngine);
// Floating rate bond (3M USD Libor + 0.1%)
// Should and will be priced on another curve later...
final RelinkableHandle<YieldTermStructure> liborTermStructure = new RelinkableHandle<YieldTermStructure>();
final IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), liborTermStructure);
libor3m.addFixing(new Date(17, Month.July, 2008), 0.0278625);
final Schedule floatingBondSchedule = new Schedule(
new Date(21, Month.October, 2005),
new Date(21, Month.October, 2010), new Period(Frequency.Quarterly),
new UnitedStates(UnitedStates.Market.NYSE),
BusinessDayConvention.Unadjusted,
BusinessDayConvention.Unadjusted,
DateGeneration.Rule.Backward, true);
final FloatingRateBond floatingRateBond = new FloatingRateBond(
settlementDays,
faceAmount,
floatingBondSchedule,
libor3m,
new Actual360(),
BusinessDayConvention.ModifiedFollowing,
2,
new Array(1).fill(1.0), //Gearings
new Array(1).fill(0.001),//Spreads
new Array(0), // Caps
new Array(0), // Floors
true, // Fixing in arrears
100.0,
new Date(21, Month.October, 2005));
floatingRateBond.setPricingEngine(bondEngine);
// optionLet volatilities
final double volatility = 0.0;
final Handle<OptionletVolatilityStructure> vol =
new Handle<OptionletVolatilityStructure>(
new ConstantOptionletVolatility(
settlementDays,
calendar,
BusinessDayConvention.ModifiedFollowing,
volatility,
new Actual365Fixed()));
// Coupon pricers
final IborCouponPricer pricer = new BlackIborCouponPricer(vol);
PricerSetter.setCouponPricer(floatingRateBond.cashflows(),pricer);
// Yield curve bootstrapping
forecastingTermStructure.linkTo(depoSwapTermStructure);
discountingTermStructure.linkTo(bondDiscountingTermStructur);
// We are using the depo & swap curve to estimate the future Libor
// rates
liborTermStructure.linkTo(depoSwapTermStructure);
/***************
* BOND PRICING *
****************/
QL.info("Results:");
System.out.println(" "
+ " " + "ZC"
+ " " + "Fixed"
+ " " + "Floating"
);
System.out.println( "Net present value"
+ " " + zeroCouponBond.NPV()
+ " " + fixedRateBond.NPV()
+ " " + floatingRateBond.NPV());
System.out.println("Clean Price "
+ " " +zeroCouponBond.cleanPrice()
+ " " +fixedRateBond.cleanPrice()
+ " " + floatingRateBond.cleanPrice()
);
System.out.println("Dirty price "
+ " " + zeroCouponBond.dirtyPrice()
+ " " + fixedRateBond.dirtyPrice()
+ " " + floatingRateBond.dirtyPrice()
);
System.out.println( "Accrued coupon "
+ " " + zeroCouponBond.accruedAmount()
+ " " + fixedRateBond.accruedAmount()
+ " " + floatingRateBond.accruedAmount()
);
System.out.println( "Previous coupon "
+ " " + "N/A" //zeroCouponBond
+ " " + fixedRateBond.previousCoupon()
+ " " + floatingRateBond.previousCoupon()
);
System.out.println( "Next coupon "
+ " " + "N/A" //zeroCouponBond
+ " " + fixedRateBond.nextCoupon()
+ " " + floatingRateBond.nextCoupon()
);
System.out.println( "Yield "
+ " " + zeroCouponBond.yield(new Actual360(),Compounding.Compounded, Frequency.Annual)
+ " " + fixedRateBond.yield(new Actual360(),Compounding.Compounded, Frequency.Annual)
+ " " + floatingRateBond.yield(new Actual360(),Compounding.Compounded, Frequency.Annual)
);
// Other computations
System.out.println("Sample indirect computations (for the floating rate bond): " );
System.out.println( "Yield to Clean Price: " +
floatingRateBond.cleanPrice(floatingRateBond.yield(new Actual360(),Compounding.Compounded,Frequency.Annual),new Actual360(),Compounding.Compounded,Frequency.Annual,settlementDate)
);
System.out.println("Clean Price to Yield: " +
floatingRateBond.yield(floatingRateBond.cleanPrice(),new Actual360(),Compounding.Compounded,Frequency.Annual,settlementDate)
);
/* "Yield to Price"
"Price to Yield"
*/