static void Main(string[] args) {

            DateTime timer = DateTime.Now;

            /*********************
             ***  MARKET DATA  ***
             *********************/

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(18, Month.September, 2008);
            // must be a business day
            settlementDate = calendar.adjust(settlementDate);

            int fixingDays = 3;
            int settlementDays = 3;

            Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days);
            // nothing to do with Date::todaysDate
            Settings.setEvaluationDate(todaysDate);

            Console.WriteLine("Today: {0}, {1}", todaysDate.DayOfWeek, todaysDate);
            Console.WriteLine("Settlement date: {0}, {1}", settlementDate.DayOfWeek, settlementDate);


            // Building of the bonds discounting yield curve

            /*********************
             ***  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.

            // Common data

            // ZC rates for the short end
             double zc3mQuote=0.0096;
             double zc6mQuote=0.0145;
             double zc1yQuote=0.0194;

             Quote zc3mRate = new SimpleQuote(zc3mQuote);
             Quote zc6mRate = new SimpleQuote(zc6mQuote);
             Quote zc1yRate = new SimpleQuote(zc1yQuote);

             DayCounter zcBondsDayCounter = new Actual365Fixed();

             RateHelper zc3m = new DepositRateHelper(new Handle<Quote>(zc3mRate),
                                                          new Period(3, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc6m = new DepositRateHelper(new Handle<Quote>(zc6mRate),
                                                          new Period(6, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc1y = new DepositRateHelper(new Handle<Quote>(zc1yRate),
                                                          new Period(1, TimeUnit.Years), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);

            // setup bonds
            double redemption = 100.0;

            const int numberOfBonds = 5;

            Date[] issueDates = {
                    new Date (15, Month.March, 2005),
                    new Date (15, Month.June, 2005),
                    new Date (30, Month.June, 2006),
                    new Date (15, Month.November, 2002),
                    new Date (15, Month.May, 1987)
            };

            Date[] maturities = {
                    new Date (31, Month.August, 2010),
                    new Date (31, Month.August, 2011),
                    new Date (31, Month.August, 2013),
                    new Date (15, Month.August, 2018),
                    new Date (15, Month.May, 2038)
            };

            double[] couponRates = {
                    0.02375,
                    0.04625,
                    0.03125,
                    0.04000,
                    0.04500
            };

            double[] marketQuotes = {
                    100.390625,
                    106.21875,
                    100.59375,
                    101.6875,
                    102.140625
            };

            List<SimpleQuote> quote = new List<SimpleQuote>();
            for (int i=0; i<numberOfBonds; i++) {
                SimpleQuote cp = new SimpleQuote(marketQuotes[i]);
                quote.Add(cp);
            }

            List<RelinkableHandle<Quote>> quoteHandle = new InitializedList<RelinkableHandle<Quote>>(numberOfBonds);
            for (int i=0; i<numberOfBonds; i++) {
                quoteHandle[i].linkTo(quote[i]);
            }

            // Definition of the rate helpers
            List<FixedRateBondHelper> bondsHelpers = new List<FixedRateBondHelper>();
            for (int i=0; i<numberOfBonds; i++) {

                Schedule schedule = new Schedule(issueDates[i], maturities[i], new Period(Frequency.Semiannual), 
                                                 new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                 BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, 
                                                 DateGeneration.Rule.Backward, false);

                FixedRateBondHelper bondHelper = new FixedRateBondHelper(quoteHandle[i],
                                                                         settlementDays,
                                                                         100.0,
                                                                         schedule,
                                                                         new List<double>() { couponRates[i] },
                                                                         new ActualActual(ActualActual.Convention.Bond),
                                                                         BusinessDayConvention.Unadjusted,
                                                                         redemption,
                                                                         issueDates[i]);

                bondsHelpers.Add(bondHelper);
            }

            /*********************
             **  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-bond curve
             List<RateHelper> bondInstruments = new List<RateHelper>();

             // Adding the ZC bonds to the curve for the short end
             bondInstruments.Add(zc3m);
             bondInstruments.Add(zc6m);
             bondInstruments.Add(zc1y);

             // Adding the Fixed rate bonds to the curve for the long end
             for (int i=0; i<numberOfBonds; i++) {
                 bondInstruments.Add(bondsHelpers[i]);
             }

             YieldTermStructure bondDiscountingTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>(
                                                                     settlementDate, bondInstruments,
                                                                     termStructureDayCounter,
                                                                     new List<Handle<Quote>>(),
                                                                     new List<Date>(),
                                                                     tolerance);

             // Building of the Libor forecasting curve
             // deposits
             double d1wQuote=0.043375;
             double d1mQuote=0.031875;
             double d3mQuote=0.0320375;
             double d6mQuote=0.03385;
             double d9mQuote=0.0338125;
             double d1yQuote=0.0335125;
             // swaps
             double s2yQuote=0.0295;
             double s3yQuote=0.0323;
             double s5yQuote=0.0359;
             double s10yQuote=0.0412;
             double s15yQuote=0.0433;


             /********************
              ***    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);
             // 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 swaps
             Frequency swFixedLegFrequency =Frequency.Annual;
             BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
             DayCounter swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
             IborIndex swFloatingLegIndex = new Euribor6M();

             Period forwardStart = new Period(1, TimeUnit.Days);

             RateHelper s2y = new SwapRateHelper(
                     new Handle<Quote>(s2yRate), new Period(2, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s3y = new SwapRateHelper(
                     new Handle<Quote>(s3yRate), new Period(3, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s5y = new SwapRateHelper(
                     new Handle<Quote>(s5yRate), new Period(5, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s10y = new SwapRateHelper(
                     new Handle<Quote>(s10yRate), new Period(10, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             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
             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);

             // 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>();

             /*********************
              * BONDS TO BE PRICED *
              **********************/

             // Common data
             double faceAmount = 100;

             // Pricing engine
             IPricingEngine bondEngine = new DiscountingBondEngine(discountingTermStructure);

             // Zero coupon bond
             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
             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);

             FixedRateBond fixedRateBond = new FixedRateBond(
                     settlementDays,
                     faceAmount,
                     fixedBondSchedule,
                     new List<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...

             RelinkableHandle<YieldTermStructure> liborTermStructure = new RelinkableHandle<YieldTermStructure>();
             IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), liborTermStructure);
             libor3m.addFixing(new Date(17, Month.July, 2008),0.0278625);

             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);

             FloatingRateBond floatingRateBond = new FloatingRateBond(
                     settlementDays,
                     faceAmount,
                     floatingBondSchedule,
                     libor3m,
                     new Actual360(),
                     BusinessDayConvention.ModifiedFollowing,
                     2,
                     // Gearings
                     new List<double>() { 1.0 },
                     // Spreads
                     new List<double>() { 0.001 },
                     // Caps
                     new List<double>(),
                     // Floors
                     new List<double>(),
                     // Fixing in arrears
                     true,
                     100.0,
                     new Date(21, Month.October, 2005));

             floatingRateBond.setPricingEngine(bondEngine);

             // Coupon pricers
             IborCouponPricer pricer = new BlackIborCouponPricer();

             // optionLet volatilities
             double volatility = 0.0;
             Handle<OptionletVolatilityStructure> vol;
             vol = new Handle<OptionletVolatilityStructure>(
                                new ConstantOptionletVolatility(
                                     settlementDays,
                                     calendar,
                                     BusinessDayConvention.ModifiedFollowing,
                                     volatility,
                                     new Actual365Fixed()));

             pricer.setCapletVolatility(vol);
             Utils.setCouponPricer(floatingRateBond.cashflows(),pricer);

             // Yield curve bootstrapping
             forecastingTermStructure.linkTo(depoSwapTermStructure);
             discountingTermStructure.linkTo(bondDiscountingTermStructure);

             // We are using the depo & swap curve to estimate the future Libor rates
             liborTermStructure.linkTo(depoSwapTermStructure);

             /***************
              * BOND PRICING *
              ****************/

             // write column headings
             int[] widths = { 18, 10, 10, 10 };

            Console.WriteLine("{0,18}{1,10}{2,10}{3,10}", "", "ZC", "Fixed", "Floating");

            string separator = " | ";
            int width = widths[0]
                                 + widths[1]
                                          + widths[2]
                                                   + widths[3];
            string rule = "".PadLeft(width, '-'), dblrule = "".PadLeft(width, '=');
            string tab = "".PadLeft(8, ' ');

            Console.WriteLine(rule);

            Console.WriteLine("Net present value".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}", 
                                zeroCouponBond.NPV(),
                                fixedRateBond.NPV(),
                                floatingRateBond.NPV());

            Console.WriteLine("Clean price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.cleanPrice(),
                                fixedRateBond.cleanPrice(),
                                floatingRateBond.cleanPrice());

            Console.WriteLine("Dirty price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.dirtyPrice(),
                                fixedRateBond.dirtyPrice(),
                                floatingRateBond.dirtyPrice());

            Console.WriteLine("Accrued coupon".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.accruedAmount(),
                                fixedRateBond.accruedAmount(),
                                floatingRateBond.accruedAmount());

            Console.WriteLine("Previous coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                                "N/A",
                                fixedRateBond.previousCoupon(),
                                floatingRateBond.previousCoupon());

            Console.WriteLine("Next coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.nextCoupon(),
                              floatingRateBond.nextCoupon());

            Console.WriteLine("Yield".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              zeroCouponBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual));

            Console.WriteLine();

            // Other computations
            Console.WriteLine("Sample indirect computations (for the floating rate bond): ");
            Console.WriteLine(rule);

            Console.WriteLine("Yield to Clean Price: {0:n2}",
                floatingRateBond.cleanPrice(floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                                                                   new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                                   settlementDate));

            Console.WriteLine("Clean Price to Yield: {0:0.00%}",
                floatingRateBond.yield(floatingRateBond.cleanPrice(),new Actual360(), Compounding.Compounded, Frequency.Annual,
                                       settlementDate));

            /* "Yield to Price"
               "Price to Yield" */

            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #2
