Пример #1
0
        public void zciisconsistency()
        {
            CommonVars common = new CommonVars();

            ZeroCouponInflationSwap.Type ztype = ZeroCouponInflationSwap.Type.Payer;
            double   nominal   = 1000000.0;
            Date     startDate = new Date(common.evaluationDate);
            Date     endDate   = new Date(25, Month.November, 2059);
            Calendar cal       = new UnitedKingdom();
            BusinessDayConvention paymentConvention = BusinessDayConvention.ModifiedFollowing;
            DayCounter            dummyDC = null, dc = new ActualActual();
            Period observationLag = new Period(2, TimeUnit.Months);

            double quote          = 0.03714;
            ZeroCouponInflationSwap zciis = new ZeroCouponInflationSwap(ztype, nominal, startDate, endDate, cal,
                                                                        paymentConvention, dc, quote, common.ii, observationLag);

            // simple structure so simple pricing engine - most work done by index
            DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK);

            zciis.setPricingEngine(dse);
            QAssert.IsTrue(Math.Abs(zciis.NPV()) < 1e-3, "zciis does not reprice to zero");

            List <Date> oneDate = new List <Date>();

            oneDate.Add(endDate);
            Schedule schOneDate = new Schedule(oneDate, cal, paymentConvention);

            CPISwap.Type stype = CPISwap.Type.Payer;
            double       inflationNominal = nominal;
            double       floatNominal = inflationNominal * Math.Pow(1.0 + quote, 50);
            bool         subtractInflationNominal = true;
            double       dummySpread = 0.0, dummyFixedRate = 0.0;
            int          fixingDays = 0;
            Date         baseDate   = startDate - observationLag;
            double       baseCPI    = common.ii.fixing(baseDate);

            IborIndex dummyFloatIndex = new IborIndex();

            CPISwap cS = new CPISwap(stype, floatNominal, subtractInflationNominal, dummySpread, dummyDC, schOneDate,
                                     paymentConvention, fixingDays, dummyFloatIndex,
                                     dummyFixedRate, baseCPI, dummyDC, schOneDate, paymentConvention, observationLag,
                                     common.ii, InterpolationType.AsIndex, inflationNominal);

            cS.setPricingEngine(dse);
            QAssert.IsTrue(Math.Abs(cS.NPV()) < 1e-3, "CPISwap as ZCIIS does not reprice to zero");

            for (int i = 0; i < 2; i++)
            {
                double cs = cS.legNPV(i).GetValueOrDefault();
                double z  = zciis.legNPV(i).GetValueOrDefault();
                QAssert.IsTrue(Math.Abs(cs - z) < 1e-3, "zciis leg does not equal CPISwap leg");
            }
            // remove circular refernce
            common.hcpi.linkTo(null);
        }
Пример #2
0
        //@}

        protected override void initializeDates()
        {
            Date settlementDate = settlementCalendar_.advance(evaluationDate_, settlementDays_, TimeUnit.Days);
            Date maturityDate   = settlementDate + swapTenor_;

            Period   shortLegTenor    = shortIndex_.tenor();
            Schedule shortLegSchedule = new MakeSchedule()
                                        .from(settlementDate)
                                        .to(maturityDate)
                                        .withTenor(shortLegTenor)
                                        .withCalendar(settlementCalendar_)
                                        .withConvention(rollConvention_)
                                        .endOfMonth(eom_)
                                        .value();

            Period   longLegTenor    = longIndex_.tenor();
            Schedule longLegSchedule = new MakeSchedule()
                                       .from(settlementDate)
                                       .to(maturityDate)
                                       .withTenor(longLegTenor)
                                       .withCalendar(settlementCalendar_)
                                       .withConvention(rollConvention_)
                                       .endOfMonth(eom_)
                                       .value();

            double nominal        = 1.0;
            double shortLegSpread = 0.0;
            double longLegSpread  = 0.0;

            if (spreadOnShort_)
            {
                shortLegSpread = quote_.link.value();
            }
            else
            {
                longLegSpread = quote_.link.value();
            }

            /* Arbitrarily set the swap as paying the long index */
            swap_ = new BasisSwap(BasisSwap.Type.Payer, nominal,
                                  shortLegSchedule, shortIndex_, shortLegSpread, shortIndex_.dayCounter(),
                                  longLegSchedule, longIndex_, longLegSpread, longIndex_.dayCounter(),
                                  BusinessDayConvention.Following);

            IPricingEngine engine;

            engine = new DiscountingSwapEngine(discountHandle_, false, settlementDate, settlementDate);
            engine.reset();

            swap_.setPricingEngine(engine);

            earliestDate_ = swap_.startDate();
            latestDate_   = swap_.maturityDate();
            maturityDate_ = latestRelevantDate_ = swap_.maturityDate();
        }
Пример #3
0
        public void testFixing()
        {
            Date     tradeDate      = new Date(17, Month.April, 2015);
            Calendar calendar       = new UnitedKingdom();
            Date     settlementDate = calendar.advance(tradeDate, 2, TimeUnit.Days, BusinessDayConvention.Following);
            Date     maturityDate   = calendar.advance(settlementDate, 5, TimeUnit.Years, BusinessDayConvention.Following);

            Date valueDate = new Date(20, Month.April, 2015);

            Settings.setEvaluationDate(valueDate);

            List <Date> dates = new List <Date>();

            dates.Add(valueDate);
            dates.Add(valueDate + new Period(1, TimeUnit.Years));
            dates.Add(valueDate + new Period(2, TimeUnit.Years));
            dates.Add(valueDate + new Period(5, TimeUnit.Years));
            dates.Add(valueDate + new Period(10, TimeUnit.Years));
            dates.Add(valueDate + new Period(20, TimeUnit.Years));

            List <double> rates = new List <double>();

            rates.Add(0.01);
            rates.Add(0.01);
            rates.Add(0.01);
            rates.Add(0.01);
            rates.Add(0.01);
            rates.Add(0.01);

            var      discountCurveHandle = new RelinkableHandle <YieldTermStructure>();
            var      forecastCurveHandle = new RelinkableHandle <YieldTermStructure>();
            GBPLibor index = new GBPLibor(new Period(6, TimeUnit.Months), forecastCurveHandle);
            InterpolatedZeroCurve <Linear> zeroCurve = new InterpolatedZeroCurve <Linear>(dates, rates, new Actual360(), new Linear());
            var         fixedSchedule = new Schedule(settlementDate, maturityDate, new Period(1, TimeUnit.Years), calendar, BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false);
            var         floatSchedule = new Schedule(settlementDate, maturityDate, index.tenor(), calendar, BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false);
            VanillaSwap swap          = new VanillaSwap(VanillaSwap.Type.Payer, 1000000, fixedSchedule, 0.01, new Actual360(), floatSchedule, index, 0, new Actual360());

            discountCurveHandle.linkTo(zeroCurve);
            forecastCurveHandle.linkTo(zeroCurve);
            var swapEngine = new DiscountingSwapEngine(discountCurveHandle, false, null);

            swap.setPricingEngine(swapEngine);

            try
            {
                double npv = swap.NPV();
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
                Console.WriteLine(ex);
            }
        }
Пример #4
0
        public void testLargeRates()
        {
            // Testing degenerate collared coupon

            CommonVars vars = new CommonVars();

            /* A vanilla floating leg and a capped floating leg with strike
             * equal to 100 and floor equal to 0 must have (about) the same NPV
             * (depending on variance: option expiry and volatility)
             */

            List <double?> caps      = new InitializedList <double?>(vars.length, 100.0);
            List <double?> floors    = new InitializedList <double?>(vars.length, 0.0);
            double         tolerance = 1e-10;

            // fixed leg with zero rate
            List <CashFlow> fixedLeg    = vars.makeFixedLeg(vars.startDate, vars.length);
            List <CashFlow> floatLeg    = vars.makeFloatingLeg(vars.startDate, vars.length);
            List <CashFlow> collaredLeg = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors, vars.volatility);

            IPricingEngine engine     = new DiscountingSwapEngine(vars.termStructure);
            Swap           vanillaLeg = new Swap(fixedLeg, floatLeg);
            Swap           collarLeg  = new Swap(fixedLeg, collaredLeg);

            vanillaLeg.setPricingEngine(engine);
            collarLeg.setPricingEngine(engine);
            double npvVanilla = vanillaLeg.NPV();
            double npvCollar  = collarLeg.NPV();

            if (Math.Abs(npvVanilla - npvCollar) > tolerance)
            {
                QAssert.Fail("Lenght: " + vars.length + " y" + "\n" +
                             "Volatility: " + vars.volatility * 100 + "%\n" +
                             "Notional: " + vars.nominal + "\n" +
                             "Vanilla floating leg NPV: " + vanillaLeg.NPV()
                             + "\n" +
                             "Collared floating leg NPV (strikes 0 and 100): "
                             + collarLeg.NPV()
                             + "\n" +
                             "Diff: " + Math.Abs(vanillaLeg.NPV() - collarLeg.NPV()));
            }
        }
Пример #5
0
        public VanillaSwap value()
        {
            Date startDate;

            if (effectiveDate_ != null)
            {
                startDate = effectiveDate_;
            }
            else
            {
                Date refDate = Settings.evaluationDate();
                // if the evaluation date is not a business day
                // then move to the next business day
                refDate = floatCalendar_.adjust(refDate);
                Date spotDate = floatCalendar_.advance(refDate, new Period(settlementDays_, TimeUnit.Days));
                startDate = spotDate + forwardStart_;
                if (forwardStart_.length() < 0)
                {
                    startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Preceding);
                }
                else
                {
                    startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Following);
                }
            }

            Date endDate = terminationDate_;

            if (endDate == null)
            {
                if (floatEndOfMonth_)
                {
                    endDate = floatCalendar_.advance(startDate,
                                                     swapTenor_,
                                                     BusinessDayConvention.ModifiedFollowing,
                                                     floatEndOfMonth_);
                }
                else
                {
                    endDate = startDate + swapTenor_;
                }
            }

            Currency curr       = iborIndex_.currency();
            Period   fixedTenor = null;

            if (fixedTenor_ != null)
            {
                fixedTenor = fixedTenor_;
            }
            else
            {
                if ((curr == new EURCurrency()) ||
                    (curr == new USDCurrency()) ||
                    (curr == new CHFCurrency()) ||
                    (curr == new SEKCurrency()) ||
                    (curr == new GBPCurrency() && swapTenor_ <= new Period(1, TimeUnit.Years)))
                {
                    fixedTenor = new Period(1, TimeUnit.Years);
                }
                else if ((curr == new GBPCurrency() && swapTenor_ > new Period(1, TimeUnit.Years) ||
                          (curr == new JPYCurrency()) ||
                          (curr == new AUDCurrency() && swapTenor_ >= new Period(4, TimeUnit.Years))))
                {
                    fixedTenor = new Period(6, TimeUnit.Months);
                }
                else if ((curr == new HKDCurrency() ||
                          (curr == new AUDCurrency() && swapTenor_ < new Period(4, TimeUnit.Years))))
                {
                    fixedTenor = new Period(3, TimeUnit.Months);
                }
                else
                {
                    Utils.QL_FAIL("unknown fixed leg default tenor for " + curr);
                }
            }

            Schedule fixedSchedule = new Schedule(startDate, endDate,
                                                  fixedTenor, fixedCalendar_,
                                                  fixedConvention_, fixedTerminationDateConvention_,
                                                  fixedRule_, fixedEndOfMonth_,
                                                  fixedFirstDate_, fixedNextToLastDate_);

            Schedule floatSchedule = new Schedule(startDate, endDate,
                                                  floatTenor_, floatCalendar_,
                                                  floatConvention_, floatTerminationDateConvention_,
                                                  floatRule_, floatEndOfMonth_,
                                                  floatFirstDate_, floatNextToLastDate_);

            DayCounter fixedDayCount = null;

            if (fixedDayCount_ != null)
            {
                fixedDayCount = fixedDayCount_;
            }
            else
            {
                if (curr == new USDCurrency())
                {
                    fixedDayCount = new Actual360();
                }
                else if (curr == new EURCurrency() || curr == new CHFCurrency() || curr == new SEKCurrency())
                {
                    fixedDayCount = new Thirty360(Thirty360.Thirty360Convention.BondBasis);
                }
                else if (curr == new GBPCurrency() || curr == new JPYCurrency() || curr == new AUDCurrency() ||
                         curr == new HKDCurrency())
                {
                    fixedDayCount = new Actual365Fixed();
                }
                else
                {
                    Utils.QL_FAIL("unknown fixed leg day counter for " + curr);
                }
            }

            double?usedFixedRate = fixedRate_;

            if (fixedRate_ == null)
            {
                VanillaSwap temp = new VanillaSwap(type_, nominal_, fixedSchedule, 0.0, fixedDayCount,
                                                   floatSchedule, iborIndex_, floatSpread_, floatDayCount_);

                if (engine_ == null)
                {
                    Handle <YieldTermStructure> disc = iborIndex_.forwardingTermStructure();
                    Utils.QL_REQUIRE(!disc.empty(), () =>
                                     "null term structure set to this instance of " + iborIndex_.name());
                    bool           includeSettlementDateFlows = false;
                    IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                    temp.setPricingEngine(engine);
                }
                else
                {
                    temp.setPricingEngine(engine_);
                }

                usedFixedRate = temp.fairRate();
            }

            VanillaSwap swap = new VanillaSwap(type_, nominal_, fixedSchedule, usedFixedRate.Value, fixedDayCount,
                                               floatSchedule, iborIndex_, floatSpread_, floatDayCount_);

            if (engine_ == null)
            {
                Handle <YieldTermStructure> disc          = iborIndex_.forwardingTermStructure();
                bool           includeSettlementDateFlows = false;
                IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                swap.setPricingEngine(engine);
            }
            else
            {
                swap.setPricingEngine(engine_);
            }

            return(swap);
        }
Пример #6
0
        private static void Main()
        {
            DateTime startTime = DateTime.Now;

            var todaysDate = new DateTime(2002, 2, 15);

            Settings.instance().setEvaluationDate(todaysDate);

            Calendar calendar       = new TARGET();
            var      settlementDate = new Date(19, Month.February, 2002);

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

            rhTermStructure.linkTo(myTermStructure);

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

            swap.setPricingEngine(swapEngine);
            double fixedAtmRate = swap.fairRate();
            double fixedOtmRate = fixedAtmRate * 1.2;
            double fixedItmRate = fixedAtmRate * 0.8;

            var atmSwap = new VanillaSwap(VanillaSwap.Type.Payer, 1000.0,
                                          fixedSchedule, fixedAtmRate, fixedLegDayCounter,
                                          floatSchedule, indexSixMonths, 0.0,
                                          indexSixMonths.dayCounter());
            var otmSwap = new VanillaSwap(VanillaSwap.Type.Payer, 1000.0,
                                          fixedSchedule, fixedOtmRate, fixedLegDayCounter,
                                          floatSchedule, indexSixMonths, 0.0,
                                          indexSixMonths.dayCounter());
            var itmSwap = new VanillaSwap(VanillaSwap.Type.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
            var swaptionMaturities = new PeriodVector
            {
                new Period(1, TimeUnit.Years),
                new Period(2, TimeUnit.Years),
                new Period(3, TimeUnit.Years),
                new Period(4, TimeUnit.Years),
                new Period(5, TimeUnit.Years)
            };

            var swaptions = new CalibrationHelperVector();

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

            for (int i = 0; i < NUM_ROWS; i++)
            {
                int   j      = NUM_COLS - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1
                int   k      = i * NUM_COLS + j;
                Quote vol    = new SimpleQuote(SWAPTION_VOLS[k]);
                var   helper = new SwaptionHelper(swaptionMaturities[i], new Period(SWAP_LENGHTS[j], TimeUnit.Years),
                                                  new QuoteHandle(vol),
                                                  indexSixMonths, indexSixMonths.tenor(),
                                                  indexSixMonths.dayCounter(),
                                                  indexSixMonths.dayCounter(),
                                                  rhTermStructure);
                swaptions.Add(helper);
                times.AddRange(helper.times());
            }

            // Building time-grid
            var grid = new TimeGrid(times, 30);

            // defining the models
            // G2 modelG2 = new G2(rhTermStructure));
            var modelHw  = new HullWhite(rhTermStructure);
            var modelHw2 = new HullWhite(rhTermStructure);
            var modelBk  = new BlackKarasinski(rhTermStructure);

            // model calibrations
            Console.WriteLine("Hull-White (analytic formulae) calibration");
            foreach (CalibrationHelper calibrationHelper in swaptions)
            {
                NQuantLibc.as_black_helper(calibrationHelper).setPricingEngine(new JamshidianSwaptionEngine(modelHw));
            }
            CalibrateModel(modelHw, swaptions, 0.05);

            Console.WriteLine("Hull-White (numerical) calibration");
            foreach (CalibrationHelper calibrationHelper in swaptions)
            {
                NQuantLibc.as_black_helper(calibrationHelper).setPricingEngine(new TreeSwaptionEngine(modelHw2, grid));
            }
            CalibrateModel(modelHw2, swaptions, 0.05);

            Console.WriteLine("Black-Karasinski (numerical) calibration");
            foreach (CalibrationHelper calibrationHelper in swaptions)
            {
                NQuantLibc.as_black_helper(calibrationHelper).setPricingEngine(new TreeSwaptionEngine(modelBk, grid));
            }
            CalibrateModel(modelBk, swaptions, 0.05);

            // ATM Bermudan swaption pricing
            Console.WriteLine("Payer bermudan swaption struck at {0} (ATM)", fixedAtmRate);

            var bermudanDates = new DateVector();
            var 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);

            var 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();
        }
