Hey all – I’m struggling with something I think should be pretty basic. I’m actually using QLNet (the dotnet port), so the code is C# below, but hopefully that doesn’t slow anyone down. Given a price, I’m attempting to calculate the Yield for each
call date (and add maturity date as the final call date) I have the following GetFixedRateBond method (taken from the docs): public static FixedRateBond GetFixedRateBond(double redemption, double coupon, Date datedDate, Date maturityDate, Date settlementDate, DayCounter dayCounter, Frequency frequency) { Settings.setEvaluationDate(new TARGET().adjust(settlementDate)); var schedule = new Schedule( datedDate, maturityDate, new Period(frequency), new UnitedStates(UnitedStates.Market.GovernmentBond), BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Forward, false); var bondHelper = new FixedRateBondHelper( new RelinkableHandle<Quote>(), 0, _bondFaceAmount, schedule, new List<double>() { coupon / 100.0 }, dayCounter, BusinessDayConvention.Unadjusted, redemption); var curve = new PiecewiseYieldCurve<Discount, LogLinear>( settlementDate, new List<RateHelper>() { bondHelper }, dayCounter); var termStructure = new RelinkableHandle<YieldTermStructure>(curve); var engine = new DiscountingBondEngine(termStructure); var fixedRateBond = bondHelper.fixedRateBond(); fixedRateBond.setPricingEngine(engine); return fixedRateBond; } Given above, I loop through a collection of call events ( Date, Call Redemption): var e = new List<CalcEvent>(); foreach (var callEvent in _callEvents) { var bond = GetFixedRateBond((double)callEvent.Price, Coupon, IssueDate, callEvent.Date, SettlementDate, DayCounter, Frequency); var transform = new CalcEvent { Date = callEvent.Date, RedemptionPrice = callEvent.Price, }; //Here price is the given price we contemplate buying the bond for.
transform.Yield = bond.yield(price, DayCounter, _compounding, Frequency, SettlementDate, _precision) * 100; e.Add(transform); } From the list of all the call events, I take the last call event (maturity) and put that yield as YTM – which seems to work consistently well. The YTW however (selecting the call with the lowest yield), fails when compared to Bloomberg,
off by .03 or so. Give the following: Cusip: 24880ACS9 Price: 100.652 Expected YTW: .803 C2017@100 YTM: 4.792 SettlementDate: 2017-07-03 Maturity: 2027-09-01 Issue: 2008-06-25 DayCount: Thirty360 Frequency: SemiAnnually Test Case: YTW Expected 0.803, was 0.815686458817721, diff: 0.0126864588177211 I’m not really sure where to look at this point, any help would be appreciated Thanks for your time, ~Prescott ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Looked at this very quickly but I think the date generation rule should be
backward. Check the dates of the schedule they should pay every March 1st and Sep 1st. Seems like you might be counting forward from the issue date. On Wednesday, June 28, 2017 6:58:34 PM EDT Prescott Nasser wrote: > Hey all - > > I'm struggling with something I think should be pretty basic. I'm actually > using QLNet (the dotnet port), so the code is C# below, but hopefully that > doesn't slow anyone down. Given a price, I'm attempting to calculate the > Yield for each call date (and add maturity date as the final call date) > > I have the following GetFixedRateBond method (taken from the docs): > > public static FixedRateBond GetFixedRateBond(double redemption, double > coupon, Date datedDate, Date maturityDate, Date settlementDate, DayCounter > dayCounter, Frequency frequency) > { > > Settings.setEvaluationDate(new TARGET().adjust(settlementDate)); > > var schedule = new Schedule( > datedDate, > maturityDate, > new Period(frequency), > new UnitedStates(UnitedStates.Market.GovernmentBond), > BusinessDayConvention.Unadjusted, > BusinessDayConvention.Unadjusted, > DateGeneration.Rule.Forward, > false); > > var bondHelper = new FixedRateBondHelper( > new RelinkableHandle<Quote>(), > 0, > _bondFaceAmount, > schedule, > new List<double>() { coupon / 100.0 }, > dayCounter, > BusinessDayConvention.Unadjusted, > redemption); > > var curve = new PiecewiseYieldCurve<Discount, LogLinear>( > settlementDate, > new List<RateHelper>() { bondHelper }, > dayCounter); > > var termStructure = new > RelinkableHandle<YieldTermStructure>(curve); var engine = new > DiscountingBondEngine(termStructure); > > var fixedRateBond = bondHelper.fixedRateBond(); > fixedRateBond.setPricingEngine(engine); > > return fixedRateBond; > } > > Given above, I loop through a collection of call events ( Date, Call > Redemption): > > var e = new List<CalcEvent>(); > foreach (var callEvent in _callEvents) > { > > var bond = GetFixedRateBond((double)callEvent.Price, Coupon, > IssueDate, callEvent.Date, SettlementDate, DayCounter, Frequency); > > > var transform = new CalcEvent > { > Date = callEvent.Date, > RedemptionPrice = callEvent.Price, > }; > > //Here price is the given price we contemplate buying the > bond for. transform.Yield = bond.yield(price, DayCounter, _compounding, > Frequency, SettlementDate, _precision) * 100; e.Add(transform); > } > > From the list of all the call events, I take the last call event (maturity) > and put that yield as YTM - which seems to work consistently well. The YTW > however (selecting the call with the lowest yield), fails when compared to > Bloomberg, off by .03 or so. > > Give the following: > Cusip: 24880ACS9 > Price: 100.652 > Expected YTW: .803 C2017@100 > YTM: 4.792 > SettlementDate: 2017-07-03 > > Maturity: 2027-09-01 > Issue: 2008-06-25 > DayCount: Thirty360 > Frequency: SemiAnnually > > Test Case: > YTW Expected 0.803, was 0.815686458817721, diff: 0.0126864588177211 > > I'm not really sure where to look at this point, any help would be > appreciated > > Thanks for your time, > ~Prescott ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Well - well done. That seemed to fix it. Do you mind explaining a little bit more what was going on with that? I don't quite understand what that means backwards vs forwards - or when I'd never toggle between them.
Thanks very much for you help! -----Original Message----- From: [hidden email] [mailto:[hidden email]] Sent: Wednesday, June 28, 2017 5:21 PM To: [hidden email] Cc: Prescott Nasser <[hidden email]> Subject: Re: [Quantlib-users] YTC for all call dates given price Looked at this very quickly but I think the date generation rule should be backward. Check the dates of the schedule they should pay every March 1st and Sep 1st. Seems like you might be counting forward from the issue date. On Wednesday, June 28, 2017 6:58:34 PM EDT Prescott Nasser wrote: > Hey all - > > I'm struggling with something I think should be pretty basic. I'm > actually using QLNet (the dotnet port), so the code is C# below, but > hopefully that doesn't slow anyone down. Given a price, I'm attempting > to calculate the Yield for each call date (and add maturity date as > the final call date) > > I have the following GetFixedRateBond method (taken from the docs): > > public static FixedRateBond GetFixedRateBond(double redemption, double > coupon, Date datedDate, Date maturityDate, Date settlementDate, > DayCounter dayCounter, Frequency frequency) > { > > Settings.setEvaluationDate(new > TARGET().adjust(settlementDate)); > > var schedule = new Schedule( > datedDate, > maturityDate, > new Period(frequency), > new UnitedStates(UnitedStates.Market.GovernmentBond), > BusinessDayConvention.Unadjusted, > BusinessDayConvention.Unadjusted, > DateGeneration.Rule.Forward, > false); > > var bondHelper = new FixedRateBondHelper( > new RelinkableHandle<Quote>(), > 0, > _bondFaceAmount, > schedule, > new List<double>() { coupon / 100.0 }, > dayCounter, > BusinessDayConvention.Unadjusted, > redemption); > > var curve = new PiecewiseYieldCurve<Discount, LogLinear>( > settlementDate, > new List<RateHelper>() { bondHelper }, > dayCounter); > > var termStructure = new > RelinkableHandle<YieldTermStructure>(curve); var engine = new > DiscountingBondEngine(termStructure); > > var fixedRateBond = bondHelper.fixedRateBond(); > fixedRateBond.setPricingEngine(engine); > > return fixedRateBond; > } > > Given above, I loop through a collection of call events ( Date, Call > Redemption): > > var e = new List<CalcEvent>(); > foreach (var callEvent in _callEvents) > { > > var bond = GetFixedRateBond((double)callEvent.Price, > Coupon, IssueDate, callEvent.Date, SettlementDate, DayCounter, > Frequency); > > > var transform = new CalcEvent > { > Date = callEvent.Date, > RedemptionPrice = callEvent.Price, > }; > > //Here price is the given price we contemplate buying > the bond for. transform.Yield = bond.yield(price, DayCounter, > _compounding, Frequency, SettlementDate, _precision) * 100; e.Add(transform); > } > > From the list of all the call events, I take the last call event > (maturity) and put that yield as YTM - which seems to work > consistently well. The YTW however (selecting the call with the lowest > yield), fails when compared to Bloomberg, off by .03 or so. > > Give the following: > Cusip: 24880ACS9 > Price: 100.652 > Expected YTW: .803 C2017@100 > YTM: 4.792 > SettlementDate: 2017-07-03 > > Maturity: 2027-09-01 > Issue: 2008-06-25 > DayCount: Thirty360 > Frequency: SemiAnnually > > Test Case: > YTW Expected 0.803, was 0.815686458817721, diff: 0.0126864588177211 > > I'm not really sure where to look at this point, any help would be > appreciated > > Thanks for your time, > ~Prescott ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
You had the issue date set as 2008-06-25 and the maturity set as 2027-09-01. If you pass those to a Schedule constructor and tell it to generate dates semiannually and forward, you'll get dates six months apart starting from the issue date and going forward, so 2008-12-25, 2009-06-25 and so on until 2027-06-25, plus a short coupon from there to maturity. If you generate dates backwards instead, the schedule starts from the maturity and goes back by six months each time, so you get 2027-03-01, 2026-09-01, 2026-03-01 and so on until 2008-09-01 plus a short first coupon. Luigi On Thu, Jun 29, 2017 at 10:28 AM Prescott Nasser <[hidden email]> wrote: Well - well done. That seemed to fix it. Do you mind explaining a little bit more what was going on with that? I don't quite understand what that means backwards vs forwards - or when I'd never toggle between them. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ QuantLib-users mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-users |
Free forum by Nabble | Edit this page |