0
        public void testCached()
        {
            // ("Testing bond price/yield calculation against cached values...");

             CommonVars vars = new CommonVars();

             // with implicit settlement calculation:
             Date today = new Date(22, Month.November, 2004);
             Settings.setEvaluationDate(today);

             Calendar bondCalendar = new NullCalendar();
             DayCounter bondDayCount = new ActualActual(ActualActual.Convention.ISMA);
             int settlementDays = 1;

             var discountCurve = new Handle<YieldTermStructure>(Utilities.flatRate(today, new SimpleQuote(0.03), new Actual360()));

             // actual market values from the evaluation date
             Frequency freq = Frequency.Semiannual;
             Schedule sch1 = new Schedule(new Date(31, Month.October, 2004), new Date(31, Month.October, 2006), new Period(freq),
                                      bondCalendar, BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                      DateGeneration.Rule.Backward, false);

             FixedRateBond bond1 = new FixedRateBond(settlementDays, vars.faceAmount, sch1, new List<double>() { 0.025 },
                                 bondDayCount, BusinessDayConvention.ModifiedFollowing, 100.0, new Date(1, Month.November, 2004));

             IPricingEngine bondEngine = new DiscountingBondEngine(discountCurve);
             bond1.setPricingEngine(bondEngine);

             double marketPrice1 = 99.203125;
             double marketYield1 = 0.02925;

             Schedule sch2 = new Schedule(new Date(15, Month.November, 2004), new Date(15, Month.November, 2009), new Period(freq),
                                      bondCalendar, BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                      DateGeneration.Rule.Backward, false);

             FixedRateBond bond2 = new FixedRateBond(settlementDays, vars.faceAmount, sch2, new List<double>() { 0.035 },
                                      bondDayCount, BusinessDayConvention.ModifiedFollowing,
                                      100.0, new Date(15, Month.November, 2004));

             bond2.setPricingEngine(bondEngine);

             double marketPrice2 = 99.6875;
             double marketYield2 = 0.03569;

             // calculated values
             double cachedPrice1a = 99.204505, cachedPrice2a = 99.687192;
             double cachedPrice1b = 98.943393, cachedPrice2b = 101.986794;
             double cachedYield1a = 0.029257, cachedYield2a = 0.035689;
             double cachedYield1b = 0.029045, cachedYield2b = 0.035375;
             double cachedYield1c = 0.030423, cachedYield2c = 0.030432;

             // check
             double tolerance = 1.0e-6;
             double price, yield;

             price = bond1.cleanPrice(marketYield1, bondDayCount, Compounding.Compounded, freq);
             if (Math.Abs(price - cachedPrice1a) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:"
                       + "\n    calculated: " + price
                       + "\n    expected:   " + cachedPrice1a
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (price - cachedPrice1a));
             }

             price = bond1.cleanPrice();
             if (Math.Abs(price - cachedPrice1b) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:"
                       + "\n    calculated: " + price
                       + "\n    expected:   " + cachedPrice1b
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (price - cachedPrice1b));
             }

             yield = bond1.yield(marketPrice1, bondDayCount, Compounding.Compounded, freq);
             if (Math.Abs(yield - cachedYield1a) > tolerance)
             {
            Assert.Fail("failed to reproduce cached compounded yield:"
                       + "\n    calculated: " + yield
                       + "\n    expected:   " + cachedYield1a
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (yield - cachedYield1a));
             }

             yield = bond1.yield(marketPrice1, bondDayCount, Compounding.Continuous, freq);
             if (Math.Abs(yield - cachedYield1b) > tolerance)
             {
            Assert.Fail("failed to reproduce cached continuous yield:"
                       + "\n    calculated: " + yield
                       + "\n    expected:   " + cachedYield1b
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (yield - cachedYield1b));
             }

             yield = bond1.yield(bondDayCount, Compounding.Continuous, freq);
             if (Math.Abs(yield - cachedYield1c) > tolerance)
             {
            Assert.Fail("failed to reproduce cached continuous yield:"
                       + "\n    calculated: " + yield
                       + "\n    expected:   " + cachedYield1c
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (yield - cachedYield1c));
             }

             price = bond2.cleanPrice(marketYield2, bondDayCount, Compounding.Compounded, freq);
             if (Math.Abs(price - cachedPrice2a) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:"
                       + "\n    calculated: " + price
                       + "\n    expected:   " + cachedPrice2a
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (price - cachedPrice2a));
             }

             price = bond2.cleanPrice();
             if (Math.Abs(price - cachedPrice2b) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:"
                       + "\n    calculated: " + price
                       + "\n    expected:   " + cachedPrice2b
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (price - cachedPrice2b));
             }

             yield = bond2.yield(marketPrice2, bondDayCount, Compounding.Compounded, freq);
             if (Math.Abs(yield - cachedYield2a) > tolerance)
             {
            Assert.Fail("failed to reproduce cached compounded yield:"
                       + "\n    calculated: " + yield
                       + "\n    expected:   " + cachedYield2a
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (yield - cachedYield2a));
             }

             yield = bond2.yield(marketPrice2, bondDayCount, Compounding.Continuous, freq);
             if (Math.Abs(yield - cachedYield2b) > tolerance)
             {
            Assert.Fail("failed to reproduce cached continuous yield:"
                       + "\n    calculated: " + yield
                       + "\n    expected:   " + cachedYield2b
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (yield - cachedYield2b));
             }

             yield = bond2.yield(bondDayCount, Compounding.Continuous, freq);
             if (Math.Abs(yield - cachedYield2c) > tolerance)
             {
            Assert.Fail("failed to reproduce cached continuous yield:"
                       + "\n    calculated: " + yield
                       + "\n    expected:   " + cachedYield2c
                       + "\n    tolerance:  " + tolerance
                       + "\n    error:      " + (yield - cachedYield2c));
             }

             // with explicit settlement date:
             Schedule sch3 = new Schedule(new Date(30, Month.November, 2004), new Date(30, Month.November, 2006), new Period(freq),
                                      new UnitedStates(UnitedStates.Market.GovernmentBond), BusinessDayConvention.Unadjusted,
                                      BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false);

             FixedRateBond bond3 = new FixedRateBond(settlementDays, vars.faceAmount, sch3, new List<double>() { 0.02875 },
                             new ActualActual(ActualActual.Convention.ISMA),
                             BusinessDayConvention.ModifiedFollowing, 100.0, new Date(30, Month.November, 2004));

             bond3.setPricingEngine(bondEngine);

             double marketYield3 = 0.02997;

             Date settlementDate = new Date(30, Month.November, 2004);
             double cachedPrice3 = 99.764759;

             price = bond3.cleanPrice(marketYield3, bondDayCount, Compounding.Compounded, freq, settlementDate);
             if (Math.Abs(price - cachedPrice3) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:"
                       + "\n    calculated: " + price + ""
                       + "\n    expected:   " + cachedPrice3 + ""
                       + "\n    error:      " + (price - cachedPrice3));
             }

             // this should give the same result since the issue date is the
             // earliest possible settlement date
             Settings.setEvaluationDate(new Date(22, Month.November, 2004));

             price = bond3.cleanPrice(marketYield3, bondDayCount, Compounding.Compounded, freq);
             if (Math.Abs(price - cachedPrice3) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:"
                       + "\n    calculated: " + price + ""
                       + "\n    expected:   " + cachedPrice3 + ""
                       + "\n    error:      " + (price - cachedPrice3));
             }
        }