Пример #7
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(DiscountingSwapEngine obj) {
   return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
 }
Пример #8
0
        public static object eqInstIROISSwap(
            [ExcelArgument(Description = "trade id ")] string tradeid,
            [ExcelArgument(Description = "payer/receiver (1/0) ")] bool ispayer,
            [ExcelArgument(Description = "notional ")] double notional,
            [ExcelArgument(Description = "fixed rate ")] double fixedRate,
            [ExcelArgument(Description = "start date ")] DateTime startdate,
            [ExcelArgument(Description = " (String) forward start month, e.g. 7D, 3M, 7Y ")] string Tenor,
            [ExcelArgument(Description = "id of overnight index ")] string indexid,
            [ExcelArgument(Description = "floating leg spread ")] double spread,
            [ExcelArgument(Description = "id of discount curve ")] string discountId,
            [ExcelArgument(Description = "trigger ")] object trigger)
        {
            if (ExcelUtil.CallFromWizard())
            {
                return("");
            }

            string callerAddress = "";

            callerAddress = ExcelUtil.getActiveCellAddress();

            try
            {
                Xl.Range rng = ExcelUtil.getActiveCellRange();

                // by default
                // endOfMonth_(1*Months<=swapTenor && swapTenor<=2*Years ? true : false),
                bool end_of_month             = true;
                EliteQuant.DayCounter fixeddc = new EliteQuant.Actual360();

                if (!indexid.Contains('@'))
                {
                    indexid = "IDX@" + indexid;
                }
                OvernightIndex idx = OHRepository.Instance.getObject <OvernightIndex>(indexid);
                if (!discountId.Contains('@'))
                {
                    discountId = "CRV@" + discountId;
                }
                YieldTermStructure       discountcurve = OHRepository.Instance.getObject <YieldTermStructure>(discountId);
                YieldTermStructureHandle dch           = new YieldTermStructureHandle(discountcurve);

                EliteQuant.Period tenor_ = EliteQuant.EQConverter.ConvertObject <EliteQuant.Period>(Tenor);
                EliteQuant.Date   sdate  = EliteQuant.EQConverter.ConvertObject <EliteQuant.Date>(startdate);
                EliteQuant.Date   fdate  = idx.fixingDate(sdate);
                EliteQuant.Date   tdate  = idx.fixingCalendar().advance(sdate, tenor_);

                // fixed leg 1 yr. Forward?
                Schedule fixedsch = new Schedule(sdate, tdate, new Period(1, TimeUnit.Years),
                                                 idx.fixingCalendar(), idx.businessDayConvention(), idx.businessDayConvention(),
                                                 DateGeneration.Rule.Forward, end_of_month);

                OvernightIndexedSwap swap = new OvernightIndexedSwap(ispayer ? _OvernightIndexedSwap.Type.Payer : _OvernightIndexedSwap.Type.Receiver,
                                                                     notional, fixedsch, fixedRate, fixeddc, idx, spread);

                DiscountingSwapEngine engine = new DiscountingSwapEngine(dch);
                swap.setPricingEngine(engine);

                Date refDate = discountcurve.referenceDate();

                // Store the futures and return its id
                string id = "SWP@" + tradeid;
                OHRepository.Instance.storeObject(id, swap, callerAddress);
                id += "#" + (String)DateTime.Now.ToString(@"HH:mm:ss");
                return(id);
            }
            catch (Exception e)
            {
                ExcelUtil.logError(callerAddress, System.Reflection.MethodInfo.GetCurrentMethod().Name.ToString(), e.Message);
                return("#EQ_ERR!");
            }
        }
Пример #9
0
        public void testInstrumentEquality()
        {
            // Testing inflation capped/floored coupon against inflation capfloor instrument...

            CommonVars vars = new CommonVars();

            int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            // vol is low ...
            double[] strikes = { 0.01, 0.025, 0.029, 0.03, 0.031, 0.035, 0.07 };
            // yoy inflation vol is generally very low
            double[] vols = { 0.001, 0.005, 0.010, 0.015, 0.020 };

            // this is model independent
            // capped coupon = fwd - cap, and fwd = swap(0)
            // floored coupon = fwd + floor
            for (int whichPricer = 0; whichPricer < 3; whichPricer++)
            {
                for (int i = 0; i < lengths.Length; i++)
                {
                    for (int j = 0; j < strikes.Length; j++)
                    {
                        for (int k = 0; k < vols.Length; k++)
                        {
                            List <CashFlow> leg = vars.makeYoYLeg(vars.evaluationDate, lengths[i]);

                            Instrument cap = vars.makeYoYCapFloor(CapFloorType.Cap,
                                                                  leg, strikes[j], vols[k], whichPricer);

                            Instrument floor = vars.makeYoYCapFloor(CapFloorType.Floor,
                                                                    leg, strikes[j], vols[k], whichPricer);

                            Date     from        = vars.nominalTS.link.referenceDate();
                            Date     to          = from + new Period(lengths[i], TimeUnit.Years);
                            Schedule yoySchedule = new MakeSchedule().from(from).to(to)
                                                   .withTenor(new Period(1, TimeUnit.Years))
                                                   .withCalendar(new UnitedKingdom())
                                                   .withConvention(BusinessDayConvention.Unadjusted)
                                                   .backwards().value();

                            YearOnYearInflationSwap swap = new YearOnYearInflationSwap(YearOnYearInflationSwap.Type.Payer,
                                                                                       1000000.0,
                                                                                       yoySchedule, //fixed schedule, but same as yoy
                                                                                       0.0,         //strikes[j],
                                                                                       vars.dc,
                                                                                       yoySchedule,
                                                                                       vars.iir,
                                                                                       vars.observationLag,
                                                                                       0.0, //spread on index
                                                                                       vars.dc,
                                                                                       new UnitedKingdom());

                            Handle <YieldTermStructure> hTS = new Handle <YieldTermStructure>(vars.nominalTS);
                            IPricingEngine sppe             = new DiscountingSwapEngine(hTS);
                            swap.setPricingEngine(sppe);

                            List <CashFlow> leg2 = vars.makeYoYCapFlooredLeg(whichPricer, from,
                                                                             lengths[i],
                                                                             new InitializedList <double>(lengths[i], strikes[j]), //cap
                                                                             new List <double>(),                                  //floor
                                                                             vols[k],
                                                                             1.0,                                                  // gearing
                                                                             0.0);                                                 // spread

                            List <CashFlow> leg3 = vars.makeYoYCapFlooredLeg(whichPricer, from,
                                                                             lengths[i],
                                                                             new List <double>(),                                  // cap
                                                                             new InitializedList <double>(lengths[i], strikes[j]), //floor
                                                                             vols[k],
                                                                             1.0,                                                  // gearing
                                                                             0.0);                                                 // spread

                            // N.B. nominals are 10e6
                            double capped = CashFlows.npv(leg2, vars.nominalTS, false);
                            if (Math.Abs(capped - (swap.NPV() - cap.NPV())) > 1.0e-6)
                            {
                                QAssert.Fail(
                                    "capped coupon != swap(0) - cap:\n"
                                    + "    length:      " + lengths[i] + " years\n"
                                    + "    volatility:  " + vols[k] + "\n"
                                    + "    strike:      " + strikes[j] + "\n"
                                    + "    cap value:   " + cap.NPV() + "\n"
                                    + "    swap value:  " + swap.NPV() + "\n"
                                    + "   capped coupon " + capped);
                            }


                            // N.B. nominals are 10e6
                            double floored = CashFlows.npv(leg3, vars.nominalTS, false);
                            if (Math.Abs(floored - (swap.NPV() + floor.NPV())) > 1.0e-6)
                            {
                                QAssert.Fail(
                                    "floored coupon != swap(0) + floor :\n"
                                    + "    length:      " + lengths[i] + " years\n"
                                    + "    volatility:  " + vols[k] + "\n"
                                    + "    strike:      " + strikes[j] + "\n"
                                    + "    floor value: " + floor.NPV() + "\n"
                                    + "    swap value:  " + swap.NPV() + "\n"
                                    + "  floored coupon " + floored);
                            }
                        }
                    }
                }
            }
            // remove circular refernce
            vars.hy.linkTo(null);
        }
