Exemple #1
1
        static void Main(string[] args)
        {
            try
            {
                var timer = new System.Diagnostics.Stopwatch();
                timer.Start();

                #region MARKET DATA

                var calendar = new TARGET();

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

                int fixingDays = 3;
                uint settlementDays = 3;

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

                Console.WriteLine("Today: {0} {1} {2} {3}", todaysDate.weekday(), todaysDate.dayOfMonth(), todaysDate.month(), todaysDate.year());
                Console.WriteLine("Settlement date: {0} {1} {2} {3}", settlementDate.weekday(), settlementDate.dayOfMonth(), settlementDate.month(), settlementDate.year());

                // Building of the bonds discounting yield curve

                #endregion

                #region 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;

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

                var zcBondsDayCounter = new Actual365Fixed();

                var zc3m = new DepositRateHelper(new QuoteHandle(zc3mRate),
                    new Period(3, TimeUnit.Months),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    zcBondsDayCounter);

                var zc6m = new DepositRateHelper(new QuoteHandle(zc6mRate),
                    new Period(6, TimeUnit.Months),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    zcBondsDayCounter);

                var zc1y = new DepositRateHelper(new QuoteHandle(zc1yRate),
                    new Period(1, TimeUnit.Years),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    zcBondsDayCounter);

                // setup bonds
                double redemption = 100.0;

                const uint numberOfBonds = 5;

                var issueDates = new Date[] { 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) };

                var maturities = new Date[] { 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) };

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

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

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

                var quoteHandle = new RelinkableQuoteHandleVector((int)numberOfBonds);
                for (int i = 0; i < (int)numberOfBonds; i++)
                {
                    quoteHandle.Add(new RelinkableQuoteHandle());
                    quoteHandle[i].linkTo(quote[i]);
                }

                // Definition of the rate helpers
                var bondsHelpers = new RateHelperVector((int)numberOfBonds);
                for (int i = 0; i < (int)numberOfBonds; i++)
                {
                    var schedule = new Schedule(issueDates[i],
                        maturities[i],
                        new Period(Frequency.Semiannual),
                        new UnitedStates(UnitedStates.Market.GovernmentBond),
                        BusinessDayConvention.Unadjusted,
                        BusinessDayConvention.Unadjusted,
                        DateGeneration.Rule.Backward,
                        false);

                    var bondHelper = new FixedRateBondHelper(quoteHandle[i],
                            settlementDays,
                            100.0,
                            schedule,
                            new DoubleVector(1) { couponRates[i] },
                            new ActualActual(ActualActual.Convention.Bond),
                            BusinessDayConvention.Unadjusted,
                            redemption,
                            issueDates[i]);

                    bondsHelpers.Add(bondHelper);
                }

                #endregion

                #region CURVE BUILDING

                // Any DayCounter would be fine.
                // ActualActual::ISDA ensures that 30 years is 30.0
                var termStructureDayCounter = new ActualActual(ActualActual.Convention.ISDA);
                //double tolerance = 1.0e-15;

                // A depo-bond curve
                var bondInstruments = new RateHelperVector();

                // 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[3]);

                var bondDiscountingTermStructure = new PiecewiseFlatForward(settlementDate,
                    bondInstruments,
                    termStructureDayCounter);

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

                #endregion

                #region 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
                var d1wRate = new SimpleQuote(d1wQuote);
                var d1mRate = new SimpleQuote(d1mQuote);
                var d3mRate = new SimpleQuote(d3mQuote);
                var d6mRate = new SimpleQuote(d6mQuote);
                var d9mRate = new SimpleQuote(d9mQuote);
                var d1yRate = new SimpleQuote(d1yQuote);
                // swaps
                var s2yRate = new SimpleQuote(s2yQuote);
                var s3yRate = new SimpleQuote(s3yQuote);
                var s5yRate = new SimpleQuote(s5yQuote);
                var s10yRate = new SimpleQuote(s10yQuote);
                var s15yRate = new SimpleQuote(s15yQuote);

                #endregion

                #region 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
                var depositDayCounter = new Actual360();

                var d1w = new DepositRateHelper(new QuoteHandle(d1wRate),
                    new Period(1, TimeUnit.Weeks),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    depositDayCounter);

                var d1m = new DepositRateHelper(new QuoteHandle(d1mRate),
                    new Period(1, TimeUnit.Months),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    depositDayCounter);

                var d3m = new DepositRateHelper(new QuoteHandle(d3mRate),
                    new Period(3, TimeUnit.Months),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    depositDayCounter);

                var d6m = new DepositRateHelper(new QuoteHandle(d6mRate),
                    new Period(6, TimeUnit.Months),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    depositDayCounter);

                var d9m = new DepositRateHelper(new QuoteHandle(d9mRate),
                    new Period(9, TimeUnit.Months),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    depositDayCounter);

                var d1y = new DepositRateHelper(new QuoteHandle(d1yRate),
                    new Period(1, TimeUnit.Years),
                    (uint)fixingDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    true,
                    depositDayCounter);

                // setup swaps
                var swFixedLegFrequency = Frequency.Annual;
                var swFixedLegConvention = BusinessDayConvention.Unadjusted;
                var swFixedLegDayCounter = new Thirty360(Thirty360.Convention.European);
                var swFloatingLegIndex = new Euribor6M();

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

                var s2y = new SwapRateHelper(new QuoteHandle(s2yRate),
                    new Period(2, TimeUnit.Years),
                    calendar,
                    swFixedLegFrequency,
                    swFixedLegConvention,
                    swFixedLegDayCounter,
                    swFloatingLegIndex,
                    new QuoteHandle(),
                    forwardStart);

                var s3y = new SwapRateHelper(new QuoteHandle(s3yRate),
                    new Period(3, TimeUnit.Years),
                    calendar,
                    swFixedLegFrequency,
                    swFixedLegConvention,
                    swFixedLegDayCounter,
                    swFloatingLegIndex,
                    new QuoteHandle(),
                    forwardStart);

                var s5y = new SwapRateHelper(new QuoteHandle(s5yRate),
                    new Period(5, TimeUnit.Years),
                    calendar,
                    swFixedLegFrequency,
                    swFixedLegConvention,
                    swFixedLegDayCounter,
                    swFloatingLegIndex,
                    new QuoteHandle(),
                    forwardStart);

                var s10y = new SwapRateHelper(new QuoteHandle(s10yRate),
                    new Period(10, TimeUnit.Years),
                    calendar,
                    swFixedLegFrequency,
                    swFixedLegConvention,
                    swFixedLegDayCounter,
                    swFloatingLegIndex,
                    new QuoteHandle(),
                    forwardStart);

                var s15y = new SwapRateHelper(new QuoteHandle(s15yRate),
                    new Period(15, TimeUnit.Years),
                    calendar,
                    swFixedLegFrequency,
                    swFixedLegConvention,
                    swFixedLegDayCounter,
                    swFloatingLegIndex,
                    new QuoteHandle(),
                    forwardStart);

                #endregion

                #region CURVE BUILDING

                // Any DayCounter would be fine.
                // ActualActual::ISDA ensures that 30 years is 30.0

                // A depo-swap curve
                var depoSwapInstruments = new RateHelperVector();
                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);

                var depoSwapTermStructure = new PiecewiseFlatForward(settlementDate,
                    depoSwapInstruments,
                    termStructureDayCounter);

                // Term structures that will be used for pricing:
                // the one used for discounting cash flows
                var discountingTermStructure = new RelinkableYieldTermStructureHandle();
                // the one used for forward rate forecasting
                //var forecastingTermStructure = new RelinkableYieldTermStructureHandle();

                #endregion

                #region BONDS TO BE PRICED

                // Common data
                double faceAmount = 100;

                // Pricing engine
                var bondEngine = new DiscountingBondEngine(new YieldTermStructureHandle(bondDiscountingTermStructure));

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

                var fixedRateBond = new FixedRateBond((int)settlementDays,
                    faceAmount,
                    fixedBondSchedule,
                    new DoubleVector(1) { 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...

                var liborTermStructure = new RelinkableYieldTermStructureHandle();
                var libor3m = new USDLibor(new Period(3, TimeUnit.Months),
                    liborTermStructure);
                libor3m.addFixing(new Date(17, Month.July, 2008), 0.0278625);

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

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

                floatingRateBond.setPricingEngine(bondEngine);

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

                // optionLet volatilities
                double volatility = 0.0;
                var vol = new OptionletVolatilityStructureHandle(new ConstantOptionletVolatility(settlementDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    volatility,
                    new Actual365Fixed()));

                pricer.setCapletVolatility(vol);
                NQuantLibc.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);

                #endregion

                #region BOND PRICING

                Console.WriteLine();

                // write column headings
                int[] widths = new int[] { 0, 28, 38, 48 };

                Console.CursorLeft = widths[0]; Console.Write("                 ");
                Console.CursorLeft = widths[1]; Console.Write("ZC");
                Console.CursorLeft = widths[2]; Console.Write("Fixed");
                Console.CursorLeft = widths[3]; Console.WriteLine("Floating");

                //string separator = " | ";
                int width = widths[3];
                string rule = new string('-', width);
                string dblrule = new string('=', width);
                string tab = new string(' ', 8);

                Console.WriteLine(rule);

                Console.CursorLeft = widths[0]; Console.Write("Net present value");
                Console.CursorLeft = widths[1]; Console.Write(zeroCouponBond.NPV().ToString("000.00"));
                Console.CursorLeft = widths[2]; Console.Write(fixedRateBond.NPV().ToString("000.00"));
                Console.CursorLeft = widths[3]; Console.WriteLine(floatingRateBond.NPV().ToString("000.00"));

                Console.CursorLeft = widths[0]; Console.Write("Clean price");
                Console.CursorLeft = widths[1]; Console.Write(zeroCouponBond.cleanPrice().ToString("000.00"));
                Console.CursorLeft = widths[2]; Console.Write(fixedRateBond.cleanPrice().ToString("000.00"));
                Console.CursorLeft = widths[3]; Console.WriteLine(floatingRateBond.cleanPrice().ToString("000.00"));

                Console.CursorLeft = widths[0]; Console.Write("Dirty price");
                Console.CursorLeft = widths[1]; Console.Write(zeroCouponBond.dirtyPrice().ToString("000.00"));
                Console.CursorLeft = widths[2]; Console.Write(fixedRateBond.dirtyPrice().ToString("000.00"));
                Console.CursorLeft = widths[3]; Console.WriteLine(floatingRateBond.dirtyPrice().ToString("000.00"));

                Console.CursorLeft = widths[0]; Console.Write("Accrued coupon");
                Console.CursorLeft = widths[1]; Console.Write(zeroCouponBond.accruedAmount().ToString("000.00"));
                Console.CursorLeft = widths[2]; Console.Write(fixedRateBond.accruedAmount().ToString("000.00"));
                Console.CursorLeft = widths[3]; Console.WriteLine(floatingRateBond.accruedAmount().ToString("000.00"));

                Console.CursorLeft = widths[0]; Console.Write("Previous coupon");
                Console.CursorLeft = widths[1]; Console.Write("N/A");
                Console.CursorLeft = widths[2]; Console.Write(fixedRateBond.previousCouponRate().ToString("000.00"));
                Console.CursorLeft = widths[3]; Console.WriteLine(floatingRateBond.previousCouponRate().ToString("000.00"));

                Console.CursorLeft = widths[0]; Console.Write("Next coupon");
                Console.CursorLeft = widths[1]; Console.Write("N/A");
                Console.CursorLeft = widths[2]; Console.Write(fixedRateBond.nextCouponRate().ToString("000.00"));
                Console.CursorLeft = widths[3]; Console.WriteLine(floatingRateBond.nextCouponRate().ToString("000.00"));

                Console.CursorLeft = widths[0]; Console.Write("Yield");
                Console.CursorLeft = widths[1]; Console.Write(zeroCouponBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual).ToString("000.00"));
                Console.CursorLeft = widths[2]; Console.Write(fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual).ToString("000.00"));
                Console.CursorLeft = widths[3]; Console.WriteLine(floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual).ToString("000.00"));

                double yield = fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual);
                Console.CursorLeft = widths[2]; Console.Write(BondFunctions.duration(fixedRateBond, new InterestRate(yield, fixedRateBond.dayCounter(), Compounding.Compounded, Frequency.Annual), Duration.Type.Modified));
                
                Console.WriteLine();

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

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

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

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

                double milliseconds = timer.ElapsedMilliseconds;
                Console.WriteLine();
                Console.WriteLine("Run completed in " + milliseconds + "ms");

                #endregion
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                Console.Read();
            }
        }
 internal NokNibor(QlPeriod tenor, global::QuantLib.YieldTermStructureHandle h)
     : base("Nibor", tenor, 2, new global::QuantLib.NOKCurrency(), new global::QuantLib.Norway(), QlBdc.ModifiedFollowing, false, new global::QuantLib.Actual360(), h)
 {
 }
 internal NokNibor(QlPeriod tenor)
     : base("Nibor", tenor, 2, new global::QuantLib.NOKCurrency(), new global::QuantLib.Norway(), QlBdc.ModifiedFollowing, false, new global::QuantLib.Actual360())
 {
 }
 internal DkkCibor(QlPeriod tenor, global::QuantLib.YieldTermStructureHandle h)
     : base("Cibor", tenor, 2, new global::QuantLib.DKKCurrency(), new global::QuantLib.Denmark(), QlBdc.ModifiedFollowing, false, new global::QuantLib.Actual360(), h)
 {
 }
 internal DkkCibor(QlPeriod tenor)
     : base("Cibor", tenor, 2, new global::QuantLib.DKKCurrency(), new global::QuantLib.Denmark(), QlBdc.ModifiedFollowing, false, new global::QuantLib.Actual360())
 {
 }
 internal SekStibor(QlPeriod tenor, global::QuantLib.YieldTermStructureHandle h)
     : base("Stibor", tenor, 2, new global::QuantLib.SEKCurrency(), new global::QuantLib.Sweden(), QlBdc.ModifiedFollowing, false, new global::QuantLib.Actual360(), h)
 {
 }
 internal SekStibor(QlPeriod tenor)
     : base("Stibor", tenor, 2, new global::QuantLib.SEKCurrency(), new global::QuantLib.Sweden(), QlBdc.ModifiedFollowing, false, new global::QuantLib.Actual360())
 {
 }
        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;

            Option.Type optionType = Option.Type.Put;
            double underlyingPrice = 36;
            double strikePrice = 40;
            double dividendYield = 0.0;
            double riskFreeRate = 0.06;
            double volatility = 0.2;

            Date todaysDate = new Date(15, Month.May, 1998);
            Settings.instance().setEvaluationDate(todaysDate);

            Date settlementDate = new Date(17, Month.May, 1998);
            Date maturityDate = new Date(17, Month.May, 1999);

            Calendar calendar = new TARGET();

            DateVector exerciseDates = new DateVector(4);
            for (int i = 1; i <= 4; i++) {
                Period forwardPeriod = new Period(3 * i, TimeUnit.Months);
                Date forwardDate = settlementDate.Add(forwardPeriod);
                exerciseDates.Add(forwardDate);
            }

            EuropeanExercise europeanExercise =
                new EuropeanExercise(maturityDate);
            BermudanExercise bermudanExercise =
                new BermudanExercise(exerciseDates);
            AmericanExercise americanExercise =
                new AmericanExercise(settlementDate, maturityDate);

            // bootstrap the yield/dividend/vol curves and create a
            // BlackScholesMerton stochastic process
            DayCounter dayCounter = new Actual365Fixed();
            YieldTermStructureHandle flatRateTSH =
                new YieldTermStructureHandle(
                                new FlatForward(settlementDate, riskFreeRate,
                                                 dayCounter));
            YieldTermStructureHandle flatDividendTSH =
                new YieldTermStructureHandle(
                                new FlatForward(settlementDate, dividendYield,
                                                dayCounter));
            BlackVolTermStructureHandle flatVolTSH =
                new BlackVolTermStructureHandle(
                                new BlackConstantVol(settlementDate, calendar,
                                                     volatility, dayCounter));

            QuoteHandle underlyingQuoteH =
                new QuoteHandle(new SimpleQuote(underlyingPrice));
            BlackScholesMertonProcess stochasticProcess =
                new BlackScholesMertonProcess(underlyingQuoteH,
                                              flatDividendTSH,
                                              flatRateTSH,
                                              flatVolTSH);

            PlainVanillaPayoff payoff =
                new PlainVanillaPayoff(optionType, strikePrice);

            // options
            VanillaOption europeanOption =
                new VanillaOption(payoff, europeanExercise);
            VanillaOption bermudanOption =
                new VanillaOption(payoff, bermudanExercise);
            VanillaOption americanOption =
                new VanillaOption(payoff, americanExercise);

            // report the parameters we are using
            ReportParameters(optionType, underlyingPrice, strikePrice,
                             dividendYield, riskFreeRate,
                             volatility, maturityDate);

            // write out the column headings
            ReportHeadings();

            #region Analytic Formulas

            // Black-Scholes for European
            try {
                europeanOption.setPricingEngine(
                               new AnalyticEuropeanEngine(stochasticProcess));
                ReportResults("Black-Scholes",
                              europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Barone-Adesi and Whaley approximation for American
            try {
                americanOption.setPricingEngine(
                              new BaroneAdesiWhaleyEngine(stochasticProcess));
                ReportResults("Barone-Adesi/Whaley",
                              null, null, americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Bjerksund and Stensland approximation for American
            try {
                americanOption.setPricingEngine(
                             new BjerksundStenslandEngine(stochasticProcess));
                ReportResults("Bjerksund/Stensland",
                              null, null, americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Integral
            try {
                europeanOption.setPricingEngine(
                                       new IntegralEngine(stochasticProcess));
                ReportResults("Integral",
                              europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            uint timeSteps = 801;

            // Finite differences
            try {
                europeanOption.setPricingEngine(
                              new FDEuropeanEngine(stochasticProcess,
                                                   timeSteps, timeSteps - 1));
                bermudanOption.setPricingEngine(
                              new FDBermudanEngine(stochasticProcess,
                                                   timeSteps, timeSteps - 1));
                americanOption.setPricingEngine(
                              new FDAmericanEngine(stochasticProcess,
                                                   timeSteps, timeSteps - 1));
                ReportResults("Finite differences",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            #endregion Analytic Formulas

            #region Binomial Methods

            // Binomial Jarrow-Rudd
            try {
                europeanOption.setPricingEngine(
                          new BinomialVanillaEngine(stochasticProcess,
                                                    "jarrowrudd", timeSteps));
                bermudanOption.setPricingEngine(
                          new BinomialVanillaEngine(stochasticProcess,
                                                    "jarrowrudd", timeSteps));
                americanOption.setPricingEngine(
                          new BinomialVanillaEngine(stochasticProcess,
                                                    "jarrowrudd", timeSteps));
                ReportResults("Binomial Jarrow-Rudd",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Cox-Ross-Rubinstein
            try {
                europeanOption.setPricingEngine(
                   new BinomialVanillaEngine(stochasticProcess,
                                             "coxrossrubinstein", timeSteps));
                bermudanOption.setPricingEngine(
                   new BinomialVanillaEngine(stochasticProcess,
                                             "coxrossrubinstein", timeSteps));
                americanOption.setPricingEngine(
                   new BinomialVanillaEngine(stochasticProcess,
                                             "coxrossrubinstein", timeSteps));
                ReportResults("Binomial Cox-Ross-Rubinstein",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Additive Equiprobabilities
            try {
                europeanOption.setPricingEngine(
                                 new BinomialVanillaEngine(stochasticProcess,
                                                           "eqp", timeSteps));
                bermudanOption.setPricingEngine(
                                 new BinomialVanillaEngine(stochasticProcess,
                                                           "eqp", timeSteps));
                americanOption.setPricingEngine(
                                 new BinomialVanillaEngine(stochasticProcess,
                                                           "eqp", timeSteps));
                ReportResults("Additive Equiprobabilities",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Trigeorgis
            try {
                europeanOption.setPricingEngine(
                          new BinomialVanillaEngine(stochasticProcess,
                                                    "trigeorgis", timeSteps));
                bermudanOption.setPricingEngine(
                          new BinomialVanillaEngine(stochasticProcess,
                                                    "trigeorgis", timeSteps));
                americanOption.setPricingEngine(
                          new BinomialVanillaEngine(stochasticProcess,
                                                    "trigeorgis", timeSteps));
                ReportResults("Binomial Trigeorgis",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Tian
            try {
                europeanOption.setPricingEngine(
                                new BinomialVanillaEngine(stochasticProcess,
                                                          "tian", timeSteps));
                bermudanOption.setPricingEngine(
                                new BinomialVanillaEngine(stochasticProcess,
                                                          "tian", timeSteps));
                americanOption.setPricingEngine(
                                new BinomialVanillaEngine(stochasticProcess,
                                                          "tian", timeSteps));
                ReportResults("Binomial Tian",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Leisen-Reimer
            try {
                europeanOption.setPricingEngine(
                        new BinomialVanillaEngine(stochasticProcess,
                                                  "leisenreimer", timeSteps));
                bermudanOption.setPricingEngine(
                        new BinomialVanillaEngine(stochasticProcess,
                                                  "leisenreimer", timeSteps));
                americanOption.setPricingEngine(
                        new BinomialVanillaEngine(stochasticProcess,
                                                  "leisenreimer", timeSteps));
                ReportResults("Binomial Leisen-Reimer",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Joshi
            try {
                europeanOption.setPricingEngine(
                              new BinomialVanillaEngine(stochasticProcess,
                                                        "joshi4", timeSteps));
                bermudanOption.setPricingEngine(
                              new BinomialVanillaEngine(stochasticProcess,
                                                        "joshi4", timeSteps));
                americanOption.setPricingEngine(
                              new BinomialVanillaEngine(stochasticProcess,
                                                        "joshi4", timeSteps));
                ReportResults("Binomial Joshi",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            #endregion Binomial Methods

            #region Monte Carlo Methods

            // quantlib appears to use max numeric (int and real) values to test for 'null' (or rather 'default') values

            // MC (crude)
            try {
                string traits = "pseudorandom";
                int mcTimeSteps = 1;
                int timeStepsPerYear = int.MaxValue;
                bool brownianBridge = false;
                bool antitheticVariate = false;
                int requiredSamples = int.MaxValue;
                double requiredTolerance = 0.02;
                int maxSamples = int.MaxValue;
                int seed = 42;
                europeanOption.setPricingEngine(
                    new MCEuropeanEngine(stochasticProcess,
                                         traits, mcTimeSteps,
                                         timeStepsPerYear,
                                         brownianBridge,
                                         antitheticVariate,
                                         requiredSamples,
                                         requiredTolerance,
                                         maxSamples, seed));
                ReportResults("MC (crude)", europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // MC (Sobol)
            try {
                string traits = "lowdiscrepancy";
                int mcTimeSteps = 1;
                int timeStepsPerYear = int.MaxValue;
                bool brownianBridge = false;
                bool antitheticVariate = false;
                int requiredSamples = 32768;  // 2^15
                double requiredTolerance = double.MaxValue;
                int maxSamples = int.MaxValue;
                int seed = 0;
                europeanOption.setPricingEngine(
                    new MCEuropeanEngine(stochasticProcess,
                                         traits, mcTimeSteps,
                                         timeStepsPerYear,
                                         brownianBridge,
                                         antitheticVariate,
                                         requiredSamples,
                                         requiredTolerance, maxSamples, seed));
                ReportResults("MC (Sobol)", europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // MC (Longstaff Schwartz)
            /*
            try {
                // MCAmericanEngine is not currently exposed in SWIG
                //americanOption.setPricingEngine(new MCAmericanEngine());
                ReportResults("MC (Longstaff Schwartz)", null, null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }
            */

            #endregion Monte Carlo Methods

            DateTime endTime = DateTime.Now;
            TimeSpan delta = endTime - startTime;
            Console.WriteLine();
            Console.WriteLine("Run completed in {0} s", delta.TotalSeconds);
            Console.WriteLine();
        }
Exemple #9
0
        private static void RunTestCases()
        {
            Action <string, IEnumerable <ql.Period> > writePeriods = (heading, periods2Write) =>
            {
                Console.Write($"  {heading}:  ");
                foreach (var item in periods2Write)
                {
                    var itemAsString = item != null?item.ToString() : "null";

                    Console.Write($"{itemAsString}  ");
                }
                Console.WriteLine();
            };

            Action <bool> testCase = (testResult) =>
            {
                if (!testResult)
                {
                    throw new TestCaseException();
                }
            };

            var tenorNull = null as ql.Period;
            var tenor91D  = new ql.Period("91D");
            var tenor03M  = new ql.Period("03M");
            var tenor06M  = new ql.Period("06M");
            var tenor12M  = new ql.Period("12M");
            var tenor01Y  = new ql.Period("01Y");
            var tenor02Y  = new ql.Period("02Y");

            var periods = new List <ql.Period>()
            {
                tenor01Y, tenorNull, tenor02Y, tenor06M, tenor03M
            };

            Console.WriteLine("Testing sorting of a list.");
            writePeriods("Before sorting", periods);

            periods.Sort();

            writePeriods(" After sorting", periods);

            testCase(periods[0] == tenorNull);
            testCase(periods[1] == tenor03M);
            testCase(periods[2] == tenor06M);
            testCase(periods[3] == tenor01Y);
            testCase(periods[4] == tenor02Y);


            #region test Period.CompareTo(Period)

            Console.WriteLine("test Period.CompareTo(Period)");

            testCase(tenor12M.CompareTo(tenorNull) > 0);
            testCase(tenor12M.CompareTo(tenor03M) > 0);
            testCase(tenor12M.CompareTo(tenor06M) > 0);
            testCase(tenor12M.CompareTo(tenor01Y) == 0);
            testCase(tenor01Y.CompareTo(tenor01Y) == 0);
            testCase(tenor12M.CompareTo(tenor02Y) < 0);

            #endregion

            #region test Period == Period

            Console.WriteLine("test Period == Period");

            testCase(tenorNull == null);
            testCase(null == tenorNull);
            testCase(!(tenorNull == tenor12M));
            testCase(!(tenor12M == null));
            testCase(tenor12M == tenor12M);
            testCase(tenor12M == tenor01Y);
            testCase(!(tenor12M == tenor06M));
            testCase(!(tenor06M == tenor12M));

            #endregion

            #region test Period != Period

            Console.WriteLine("test Period != Period");

            testCase(!(tenorNull != null));
            testCase(!(null != tenorNull));
            testCase(tenorNull != tenor12M);
            testCase(tenor12M != null);
            testCase(!(tenor12M != tenor12M));
            testCase(!(tenor12M != tenor01Y));
            testCase(tenor12M != tenor06M);

            #endregion

            #region test Period < Period

            Console.WriteLine("test Period < Period");

            testCase(!(tenorNull < null));
            testCase(!(null < tenorNull));
            testCase(tenorNull < tenor12M);
            testCase(!(tenor12M < null));
            testCase(!(tenor12M < tenor12M));
            testCase(!(tenor12M < tenor01Y));
            testCase(!(tenor12M < tenor06M));
            testCase(tenor06M < tenor12M);

            #endregion

            #region test Period <= Period

            Console.WriteLine("test Period <= Period");

            testCase(tenorNull <= null);
            testCase(null <= tenorNull);
            testCase(tenorNull <= tenor12M);
            testCase(!(tenor12M <= null));
            testCase(tenor12M <= tenor12M);
            testCase(tenor12M <= tenor01Y);
            testCase(!(tenor12M <= tenor06M));
            testCase(tenor06M <= tenor12M);

            #endregion

            #region test Period > Period

            Console.WriteLine("test Period > Period");

            testCase(!(tenorNull > null));
            testCase(!(null > tenorNull));
            testCase(!(tenorNull > tenor12M));
            testCase(tenor12M > null);
            testCase(!(tenor12M > tenor12M));
            testCase(!(tenor12M > tenor01Y));
            testCase(tenor12M > tenor06M);
            testCase(!(tenor06M > tenor12M));

            #endregion

            #region test Period >= Period

            Console.WriteLine("test Period >= Period");

            testCase(tenorNull >= null);
            testCase(null >= tenorNull);
            testCase(!(tenorNull >= tenor12M));
            testCase(tenor12M >= null);
            testCase(tenor12M >= tenor12M);
            testCase(tenor12M >= tenor01Y);
            testCase(tenor12M >= tenor06M);
            testCase(!(tenor06M >= tenor12M));

            #endregion

            Console.WriteLine("test Period.GetHashCode()");
            testCase(tenor01Y.GetHashCode() == tenor12M.GetHashCode());

            Console.WriteLine("test that uncomparable periods throw");
            Func <bool> compare91Dversus03MthrowsApplicationException = () =>
            {
                bool hasThrown = false;
                try
                {
                    tenor91D.CompareTo(tenor03M);
                }
                catch (System.ApplicationException)
                {
                    hasThrown = true;
                }
                return(hasThrown);
            };

            testCase(compare91Dversus03MthrowsApplicationException());
        }
Exemple #10
-1
        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;

            Date todaysDate = new Date(15, Month.February, 2002);
            Calendar calendar = new TARGET();
            Date settlementDate = new Date(19, Month.February, 2002);
            Settings.instance().setEvaluationDate( todaysDate );

            // flat yield term structure impling 1x5 swap at 5%
            Quote flatRate = new SimpleQuote(0.04875825);
            FlatForward myTermStructure = new FlatForward(
                settlementDate,
                new QuoteHandle( flatRate ),
                new Actual365Fixed() );
            RelinkableYieldTermStructureHandle rhTermStructure =
                new RelinkableYieldTermStructureHandle();
            rhTermStructure.linkTo( myTermStructure );

            // Define the ATM/OTM/ITM swaps
            Period fixedLegTenor = new Period(1,TimeUnit.Years);
            BusinessDayConvention fixedLegConvention =
                BusinessDayConvention.Unadjusted;
            BusinessDayConvention floatingLegConvention =
                BusinessDayConvention.ModifiedFollowing;
            DayCounter fixedLegDayCounter =
                new Thirty360( Thirty360.Convention.European );
            Period floatingLegTenor = new Period(6,TimeUnit.Months);
            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,
                fixedLegTenor,calendar,fixedLegConvention,fixedLegConvention,
                DateGeneration.Rule.Forward,false);
            Schedule floatSchedule = new Schedule(startDate,maturity,
                floatingLegTenor,calendar,floatingLegConvention,
                floatingLegConvention,DateGeneration.Rule.Forward,false);
            VanillaSwap swap = new VanillaSwap(
                       VanillaSwap.Payer, 1000.0,
                       fixedSchedule, dummyFixedRate, fixedLegDayCounter,
                       floatSchedule, indexSixMonths, 0.0,
                       indexSixMonths.dayCounter());
            DiscountingSwapEngine swapEngine =
                new DiscountingSwapEngine(rhTermStructure);
            swap.setPricingEngine(swapEngine);
            double fixedATMRate = swap.fairRate();
            double fixedOTMRate = fixedATMRate * 1.2;
            double fixedITMRate = fixedATMRate * 0.8;

            VanillaSwap atmSwap = new VanillaSwap(
                       VanillaSwap.Payer, 1000.0,
                       fixedSchedule, fixedATMRate, fixedLegDayCounter,
                       floatSchedule, indexSixMonths, 0.0,
                       indexSixMonths.dayCounter() );
            VanillaSwap otmSwap = new VanillaSwap(
                       VanillaSwap.Payer, 1000.0,
                       fixedSchedule, fixedOTMRate, fixedLegDayCounter,
                       floatSchedule, indexSixMonths, 0.0,
                       indexSixMonths.dayCounter());
            VanillaSwap itmSwap = new VanillaSwap(
                       VanillaSwap.Payer, 1000.0,
                       fixedSchedule, fixedITMRate, fixedLegDayCounter,
                       floatSchedule, indexSixMonths, 0.0,
                       indexSixMonths.dayCounter());
            atmSwap.setPricingEngine(swapEngine);
            otmSwap.setPricingEngine(swapEngine);
            itmSwap.setPricingEngine(swapEngine);

            // defining the swaptions to be used in model calibration
            PeriodVector swaptionMaturities = new PeriodVector();
            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) );

            CalibrationHelperVector swaptions = new CalibrationHelperVector();

            // List of times that have to be included in the timegrid
            DoubleVector times = new DoubleVector();

            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] );
                SwaptionHelper helper = new SwaptionHelper(
                                swaptionMaturities[i],
                               new Period(swapLenghts[j], TimeUnit.Years),
                               new QuoteHandle(vol),
                               indexSixMonths,
                               indexSixMonths.tenor(),
                               indexSixMonths.dayCounter(),
                               indexSixMonths.dayCounter(),
                               rhTermStructure );
                swaptions.Add( helper );
                times.AddRange( helper.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, 0.05);
//          Console.WriteLine( "calibrated to:" );
//          Console.WriteLine( "a     = " + modelG2.parameters()[0] );
//          Console.WriteLine( "sigma = " + modelG2.parameters()[1] );
//          Console.WriteLine( "b     = " + modelG2.parameters()[2] );
//          Console.WriteLine( "eta   = " + modelG2.parameters()[3] );
//          Console.WriteLine( "rho   = " + 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, 0.05);
//          Console.WriteLine( "calibrated to:" );
//            Console.WriteLine( "a = " + modelHW.parameters()[0] );
//            Console.WriteLine( "sigma = " + 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, 0.05);
//        std::cout << "calibrated to:\n"
//                  << "a = " << modelHW2->params()[0] << ", "
//                  << "sigma = " << modelHW2->params()[1]
//                  << std::endl << std::endl;


            Console.WriteLine( "Black-Karasinski (numerical) calibration" );
            for (int i=0; i<swaptions.Count; i++)
                swaptions[i].setPricingEngine(
                                        new TreeSwaptionEngine(modelBK,grid));

            calibrateModel(modelBK, swaptions, 0.05);
//        std::cout << "calibrated to:\n"
//                  << "a = " << modelBK->params()[0] << ", "
//                  << "sigma = " << modelBK->params()[1]
//                  << std::endl << std::endl;

            // ATM Bermudan swaption pricing

            Console.WriteLine( "Payer bermudan swaption struck at {0} (ATM)",
                               fixedATMRate );

            DateVector bermudanDates = new DateVector();
            Schedule schedule = new Schedule(startDate,maturity,
                new Period(3,TimeUnit.Months),calendar,
                BusinessDayConvention.Following,
                BusinessDayConvention.Following,
                DateGeneration.Rule.Forward,false);

            for (uint i=0; i<schedule.size(); i++)
                bermudanDates.Add( schedule.date( i ) );
            Exercise bermudaExercise = new BermudanExercise( bermudanDates );

            Swaption bermudanSwaption =
                new Swaption( atmSwap, bermudaExercise);
            bermudanSwaption.setPricingEngine(
                              new TreeSwaptionEngine(modelHW, 50));
            Console.WriteLine( "HW: " + bermudanSwaption.NPV() );

            bermudanSwaption.setPricingEngine(
                                       new TreeSwaptionEngine(modelHW2, 50));
            Console.WriteLine( "HW (num): " + bermudanSwaption.NPV() );

            bermudanSwaption.setPricingEngine(
                                       new TreeSwaptionEngine(modelBK, 50));
            Console.WriteLine( "BK (num): " + bermudanSwaption.NPV() );

            DateTime endTime = DateTime.Now;
            TimeSpan delta = endTime - startTime;
            Console.WriteLine();
            Console.WriteLine("Run completed in {0} s", delta.TotalSeconds);
            Console.WriteLine();
        }