Пример #3
0
        public void testTheoretical()
        {
            // "Testing theoretical bond price/yield calculation...");

             CommonVars vars = new CommonVars();

             double tolerance = 1.0e-7;
             int maxEvaluations = 100;

             int[] lengths = new int[] { 3, 5, 10, 15, 20 };
             int settlementDays = 3;
             double[] coupons = new double[] { 0.02, 0.05, 0.08 };
             Frequency[] frequencies = new Frequency[] { Frequency.Semiannual, Frequency.Annual };
             DayCounter bondDayCount = new Actual360();
             BusinessDayConvention accrualConvention = BusinessDayConvention.Unadjusted;
             BusinessDayConvention paymentConvention = BusinessDayConvention.ModifiedFollowing;
             double redemption = 100.0;

             double[] yields = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 };

             for (int j = 0; j < lengths.Length; j++)
             {
            for (int k = 0; k < coupons.Length; k++)
            {
               for (int l = 0; l < frequencies.Length; l++)
               {

                  Date dated = vars.today;
                  Date issue = dated;
                  Date maturity = vars.calendar.advance(issue, lengths[j], TimeUnit.Years);

                  SimpleQuote rate = new SimpleQuote(0.0);
                  var discountCurve = new Handle<YieldTermStructure>(Utilities.flatRate(vars.today, rate, bondDayCount));

                  Schedule sch = new Schedule(dated, maturity, new Period(frequencies[l]), vars.calendar,
                                              accrualConvention, accrualConvention, DateGeneration.Rule.Backward, false);

                  FixedRateBond bond = new FixedRateBond(settlementDays, vars.faceAmount, sch, new List<double>() { coupons[k] },
                                                         bondDayCount, paymentConvention, redemption, issue);

                  IPricingEngine bondEngine = new DiscountingBondEngine(discountCurve);
                  bond.setPricingEngine(bondEngine);

                  for (int m = 0; m < yields.Length; m++)
                  {

                     rate.setValue(yields[m]);

                     double price = bond.cleanPrice(yields[m], bondDayCount, Compounding.Continuous, frequencies[l]);
                     double calculatedPrice = bond.cleanPrice();

                     if (Math.Abs(price - calculatedPrice) > tolerance)
                     {
                        Assert.Fail("price calculation failed:"
                            + "\n    issue:     " + issue
                            + "\n    maturity:  " + maturity
                            + "\n    coupon:    " + coupons[k]
                            + "\n    frequency: " + frequencies[l] + "\n"
                            + "\n    yield:     " + yields[m]
                            + "\n    expected:    " + price
                            + "\n    calculated': " + calculatedPrice
                            + "\n    error':      " + (price - calculatedPrice));
                     }

                     double calculatedYield = bond.yield(bondDayCount, Compounding.Continuous, frequencies[l],
                                              tolerance, maxEvaluations);
                     if (Math.Abs(yields[m] - calculatedYield) > tolerance)
                     {
                        Assert.Fail("yield calculation failed:"
                            + "\n    issue:     " + issue
                            + "\n    maturity:  " + maturity
                            + "\n    coupon:    " + coupons[k]
                            + "\n    frequency: " + frequencies[l] + "\n"
                            + "\n    yield:  " + yields[m]
                            + "\n    price:  " + price
                            + "\n    yield': " + calculatedYield);
                     }
                  }
               }
            }
             }
        }