Пример #10
0
        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.Type.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.Type.Payer, 1000.0,
                fixedSchedule, fixedATMRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            VanillaSwap otmSwap = new VanillaSwap(
                VanillaSwap.Type.Payer, 1000.0,
                fixedSchedule, fixedOTMRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            VanillaSwap itmSwap = new VanillaSwap(
                VanillaSwap.Type.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(swapLengths[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++)
//              NQuantLibc.as_black_helper(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++)
            {
                NQuantLibc.as_black_helper(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++)
            {
                NQuantLibc.as_black_helper(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++)
            {
                NQuantLibc.as_black_helper(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();
        }
Пример #11
0
        public void consistency()
        {
            // check inflation leg vs calculation directly from inflation TS
            CommonVars common = new CommonVars();

            // ZeroInflationSwap aka CPISwap
            CPISwap.Type type    = CPISwap.Type.Payer;
            double       nominal = 1000000.0;
            bool         subtractInflationNominal = true;
            // float+spread leg
            double                spread                 = 0.0;
            DayCounter            floatDayCount          = new Actual365Fixed();
            BusinessDayConvention floatPaymentConvention = BusinessDayConvention.ModifiedFollowing;
            int       fixingDays = 0;
            IborIndex floatIndex = new GBPLibor(new Period(6, TimeUnit.Months), common.nominalUK);

            // fixed x inflation leg
            double                fixedRate                = 0.1;   //1% would be 0.01
            double                baseCPI                  = 206.1; // would be 206.13871 if we were interpolating
            DayCounter            fixedDayCount            = new Actual365Fixed();
            BusinessDayConvention fixedPaymentConvention   = BusinessDayConvention.ModifiedFollowing;
            Calendar              fixedPaymentCalendar     = new UnitedKingdom();
            ZeroInflationIndex    fixedIndex               = common.ii;
            Period                contractObservationLag   = common.contractObservationLag;
            InterpolationType     observationInterpolation = common.contractObservationInterpolation;

            // set the schedules
            Date     startDate     = new Date(2, Month.October, 2007);
            Date     endDate       = new Date(2, Month.October, 2052);
            Schedule floatSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(floatPaymentConvention)
                                     .backwards().value();
            Schedule fixedSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(BusinessDayConvention.Unadjusted)
                                     .backwards().value();


            CPISwap zisV = new CPISwap(type, nominal, subtractInflationNominal,
                                       spread, floatDayCount, floatSchedule,
                                       floatPaymentConvention, fixingDays, floatIndex,
                                       fixedRate, baseCPI, fixedDayCount, fixedSchedule,
                                       fixedPaymentConvention, contractObservationLag,
                                       fixedIndex, observationInterpolation);
            Date asofDate = Settings.evaluationDate();

            double[] floatFix = { 0.06255, 0.05975, 0.0637, 0.018425, 0.0073438, -1, -1 };
            double[] cpiFix   = { 211.4, 217.2, 211.4, 213.4, -2, -2 };
            for (int i = 0; i < floatSchedule.Count; i++)
            {
                if (floatSchedule[i] < common.evaluationDate)
                {
                    floatIndex.addFixing(floatSchedule[i], floatFix[i], true);//true=overwrite
                }

                CPICoupon zic = zisV.cpiLeg()[i] as CPICoupon;
                if (zic != null)
                {
                    if (zic.fixingDate() < (common.evaluationDate - new Period(1, TimeUnit.Months)))
                    {
                        fixedIndex.addFixing(zic.fixingDate(), cpiFix[i], true);
                    }
                }
            }

            // simple structure so simple pricing engine - most work done by index
            DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK);

            zisV.setPricingEngine(dse);

            // get float+spread & fixed*inflation leg prices separately
            double testInfLegNPV = 0.0;
            double diff;

            for (int i = 0; i < zisV.leg(0).Count; i++)
            {
                Date zicPayDate = (zisV.leg(0))[i].date();
                if (zicPayDate > asofDate)
                {
                    testInfLegNPV += (zisV.leg(0))[i].amount() * common.nominalUK.link.discount(zicPayDate);
                }

                CPICoupon zicV = zisV.cpiLeg()[i] as CPICoupon;
                if (zicV != null)
                {
                    diff = Math.Abs(zicV.rate() - (fixedRate * (zicV.indexFixing() / baseCPI)));
                    QAssert.IsTrue(diff < 1e-8, "failed " + i + "th coupon reconstruction as "
                                   + (fixedRate * (zicV.indexFixing() / baseCPI)) + " vs rate = "
                                   + zicV.rate() + ", with difference: " + diff);
                }
            }

            double error = Math.Abs(testInfLegNPV - zisV.legNPV(0).Value);

            QAssert.IsTrue(error < 1e-5, "failed manual inf leg NPV calc vs pricing engine: " + testInfLegNPV + " vs " +
                           zisV.legNPV(0));

            diff = Math.Abs(1 - zisV.NPV() / 4191660.0);
         #if QL_USE_INDEXED_COUPON
            double max_diff = 1e-5;
         #else
            double max_diff = 3e-5;
         #endif
            QAssert.IsTrue(diff < max_diff, "failed stored consistency value test, ratio = " + diff);

            // remove circular refernce
            common.hcpi.linkTo(null);
        }
Пример #12
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(DiscountingSwapEngine obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
Пример #13
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

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

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(22, Month.September, 2004);

            // must be a business day
            settlementDate = calendar.adjust(settlementDate);

            int  fixingDays = 2;
            Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days);

            // nothing to do with Date::todaysDate
            Settings.setEvaluationDate(todaysDate);


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


            // deposits
            double d1wQuote = 0.0382;
            double d1mQuote = 0.0372;
            double d3mQuote = 0.0363;
            double d6mQuote = 0.0353;
            double d9mQuote = 0.0348;
            double d1yQuote = 0.0345;
            // FRAs
            double fra3x6Quote  = 0.037125;
            double fra6x9Quote  = 0.037125;
            double fra6x12Quote = 0.037125;
            // futures
            double fut1Quote = 96.2875;
            double fut2Quote = 96.7875;
            double fut3Quote = 96.9875;
            double fut4Quote = 96.6875;
            double fut5Quote = 96.4875;
            double fut6Quote = 96.3875;
            double fut7Quote = 96.2875;
            double fut8Quote = 96.0875;
            // swaps
            double s2yQuote  = 0.037125;
            double s3yQuote  = 0.0398;
            double s5yQuote  = 0.0443;
            double s10yQuote = 0.05165;
            double s15yQuote = 0.055175;


            /********************
            ***    QUOTES    ***
            ********************/

            // SimpleQuote stores a value which can be manually changed;
            // other Quote subclasses could read the value from a database
            // or some kind of data feed.

            // deposits
            Quote d1wRate = new SimpleQuote(d1wQuote);
            Quote d1mRate = new SimpleQuote(d1mQuote);
            Quote d3mRate = new SimpleQuote(d3mQuote);
            Quote d6mRate = new SimpleQuote(d6mQuote);
            Quote d9mRate = new SimpleQuote(d9mQuote);
            Quote d1yRate = new SimpleQuote(d1yQuote);
            // FRAs
            Quote fra3x6Rate  = new SimpleQuote(fra3x6Quote);
            Quote fra6x9Rate  = new SimpleQuote(fra6x9Quote);
            Quote fra6x12Rate = new SimpleQuote(fra6x12Quote);
            // futures
            Quote fut1Price = new SimpleQuote(fut1Quote);
            Quote fut2Price = new SimpleQuote(fut2Quote);
            Quote fut3Price = new SimpleQuote(fut3Quote);
            Quote fut4Price = new SimpleQuote(fut4Quote);
            Quote fut5Price = new SimpleQuote(fut5Quote);
            Quote fut6Price = new SimpleQuote(fut6Quote);
            Quote fut7Price = new SimpleQuote(fut7Quote);
            Quote fut8Price = new SimpleQuote(fut8Quote);
            // swaps
            Quote s2yRate  = new SimpleQuote(s2yQuote);
            Quote s3yRate  = new SimpleQuote(s3yQuote);
            Quote s5yRate  = new SimpleQuote(s5yQuote);
            Quote s10yRate = new SimpleQuote(s10yQuote);
            Quote s15yRate = new SimpleQuote(s15yQuote);


            /*********************
            ***  RATE HELPERS ***
            *********************/

            // RateHelpers are built from the above quotes together with
            // other instrument dependant infos.  Quotes are passed in
            // relinkable handles which could be relinked to some other
            // data source later.

            // deposits
            DayCounter depositDayCounter = new Actual360();

            RateHelper d1w = new DepositRateHelper(new Handle <Quote>(d1wRate), new Period(1, TimeUnit.Weeks),
                                                   fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper d1m = new DepositRateHelper(new Handle <Quote>(d1mRate), new Period(1, TimeUnit.Months),
                                                   fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper d3m = new DepositRateHelper(new Handle <Quote>(d3mRate), new Period(3, TimeUnit.Months),
                                                   fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper d6m = new DepositRateHelper(new Handle <Quote>(d6mRate), new Period(6, TimeUnit.Months),
                                                   fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper d9m = new DepositRateHelper(new Handle <Quote>(d9mRate), new Period(9, TimeUnit.Months),
                                                   fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper d1y = new DepositRateHelper(new Handle <Quote>(d1yRate), new Period(1, TimeUnit.Years),
                                                   fixingDays, calendar, BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            // setup FRAs
            RateHelper fra3x6 = new FraRateHelper(new Handle <Quote>(fra3x6Rate), 3, 6, fixingDays, calendar,
                                                  BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper fra6x9 = new FraRateHelper(new Handle <Quote>(fra6x9Rate), 6, 9, fixingDays, calendar,
                                                  BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper fra6x12 = new FraRateHelper(new Handle <Quote>(fra6x12Rate), 6, 12, fixingDays, calendar,
                                                   BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);


            // setup futures
            // Handle<Quote> convexityAdjustment = new Handle<Quote>(new SimpleQuote(0.0));
            int  futMonths = 3;
            Date imm       = IMM.nextDate(settlementDate);

            RateHelper fut1 = new FuturesRateHelper(new Handle <Quote>(fut1Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut2 = new FuturesRateHelper(new Handle <Quote>(fut2Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut3 = new FuturesRateHelper(new Handle <Quote>(fut3Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut4 = new FuturesRateHelper(new Handle <Quote>(fut4Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut5 = new FuturesRateHelper(new Handle <Quote>(fut5Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut6 = new FuturesRateHelper(new Handle <Quote>(fut6Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut7 = new FuturesRateHelper(new Handle <Quote>(fut7Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut8 = new FuturesRateHelper(new Handle <Quote>(fut8Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);


            // setup swaps
            Frequency             swFixedLegFrequency  = Frequency.Annual;
            BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
            DayCounter            swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);

            IborIndex swFloatingLegIndex = new Euribor6M();

            RateHelper s2y = new SwapRateHelper(new Handle <Quote>(s2yRate), new Period(2, TimeUnit.Years),
                                                calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex);
            RateHelper s3y = new SwapRateHelper(new Handle <Quote>(s3yRate), new Period(3, TimeUnit.Years),
                                                calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex);
            RateHelper s5y = new SwapRateHelper(new Handle <Quote>(s5yRate), new Period(5, TimeUnit.Years),
                                                calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex);
            RateHelper s10y = new SwapRateHelper(new Handle <Quote>(s10yRate), new Period(10, TimeUnit.Years),
                                                 calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex);
            RateHelper s15y = new SwapRateHelper(new Handle <Quote>(s15yRate), new Period(15, TimeUnit.Years),
                                                 calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex);



            /*********************
            **  CURVE BUILDING **
            *********************/

            // Any DayCounter would be fine.
            // ActualActual::ISDA ensures that 30 years is 30.0
            DayCounter termStructureDayCounter = new ActualActual(ActualActual.Convention.ISDA);

            double tolerance = 1.0e-15;

            // A depo-swap curve
            List <RateHelper> depoSwapInstruments = new List <RateHelper>();

            depoSwapInstruments.Add(d1w);
            depoSwapInstruments.Add(d1m);
            depoSwapInstruments.Add(d3m);
            depoSwapInstruments.Add(d6m);
            depoSwapInstruments.Add(d9m);
            depoSwapInstruments.Add(d1y);
            depoSwapInstruments.Add(s2y);
            depoSwapInstruments.Add(s3y);
            depoSwapInstruments.Add(s5y);
            depoSwapInstruments.Add(s10y);
            depoSwapInstruments.Add(s15y);
            YieldTermStructure depoSwapTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, depoSwapInstruments, termStructureDayCounter, new List <Handle <Quote> >(), new List <Date>(), tolerance);


            // A depo-futures-swap curve
            List <RateHelper> depoFutSwapInstruments = new List <RateHelper>();

            depoFutSwapInstruments.Add(d1w);
            depoFutSwapInstruments.Add(d1m);
            depoFutSwapInstruments.Add(fut1);
            depoFutSwapInstruments.Add(fut2);
            depoFutSwapInstruments.Add(fut3);
            depoFutSwapInstruments.Add(fut4);
            depoFutSwapInstruments.Add(fut5);
            depoFutSwapInstruments.Add(fut6);
            depoFutSwapInstruments.Add(fut7);
            depoFutSwapInstruments.Add(fut8);
            depoFutSwapInstruments.Add(s3y);
            depoFutSwapInstruments.Add(s5y);
            depoFutSwapInstruments.Add(s10y);
            depoFutSwapInstruments.Add(s15y);
            YieldTermStructure depoFutSwapTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, depoFutSwapInstruments, termStructureDayCounter, new List <Handle <Quote> >(), new List <Date>(), tolerance);


            // A depo-FRA-swap curve
            List <RateHelper> depoFRASwapInstruments = new List <RateHelper>();

            depoFRASwapInstruments.Add(d1w);
            depoFRASwapInstruments.Add(d1m);
            depoFRASwapInstruments.Add(d3m);
            depoFRASwapInstruments.Add(fra3x6);
            depoFRASwapInstruments.Add(fra6x9);
            depoFRASwapInstruments.Add(fra6x12);
            depoFRASwapInstruments.Add(s2y);
            depoFRASwapInstruments.Add(s3y);
            depoFRASwapInstruments.Add(s5y);
            depoFRASwapInstruments.Add(s10y);
            depoFRASwapInstruments.Add(s15y);
            YieldTermStructure depoFRASwapTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, depoFRASwapInstruments, termStructureDayCounter, new List <Handle <Quote> >(), new List <Date>(), tolerance);

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


            /*********************
             * SWAPS TO BE PRICED *
             **********************/

            // constant nominal 1,000,000 Euro
            double nominal = 1000000.0;
            // fixed leg
            Frequency             fixedLegFrequency     = Frequency.Annual;
            BusinessDayConvention fixedLegConvention    = BusinessDayConvention.Unadjusted;
            BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing;
            DayCounter            fixedLegDayCounter    = new Thirty360(Thirty360.Thirty360Convention.European);
            double     fixedRate             = 0.04;
            DayCounter floatingLegDayCounter = new Actual360();

            // floating leg
            Frequency floatingLegFrequency = Frequency.Semiannual;
            IborIndex euriborIndex         = new Euribor6M(forecastingTermStructure);
            double    spread = 0.0;

            int lenghtInYears = 5;

            VanillaSwap.Type swapType = VanillaSwap.Type.Payer;

            Date     maturity      = settlementDate + new Period(lenghtInYears, TimeUnit.Years);
            Schedule fixedSchedule = new Schedule(settlementDate, maturity, new Period(fixedLegFrequency),
                                                  calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false);
            Schedule floatSchedule = new Schedule(settlementDate, maturity, new Period(floatingLegFrequency),
                                                  calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false);
            VanillaSwap spot5YearSwap = new VanillaSwap(swapType, nominal, fixedSchedule, fixedRate, fixedLegDayCounter,
                                                        floatSchedule, euriborIndex, spread, floatingLegDayCounter);

            Date     fwdStart         = calendar.advance(settlementDate, 1, TimeUnit.Years);
            Date     fwdMaturity      = fwdStart + new Period(lenghtInYears, TimeUnit.Years);
            Schedule fwdFixedSchedule = new Schedule(fwdStart, fwdMaturity, new Period(fixedLegFrequency),
                                                     calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false);
            Schedule fwdFloatSchedule = new Schedule(fwdStart, fwdMaturity, new Period(floatingLegFrequency),
                                                     calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false);
            VanillaSwap oneYearForward5YearSwap = new VanillaSwap(swapType, nominal, fwdFixedSchedule, fixedRate, fixedLegDayCounter,
                                                                  fwdFloatSchedule, euriborIndex, spread, floatingLegDayCounter);


            /***************
             * SWAP PRICING *
             ****************/

            // utilities for reporting
            List <string> headers = new List <string>();

            headers.Add("term structure");
            headers.Add("net present value");
            headers.Add("fair spread");
            headers.Add("fair fixed rate");
            string separator = " | ";
            int    width     = headers[0].Length + separator.Length
                               + headers[1].Length + separator.Length
                               + headers[2].Length + separator.Length
                               + headers[3].Length + separator.Length - 1;
            string rule = string.Format("").PadLeft(width, '-'), dblrule = string.Format("").PadLeft(width, '=');
            string tab = string.Format("").PadLeft(8, ' ');

            // calculations

            Console.WriteLine(dblrule);
            Console.WriteLine("5-year market swap-rate = {0:0.00%}", s5yRate.value());
            Console.WriteLine(dblrule);

            Console.WriteLine(tab + "5-years swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            double NPV;
            double fairRate;
            double fairSpread;

            IPricingEngine swapEngine = new DiscountingSwapEngine(discountingTermStructure);

            spot5YearSwap.setPricingEngine(swapEngine);
            oneYearForward5YearSwap.setPricingEngine(swapEngine);

            // Of course, you're not forced to really use different curves
            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            // let's check that the 5 years swap has been correctly re-priced
            if (!(Math.Abs(fairRate - s5yQuote) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yQuote));
            }


            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yQuote) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yQuote));
            }

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yQuote) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yQuote));
            }

            Console.WriteLine(rule);

            // now let's price the 1Y forward 5Y swap
            Console.WriteLine(tab + "5-years, 1-year forward swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            // now let's say that the 5-years swap rate goes up to 4.60%.
            // A smarter market element--say, connected to a data source-- would
            // notice the change itself. Since we're using SimpleQuotes,
            // we'll have to change the value manually--which forces us to
            // downcast the handle and use the SimpleQuote
            // interface. In any case, the point here is that a change in the
            // value contained in the Quote triggers a new bootstrapping
            // of the curve and a repricing of the swap.

            SimpleQuote fiveYearsRate = s5yRate as SimpleQuote;

            fiveYearsRate.setValue(0.0460);

            Console.WriteLine(dblrule);
            Console.WriteLine("5-year market swap-rate = {0:0.00%}", s5yRate.value());
            Console.WriteLine(dblrule);

            Console.WriteLine(tab + "5-years swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            // now get the updated results
            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yRate.value()) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yRate.value()));
            }

            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yRate.value()) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yRate.value()));
            }

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yRate.value()) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yRate.value()));
            }

            Console.WriteLine(rule);

            // the 1Y forward 5Y swap changes as well

            Console.WriteLine(tab + "5-years, 1-year forward swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);


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

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #14
0
        public void testYYTermStructure()
        {
            // Testing year-on-year inflation term structure...

            SavedSettings backup = new SavedSettings();
            //IndexHistoryCleaner cleaner;

            // try the YY UK
            Calendar calendar         = new UnitedKingdom();
            BusinessDayConvention bdc = BusinessDayConvention.ModifiedFollowing;
            Date evaluationDate       = new Date(13, Month.August, 2007);

            evaluationDate = calendar.adjust(evaluationDate);
            Settings.setEvaluationDate(evaluationDate);


            // fixing data
            Date     from        = new Date(1, Month.January, 2005);
            Date     to          = new Date(13, Month.August, 2007);
            Schedule rpiSchedule = new MakeSchedule().from(from).to(to)
                                   .withTenor(new Period(1, TimeUnit.Months))
                                   .withCalendar(new UnitedKingdom())
                                   .withConvention(BusinessDayConvention.ModifiedFollowing).value();

            double[] fixData = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0,
                                 192.2, 192.2, 192.6, 193.1, 193.3, 193.6,
                                 194.1, 193.4, 194.2, 195.0, 196.5, 197.7,
                                 198.5, 198.5, 199.2, 200.1, 200.4, 201.1,
                                 202.7, 201.6, 203.1, 204.4, 205.4, 206.2,
                                 207.3 };

            RelinkableHandle <YoYInflationTermStructure> hy = new RelinkableHandle <YoYInflationTermStructure>();
            bool     interp = false;
            YYUKRPIr iir    = new YYUKRPIr(interp, hy);

            for (int i = 0; i < fixData.Length; i++)
            {
                iir.addFixing(rpiSchedule[i], fixData[i]);
            }

            YieldTermStructure nominalTS = nominalTermStructure();

            // now build the YoY inflation curve
            Datum[] yyData =
            {
                new Datum(new Date(13, Month.August, 2008),  2.95),
                new Datum(new Date(13, Month.August, 2009),  2.95),
                new Datum(new Date(13, Month.August, 2010),  2.93),
                new Datum(new Date(15, Month.August, 2011), 2.955),
                new Datum(new Date(13, Month.August, 2012), 2.945),
                new Datum(new Date(13, Month.August, 2013), 2.985),
                new Datum(new Date(13, Month.August, 2014),  3.01),
                new Datum(new Date(13, Month.August, 2015), 3.035),
                new Datum(new Date(13, Month.August, 2016), 3.055),                    // note that
                new Datum(new Date(13, Month.August, 2017), 3.075),                    // some dates will be on
                new Datum(new Date(13, Month.August, 2019), 3.105),                    // holidays but the payment
                new Datum(new Date(15, Month.August, 2022), 3.135),                    // calendar will roll them
                new Datum(new Date(13, Month.August, 2027), 3.155),
                new Datum(new Date(13, Month.August, 2032), 3.145),
                new Datum(new Date(13, Month.August, 2037), 3.145)
            };

            Period     observationLag = new Period(2, TimeUnit.Months);
            DayCounter dc             = new Thirty360();

            // now build the helpers ...
            List <BootstrapHelper <YoYInflationTermStructure> > helpers =
                makeHelpers(yyData, yyData.Length, iir, observationLag, calendar, bdc, dc);

            double baseYYRate = yyData[0].rate / 100.0;
            PiecewiseYoYInflationCurve <Linear> pYYTS = new PiecewiseYoYInflationCurve <Linear>(
                evaluationDate, calendar, dc, observationLag,
                iir.frequency(), iir.interpolated(), baseYYRate,
                new Handle <YieldTermStructure>(nominalTS), helpers);

            pYYTS.recalculate();

            // validation
            // yoy swaps should reprice to zero
            // yy rates should not equal yySwap rates
            double eps = 0.000001;
            // usual swap engine
            Handle <YieldTermStructure> hTS = new Handle <YieldTermStructure>(nominalTS);
            IPricingEngine sppe             = new DiscountingSwapEngine(hTS);

            // make sure that the index has the latest yoy term structure
            hy.linkTo(pYYTS);

            for (int j = 1; j < yyData.Length; j++)
            {
                from = nominalTS.referenceDate();
                to   = yyData[j].date;
                Schedule yoySchedule = new MakeSchedule().from(from).to(to)
                                       .withConvention(BusinessDayConvention.Unadjusted)  // fixed leg gets calendar from
                                       .withCalendar(calendar)                            // schedule
                                       .withTenor(new Period(1, TimeUnit.Years)).value(); // .back

                YearOnYearInflationSwap yyS2 = new YearOnYearInflationSwap(
                    YearOnYearInflationSwap.Type.Payer,
                    1000000.0,
                    yoySchedule,                    //fixed schedule, but same as yoy
                    yyData[j].rate / 100.0,
                    dc,
                    yoySchedule,
                    iir,
                    observationLag,
                    0.0,                            //spread on index
                    dc,
                    new UnitedKingdom());

                yyS2.setPricingEngine(sppe);



                Assert.IsTrue(Math.Abs(yyS2.NPV()) < eps, "fresh yoy swap NPV!=0 from TS "
                              + "swap quote for pt " + j
                              + ", is " + yyData[j].rate / 100.0
                              + " vs YoY rate " + pYYTS.yoyRate(yyData[j].date - observationLag)
                              + " at quote date " + (yyData[j].date - observationLag)
                              + ", NPV of a fresh yoy swap is " + yyS2.NPV()
                              + "\n      fair rate " + yyS2.fairRate()
                              + " payment " + yyS2.paymentConvention());
            }

            int jj = 3;

            for (int k = 0; k < 14; k++)
            {
                from = nominalTS.referenceDate() - new Period(k, TimeUnit.Months);
                to   = yyData[jj].date - new Period(k, TimeUnit.Months);
                Schedule yoySchedule = new MakeSchedule().from(from).to(to)
                                       .withConvention(BusinessDayConvention.Unadjusted) // fixed leg gets calendar from
                                       .withCalendar(calendar)                           // schedule
                                       .withTenor(new Period(1, TimeUnit.Years))
                                       .value();                                         //backwards()

                YearOnYearInflationSwap yyS3 = new YearOnYearInflationSwap(
                    YearOnYearInflationSwap.Type.Payer,
                    1000000.0,
                    yoySchedule,                    //fixed schedule, but same as yoy
                    yyData[jj].rate / 100.0,
                    dc,
                    yoySchedule,
                    iir,
                    observationLag,
                    0.0,                            //spread on index
                    dc,
                    new UnitedKingdom());

                yyS3.setPricingEngine(sppe);

                Assert.IsTrue(Math.Abs(yyS3.NPV()) < 20000.0,
                              "unexpected size of aged YoY swap, aged "
                              + k + " months: YY aged NPV = " + yyS3.NPV()
                              + ", legs " + yyS3.legNPV(0) + " and " + yyS3.legNPV(1)
                              );
            }
            // remove circular refernce
            hy.linkTo(new YoYInflationTermStructure());
        }
Пример #15
0
        public void testZeroTermStructure()
        {
            // Testing zero inflation term structure...

            SavedSettings backup = new SavedSettings();

            // try the Zero UK
            Calendar calendar         = new UnitedKingdom();
            BusinessDayConvention bdc = BusinessDayConvention.ModifiedFollowing;
            Date evaluationDate       = new Date(13, Month.August, 2007);

            evaluationDate = calendar.adjust(evaluationDate);
            Settings.setEvaluationDate(evaluationDate);

            // fixing data
            Date     from        = new Date(1, Month.January, 2005);
            Date     to          = new Date(13, Month.August, 2007);
            Schedule rpiSchedule = new MakeSchedule().from(from).to(to)
                                   .withTenor(new Period(1, TimeUnit.Months))
                                   .withCalendar(new UnitedKingdom())
                                   .withConvention(BusinessDayConvention.ModifiedFollowing)
                                   .value();

            double[] fixData = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0,
                                 192.2, 192.2, 192.6, 193.1, 193.3, 193.6,
                                 194.1, 193.4, 194.2, 195.0, 196.5, 197.7,
                                 198.5, 198.5, 199.2, 200.1, 200.4, 201.1,
                                 202.7, 201.6, 203.1, 204.4, 205.4, 206.2,
                                 207.3, 206.1, -999.0 };

            RelinkableHandle <ZeroInflationTermStructure> hz = new RelinkableHandle <ZeroInflationTermStructure>();
            bool  interp  = false;
            UKRPI iiUKRPI = new UKRPI(interp, hz);

            for (int i = 0; i < rpiSchedule.Count; i++)
            {
                iiUKRPI.addFixing(rpiSchedule[i], fixData[i]);
            }


            ZeroInflationIndex ii        = iiUKRPI as ZeroInflationIndex;
            YieldTermStructure nominalTS = nominalTermStructure();


            // now build the zero inflation curve

            Datum[] zcData =
            {
                new Datum(new Date(13, Month.August, 2008),  2.93),
                new Datum(new Date(13, Month.August, 2009),  2.95),
                new Datum(new Date(13, Month.August, 2010), 2.965),
                new Datum(new Date(15, Month.August, 2011),  2.98),
                new Datum(new Date(13, Month.August, 2012),   3.0),
                new Datum(new Date(13, Month.August, 2014),  3.06),
                new Datum(new Date(13, Month.August, 2017), 3.175),
                new Datum(new Date(13, Month.August, 2019), 3.243),
                new Datum(new Date(15, Month.August, 2022), 3.293),
                new Datum(new Date(14, Month.August, 2027), 3.338),
                new Datum(new Date(13, Month.August, 2032), 3.348),
                new Datum(new Date(15, Month.August, 2037), 3.348),
                new Datum(new Date(13, Month.August, 2047), 3.308),
                new Datum(new Date(13, Month.August, 2057), 3.228)
            };


            Period     observationLag = new Period(2, TimeUnit.Months);
            DayCounter dc             = new Thirty360();
            Frequency  frequency      = Frequency.Monthly;
            List <BootstrapHelper <ZeroInflationTermStructure> > helpers =
                makeHelpers(zcData, zcData.Length, ii,
                            observationLag,
                            calendar, bdc, dc);

            double baseZeroRate = zcData[0].rate / 100.0;
            PiecewiseZeroInflationCurve <Linear> pZITS = new PiecewiseZeroInflationCurve <Linear>(
                evaluationDate, calendar, dc, observationLag,
                frequency, ii.interpolated(), baseZeroRate,
                new Handle <YieldTermStructure>(nominalTS), helpers);

            pZITS.recalculate();

            // first check that the zero rates on the curve match the data
            // and that the helpers give the correct impled rates
            const double eps = 0.00000001;
            bool         forceLinearInterpolation = false;

            for (int i = 0; i < zcData.Length; i++)
            {
                Assert.IsTrue(Math.Abs(zcData[i].rate / 100.0
                                       - pZITS.zeroRate(zcData[i].date, observationLag, forceLinearInterpolation)) < eps,
                              "ZITS zeroRate != instrument "
                              + pZITS.zeroRate(zcData[i].date, observationLag, forceLinearInterpolation)
                              + " vs " + zcData[i].rate / 100.0
                              + " interpolation: " + ii.interpolated()
                              + " forceLinearInterpolation " + forceLinearInterpolation);

                Assert.IsTrue(Math.Abs(helpers[i].impliedQuote()
                                       - zcData[i].rate / 100.0) < eps,
                              "ZITS implied quote != instrument "
                              + helpers[i].impliedQuote()
                              + " vs " + zcData[i].rate / 100.0);
            }

            // now test the forecasting capability of the index.
            hz.linkTo(pZITS);
            from = hz.link.baseDate();
            to   = hz.link.maxDate() - new Period(1, TimeUnit.Months);             // a bit of margin for adjustments
            Schedule testIndex = new MakeSchedule().from(from).to(to)
                                 .withTenor(new Period(1, TimeUnit.Months))
                                 .withCalendar(new UnitedKingdom())
                                 .withConvention(BusinessDayConvention.ModifiedFollowing).value();

            // we are testing UKRPI which is not interpolated
            Date   bd = hz.link.baseDate();
            double bf = ii.fixing(bd);

            for (int i = 0; i < testIndex.Count; i++)
            {
                Date   d = testIndex[i];
                double z = hz.link.zeroRate(d, new Period(0, TimeUnit.Days));
                double t = hz.link.dayCounter().yearFraction(bd, d);
                if (!ii.interpolated())                   // because fixing constant over period
                {
                    t = hz.link.dayCounter().yearFraction(bd,
                                                          Utils.inflationPeriod(d, ii.frequency()).Key);
                }
                double calc = bf * Math.Pow(1 + z, t);
                if (t <= 0)
                {
                    calc = ii.fixing(d, false);                       // still historical
                }
                if (Math.Abs(calc - ii.fixing(d, true)) / 10000.0 > eps)
                {
                    Assert.Fail("ZC index does not forecast correctly for date " + d
                                + " from base date " + bd
                                + " with fixing " + bf
                                + ", correct:  " + calc
                                + ", fix: " + ii.fixing(d, true)
                                + ", t " + t);
                }
            }

            //===========================================================================================
            // Test zero-inflation-indexed (i.e. cpi ratio) cashflow
            // just ordinary indexed cashflow with a zero inflation index

            Date  baseDate = new Date(1, Month.January, 2006);
            Date  fixDate  = new Date(1, Month.August, 2014);
            Date  payDate  = new UnitedKingdom().adjust(fixDate + new Period(3, TimeUnit.Months), BusinessDayConvention.ModifiedFollowing);
            Index ind      = ii as Index;

            Utils.QL_REQUIRE(ind != null, () => "dynamic_pointer_cast to Index from InflationIndex failed");

            double          notional          = 1000000.0;//1m
            IndexedCashFlow iicf              = new IndexedCashFlow(notional, ind, baseDate, fixDate, payDate);
            double          correctIndexed    = ii.fixing(iicf.fixingDate()) / ii.fixing(iicf.baseDate());
            double          calculatedIndexed = iicf.amount() / iicf.notional();

            Assert.IsTrue(Math.Abs(correctIndexed - calculatedIndexed) < eps,
                          "IndexedCashFlow indexing wrong: " + calculatedIndexed + " vs correct = "
                          + correctIndexed);

            //===========================================================================================
            // Test zero coupon swap

            // first make one ...

            ZeroInflationIndex zii = ii as ZeroInflationIndex;

            Utils.QL_REQUIRE(zii != null, () => "dynamic_pointer_cast to ZeroInflationIndex from UKRPI failed");
            ZeroCouponInflationSwap nzcis =
                new ZeroCouponInflationSwap(ZeroCouponInflationSwap.Type.Payer,
                                            1000000.0,
                                            evaluationDate,
                                            zcData[6].date,                                                                 // end date = maturity
                                            calendar, bdc, dc, zcData[6].rate / 100.0,                                      // fixed rate
                                            zii, observationLag);

            // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via
            //      inflation curve attached to the inflation index.
            Handle <YieldTermStructure> hTS = new Handle <YieldTermStructure>(nominalTS);
            IPricingEngine sppe             = new DiscountingSwapEngine(hTS);

            nzcis.setPricingEngine(sppe);

            // ... and price it, should be zero
            Assert.IsTrue(Math.Abs(nzcis.NPV()) < 0.00001, "ZCIS does not reprice to zero "
                          + nzcis.NPV()
                          + evaluationDate + " to " + zcData[6].date + " becoming " + nzcis.maturityDate()
                          + " rate " + zcData[6].rate
                          + " fixed leg " + nzcis.legNPV(0)
                          + " indexed-predicted inflated leg " + nzcis.legNPV(1)
                          + " discount " + nominalTS.discount(nzcis.maturityDate()));


            //===========================================================================================
            // Test multiplicative seasonality in price
            //

            //Seasonality factors NOT normalized
            //and UKRPI is not interpolated
            Date          trueBaseDate         = Utils.inflationPeriod(hz.link.baseDate(), ii.frequency()).Value;
            Date          seasonallityBaseDate = new Date(31, Month.January, trueBaseDate.year());
            List <double> seasonalityFactors   = new List <double>(12);

            seasonalityFactors.Add(1.003245);
            seasonalityFactors.Add(1.000000);
            seasonalityFactors.Add(0.999715);
            seasonalityFactors.Add(1.000495);
            seasonalityFactors.Add(1.000929);
            seasonalityFactors.Add(0.998687);
            seasonalityFactors.Add(0.995949);
            seasonalityFactors.Add(0.994682);
            seasonalityFactors.Add(0.995949);
            seasonalityFactors.Add(1.000519);
            seasonalityFactors.Add(1.003705);
            seasonalityFactors.Add(1.004186);

            //Creating two different seasonality objects
            //
            MultiplicativePriceSeasonality seasonality_1        = new MultiplicativePriceSeasonality();
            InitializedList <double>       seasonalityFactors_1 = new InitializedList <double>(12, 1.0);

            seasonality_1.set(seasonallityBaseDate, Frequency.Monthly, seasonalityFactors_1);

            MultiplicativePriceSeasonality seasonality_real =
                new MultiplicativePriceSeasonality(seasonallityBaseDate, Frequency.Monthly, seasonalityFactors);

            //Testing seasonality correction when seasonality factors are = 1
            //
            double[] fixing =
            {
                ii.fixing(new Date(14, Month.January,   2013), true),
                ii.fixing(new Date(14, Month.February,  2013), true),
                ii.fixing(new Date(14, Month.March,     2013), true),
                ii.fixing(new Date(14, Month.April,     2013), true),
                ii.fixing(new Date(14, Month.May,       2013), true),
                ii.fixing(new Date(14, Month.June,      2013), true),
                ii.fixing(new Date(14, Month.July,      2013), true),
                ii.fixing(new Date(14, Month.August,    2013), true),
                ii.fixing(new Date(14, Month.September, 2013), true),
                ii.fixing(new Date(14, Month.October,   2013), true),
                ii.fixing(new Date(14, Month.November,  2013), true),
                ii.fixing(new Date(14, Month.December,  2013), true)
            };

            hz.link.setSeasonality(seasonality_1);
            Utils.QL_REQUIRE(hz.link.hasSeasonality(), () => "[44] incorrectly believes NO seasonality correction");

            double[] seasonalityFixing_1 =
            {
                ii.fixing(new Date(14, Month.January,   2013), true),
                ii.fixing(new Date(14, Month.February,  2013), true),
                ii.fixing(new Date(14, Month.March,     2013), true),
                ii.fixing(new Date(14, Month.April,     2013), true),
                ii.fixing(new Date(14, Month.May,       2013), true),
                ii.fixing(new Date(14, Month.June,      2013), true),
                ii.fixing(new Date(14, Month.July,      2013), true),
                ii.fixing(new Date(14, Month.August,    2013), true),
                ii.fixing(new Date(14, Month.September, 2013), true),
                ii.fixing(new Date(14, Month.October,   2013), true),
                ii.fixing(new Date(14, Month.November,  2013), true),
                ii.fixing(new Date(14, Month.December,  2013), true)
            };

            for (int i = 0; i < 12; i++)
            {
                if (Math.Abs(fixing[i] - seasonalityFixing_1[i]) > eps)
                {
                    Assert.Fail("Seasonality doesn't work correctly when seasonality factors are set = 1");
                }
            }

            //Testing seasonality correction when seasonality factors are different from 1
            //
            //0.998687 is the seasonality factor corresponding to June (the base CPI curve month)
            //
            double[] expectedFixing =
            {
                ii.fixing(new Date(14, Month.January,   2013), true) * 1.003245 / 0.998687,
                ii.fixing(new Date(14, Month.February,  2013), true) * 1.000000 / 0.998687,
                ii.fixing(new Date(14, Month.March,     2013), true) * 0.999715 / 0.998687,
                ii.fixing(new Date(14, Month.April,     2013), true) * 1.000495 / 0.998687,
                ii.fixing(new Date(14, Month.May,       2013), true) * 1.000929 / 0.998687,
                ii.fixing(new Date(14, Month.June,      2013), true) * 0.998687 / 0.998687,
                ii.fixing(new Date(14, Month.July,      2013), true) * 0.995949 / 0.998687,
                ii.fixing(new Date(14, Month.August,    2013), true) * 0.994682 / 0.998687,
                ii.fixing(new Date(14, Month.September, 2013), true) * 0.995949 / 0.998687,
                ii.fixing(new Date(14, Month.October,   2013), true) * 1.000519 / 0.998687,
                ii.fixing(new Date(14, Month.November,  2013), true) * 1.003705 / 0.998687,
                ii.fixing(new Date(14, Month.December,  2013), true) * 1.004186 / 0.998687
            };

            hz.link.setSeasonality(seasonality_real);

            double[] seasonalityFixing_real =
            {
                ii.fixing(new Date(14, Month.January,   2013), true),
                ii.fixing(new Date(14, Month.February,  2013), true),
                ii.fixing(new Date(14, Month.March,     2013), true),
                ii.fixing(new Date(14, Month.April,     2013), true),
                ii.fixing(new Date(14, Month.May,       2013), true),
                ii.fixing(new Date(14, Month.June,      2013), true),
                ii.fixing(new Date(14, Month.July,      2013), true),
                ii.fixing(new Date(14, Month.August,    2013), true),
                ii.fixing(new Date(14, Month.September, 2013), true),
                ii.fixing(new Date(14, Month.October,   2013), true),
                ii.fixing(new Date(14, Month.November,  2013), true),
                ii.fixing(new Date(14, Month.December,  2013), true)
            };

            for (int i = 0; i < 12; i++)
            {
                if (Math.Abs(expectedFixing[i] - seasonalityFixing_real[i]) > 0.01)
                {
                    Assert.Fail("Seasonality doesn't work correctly when considering seasonality factors != 1 "
                                + expectedFixing[i] + " vs " + seasonalityFixing_real[i]);
                }
            }


            //Testing Unset function
            //
            Utils.QL_REQUIRE(hz.link.hasSeasonality(), () => "[4] incorrectly believes NO seasonality correction");
            hz.link.setSeasonality();
            Utils.QL_REQUIRE(!hz.link.hasSeasonality(), () => "[5] incorrectly believes HAS seasonality correction");

            double[] seasonalityFixing_unset =
            {
                ii.fixing(new Date(14, Month.January,   2013), true),
                ii.fixing(new Date(14, Month.February,  2013), true),
                ii.fixing(new Date(14, Month.March,     2013), true),
                ii.fixing(new Date(14, Month.April,     2013), true),
                ii.fixing(new Date(14, Month.May,       2013), true),
                ii.fixing(new Date(14, Month.June,      2013), true),
                ii.fixing(new Date(14, Month.July,      2013), true),
                ii.fixing(new Date(14, Month.August,    2013), true),
                ii.fixing(new Date(14, Month.September, 2013), true),
                ii.fixing(new Date(14, Month.October,   2013), true),
                ii.fixing(new Date(14, Month.November,  2013), true),
                ii.fixing(new Date(14, Month.December,  2013), true)
            };

            for (int i = 0; i < 12; i++)
            {
                if (Math.Abs(seasonalityFixing_unset[i] - seasonalityFixing_1[i]) > eps)
                {
                    Assert.Fail("UnsetSeasonality doesn't work correctly "
                                + seasonalityFixing_unset[i] + " vs " + seasonalityFixing_1[i]);
                }
            }


            //==============================================================================
            // now do an INTERPOLATED index, i.e. repeat everything on a fake version of
            // UKRPI (to save making another term structure)

            bool  interpYES  = true;
            UKRPI iiUKRPIyes = new UKRPI(interpYES, hz);

            for (int i = 0; i < fixData.Length; i++)
            {
                iiUKRPIyes.addFixing(rpiSchedule[i], fixData[i]);
            }

            ZeroInflationIndex iiyes = iiUKRPIyes as ZeroInflationIndex;

            // now build the zero inflation curve
            // same data, bigger lag or it will be a self-contradiction
            Period observationLagyes = new Period(3, TimeUnit.Months);
            List <BootstrapHelper <ZeroInflationTermStructure> > helpersyes =
                makeHelpers(zcData, zcData.Length,
                            iiyes, observationLagyes, calendar, bdc, dc);

            PiecewiseZeroInflationCurve <Linear> pZITSyes =
                new PiecewiseZeroInflationCurve <Linear>(
                    evaluationDate, calendar, dc, observationLagyes,
                    frequency, iiyes.interpolated(), baseZeroRate,
                    new Handle <YieldTermStructure>(nominalTS), helpersyes);

            pZITSyes.recalculate();

            // first check that the zero rates on the curve match the data
            // and that the helpers give the correct impled rates
            forceLinearInterpolation = false;               // still
            for (int i = 0; i < zcData.Length; i++)
            {
                Assert.IsTrue(Math.Abs(zcData[i].rate / 100.0
                                       - pZITSyes.zeroRate(zcData[i].date, observationLagyes, forceLinearInterpolation)) < eps,
                              "ZITS INTERPOLATED zeroRate != instrument "
                              + pZITSyes.zeroRate(zcData[i].date, observationLagyes, forceLinearInterpolation)
                              + " date " + zcData[i].date + " observationLagyes " + observationLagyes
                              + " vs " + zcData[i].rate / 100.0
                              + " interpolation: " + iiyes.interpolated()
                              + " forceLinearInterpolation " + forceLinearInterpolation);
                Assert.IsTrue(Math.Abs(helpersyes[i].impliedQuote()
                                       - zcData[i].rate / 100.0) < eps,
                              "ZITS INTERPOLATED implied quote != instrument "
                              + helpersyes[i].impliedQuote()
                              + " vs " + zcData[i].rate / 100.0);
            }


            //======================================================================================
            // now test the forecasting capability of the index.
            hz.linkTo(pZITSyes);
            from      = hz.link.baseDate() + new Period(1, TimeUnit.Months);       // to avoid historical linear bit for rest of base month
            to        = hz.link.maxDate() - new Period(1, TimeUnit.Months);        // a bit of margin for adjustments
            testIndex = new MakeSchedule().from(from).to(to)
                        .withTenor(new Period(1, TimeUnit.Months))
                        .withCalendar(new UnitedKingdom())
                        .withConvention(BusinessDayConvention.ModifiedFollowing).value();

            // we are testing UKRPI which is FAKE interpolated for testing here
            bd = hz.link.baseDate();
            bf = iiyes.fixing(bd);
            for (int i = 0; i < testIndex.Count; i++)
            {
                Date   d    = testIndex[i];
                double z    = hz.link.zeroRate(d, new Period(0, TimeUnit.Days));
                double t    = hz.link.dayCounter().yearFraction(bd, d);
                double calc = bf * Math.Pow(1 + z, t);
                if (t <= 0)
                {
                    calc = iiyes.fixing(d);                             // still historical
                }
                if (Math.Abs(calc - iiyes.fixing(d)) > eps)
                {
                    Assert.Fail("ZC INTERPOLATED index does not forecast correctly for date " + d
                                + " from base date " + bd
                                + " with fixing " + bf
                                + ", correct:  " + calc
                                + ", fix: " + iiyes.fixing(d)
                                + ", t " + t
                                + ", zero " + z);
                }
            }


            //===========================================================================================
            // Test zero coupon swap

            ZeroInflationIndex ziiyes = iiyes as ZeroInflationIndex;

            Utils.QL_REQUIRE(ziiyes != null, () => "dynamic_pointer_cast to ZeroInflationIndex from UKRPI-I failed");
            ZeroCouponInflationSwap nzcisyes = new ZeroCouponInflationSwap(ZeroCouponInflationSwap.Type.Payer,
                                                                           1000000.0,
                                                                           evaluationDate,
                                                                           zcData[6].date,                                                   // end date = maturity
                                                                           calendar, bdc, dc, zcData[6].rate / 100.0,                        // fixed rate
                                                                           ziiyes, observationLagyes);

            // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via
            //      inflation curve attached to the inflation index.
            nzcisyes.setPricingEngine(sppe);

            // ... and price it, should be zero
            Assert.IsTrue(Math.Abs(nzcisyes.NPV()) < 0.00001, "ZCIS-I does not reprice to zero "
                          + nzcisyes.NPV()
                          + evaluationDate + " to " + zcData[6].date + " becoming " + nzcisyes.maturityDate()
                          + " rate " + zcData[6].rate
                          + " fixed leg " + nzcisyes.legNPV(0)
                          + " indexed-predicted inflated leg " + nzcisyes.legNPV(1)
                          + " discount " + nominalTS.discount(nzcisyes.maturityDate())
                          );

            // remove circular refernce
            hz.linkTo(new ZeroInflationTermStructure());
        }
Пример #16
0
        static void Main(string[] args)
        {
            double nominal = 575000000;

            Date _marketDate;
            Date _settlementDate;
            Dictionary <string, double> _depositRates;
            Dictionary <string, double> _swapRates;
            List <RateHelper>           _rateHelpers;
            Calendar _calendar   = new TARGET();
            int      _fixingDays = 2;

            _marketDate = new Date(new DateTime(2015, 12, 17));
            Settings.setEvaluationDate(_marketDate);

            _depositRates = new Dictionary <string, double>();
            _depositRates.Add("1M", 0.0045);
            _depositRates.Add("3M", 0.0070);
            _depositRates.Add("6M", 0.0090);

            _swapRates = new Dictionary <string, double>();
            _swapRates.Add("1Y", 0.0080);
            _swapRates.Add("2Y", 0.0109);
            _swapRates.Add("3Y", 0.0134);
            _swapRates.Add("4Y", 0.0153);
            _swapRates.Add("5Y", 0.0169);
            _swapRates.Add("7Y", 0.0193);
            _swapRates.Add("10Y", 0.0218);
            _swapRates.Add("30Y", 0.0262);

            _rateHelpers = new List <RateHelper>();
            foreach (var v in _depositRates)
            {
                SimpleQuote sq = new SimpleQuote(v.Value);
                _rateHelpers.Add(new DepositRateHelper(new Handle <Quote>(sq), new Period(v.Key),
                                                       _fixingDays, _calendar, BusinessDayConvention.ModifiedFollowing, true, new Actual360()));
            }
            foreach (var v in _swapRates)
            {
                SimpleQuote sq = new SimpleQuote(v.Value);
                _rateHelpers.Add(new SwapRateHelper(new Handle <Quote>(sq), new Period(v.Key),
                                                    _calendar, Frequency.Semiannual, BusinessDayConvention.Unadjusted,
                                                    new Thirty360(Thirty360.Thirty360Convention.USA), new Euribor3M()));
            }

            _marketDate     = _calendar.adjust(_marketDate);
            _settlementDate = _calendar.advance(_marketDate, _fixingDays, TimeUnit.Days);

            YieldTermStructure yieldTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                _settlementDate, _rateHelpers, new ActualActual(ActualActual.Convention.ISDA));

            RelinkableHandle <YieldTermStructure> yieldTermStructureHandle = new RelinkableHandle <YieldTermStructure>();


            Frequency             fixedLegFrequency  = Frequency.Semiannual;
            BusinessDayConvention fixedLegConvention = BusinessDayConvention.ModifiedFollowing;
            DayCounter            fixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.USA);
            double fixedRate = 0.0144;

            Frequency             floatLegFrequency  = Frequency.Quarterly;
            BusinessDayConvention floatLegConvention = BusinessDayConvention.ModifiedFollowing;
            DayCounter            floatLegDayCounter = new Actual360();
            IborIndex             iborIndex          = new Euribor3M(yieldTermStructureHandle);

            iborIndex.addFixing(new Date(18, Month.Aug, 2015), 0.0033285);
            iborIndex.addFixing(new Date(18, Month.Nov, 2015), 0.0036960);
            double floatSpread = 0.0;

            VanillaSwap.Type swapType = VanillaSwap.Type.Receiver;

            Date     maturity      = new Date(20, Month.Nov, 2018);
            Date     effective     = new Date(20, Month.Nov, 2013);
            Schedule fixedSchedule = new Schedule(effective, maturity, new Period(fixedLegFrequency), _calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false);
            Schedule floatSchedule = new Schedule(effective, maturity, new Period(floatLegFrequency), _calendar, floatLegConvention, floatLegConvention, DateGeneration.Rule.Forward, false);

            VanillaSwap vanillaSwap = new VanillaSwap(swapType, nominal, fixedSchedule, fixedRate, fixedLegDayCounter, floatSchedule, iborIndex, floatSpread, floatLegDayCounter);

            InterestRate        interestRate = new InterestRate(fixedRate, fixedLegDayCounter, Compounding.Simple, fixedLegFrequency);
            List <InterestRate> coupons      = new List <InterestRate>();

            for (int i = 0; i < fixedSchedule.Count; i++)
            {
                coupons.Add(interestRate);
            }
            FixedRateBond    fixedBond = new FixedRateBond(_fixingDays, nominal, fixedSchedule, coupons, BusinessDayConvention.ModifiedFollowing);
            FloatingRateBond floatBond = new FloatingRateBond(_fixingDays, nominal, floatSchedule, iborIndex, floatLegDayCounter);

            IPricingEngine bondPricingEngine = new DiscountingBondEngine(yieldTermStructureHandle);

            fixedBond.setPricingEngine(bondPricingEngine);
            floatBond.setPricingEngine(bondPricingEngine);

            IPricingEngine swapPricingEngine = new DiscountingSwapEngine(yieldTermStructureHandle);

            vanillaSwap.setPricingEngine(swapPricingEngine);

            yieldTermStructureHandle.linkTo(yieldTermStructure);

            double swapNPV      = vanillaSwap.NPV();
            double swapFixedNPV = vanillaSwap.fixedLegNPV();
            double swapFloatNPV = vanillaSwap.floatingLegNPV();

            double bondFixedNPV = fixedBond.NPV();
            double bondFloatNPV = floatBond.NPV();

            int    w = (swapType == VanillaSwap.Type.Receiver ? 1 : -1);
            double asBondsMarketValue      = w * (bondFixedNPV - bondFloatNPV);
            double asBondsMarketValueNoAcc = w * (fixedBond.cleanPrice() - floatBond.cleanPrice()) / 100.0 * nominal;
            double asBondsAccruedInterest  = asBondsMarketValue - asBondsMarketValueNoAcc;

            Console.WriteLine("Vanilla Swap Maket Value      : {0:N}", swapNPV);
            Console.WriteLine("As Bonds Market Value         : {0:N}", asBondsMarketValue);
            Console.WriteLine("As Bonds Market Value (no acc): {0:N}", asBondsMarketValueNoAcc);
            Console.WriteLine("As Bonds Accrued Interest     : {0:N}", asBondsAccruedInterest);

            Date   rollDate      = new Date(1, Month.Nov, 2015);
            double bondFixedCash = 0;

            foreach (CashFlow cf in fixedBond.cashflows())
            {
                if (cf.date() > rollDate & cf.date() <= _marketDate)
                {
                    bondFixedCash += cf.amount();
                }
            }
            double bondFloatCash = 0;

            foreach (CashFlow cf in floatBond.cashflows())
            {
                if (cf.date() > rollDate & cf.date() <= _marketDate)
                {
                    bondFloatCash += cf.amount();
                }
            }
            double asBondsCash = w * (bondFixedCash - bondFloatCash);

            Console.WriteLine("As Bonds Settled Cash         : {0:N}", asBondsCash);
        }
Пример #17
0
        public void testDecomposition()
        {
            // Testing collared coupon against its decomposition

            CommonVars vars = new CommonVars();

            double         tolerance = 1e-12;
            double         npvVanilla, npvCappedLeg, npvFlooredLeg, npvCollaredLeg, npvCap, npvFloor, npvCollar;
            double         error;
            double         floorstrike = 0.05;
            double         capstrike   = 0.10;
            List <double?> caps        = new InitializedList <double?>(vars.length, capstrike);
            List <double?> caps0       = new List <double?>();
            List <double?> floors      = new InitializedList <double?>(vars.length, floorstrike);
            List <double?> floors0     = new List <double?>();
            double         gearing_p   = 0.5;
            double         spread_p    = 0.002;
            double         gearing_n   = -1.5;
            double         spread_n    = 0.12;
            // fixed leg with zero rate
            List <CashFlow> fixedLeg = vars.makeFixedLeg(vars.startDate, vars.length);
            // floating leg with gearing=1 and spread=0
            List <CashFlow> floatLeg = vars.makeFloatingLeg(vars.startDate, vars.length);
            // floating leg with positive gearing (gearing_p) and spread<>0
            List <CashFlow> floatLeg_p = vars.makeFloatingLeg(vars.startDate, vars.length, gearing_p, spread_p);
            // floating leg with negative gearing (gearing_n) and spread<>0
            List <CashFlow> floatLeg_n = vars.makeFloatingLeg(vars.startDate, vars.length, gearing_n, spread_n);
            // Swap with null fixed leg and floating leg with gearing=1 and spread=0
            Swap vanillaLeg = new Swap(fixedLeg, floatLeg);
            // Swap with null fixed leg and floating leg with positive gearing and spread<>0
            Swap vanillaLeg_p = new Swap(fixedLeg, floatLeg_p);
            // Swap with null fixed leg and floating leg with negative gearing and spread<>0
            Swap vanillaLeg_n = new Swap(fixedLeg, floatLeg_n);

            IPricingEngine engine = new DiscountingSwapEngine(vars.termStructure);

            vanillaLeg.setPricingEngine(engine);
            vanillaLeg_p.setPricingEngine(engine);
            vanillaLeg_n.setPricingEngine(engine);

            /* CAPPED coupon - Decomposition of payoff
             * Payoff = Nom * Min(rate,strike) * accrualperiod =
             *       = Nom * [rate + Min(0,strike-rate)] * accrualperiod =
             *       = Nom * rate * accrualperiod - Nom * Max(rate-strike,0) * accrualperiod =
             *       = VanillaFloatingLeg - Call
             */

            // Case gearing = 1 and spread = 0
            List <CashFlow> cappedLeg = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors0, vars.volatility);
            Swap            capLeg    = new Swap(fixedLeg, cappedLeg);

            capLeg.setPricingEngine(engine);
            Cap cap = new Cap(floatLeg, new InitializedList <double>(1, capstrike));

            cap.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla   = vanillaLeg.NPV();
            npvCappedLeg = capLeg.NPV();
            npvCap       = cap.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=1, spread=0%, strike=" + capstrike * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = 1 and spread = 0
             * FLOORED coupon - Decomposition of payoff
             * Payoff = Nom * Max(rate,strike) * accrualperiod =
             *       = Nom * [rate + Max(0,strike-rate)] * accrualperiod =
             *       = Nom * rate * accrualperiod + Nom * Max(strike-rate,0) * accrualperiod =
             *       = VanillaFloatingLeg + Put
             */

            List <CashFlow> flooredLeg = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps0, floors, vars.volatility);
            Swap            floorLeg   = new Swap(fixedLeg, flooredLeg);

            floorLeg.setPricingEngine(engine);
            Floor floor = new Floor(floatLeg, new InitializedList <double>(1, floorstrike));

            floor.setPricingEngine(vars.makeEngine(vars.volatility));
            npvFlooredLeg = floorLeg.NPV();
            npvFloor      = floor.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("Floored Leg: gearing=1, spread=0%, strike=" + floorstrike * 100 +
                             "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = 1 and spread = 0
             * COLLARED coupon - Decomposition of payoff
             * Payoff = Nom * Min(strikem,Max(rate,strikeM)) * accrualperiod =
             *       = VanillaFloatingLeg - Collar
             */

            List <CashFlow> collaredLeg = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors, vars.volatility);
            Swap            collarLeg   = new Swap(fixedLeg, collaredLeg);

            collarLeg.setPricingEngine(engine);
            Collar collar = new Collar(floatLeg, new InitializedList <double>(1, capstrike),
                                       new InitializedList <double>(1, floorstrike));

            collar.setPricingEngine(vars.makeEngine(vars.volatility));
            npvCollaredLeg = collarLeg.NPV();
            npvCollar      = collar.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nCollared Leg: gearing=1, spread=0%, strike=" +
                             floorstrike * 100 + "% and " + capstrike * 100 + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = a and spread = b
             * CAPPED coupon - Decomposition of payoff
             * Payoff
             * = Nom * Min(a*rate+b,strike) * accrualperiod =
             * = Nom * [a*rate+b + Min(0,strike-a*rate-b)] * accrualperiod =
             * = Nom * a*rate+b * accrualperiod + Nom * Min(strike-b-a*rate,0) * accrualperiod
             * --> If a>0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg - Call(a*rate+b,strike)
             * --> If a<0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Nom * Min(strike-b+|a|*rate+,0) * accrualperiod =
             *          = VanillaFloatingLeg + Put(|a|*rate+b,strike)
             */

            // Positive gearing
            List <CashFlow> cappedLeg_p = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors0,
                                                                 vars.volatility, gearing_p, spread_p);
            Swap capLeg_p = new Swap(fixedLeg, cappedLeg_p);

            capLeg_p.setPricingEngine(engine);
            Cap cap_p = new Cap(floatLeg_p, new InitializedList <double>(1, capstrike));

            cap_p.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla   = vanillaLeg_p.NPV();
            npvCappedLeg = capLeg_p.NPV();
            npvCap       = cap_p.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=" + gearing_p + ", " +
                             "spread= " + spread_p * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + (capstrike - spread_p) / gearing_p * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Vanilla Leg NPV: " + npvVanilla + "\n" +
                             "  Cap NPV: " + npvCap + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            // Negative gearing
            List <CashFlow> cappedLeg_n = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors0,
                                                                 vars.volatility, gearing_n, spread_n);
            Swap capLeg_n = new Swap(fixedLeg, cappedLeg_n);

            capLeg_n.setPricingEngine(engine);
            Floor floor_n = new Floor(floatLeg, new InitializedList <double>(1, (capstrike - spread_n) / gearing_n));

            floor_n.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla   = vanillaLeg_n.NPV();
            npvCappedLeg = capLeg_n.NPV();
            npvFloor     = floor_n.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla + gearing_n * npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + (capstrike - spread_n) / gearing_n * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  npv Vanilla: " + npvVanilla + "\n" +
                             "  npvFloor: " + npvFloor + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla + gearing_n * npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = a and spread = b
             * FLOORED coupon - Decomposition of payoff
             * Payoff
             * = Nom * Max(a*rate+b,strike) * accrualperiod =
             * = Nom * [a*rate+b + Max(0,strike-a*rate-b)] * accrualperiod =
             * = Nom * a*rate+b * accrualperiod + Nom * Max(strike-b-a*rate,0) * accrualperiod
             * --> If a>0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Put(a*rate+b,strike)
             * --> If a<0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Nom * Max(strike-b+|a|*rate+,0) * accrualperiod =
             *          = VanillaFloatingLeg - Call(|a|*rate+b,strike)
             */

            // Positive gearing
            List <CashFlow> flooredLeg_p1 = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps0, floors,
                                                                   vars.volatility, gearing_p, spread_p);
            Swap floorLeg_p1 = new Swap(fixedLeg, flooredLeg_p1);

            floorLeg_p1.setPricingEngine(engine);
            Floor floor_p1 = new Floor(floatLeg_p, new InitializedList <double>(1, floorstrike));

            floor_p1.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla    = vanillaLeg_p.NPV();
            npvFlooredLeg = floorLeg_p1.NPV();
            npvFloor      = floor_p1.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nFloored Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike=" + floorstrike * 100 + "%, "
                             + "effective strike= " + (floorstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg
                             + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> flooredLeg_n = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps0, floors,
                                                                  vars.volatility, gearing_n, spread_n);
            Swap floorLeg_n = new Swap(fixedLeg, flooredLeg_n);

            floorLeg_n.setPricingEngine(engine);
            Cap cap_n = new Cap(floatLeg, new InitializedList <double>(1, (floorstrike - spread_n) / gearing_n));

            cap_n.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla    = vanillaLeg_n.NPV();
            npvFlooredLeg = floorLeg_n.NPV();
            npvCap        = cap_n.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla - gearing_n * npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + floorstrike * 100 + "%, " +
                             "effective strike= " + (floorstrike - spread_n) / gearing_n * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - gearing_n * npvCap) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = a and spread = b
             * COLLARED coupon - Decomposition of payoff
             * Payoff = Nom * Min(caprate,Max(a*rate+b,floorrate)) * accrualperiod
             * --> If a>0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg - Collar(a*rate+b, floorrate, caprate)
             * --> If a<0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Collar(|a|*rate+b, caprate, floorrate)
             */
            // Positive gearing
            List <CashFlow> collaredLeg_p = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors,
                                                                   vars.volatility, gearing_p, spread_p);
            Swap collarLeg_p1 = new Swap(fixedLeg, collaredLeg_p);

            collarLeg_p1.setPricingEngine(engine);
            Collar collar_p = new Collar(floatLeg_p, new InitializedList <double>(1, capstrike),
                                         new InitializedList <double>(1, floorstrike));

            collar_p.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla     = vanillaLeg_p.NPV();
            npvCollaredLeg = collarLeg_p1.NPV();
            npvCollar      = collar_p.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nCollared Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_p) / gearing_p * 100
                             + "% and " + (capstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> collaredLeg_n = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors,
                                                                   vars.volatility, gearing_n, spread_n);
            Swap collarLeg_n1 = new Swap(fixedLeg, collaredLeg_n);

            collarLeg_n1.setPricingEngine(engine);
            Collar collar_n = new Collar(floatLeg, new InitializedList <double>(1, (floorstrike - spread_n) / gearing_n),
                                         new InitializedList <double>(1, (capstrike - spread_n) / gearing_n));

            collar_n.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla     = vanillaLeg_n.NPV();
            npvCollaredLeg = collarLeg_n1.NPV();
            npvCollar      = collar_n.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - gearing_n * npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nCollared Leg: gearing=" + gearing_n + ", "
                             + "spread= " + spread_n * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_n) / gearing_n * 100
                             + "% and " + (capstrike - spread_n) / gearing_n * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - gearing_n * npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
        }