Пример #4
0
        public void testYield()
        {
            //"Testing consistency of bond price/yield calculation...");

             CommonVars vars = new CommonVars();

             double tolerance = 1.0e-7;
             int maxEvaluations = 100;

             int[] issueMonths = new int[] { -24, -18, -12, -6, 0, 6, 12, 18, 24 };
             int[] lengths = new int[] { 3, 5, 10, 15, 20 };
             int settlementDays = 3;
             double[] coupons = new double[] { 0.02, 0.05, 0.08 };
             Frequency[] frequencies = new Frequency[] { Frequency.Semiannual, Frequency.Annual };
             DayCounter bondDayCount = new Thirty360();
             BusinessDayConvention accrualConvention = BusinessDayConvention.Unadjusted;
             BusinessDayConvention paymentConvention = BusinessDayConvention.ModifiedFollowing;
             double redemption = 100.0;

             double[] yields = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 };
             Compounding[] compounding = new Compounding[] { Compounding.Compounded, Compounding.Continuous };

             for (int i = 0; i < issueMonths.Length; i++)
             {
            for (int j = 0; j < lengths.Length; j++)
            {
               for (int k = 0; k < coupons.Length; k++)
               {
                  for (int l = 0; l < frequencies.Length; l++)
                  {
                     for (int n = 0; n < compounding.Length; n++)
                     {

                        Date dated = vars.calendar.advance(vars.today, issueMonths[i], TimeUnit.Months);
                        Date issue = dated;
                        Date maturity = vars.calendar.advance(issue, lengths[j], TimeUnit.Years);

                        Schedule sch = new Schedule(dated, maturity, new Period(frequencies[l]), vars.calendar,
                                                    accrualConvention, accrualConvention, DateGeneration.Rule.Backward, false);

                        FixedRateBond bond = new FixedRateBond(settlementDays, vars.faceAmount, sch,
                                                               new List<double>() { coupons[k] },
                                                               bondDayCount, paymentConvention,
                                                               redemption, issue);

                        for (int m = 0; m < yields.Length; m++)
                        {

                           double price = bond.cleanPrice(yields[m], bondDayCount, compounding[n], frequencies[l]);
                           double calculated = bond.yield(price, bondDayCount, compounding[n], frequencies[l], null,
                                                          tolerance, maxEvaluations);

                           if (Math.Abs(yields[m] - calculated) > tolerance)
                           {
                              // the difference might not matter
                              double price2 = bond.cleanPrice(calculated, bondDayCount, compounding[n], frequencies[l]);
                              if (Math.Abs(price - price2) / price > tolerance)
                              {
                                 Assert.Fail("yield recalculation failed:\n"
                                     + "    issue:     " + issue + "\n"
                                     + "    maturity:  " + maturity + "\n"
                                     + "    coupon:    " + coupons[k] + "\n"
                                     + "    frequency: " + frequencies[l] + "\n\n"
                                     + "    yield:  " + yields[m] + " "
                                     + (compounding[n] == Compounding.Compounded ? "compounded" : "continuous") + "\n"
                                     + "    price:  " + price + "\n"
                                     + "    yield': " + calculated + "\n"
                                     + "    price': " + price2);
                              }
                           }
                        }
                     }
                  }
               }
            }
             }
        }