Пример #18
0
        public void cpibondconsistency()
        {
            CommonVars common = new CommonVars();

            // ZeroInflationSwap aka CPISwap

            CPISwap.Type type    = CPISwap.Type.Payer;
            double       nominal = 1000000.0;
            bool         subtractInflationNominal = true;
            // float+spread leg
            double                spread                 = 0.0;
            DayCounter            floatDayCount          = new Actual365Fixed();
            BusinessDayConvention floatPaymentConvention = BusinessDayConvention.ModifiedFollowing;
            int       fixingDays = 0;
            IborIndex floatIndex = new GBPLibor(new Period(6, TimeUnit.Months), common.nominalUK);

            // fixed x inflation leg
            double                fixedRate                = 0.1;   //1% would be 0.01
            double                baseCPI                  = 206.1; // would be 206.13871 if we were interpolating
            DayCounter            fixedDayCount            = new Actual365Fixed();
            BusinessDayConvention fixedPaymentConvention   = BusinessDayConvention.ModifiedFollowing;
            Calendar              fixedPaymentCalendar     = new UnitedKingdom();
            ZeroInflationIndex    fixedIndex               = common.ii;
            Period                contractObservationLag   = common.contractObservationLag;
            InterpolationType     observationInterpolation = common.contractObservationInterpolation;

            // set the schedules
            Date     startDate     = new Date(2, Month.October, 2007);
            Date     endDate       = new Date(2, Month.October, 2052);
            Schedule floatSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(floatPaymentConvention)
                                     .backwards().value();
            Schedule fixedSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(BusinessDayConvention.Unadjusted)
                                     .backwards().value();

            CPISwap zisV = new CPISwap(type, nominal, subtractInflationNominal,
                                       spread, floatDayCount, floatSchedule,
                                       floatPaymentConvention, fixingDays, floatIndex,
                                       fixedRate, baseCPI, fixedDayCount, fixedSchedule,
                                       fixedPaymentConvention, contractObservationLag,
                                       fixedIndex, observationInterpolation);

            double[] floatFix = { 0.06255, 0.05975, 0.0637, 0.018425, 0.0073438, -1, -1 };
            double[] cpiFix   = { 211.4, 217.2, 211.4, 213.4, -2, -2 };
            for (int i = 0; i < floatSchedule.Count; i++)
            {
                if (floatSchedule[i] < common.evaluationDate)
                {
                    floatIndex.addFixing(floatSchedule[i], floatFix[i], true);//true=overwrite
                }

                CPICoupon zic = zisV.cpiLeg()[i] as CPICoupon;
                if (zic != null)
                {
                    if (zic.fixingDate() < (common.evaluationDate - new Period(1, TimeUnit.Months)))
                    {
                        fixedIndex.addFixing(zic.fixingDate(), cpiFix[i], true);
                    }
                }
            }

            // simple structure so simple pricing engine - most work done by index
            DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK);

            zisV.setPricingEngine(dse);

            // now do the bond equivalent
            List <double> fixedRates     = new InitializedList <double>(1, fixedRate);
            int           settlementDays = 1;// cannot be zero!
            bool          growthOnly     = true;
            CPIBond       cpiB           = new CPIBond(settlementDays, nominal, growthOnly,
                                                       baseCPI, contractObservationLag, fixedIndex,
                                                       observationInterpolation, fixedSchedule,
                                                       fixedRates, fixedDayCount, fixedPaymentConvention);

            DiscountingBondEngine dbe = new DiscountingBondEngine(common.nominalUK);

            cpiB.setPricingEngine(dbe);

            QAssert.IsTrue(Math.Abs(cpiB.NPV() - zisV.legNPV(0).GetValueOrDefault()) < 1e-5,
                           "cpi bond does not equal equivalent cpi swap leg");
            // remove circular refernce
            common.hcpi.linkTo(null);
        }
Пример #19
0
        public void testDecomposition()
        {
            // Testing collared coupon against its decomposition...

            CommonVars vars = new CommonVars();

            double        tolerance = 1e-10;
            double        npvVanilla, npvCappedLeg, npvFlooredLeg, npvCollaredLeg, npvCap, npvFloor, npvCollar;
            double        error;
            double        floorstrike = 0.05;
            double        capstrike   = 0.10;
            List <double> caps        = new InitializedList <double>(vars.length, capstrike);
            List <double> caps0       = new List <double>();
            List <double> floors      = new InitializedList <double>(vars.length, floorstrike);
            List <double> floors0     = new List <double>();
            double        gearing_p   = 0.5;
            double        spread_p    = 0.002;
            double        gearing_n   = -1.5;
            double        spread_n    = 0.12;
            // fixed leg with zero rate
            List <CashFlow> fixedLeg = vars.makeFixedLeg(vars.startDate, vars.length);
            // floating leg with gearing=1 and spread=0
            List <CashFlow> floatLeg = vars.makeYoYLeg(vars.startDate, vars.length);
            // floating leg with positive gearing (gearing_p) and spread<>0
            List <CashFlow> floatLeg_p = vars.makeYoYLeg(vars.startDate, vars.length, gearing_p, spread_p);
            // floating leg with negative gearing (gearing_n) and spread<>0
            List <CashFlow> floatLeg_n = vars.makeYoYLeg(vars.startDate, vars.length, gearing_n, spread_n);
            // Swap with null fixed leg and floating leg with gearing=1 and spread=0
            Swap vanillaLeg = new Swap(fixedLeg, floatLeg);
            // Swap with null fixed leg and floating leg with positive gearing and spread<>0
            Swap vanillaLeg_p = new Swap(fixedLeg, floatLeg_p);
            // Swap with null fixed leg and floating leg with negative gearing and spread<>0
            Swap vanillaLeg_n = new Swap(fixedLeg, floatLeg_n);

            IPricingEngine engine = new DiscountingSwapEngine(vars.nominalTS);

            vanillaLeg.setPricingEngine(engine); // here use the autoset feature
            vanillaLeg_p.setPricingEngine(engine);
            vanillaLeg_n.setPricingEngine(engine);

            // CAPPED coupon - Decomposition of payoff
            // Payoff = Nom * Min(rate,strike) * accrualperiod =
            // = Nom * [rate + Min(0,strike-rate)] * accrualperiod =
            // = Nom * rate * accrualperiod - Nom * Max(rate-strike,0) * accrualperiod =
            // = VanillaFloatingLeg - Call
            //

            int whichPricer = 0;

            // Case gearing = 1 and spread = 0
            List <CashFlow> cappedLeg = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length,
                                                                  caps, floors0, vars.volatility);
            Swap capLeg = new Swap(fixedLeg, cappedLeg);

            capLeg.setPricingEngine(engine);
            YoYInflationCap cap = new YoYInflationCap(floatLeg, new List <double>()
            {
                capstrike
            });

            cap.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla   = vanillaLeg.NPV();
            npvCappedLeg = capLeg.NPV();
            npvCap       = cap.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=1, spread=0%, strike=" + capstrike * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = 1 and spread = 0
            // FLOORED coupon - Decomposition of payoff
            // Payoff = Nom * Max(rate,strike) * accrualperiod =
            // = Nom * [rate + Max(0,strike-rate)] * accrualperiod =
            // = Nom * rate * accrualperiod + Nom * Max(strike-rate,0) * accrualperiod =
            // = VanillaFloatingLeg + Put
            //

            List <CashFlow> flooredLeg = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length,
                                                                   caps0, floors, vars.volatility);
            Swap floorLeg = new Swap(fixedLeg, flooredLeg);

            floorLeg.setPricingEngine(engine);
            YoYInflationFloor floor = new YoYInflationFloor(floatLeg, new List <double>()
            {
                floorstrike
            });

            floor.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvFlooredLeg = floorLeg.NPV();
            npvFloor      = floor.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("YoY Floored Leg: gearing=1, spread=0%, strike=" + floorstrike * 100 +
                             "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = 1 and spread = 0
            // COLLARED coupon - Decomposition of payoff
            // Payoff = Nom * Min(strikem,Max(rate,strikeM)) * accrualperiod =
            // = VanillaFloatingLeg - Collar
            //

            List <CashFlow> collaredLeg = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length,
                                                                    caps, floors, vars.volatility);
            Swap collarLeg = new Swap(fixedLeg, collaredLeg);

            collarLeg.setPricingEngine(engine);
            YoYInflationCollar collar = new YoYInflationCollar(floatLeg,
                                                               new List <double>()
            {
                capstrike
            },
                                                               new List <double>()
            {
                floorstrike
            });

            collar.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvCollaredLeg = collarLeg.NPV();
            npvCollar      = collar.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Collared Leg: gearing=1, spread=0%, strike=" +
                             floorstrike * 100 + "% and " + capstrike * 100 + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = a and spread = b
            // CAPPED coupon - Decomposition of payoff
            // Payoff
            // = Nom * Min(a*rate+b,strike) * accrualperiod =
            // = Nom * [a*rate+b + Min(0,strike-a*rate-b)] * accrualperiod =
            // = Nom * a*rate+b * accrualperiod + Nom * Min(strike-b-a*rate,0) * accrualperiod
            // --> If a>0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg - Call(a*rate+b,strike)
            // --> If a<0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Nom * Min(strike-b+|a|*rate+,0) * accrualperiod =
            // = VanillaFloatingLeg + Put(|a|*rate+b,strike)
            //

            // Positive gearing
            List <CashFlow> cappedLeg_p = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors0,
                                                                    vars.volatility, gearing_p, spread_p);
            Swap capLeg_p = new Swap(fixedLeg, cappedLeg_p);

            capLeg_p.setPricingEngine(engine);
            YoYInflationCap cap_p = new YoYInflationCap(floatLeg_p, new List <double>()
            {
                capstrike
            });

            cap_p.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla   = vanillaLeg_p.NPV();
            npvCappedLeg = capLeg_p.NPV();
            npvCap       = cap_p.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=" + gearing_p + ", " +
                             "spread= " + spread_p * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + (capstrike - spread_p) / gearing_p * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Vanilla Leg NPV: " + npvVanilla + "\n" +
                             "  Cap NPV: " + npvCap + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            // Negative gearing
            List <CashFlow> cappedLeg_n = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors0,
                                                                    vars.volatility, gearing_n, spread_n);
            Swap capLeg_n = new Swap(fixedLeg, cappedLeg_n);

            capLeg_n.setPricingEngine(engine);
            YoYInflationFloor floor_n = new YoYInflationFloor(floatLeg, new List <double>()
            {
                (capstrike - spread_n) / gearing_n
            });

            floor_n.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla   = vanillaLeg_n.NPV();
            npvCappedLeg = capLeg_n.NPV();
            npvFloor     = floor_n.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla + gearing_n * npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + ((capstrike - spread_n) / gearing_n * 100) +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  npv Vanilla: " + npvVanilla + "\n" +
                             "  npvFloor: " + npvFloor + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla + gearing_n * npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = a and spread = b
            // FLOORED coupon - Decomposition of payoff
            // Payoff
            // = Nom * Max(a*rate+b,strike) * accrualperiod =
            // = Nom * [a*rate+b + Max(0,strike-a*rate-b)] * accrualperiod =
            // = Nom * a*rate+b * accrualperiod + Nom * Max(strike-b-a*rate,0) * accrualperiod
            // --> If a>0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Put(a*rate+b,strike)
            // --> If a<0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Nom * Max(strike-b+|a|*rate+,0) * accrualperiod =
            // = VanillaFloatingLeg - Call(|a|*rate+b,strike)
            //

            // Positive gearing
            List <CashFlow> flooredLeg_p1 = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps0, floors,
                                                                      vars.volatility, gearing_p, spread_p);
            Swap floorLeg_p1 = new Swap(fixedLeg, flooredLeg_p1);

            floorLeg_p1.setPricingEngine(engine);
            YoYInflationFloor floor_p1 = new YoYInflationFloor(floatLeg_p, new List <double>()
            {
                floorstrike
            });

            floor_p1.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla    = vanillaLeg_p.NPV();
            npvFlooredLeg = floorLeg_p1.NPV();
            npvFloor      = floor_p1.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Floored Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike=" + floorstrike * 100 + "%, "
                             + "effective strike= " + (floorstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg
                             + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> flooredLeg_n = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps0, floors,
                                                                     vars.volatility, gearing_n, spread_n);
            Swap floorLeg_n = new Swap(fixedLeg, flooredLeg_n);

            floorLeg_n.setPricingEngine(engine);
            YoYInflationCap cap_n = new YoYInflationCap(floatLeg, new List <double>()
            {
                (floorstrike - spread_n) / gearing_n
            });

            cap_n.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla    = vanillaLeg_n.NPV();
            npvFlooredLeg = floorLeg_n.NPV();
            npvCap        = cap_n.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla - gearing_n * npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + floorstrike * 100 + "%, " +
                             "effective strike= " + (floorstrike - spread_n) / gearing_n * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - gearing_n * npvCap) + "\n" +
                             "  Diff: " + error);
            }
            // gearing = a and spread = b
            // COLLARED coupon - Decomposition of payoff
            // Payoff = Nom * Min(caprate,Max(a*rate+b,floorrate)) * accrualperiod
            // --> If a>0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg - Collar(a*rate+b, floorrate, caprate)
            // --> If a<0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Collar(|a|*rate+b, caprate, floorrate)
            //
            // Positive gearing
            List <CashFlow> collaredLeg_p = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors,
                                                                      vars.volatility, gearing_p, spread_p);
            Swap collarLeg_p1 = new Swap(fixedLeg, collaredLeg_p);

            collarLeg_p1.setPricingEngine(engine);
            YoYInflationCollar collar_p = new YoYInflationCollar(floatLeg_p,
                                                                 new List <double>()
            {
                capstrike
            },
                                                                 new List <double>()
            {
                floorstrike
            });

            collar_p.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla     = vanillaLeg_p.NPV();
            npvCollaredLeg = collarLeg_p1.NPV();
            npvCollar      = collar_p.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Collared Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_p) / gearing_p * 100
                             + "% and " + (capstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> collaredLeg_n = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors,
                                                                      vars.volatility, gearing_n, spread_n);
            Swap collarLeg_n1 = new Swap(fixedLeg, collaredLeg_n);

            collarLeg_n1.setPricingEngine(engine);
            YoYInflationCollar collar_n = new YoYInflationCollar(floatLeg,
                                                                 new List <double>()
            {
                (floorstrike - spread_n) / gearing_n
            },
                                                                 new List <double>()
            {
                (capstrike - spread_n) / gearing_n
            });

            collar_n.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla     = vanillaLeg_n.NPV();
            npvCollaredLeg = collarLeg_n1.NPV();
            npvCollar      = collar_n.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - gearing_n * npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Collared Leg: gearing=" + gearing_n + ", "
                             + "spread= " + spread_n * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_n) / gearing_n * 100
                             + "% and " + (capstrike - spread_n) / gearing_n * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - gearing_n * npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
            // remove circular refernce
            vars.hy.linkTo(null);
        }