Пример #5
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            Date repoSettlementDate = new Date(14,Month.February,2000);;
            Date repoDeliveryDate = new Date(15,Month.August,2000);
            double repoRate = 0.05;
            DayCounter repoDayCountConvention = new Actual360();
            int repoSettlementDays = 0;
            Compounding repoCompounding = Compounding.Simple;
            Frequency repoCompoundFreq = Frequency.Annual;

            // assume a ten year bond- this is irrelevant
            Date bondIssueDate = new Date(15,Month.September,1995);
            Date bondDatedDate = new Date(15,Month.September,1995);
            Date bondMaturityDate = new Date(15,Month.September,2005);
            double bondCoupon = 0.08;
            Frequency bondCouponFrequency = Frequency.Semiannual;
            // unknown what calendar fincad is using
            Calendar bondCalendar = new NullCalendar();
            DayCounter bondDayCountConvention = new Thirty360(Thirty360.Thirty360Convention.BondBasis);
            // unknown what fincad is using. this may affect accrued calculation
            int bondSettlementDays = 0;
            BusinessDayConvention bondBusinessDayConvention = BusinessDayConvention.Unadjusted;
            double bondCleanPrice = 89.97693786;
            double bondRedemption = 100.0;
            double faceAmount = 100.0;

            Settings.setEvaluationDate(repoSettlementDate);

            RelinkableHandle<YieldTermStructure> bondCurve = new RelinkableHandle<YieldTermStructure>();
            bondCurve.linkTo(new FlatForward(repoSettlementDate,
                                               .01, // dummy rate
                                               bondDayCountConvention,
                                               Compounding.Compounded,
                                               bondCouponFrequency));

            /*
            boost::shared_ptr<FixedRateBond> bond(
                           new FixedRateBond(faceAmount,
                                             bondIssueDate,
                                             bondDatedDate,
                                             bondMaturityDate,
                                             bondSettlementDays,
                                             std::vector<Rate>(1,bondCoupon),
                                             bondCouponFrequency,
                                             bondCalendar,
                                             bondDayCountConvention,
                                             bondBusinessDayConvention,
                                             bondBusinessDayConvention,
                                             bondRedemption,
                                             bondCurve));
            */

            Schedule bondSchedule = new Schedule(bondDatedDate, bondMaturityDate,
                                  new Period(bondCouponFrequency),
                                  bondCalendar,bondBusinessDayConvention,
                                  bondBusinessDayConvention,
                                  DateGeneration.Rule.Backward,false);
            FixedRateBond bond = new FixedRateBond(bondSettlementDays,
                                             faceAmount,
                                             bondSchedule,
                                             new List<double>() { bondCoupon },
                                             bondDayCountConvention,
                                             bondBusinessDayConvention,
                                             bondRedemption,
                                             bondIssueDate);
            bond.setPricingEngine(new DiscountingBondEngine(bondCurve));

            bondCurve.linkTo(new FlatForward(repoSettlementDate,
                                       bond.yield(bondCleanPrice,
                                                   bondDayCountConvention,
                                                   Compounding.Compounded,
                                                   bondCouponFrequency),
                                       bondDayCountConvention,
                                       Compounding.Compounded,
                                       bondCouponFrequency));

            Position.Type fwdType = Position.Type.Long;
            double dummyStrike = 91.5745;

            RelinkableHandle<YieldTermStructure> repoCurve = new RelinkableHandle<YieldTermStructure>();
            repoCurve.linkTo(new FlatForward(repoSettlementDate,
                                               repoRate,
                                               repoDayCountConvention,
                                               repoCompounding,
                                               repoCompoundFreq));

            FixedRateBondForward bondFwd = new FixedRateBondForward(repoSettlementDate,
                                         repoDeliveryDate,
                                         fwdType,
                                         dummyStrike,
                                         repoSettlementDays,
                                         repoDayCountConvention,
                                         bondCalendar,
                                         bondBusinessDayConvention,
                                         bond,
                                         repoCurve,
                                         repoCurve);

            Console.WriteLine("Underlying bond clean price: " + bond.cleanPrice());
            Console.WriteLine("Underlying bond dirty price: " + bond.dirtyPrice());
            Console.WriteLine("Underlying bond accrued at settlement: "
                 + bond.accruedAmount(repoSettlementDate));
            Console.WriteLine("Underlying bond accrued at delivery:   "
                 + bond.accruedAmount(repoDeliveryDate));
            Console.WriteLine("Underlying bond spot income: "
                 + bondFwd.spotIncome(repoCurve));
            Console.WriteLine("Underlying bond fwd income:  "
                 + bondFwd.spotIncome(repoCurve)/
                    repoCurve.link.discount(repoDeliveryDate));
            Console.WriteLine("Repo strike: " + dummyStrike);
            Console.WriteLine("Repo NPV:    " + bondFwd.NPV());
            Console.WriteLine("Repo clean forward price: "
                 + bondFwd.cleanForwardPrice());
            Console.WriteLine("Repo dirty forward price: "
                 + bondFwd.forwardPrice());
            Console.WriteLine("Repo implied yield: "
                 + bondFwd.impliedYield(bond.dirtyPrice(),
                                         dummyStrike,
                                         repoSettlementDate,
                                         repoCompounding,
                                         repoDayCountConvention));
            Console.WriteLine("Market repo rate:   "
                 + repoCurve.link.zeroRate(repoDeliveryDate,
                                        repoDayCountConvention,
                                        repoCompounding,
                                        repoCompoundFreq));

            Console.WriteLine("\nCompare with example given at \n"
                 + "http://www.fincad.com/support/developerFunc/mathref/BFWD.htm");
            Console.WriteLine("Clean forward price = 88.2408");
            Console.WriteLine("\nIn that example, it is unknown what bond calendar they are\n"
                 + "using, as well as settlement Days. For that reason, I have\n"
                 + "made the simplest possible assumptions here: NullCalendar\n"
                 + "and 0 settlement days.\n");

            Console.WriteLine("nRun completed in {0}", DateTime.Now - timer);

              Console.Write("Press any key to continue ...");
              Console.ReadKey();
        }