Пример #20
0
        public void testParity()
        {
            // Testing yoy inflation cap/floor parity...

            CommonVars vars = new CommonVars();

            int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            // vol is low ...
            double[] strikes = { 0.0, 0.025, 0.029, 0.03, 0.031, 0.035, 0.07 };
            // yoy inflation vol is generally very low
            double[] vols = { 0.001, 0.005, 0.010, 0.015, 0.020 };

            // cap-floor-swap parity is model-independent
            for (int whichPricer = 0; whichPricer < 3; whichPricer++)
            {
                for (int i = 0; i < lengths.Length; i++)
                {
                    for (int j = 0; j < strikes.Length; j++)
                    {
                        for (int k = 0; k < vols.Length; k++)
                        {
                            List <CashFlow> leg = vars.makeYoYLeg(vars.evaluationDate, lengths[i]);

                            Instrument cap = vars.makeYoYCapFloor(CapFloorType.Cap,
                                                                  leg, strikes[j], vols[k], whichPricer);

                            Instrument floor = vars.makeYoYCapFloor(CapFloorType.Floor,
                                                                    leg, strikes[j], vols[k], whichPricer);

                            Date     from        = vars.nominalTS.link.referenceDate();
                            Date     to          = from + new Period(lengths[i], TimeUnit.Years);
                            Schedule yoySchedule = new MakeSchedule().from(from).to(to)
                                                   .withTenor(new Period(1, TimeUnit.Years))
                                                   .withConvention(BusinessDayConvention.Unadjusted)
                                                   .withCalendar(new UnitedKingdom()).backwards().value();

                            YearOnYearInflationSwap swap = new YearOnYearInflationSwap
                                                               (YearOnYearInflationSwap.Type.Payer,
                                                               1000000.0,
                                                               yoySchedule,                 //fixed schedule, but same as yoy
                                                               strikes[j],
                                                               vars.dc,
                                                               yoySchedule,
                                                               vars.iir,
                                                               vars.observationLag,
                                                               0.0,                         //spread on index
                                                               vars.dc,
                                                               new UnitedKingdom());

                            Handle <YieldTermStructure> hTS = new Handle <YieldTermStructure>(vars.nominalTS);
                            IPricingEngine sppe             = new DiscountingSwapEngine(hTS);
                            swap.setPricingEngine(sppe);

                            // N.B. nominals are 10e6
                            if (Math.Abs((cap.NPV() - floor.NPV()) - swap.NPV()) > 1.0e-6)
                            {
                                Assert.Fail(
                                    "put/call parity violated:\n"
                                    + "    length:      " + lengths[i] + " years\n"
                                    + "    volatility:  " + vols[k] + "\n"
                                    + "    strike:      " + strikes[j] + "\n"
                                    + "    cap value:   " + cap.NPV() + "\n"
                                    + "    floor value: " + floor.NPV() + "\n"
                                    + "    swap value:  " + swap.NPV());
                            }
                        }
                    }
                }
            }
            // remove circular refernce
            vars.hy.linkTo(new YoYInflationTermStructure());
        }
Пример #21
0
        static void Main(string[] args)
        {
            try
            {
                DateTime timer      = DateTime.Now;
                Calendar calendar   = new TARGET();
                Date     todaysDate = new Date(10, Month.March, 2004);
                // must be a business day
                todaysDate = calendar.adjust(todaysDate);

                Settings.setEvaluationDate(todaysDate);

                IborIndex yieldIndx     = new Euribor3M();
                int[]     tenorsSwapMkt = { 5, 10, 15, 20, 25, 30 };

                // rates ignoring counterparty risk:
                double[] ratesSwapmkt = { .03249, .04074, .04463, .04675, .04775, .04811 };

                List <RateHelper> swapHelpers = new List <RateHelper>();
                for (int i = 0; i < tenorsSwapMkt.Length; i++)
                {
                    swapHelpers.Add(new SwapRateHelper(new Handle <Quote>(new SimpleQuote(ratesSwapmkt[i])),
                                                       new Period(tenorsSwapMkt[i], TimeUnit.Years),
                                                       new TARGET(),
                                                       Frequency.Quarterly,
                                                       BusinessDayConvention.ModifiedFollowing,
                                                       new ActualActual(ActualActual.Convention.ISDA),
                                                       yieldIndx));
                }

                YieldTermStructure swapTS = new PiecewiseYieldCurve <Discount, LogLinear>(2, new TARGET(), swapHelpers,
                                                                                          new ActualActual(ActualActual.Convention.ISDA));
                swapTS.enableExtrapolation();

                IPricingEngine riskFreeEngine = new DiscountingSwapEngine(new Handle <YieldTermStructure>(swapTS));

                List <Handle <DefaultProbabilityTermStructure> > defaultIntensityTS =
                    new List <Handle <DefaultProbabilityTermStructure> >();

                int[] defaultTenors = { 0, 12, 36, 60, 84, 120, 180, 240, 300, 360 }; // months
                // Three risk levels:
                double[] intensitiesLow    = { 0.0036, 0.0036, 0.0065, 0.0099, 0.0111, 0.0177, 0.0177, 0.0177, 0.0177, 0.0177, 0.0177 };
                double[] intensitiesMedium = { 0.0202, 0.0202, 0.0231, 0.0266, 0.0278, 0.0349, 0.0349, 0.0349, 0.0349, 0.0349, 0.0349 };
                double[] intensitiesHigh   = { 0.0534, 0.0534, 0.0564, 0.06, 0.0614, 0.0696, 0.0696, 0.0696, 0.0696, 0.0696, 0.0696 };
                // Recovery rates:
                double ctptyRRLow = 0.4, ctptyRRMedium = 0.35, ctptyRRHigh = 0.3;

                List <Date>   defaultTSDates    = new List <Date>();
                List <double> intesitiesVLow    = new List <double>(),
                              intesitiesVMedium = new List <double>(),
                              intesitiesVHigh   = new List <double>();

                for (int i = 0; i < defaultTenors.Length; i++)
                {
                    defaultTSDates.Add(new TARGET().advance(todaysDate, new Period(defaultTenors[i], TimeUnit.Months)));
                    intesitiesVLow.Add(intensitiesLow[i]);
                    intesitiesVMedium.Add(intensitiesMedium[i]);
                    intesitiesVHigh.Add(intensitiesHigh[i]);
                }

                defaultIntensityTS.Add(new Handle <DefaultProbabilityTermStructure>(
                                           new InterpolatedHazardRateCurve <BackwardFlat>(
                                               defaultTSDates,
                                               intesitiesVLow,
                                               new Actual360(),
                                               new TARGET())));
                defaultIntensityTS.Add(new Handle <DefaultProbabilityTermStructure>(
                                           new InterpolatedHazardRateCurve <BackwardFlat>(
                                               defaultTSDates,
                                               intesitiesVMedium,
                                               new Actual360(),
                                               new TARGET())));
                defaultIntensityTS.Add(new Handle <DefaultProbabilityTermStructure>(
                                           new InterpolatedHazardRateCurve <BackwardFlat>(
                                               defaultTSDates,
                                               intesitiesVHigh,
                                               new Actual360(),
                                               new TARGET())));

                double         blackVol        = 0.15;
                IPricingEngine ctptySwapCvaLow = new CounterpartyAdjSwapEngine(new Handle <YieldTermStructure>(swapTS),
                                                                               blackVol, defaultIntensityTS[0], ctptyRRLow);

                IPricingEngine ctptySwapCvaMedium = new CounterpartyAdjSwapEngine(new Handle <YieldTermStructure>(swapTS),
                                                                                  blackVol, defaultIntensityTS[1], ctptyRRMedium);

                IPricingEngine ctptySwapCvaHigh = new CounterpartyAdjSwapEngine(new Handle <YieldTermStructure>(swapTS),
                                                                                blackVol, defaultIntensityTS[2], ctptyRRHigh);

                defaultIntensityTS[0].link.enableExtrapolation();
                defaultIntensityTS[1].link.enableExtrapolation();
                defaultIntensityTS[2].link.enableExtrapolation();

                // SWAP RISKY REPRICE----------------------------------------------

                // fixed leg
                Frequency             fixedLegFrequency     = Frequency.Quarterly;
                BusinessDayConvention fixedLegConvention    = BusinessDayConvention.ModifiedFollowing;
                DayCounter            fixedLegDayCounter    = new ActualActual(ActualActual.Convention.ISDA);
                DayCounter            floatingLegDayCounter = new ActualActual(ActualActual.Convention.ISDA);

                VanillaSwap.Type swapType =
                    //VanillaSwap::Receiver ;
                    VanillaSwap.Type.Payer;
                IborIndex          yieldIndxS = new Euribor3M(new Handle <YieldTermStructure>(swapTS));
                List <VanillaSwap> riskySwaps = new List <VanillaSwap>();
                for (int i = 0; i < tenorsSwapMkt.Length; i++)
                {
                    riskySwaps.Add(new MakeVanillaSwap(new Period(tenorsSwapMkt[i], TimeUnit.Years),
                                                       yieldIndxS,
                                                       ratesSwapmkt[i],
                                                       new Period(0, TimeUnit.Days))
                                   .withSettlementDays(2)
                                   .withFixedLegDayCount(fixedLegDayCounter)
                                   .withFixedLegTenor(new Period(fixedLegFrequency))
                                   .withFixedLegConvention(fixedLegConvention)
                                   .withFixedLegTerminationDateConvention(fixedLegConvention)
                                   .withFixedLegCalendar(calendar)
                                   .withFloatingLegCalendar(calendar)
                                   .withNominal(100.0)
                                   .withType(swapType).value());
                }

                Console.WriteLine("-- Correction in the contract fix rate in bp --");

                /* The paper plots correction to be substracted, here is printed
                 * with its sign
                 */
                for (int i = 0; i < riskySwaps.Count; i++)
                {
                    riskySwaps[i].setPricingEngine(riskFreeEngine);
                    // should recover the input here:
                    double nonRiskyFair = riskySwaps[i].fairRate();
                    Console.Write((tenorsSwapMkt[i]).ToString("0").PadLeft(6));
                    Console.Write(" | " + nonRiskyFair.ToString("P3").PadLeft(6));
                    // Low Risk:
                    riskySwaps[i].setPricingEngine(ctptySwapCvaLow);
                    Console.Write(" | " + (10000.0 * (riskySwaps[i].fairRate() - nonRiskyFair)).ToString("#0.00").PadLeft(6));
                    //cout << " | " << setw(6) << riskySwaps[i].NPV() ;

                    // Medium Risk:
                    riskySwaps[i].setPricingEngine(ctptySwapCvaMedium);
                    Console.Write(" | " + (10000.0 * (riskySwaps[i].fairRate() - nonRiskyFair)).ToString("#0.00").PadLeft(6));
                    //cout << " | " << setw(6) << riskySwaps[i].NPV() ;

                    riskySwaps[i].setPricingEngine(ctptySwapCvaHigh);
                    Console.Write(" | " + (10000.0 * (riskySwaps[i].fairRate() - nonRiskyFair)).ToString("#0.00").PadLeft(6));
                    //cout << " | " << setw(6) << riskySwaps[i].NPV() ;

                    Console.WriteLine();
                }

                Console.WriteLine();

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

                Console.Write("Press any key to continue ...");
                Console.ReadKey();
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
                Console.Write("Press any key to continue ...");
                Console.ReadKey();
            }
        }
Пример #22
0
        public static object eqInstIRGenericSwap(
            // trade info

            /*[ExcelArgument(Description = "trade id ")] string tradeid,
             * [ExcelArgument(Description = "Entity ")] string entity,
             * [ExcelArgument(Description = "Entity ID ")] string entityid,
             * [ExcelArgument(Description = "Counterparty ")] string counterparty,
             * [ExcelArgument(Description = "Counterparty ID ")] string counterpartyid,
             * [ExcelArgument(Description = "swap type ")] string swaptype,
             * [ExcelArgument(Description = "Fixing Days ")] object fixingdays,        // use object to catch missing
             * [ExcelArgument(Description = "Trade Date ")] object tradedate,
             * [ExcelArgument(Description = "Start date ")] object startdate,
             * [ExcelArgument(Description = "Maturity date ")] object maturitydate,
             * [ExcelArgument(Description = "Tenor ")] string Tenor,
             * [ExcelArgument(Description = "is notional schedule given ")] bool isschedulegiven,*/
            [ExcelArgument(Description = "swap type ")] object[] tradeinfo,
            // first leg

            /*[ExcelArgument(Description = "id of first leg index ")] string firstlegindex,
             * [ExcelArgument(Description = "first leg frequency ")] string firstlegfreq,
             * [ExcelArgument(Description = "first leg convention ")] string firstlegconv,
             * [ExcelArgument(Description = "first leg calendar ")] string firstlegcalendar,
             * [ExcelArgument(Description = "first leg day counter ")] string firstlegdc,
             * [ExcelArgument(Description = "first leg date generation rule ")] string firstlegdgrule,
             * [ExcelArgument(Description = "first leg end of month ")] bool firstlegeom,
             * [ExcelArgument(Description = "first leg fixed rate ")] double firstlegrate,*/
            [ExcelArgument(Description = "first leg info ")] object[] firstleginfo,
            [ExcelArgument(Description = "first leg notional(s) ")] object[] firstlegnotionals,     // only object[] works
            [ExcelArgument(Description = "first leg schedule(s) ")] object[,] firstlegschedule,
            // second leg

            /*[ExcelArgument(Description = "id of second leg index ")] string secondlegindex,
             * [ExcelArgument(Description = "second leg frequency  ")] string secondlegfreq,
             * [ExcelArgument(Description = "second leg convention ")] string secondlegconv,
             * [ExcelArgument(Description = "second leg calendar ")] string secondlegcalendar,
             * [ExcelArgument(Description = "second leg day counter ")] string secondlegdc,
             * [ExcelArgument(Description = "second leg date generation rule ")] string secondlegdgrule,
             * [ExcelArgument(Description = "second leg end of month ")] bool secondlegeom,
             * [ExcelArgument(Description = "second leg spread ")] double secondlegspread,*/
            [ExcelArgument(Description = "second leg info ")] object[] secondleginfo,
            [ExcelArgument(Description = "second leg notional(s) ")] object[] secondlegnotionals,
            [ExcelArgument(Description = "second leg schedule(s) ")] object[,] secondlegschedule,
            [ExcelArgument(Description = "id of discount curve ")] string discountId
            )
        {
            if (ExcelUtil.CallFromWizard())
            {
                return("");
            }

            string callerAddress = "";

            callerAddress = ExcelUtil.getActiveCellAddress();

            try
            {
                Xl.Range rng = ExcelUtil.getActiveCellRange();

                EliteQuant.Instruments.InterestRateGenericSwap genswap = new EliteQuant.Instruments.InterestRateGenericSwap();

                #region parameters
                if (ExcelUtil.isNull(tradeinfo[0]))
                {
                    return("#EQ_ERR!");
                }
                else
                {
                    genswap.ContractId = (string)tradeinfo[0];
                }

                if (ExcelUtil.isNull(tradeinfo[1]))
                {
                    genswap.Entity = "NA";
                }
                else
                {
                    genswap.Entity = (string)tradeinfo[1];
                }

                if (ExcelUtil.isNull(tradeinfo[2]))
                {
                    genswap.EntityID = "NA";
                }
                else
                {
                    genswap.EntityID = (string)tradeinfo[2];
                }

                if (ExcelUtil.isNull(tradeinfo[3]))
                {
                    genswap.Counterparty = "NA";
                }
                else
                {
                    genswap.Counterparty = (string)tradeinfo[3];
                }

                if (ExcelUtil.isNull(tradeinfo[4]))
                {
                    genswap.CounterpartyID = "NA";
                }
                else
                {
                    genswap.CounterpartyID = (string)tradeinfo[4];
                }

                if (ExcelUtil.isNull(tradeinfo[5]))
                {
                    genswap.SwapType = "Payer";
                }
                else
                {
                    genswap.SwapType = (string)tradeinfo[5];
                }

                if (ExcelUtil.isNull(tradeinfo[6]))
                {
                    genswap.FixingDays = 2;
                }
                else
                {
                    genswap.FixingDays = (int)(double)tradeinfo[6];
                }

                if (ExcelUtil.isNull(tradeinfo[7]))
                {
                    genswap.TradeDate = EliteQuant.EQConverter.DateTimeToString(DateTime.Today);
                }
                else
                {
                    genswap.TradeDate = EliteQuant.EQConverter.DateTimeToString(DateTime.FromOADate((double)tradeinfo[7]));
                }

                // set it temporarily to ""
                if (ExcelUtil.isNull(tradeinfo[8]))
                {
                    genswap.SettlementDate = string.Empty;
                }
                else
                {
                    genswap.SettlementDate = EliteQuant.EQConverter.DateTimeToString(DateTime.FromOADate((double)tradeinfo[8]));
                }

                // set it temporarily to today
                if (ExcelUtil.isNull(tradeinfo[9]))
                {
                    genswap.MaturityDate = string.Empty;
                }
                else
                {
                    genswap.MaturityDate = EliteQuant.EQConverter.DateTimeToString(DateTime.FromOADate((double)tradeinfo[9]));
                }

                // set it temporarily to blank
                if (ExcelUtil.isNull(tradeinfo[10]))
                {
                    genswap.Tenor = string.Empty;
                }
                else
                {
                    genswap.Tenor = (string)tradeinfo[10];
                }

                if (ExcelUtil.isNull(tradeinfo[11]))
                {
                    genswap.IsScheduleGiven = false;
                }
                else
                {
                    //genswap.IsScheduleGiven = Convert.ToBoolean((string)tradeinfo[11]);
                    genswap.IsScheduleGiven = (bool)tradeinfo[11];
                }
                genswap.IsScheduleGiven = false;        // set to false always, amortization currently not supported

                //***************  First Leg *************************//
                if (ExcelUtil.isNull(firstleginfo[0]))
                {
                    genswap.FirstLegIndex = "FIXED";
                }
                else
                {
                    genswap.FirstLegIndex = (string)firstleginfo[0];
                }

                if (ExcelUtil.isNull(firstleginfo[1]))
                {
                    genswap.FirstLegFrequency = "SEMIANNUAL";
                }
                else
                {
                    genswap.FirstLegFrequency = (string)firstleginfo[1];
                }

                if (ExcelUtil.isNull(firstleginfo[2]))
                {
                    genswap.FirstLegConvention = "MODIFIEDFOLLOWING";
                }
                else
                {
                    genswap.FirstLegConvention = (string)firstleginfo[2];
                }

                if (ExcelUtil.isNull(firstleginfo[3]))
                {
                    genswap.FirstLegCalendar = "NYC|LON";
                }
                else
                {
                    genswap.FirstLegCalendar = (string)firstleginfo[3];
                }

                if (ExcelUtil.isNull(firstleginfo[4]))
                {
                    genswap.FirstLegDayCounter = "ACTUAL360";
                }
                else
                {
                    genswap.FirstLegDayCounter = (string)firstleginfo[4];
                }

                if (ExcelUtil.isNull(firstleginfo[5]))
                {
                    genswap.FirstLegDateGenerationRule = "BACKWARD";
                }
                else
                {
                    genswap.FirstLegDateGenerationRule = (string)firstleginfo[5];
                }

                if (ExcelUtil.isNull(firstleginfo[6]))
                {
                    genswap.FirstLegEOM = true;
                }
                else
                {
                    genswap.FirstLegEOM = (bool)firstleginfo[6];
                }

                if (ExcelUtil.isNull(firstleginfo[7]))
                {
                    genswap.FirstLegSpread = 0.0;
                }
                else
                {
                    genswap.FirstLegSpread = (double)firstleginfo[7];
                }

                if (ExcelUtil.isNull(firstlegnotionals))
                {
                    genswap.FirstLegNotionals.Clear();
                    genswap.FirstLegNotionals.Add(0);       // size = 1
                }
                else
                {
                    genswap.FirstLegNotionals.Clear();
                    foreach (var nl in firstlegnotionals)
                    {
                        if (ExcelUtil.isNull(nl))
                        {
                            continue;
                        }

                        genswap.FirstLegNotionals.Add((double)nl);
                    }
                }

                if (ExcelUtil.isNull(firstlegschedule) || (!genswap.IsScheduleGiven))
                {
                    genswap.FirstLegSchedules.Clear();
                    genswap.FirstLegSchedules.Add(genswap.SettlementDate);
                    genswap.FirstLegSchedules.Add(genswap.MaturityDate);
                }
                else
                {
                    genswap.FirstLegSchedules.Clear();
                    for (int a = 0; a < firstlegschedule.GetLength(0); a++)
                    {
                        DateTime d;
                        if (ExcelUtil.isNull(firstlegschedule[a, 0]))
                        {
                            // add one more date
                            d = DateTime.FromOADate((double)firstlegschedule[a - 1, 1]);
                            genswap.FirstLegSchedules.Add(EliteQuant.EQConverter.DateTimeToString(d));
                            break;
                        }


                        d = DateTime.FromOADate((double)firstlegschedule[a, 0]);
                        genswap.FirstLegSchedules.Add(EliteQuant.EQConverter.DateTimeToString(d));
                    }
                }

                //***************  Second Leg *************************//

                if (ExcelUtil.isNull(secondleginfo[0]))
                {
                    genswap.SecondLegIndex = "USDLIB3M";
                }
                else
                {
                    genswap.SecondLegIndex = (string)secondleginfo[0];
                }

                if (ExcelUtil.isNull(secondleginfo[1]))
                {
                    genswap.SecondLegFrequency = "QUARTERLY";
                }
                else
                {
                    genswap.SecondLegFrequency = (string)secondleginfo[1];
                }

                if (ExcelUtil.isNull(secondleginfo[2]))
                {
                    genswap.SecondLegConvention = "MODIFIEDFOLLOWING";
                }
                else
                {
                    genswap.SecondLegConvention = (string)secondleginfo[2];
                }

                if (ExcelUtil.isNull(secondleginfo[3]))
                {
                    genswap.SecondLegCalendar = "NYC|LON";           // nor NYC|LON
                }
                else
                {
                    genswap.SecondLegCalendar = (string)secondleginfo[3];
                }

                if (ExcelUtil.isNull(secondleginfo[4]))
                {
                    genswap.SecondLegDayCounter = "ACTUAL360";
                }
                else
                {
                    genswap.SecondLegDayCounter = (string)secondleginfo[4];
                }

                if (ExcelUtil.isNull(secondleginfo[5]))
                {
                    genswap.SecondLegDateGenerationRule = "BACKWARD";
                }
                else
                {
                    genswap.SecondLegDateGenerationRule = (string)secondleginfo[5];
                }

                if (ExcelUtil.isNull(secondleginfo[6]))
                {
                    genswap.SecondLegEOM = true;
                }
                else
                {
                    genswap.SecondLegEOM = (bool)secondleginfo[6];
                }

                if (ExcelUtil.isNull(secondleginfo[7]))
                {
                    genswap.SecondLegSpread = 0.0;
                }
                else
                {
                    genswap.SecondLegSpread = (double)secondleginfo[7];
                }

                if (ExcelUtil.isNull(secondlegnotionals))
                {
                    genswap.SecondLegNotionals.Clear();
                    genswap.SecondLegNotionals.Add(0);
                }
                else
                {
                    genswap.SecondLegNotionals.Clear();
                    foreach (var nl in secondlegnotionals)
                    {
                        if (ExcelUtil.isNull(nl))
                        {
                            continue;
                        }

                        genswap.SecondLegNotionals.Add((double)nl);
                    }
                }

                if (ExcelUtil.isNull(secondlegschedule) || (!genswap.IsScheduleGiven))
                {
                    genswap.SecondLegSchedules.Clear();
                    genswap.SecondLegSchedules.Add(genswap.SettlementDate);
                    genswap.SecondLegSchedules.Add(genswap.MaturityDate);
                }
                else
                {
                    genswap.SecondLegSchedules.Clear();
                    for (int a = 0; a < secondlegschedule.GetLength(0); a++)
                    {
                        DateTime d;
                        if (ExcelUtil.isNull(secondlegschedule[a, 0]))
                        {
                            // add one more date
                            d = DateTime.FromOADate((double)secondlegschedule[a - 1, 1]);
                            genswap.SecondLegSchedules.Add(EliteQuant.EQConverter.DateTimeToString(d));
                            break;
                        }


                        d = DateTime.FromOADate((double)secondlegschedule[a, 0]);
                        genswap.SecondLegSchedules.Add(EliteQuant.EQConverter.DateTimeToString(d));
                    }
                }

                #endregion

                #region convert Interest rate generic swap to swap obj
                string firstidx = genswap.FirstLegIndex, secondidx = genswap.SecondLegIndex;
                string firstidx_id  = "IDX@" + firstidx;
                string secondidx_id = "IDX@" + secondidx;
                EliteQuant.IborIndex firstidx_obj = null;
                if (!firstidx.Contains("FIXED"))
                {
                    firstidx_obj = OHRepository.Instance.getObject <EliteQuant.IborIndex>(firstidx_id);
                }

                EliteQuant.IborIndex secondidx_obj = OHRepository.Instance.getObject <EliteQuant.IborIndex>(secondidx_id);

                genswap.ConstructSwap(firstidx_obj, secondidx_obj);

                if (!discountId.Contains('@'))
                {
                    discountId = "CRV@" + discountId;
                }
                YieldTermStructure       discountcurve = OHRepository.Instance.getObject <YieldTermStructure>(discountId);
                YieldTermStructureHandle dch           = new YieldTermStructureHandle(discountcurve);

                DiscountingSwapEngine engine = new DiscountingSwapEngine(dch);
                genswap.eqswap_.setPricingEngine(engine);
                #endregion

                string id = "SWP@" + genswap.ContractId;
                OHRepository.Instance.storeObject(id, genswap, callerAddress);
                id += "#" + (String)DateTime.Now.ToString(@"HH:mm:ss");
                return(id);
            }
            catch (Exception e)
            {
                ExcelUtil.logError(callerAddress, System.Reflection.MethodInfo.GetCurrentMethod().Name.ToString(), e.Message);
                return("#EQ_ERR!");
            }
        }