Beispiel #1
0
        public void testATMRate()
        {
            CommonVars vars = new CommonVars();

            int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 };

            Date startDate = vars.termStructure.link.referenceDate();

            for (int i = 0; i < lengths.Length; i++) {
                List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]);
                Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention);
                Schedule schedule = new Schedule(startDate, maturity,
                                                 new Period(vars.frequency), vars.calendar,
                                                 vars.convention, vars.convention,
                                                 DateGeneration.Rule.Forward, false);

                for (int j = 0; j < strikes.Length; j++) {
                    for (int k = 0; k < vols.Length; k++) {

                        CapFloor cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]);
                        CapFloor floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]);
                        double capATMRate = cap.atmRate(vars.termStructure);
                        double floorATMRate = floor.atmRate(vars.termStructure);

                        if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10))
                            Assert.Fail(
                              "Cap ATM Rate and floor ATM Rate should be equal :\n"
                              + "   length:        " + lengths[i] + " years\n"
                              + "   volatility:    " + vols[k] + "\n"
                              + "   strike:        " + strikes[j] + "\n"
                              + "   cap ATM rate:  " + capATMRate + "\n"
                              + "   floor ATM rate:" + floorATMRate + "\n"
                              + "   relative Error:"
                              + Utilities.relativeError(capATMRate, floorATMRate, capATMRate) * 100 + "%");
                        VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0],
                                                           schedule, floorATMRate,
                                                           vars.index.dayCounter(),
                                                           schedule, vars.index, 0.0,
                                                           vars.index.dayCounter());
                        swap.setPricingEngine((IPricingEngine)(
                                               new DiscountingSwapEngine(vars.termStructure)));
                        double swapNPV = swap.NPV();
                        if (!checkAbsError(swapNPV, 0, 1.0e-10))
                            Assert.Fail(
                              "the NPV of a Swap struck at ATM rate "
                              + "should be equal to 0:\n"
                              + "   length:        " + lengths[i] + " years\n"
                              + "   volatility:    " + vols[k] + "\n"
                              + "   ATM rate:      " + floorATMRate + "\n"
                              + "   swap NPV:      " + swapNPV);

                    }
                }
            }
        }
Beispiel #2
0
        public void testVega()
        {
            CommonVars vars = new CommonVars();

            int[]          lengths = { 1, 2, 3, 4, 5, 6, 7, 10, 15, 20, 30 };
            double[]       vols    = { 0.01, 0.05, 0.10, 0.15, 0.20 };
            double[]       strikes = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09 };
            CapFloorType[] types   = { CapFloorType.Cap, CapFloorType.Floor };

            Date   startDate = vars.termStructure.link.referenceDate();
            double shift     = 1e-8;
            double tolerance = 0.005;

            for (int i = 0; i < lengths.Length; i++)
            {
                for (int j = 0; j < vols.Length; j++)
                {
                    for (int k = 0; k < strikes.Length; k++)
                    {
                        for (int h = 0; h < types.Length; h++)
                        {
                            List <CashFlow> leg              = vars.makeLeg(startDate, lengths[i]);
                            CapFloor        capFloor         = vars.makeCapFloor(types[h], leg, strikes[k], vols[j]);
                            CapFloor        shiftedCapFloor2 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] + shift);
                            CapFloor        shiftedCapFloor1 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] - shift);

                            double value1 = shiftedCapFloor1.NPV();
                            double value2 = shiftedCapFloor2.NPV();

                            double numericalVega = (value2 - value1) / (2 * shift);


                            if (numericalVega > 1.0e-4)
                            {
                                double analyticalVega = (double)capFloor.result("vega");
                                double discrepancy    = Math.Abs(numericalVega - analyticalVega);
                                discrepancy /= numericalVega;
                                if (discrepancy > tolerance)
                                {
                                    QAssert.Fail(
                                        "failed to compute cap/floor vega:" +
                                        "\n   lengths:     " + new Period(lengths[j], TimeUnit.Years) +
                                        "\n   strike:      " + strikes[k] +
                                        "\n   types:       " + types[h] +
                                        "\n   calculated:  " + analyticalVega +
                                        "\n   expected:    " + numericalVega +
                                        "\n   discrepancy: " + discrepancy +
                                        "\n   tolerance:   " + tolerance);
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #3
0
        public void testParity()
        {
            CommonVars vars = new CommonVars();

            int[]    lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols    = { 0.01, 0.05, 0.10, 0.15, 0.20 };

            Date startDate = vars.termStructure.link.referenceDate();

            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.makeLeg(startDate, lengths[i]);
                        Instrument      cap      = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]);
                        Instrument      floor    = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]);
                        Date            maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention);
                        Schedule        schedule = new Schedule(startDate, maturity,
                                                                new Period(vars.frequency), vars.calendar,
                                                                vars.convention, vars.convention,
                                                                DateGeneration.Rule.Forward, false);
                        VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0],
                                                           schedule, strikes[j], vars.index.dayCounter(),
                                                           schedule, vars.index, 0.0,
                                                           vars.index.dayCounter());
                        swap.setPricingEngine((IPricingEngine) new DiscountingSwapEngine(vars.termStructure));
                        // FLOATING_POINT_EXCEPTION
                        if (Math.Abs((cap.NPV() - floor.NPV()) - swap.NPV()) > 1.0e-10)
                        {
                            QAssert.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());
                        }
                    }
                }
            }
        }
Beispiel #4
0
        public void testConsistency()
        {
            CommonVars vars = new CommonVars();

            int[]    lengths     = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] cap_rates   = { 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] floor_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols        = { 0.01, 0.05, 0.10, 0.15, 0.20 };

            Date startDate = vars.termStructure.link.referenceDate();

            for (int i = 0; i < lengths.Length; i++)
            {
                for (int j = 0; j < cap_rates.Length; j++)
                {
                    for (int k = 0; k < floor_rates.Length; k++)
                    {
                        for (int l = 0; l < vols.Length; l++)
                        {
                            List <CashFlow> leg = vars.makeLeg(startDate, lengths[i]);
                            Instrument      cap = vars.makeCapFloor(CapFloorType.Cap, leg,
                                                                    cap_rates[j], vols[l]);
                            Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg,
                                                                 floor_rates[k], vols[l]);
                            Collar collar = new Collar(leg, new InitializedList <double>(1, cap_rates[j]),
                                                       new InitializedList <double>(1, floor_rates[k]));
                            collar.setPricingEngine(vars.makeEngine(vols[l]));

                            if (Math.Abs((cap.NPV() - floor.NPV()) - collar.NPV()) > 1e-10)
                            {
                                QAssert.Fail(
                                    "inconsistency between cap, floor and collar:\n"
                                    + "    length:       " + lengths[i] + " years\n"
                                    + "    volatility:   " + vols[l] + "\n"
                                    + "    cap value:    " + cap.NPV()
                                    + " at strike: " + cap_rates[j] + "\n"
                                    + "    floor value:  " + floor.NPV()
                                    + " at strike: " + floor_rates[k] + "\n"
                                    + "    collar value: " + collar.NPV());
                            }
                        }
                    }
                }
            }
        }
Beispiel #5
0
        public void testCachedValue()
        {
            CommonVars vars = new CommonVars();

            Date cachedToday      = new Date(14, Month.March, 2002),
                 cachedSettlement = new Date(18, Month.March, 2002);

            Settings.setEvaluationDate(cachedToday);
            vars.termStructure.linkTo(Utilities.flatRate(cachedSettlement, 0.05, new Actual360()));
            Date            startDate = vars.termStructure.link.referenceDate();
            List <CashFlow> leg       = vars.makeLeg(startDate, 20);
            Instrument      cap       = vars.makeCapFloor(CapFloorType.Cap, leg, 0.07, 0.20);
            Instrument      floor     = vars.makeCapFloor(CapFloorType.Floor, leg, 0.03, 0.20);

            // par coupon price
            double cachedCapNPV   = 6.87570026732,
                   cachedFloorNPV = 2.65812927959;

            // index fixing price
            //Real cachedCapNPV   = 6.87630307745,
            //   cachedFloorNPV = 2.65796764715;

            // test Black cap price against cached value
            if (Math.Abs(cap.NPV() - cachedCapNPV) > 1.0e-11)
            {
                QAssert.Fail("failed to reproduce cached cap value:\n"
                             + "    calculated: " + cap.NPV() + "\n"
                             + "    expected:   " + cachedCapNPV);
            }

            // test Black floor price against cached value
            if (Math.Abs(floor.NPV() - cachedFloorNPV) > 1.0e-11)
            {
                QAssert.Fail("failed to reproduce cached floor value:\n"
                             + "    calculated: " + floor.NPV() + "\n"
                             + "    expected:   " + cachedFloorNPV);
            }
        }
Beispiel #6
0
        public void testImpliedVolatility()
        {
            CommonVars vars = new CommonVars();

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

            CapFloorType[] types   = { CapFloorType.Cap, CapFloorType.Floor };
            double[]       strikes = { 0.02, 0.03, 0.04 };
            int[]          lengths = { 1, 5, 10 };

            // test data
            double[] rRates = { 0.02, 0.03, 0.04 };
            double[] vols   = { 0.01, 0.20, 0.30, 0.70, 0.90 };

            for (int k = 0; k < lengths.Length; k++)
            {
                List <CashFlow> leg = vars.makeLeg(vars.settlement, lengths[k]);

                for (int i = 0; i < types.Length; i++)
                {
                    for (int j = 0; j < strikes.Length; j++)
                    {
                        CapFloor capfloor = vars.makeCapFloor(types[i], leg, strikes[j], 0.0);

                        for (int n = 0; n < rRates.Length; n++)
                        {
                            for (int m = 0; m < vols.Length; m++)
                            {
                                double r = rRates[n];
                                double v = vols[m];
                                vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, r, new Actual360()));
                                capfloor.setPricingEngine(vars.makeEngine(v));

                                double value   = capfloor.NPV();
                                double implVol = 0.0;

                                try {
                                    implVol = capfloor.impliedVolatility(value,
                                                                         vars.termStructure,
                                                                         0.10,
                                                                         tolerance,
                                                                         maxEvaluations);
                                } catch (Exception e) {
                                    // couldn't bracket?
                                    capfloor.setPricingEngine(vars.makeEngine(0.0));
                                    double value2 = capfloor.NPV();
                                    if (Math.Abs(value - value2) < tolerance)
                                    {
                                        // ok, just skip:
                                        continue;
                                    }

                                    // otherwise, report error
                                    QAssert.Fail("implied vol failure: " + typeToString(types[i]) +
                                                 "  strike:     " + strikes[j] +
                                                 "  risk-free:  " + r +
                                                 "  length:     " + lengths[k] + "Y" +
                                                 "  volatility: " + v + e.Message);
                                }
                                if (Math.Abs(implVol - v) > tolerance)
                                {
                                    // the difference might not matter
                                    capfloor.setPricingEngine(vars.makeEngine(implVol));
                                    double value2 = capfloor.NPV();
                                    if (Math.Abs(value - value2) > tolerance)
                                    {
                                        QAssert.Fail(
                                            typeToString(types[i]) + ":"
                                            + "    strike:           "
                                            + strikes[j] + "\n"
                                            + "    risk-free rate:   "
                                            + r + "\n"
                                            + "    length:         "
                                            + lengths[k] + " years\n\n"
                                            + "    original volatility: "
                                            + v + "\n"
                                            + "    price:               "
                                            + value + "\n"
                                            + "    implied volatility:  "
                                            + implVol + "\n"
                                            + "    corresponding price: " + value2);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #7
0
        public void testATMRate()
        {
            CommonVars vars = new CommonVars();

            int[]    lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols    = { 0.01, 0.05, 0.10, 0.15, 0.20 };

            Date startDate = vars.termStructure.link.referenceDate();

            for (int i = 0; i < lengths.Length; i++)
            {
                List <CashFlow> leg      = vars.makeLeg(startDate, lengths[i]);
                Date            maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention);
                Schedule        schedule = new Schedule(startDate, maturity,
                                                        new Period(vars.frequency), vars.calendar,
                                                        vars.convention, vars.convention,
                                                        DateGeneration.Rule.Forward, false);

                for (int j = 0; j < strikes.Length; j++)
                {
                    for (int k = 0; k < vols.Length; k++)
                    {
                        CapFloor cap          = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]);
                        CapFloor floor        = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]);
                        double   capATMRate   = cap.atmRate(vars.termStructure);
                        double   floorATMRate = floor.atmRate(vars.termStructure);

                        if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10))
                        {
                            QAssert.Fail(
                                "Cap ATM Rate and floor ATM Rate should be equal :\n"
                                + "   length:        " + lengths[i] + " years\n"
                                + "   volatility:    " + vols[k] + "\n"
                                + "   strike:        " + strikes[j] + "\n"
                                + "   cap ATM rate:  " + capATMRate + "\n"
                                + "   floor ATM rate:" + floorATMRate + "\n"
                                + "   relative Error:"
                                + Utilities.relativeError(capATMRate, floorATMRate, capATMRate) * 100 + "%");
                        }
                        VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0],
                                                           schedule, floorATMRate,
                                                           vars.index.dayCounter(),
                                                           schedule, vars.index, 0.0,
                                                           vars.index.dayCounter());
                        swap.setPricingEngine((IPricingEngine)(
                                                  new DiscountingSwapEngine(vars.termStructure)));
                        double swapNPV = swap.NPV();
                        if (!checkAbsError(swapNPV, 0, 1.0e-10))
                        {
                            QAssert.Fail(
                                "the NPV of a Swap struck at ATM rate "
                                + "should be equal to 0:\n"
                                + "   length:        " + lengths[i] + " years\n"
                                + "   volatility:    " + vols[k] + "\n"
                                + "   ATM rate:      " + floorATMRate + "\n"
                                + "   swap NPV:      " + swapNPV);
                        }
                    }
                }
            }
        }
Beispiel #8
0
        public void testStrikeDependency()
        {
            CommonVars vars = new CommonVars();

            int[]    lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] vols    = { 0.01, 0.05, 0.10, 0.15, 0.20 };
            double[] strikes = { 0.03, 0.04, 0.05, 0.06, 0.07 };

            Date startDate = vars.termStructure.link.referenceDate();

            for (int i = 0; i < lengths.Length; i++)
            {
                for (int j = 0; j < vols.Length; j++)
                {
                    // store the results for different strikes...
                    List <double> cap_values = new List <double>(), floor_values = new List <double>();

                    for (int k = 0; k < strikes.Length; k++)
                    {
                        List <CashFlow> leg = vars.makeLeg(startDate, lengths[i]);
                        Instrument      cap = vars.makeCapFloor(CapFloorType.Cap, leg,
                                                                strikes[k], vols[j]);
                        cap_values.Add(cap.NPV());
                        Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg,
                                                             strikes[k], vols[j]);
                        floor_values.Add(floor.NPV());
                    }
                    // and check that they go the right way
                    for (int k = 0; k < cap_values.Count - 1; k++)
                    {
                        if (cap_values[k] < cap_values[k + 1])
                        {
                            QAssert.Fail(
                                "NPV is increasing with the strike in a cap: \n"
                                + "    length:     " + lengths[i] + " years\n"
                                + "    volatility: " + vols[j] + "\n"
                                + "    value:      " + cap_values[k]
                                + " at strike: " + strikes[k] + "\n"
                                + "    value:      " + cap_values[k + 1]
                                + " at strike: " + strikes[k + 1]);
                        }
                    }

                    // same for floors
                    for (int k = 0; k < floor_values.Count - 1; k++)
                    {
                        if (floor_values[k] > floor_values[k + 1])
                        {
                            QAssert.Fail(
                                "NPV is decreasing with the strike in a floor: \n"
                                + "    length:     " + lengths[i] + " years\n"
                                + "    volatility: " + vols[j] + "\n"
                                + "    value:      " + floor_values[k]
                                + " at strike: " + strikes[k] + "\n"
                                + "    value:      " + floor_values[k + 1]
                                + " at strike: " + strikes[k + 1]);
                        }
                    }
                }
            }
        }
Beispiel #9
0
        public void testVega()
        {
            CommonVars vars = new CommonVars();

            int[] lengths = { 1, 2, 3, 4, 5, 6, 7, 10, 15, 20, 30 };
            double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 };
            double[] strikes = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09 };
            CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor };

            Date startDate = vars.termStructure.link.referenceDate();
            double shift = 1e-8;
            double tolerance = 0.005;

            for (int i = 0; i < lengths.Length; i++) {
                for (int j = 0; j < vols.Length; j++) {
                    for (int k = 0; k < strikes.Length; k++) {
                        for (int h = 0; h < types.Length; h++) {
                            List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]);
                            CapFloor capFloor = vars.makeCapFloor(types[h], leg, strikes[k], vols[j]);
                            CapFloor shiftedCapFloor2 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] + shift);
                            CapFloor shiftedCapFloor1 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] - shift);

                            double value1 = shiftedCapFloor1.NPV();
                            double value2 = shiftedCapFloor2.NPV();

                            double numericalVega = (value2 - value1) / (2 * shift);

                            if (numericalVega > 1.0e-4) {
                                double analyticalVega = (double)capFloor.result("vega");
                                double discrepancy = Math.Abs(numericalVega - analyticalVega);
                                discrepancy /= numericalVega;
                                if (discrepancy > tolerance)
                                    Assert.Fail(
                                        "failed to compute cap/floor vega:" +
                                        "\n   lengths:     " + new Period(lengths[j], TimeUnit.Years) +
                                        "\n   strike:      " + strikes[k] +
                                        "\n   types:       " + types[h] +
                                        "\n   calculated:  " + analyticalVega +
                                        "\n   expected:    " + numericalVega +
                                        "\n   discrepancy: " + discrepancy +
                                        "\n   tolerance:   " + tolerance);

                            }
                        }
                    }
                }
            }
        }
Beispiel #10
0
        public void testStrikeDependency()
        {
            CommonVars vars = new CommonVars();

            int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 };
            double[] strikes = { 0.03, 0.04, 0.05, 0.06, 0.07 };

            Date startDate = vars.termStructure.link.referenceDate();

            for (int i = 0; i < lengths.Length; i++) {
                for (int j = 0; j < vols.Length; j++) {
                    // store the results for different strikes...
                    List<double> cap_values = new List<double>(), floor_values = new List<double>();

                    for (int k = 0; k < strikes.Length; k++) {
                        List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]);
                        Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg,
                                              strikes[k], vols[j]);
                        cap_values.Add(cap.NPV());
                        Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg,
                                              strikes[k], vols[j]);
                        floor_values.Add(floor.NPV());
                    }
                    // and check that they go the right way
                    for (int k = 0; k < cap_values.Count - 1; k++) {
                        if (cap_values[k] < cap_values[k + 1])
                            Assert.Fail(
                              "NPV is increasing with the strike in a cap: \n"
                              + "    length:     " + lengths[i] + " years\n"
                              + "    volatility: " + vols[j] + "\n"
                              + "    value:      " + cap_values[k]
                              + " at strike: " + strikes[k] + "\n"
                              + "    value:      " + cap_values[k + 1]
                              + " at strike: " + strikes[k + 1]);
                    }

                    // same for floors
                    for (int k = 0; k < floor_values.Count - 1; k++) {
                        if (floor_values[k] > floor_values[k + 1])
                            Assert.Fail(
                              "NPV is decreasing with the strike in a floor: \n"
                              + "    length:     " + lengths[i] + " years\n"
                              + "    volatility: " + vols[j] + "\n"
                              + "    value:      " + floor_values[k]
                              + " at strike: " + strikes[k] + "\n"
                              + "    value:      " + floor_values[k + 1]
                              + " at strike: " + strikes[k + 1]);
                    }
                }
            }
        }
Beispiel #11
0
        public void testParity()
        {
            CommonVars vars = new CommonVars();

            int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 };

            Date startDate = vars.termStructure.link.referenceDate();

            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.makeLeg(startDate, lengths[i]);
                        Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]);
                        Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]);
                        Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention);
                        Schedule schedule = new Schedule(startDate, maturity,
                                                         new Period(vars.frequency), vars.calendar,
                                                         vars.convention, vars.convention,
                                                         DateGeneration.Rule.Forward, false);
                        VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0],
                                                           schedule, strikes[j], vars.index.dayCounter(),
                                                           schedule, vars.index, 0.0,
                                                           vars.index.dayCounter());
                        swap.setPricingEngine((IPricingEngine)new DiscountingSwapEngine(vars.termStructure));
                        // FLOATING_POINT_EXCEPTION
                        if (Math.Abs((cap.NPV() - floor.NPV()) - swap.NPV()) > 1.0e-10) {
                            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());
                        }
                    }
                }
            }
        }
Beispiel #12
0
        public void testImpliedVolatility()
        {
            CommonVars vars = new CommonVars();

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

            CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor };
            double[] strikes = { 0.02, 0.03, 0.04 };
            int[] lengths = { 1, 5, 10 };

            // test data
            double[] rRates = { 0.02, 0.03, 0.04 };
            double[] vols = { 0.01, 0.20, 0.30, 0.70, 0.90 };

            for (int k = 0; k < lengths.Length; k++) {
                List<CashFlow> leg = vars.makeLeg(vars.settlement, lengths[k]);

                for (int i = 0; i < types.Length; i++) {
                    for (int j = 0; j < strikes.Length; j++) {
                        CapFloor capfloor = vars.makeCapFloor(types[i], leg, strikes[j], 0.0);

                        for (int n = 0; n < rRates.Length; n++) {
                            for (int m = 0; m < vols.Length; m++) {
                                double r = rRates[n];
                                double v = vols[m];
                                vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, r, new Actual360()));
                                capfloor.setPricingEngine(vars.makeEngine(v));

                                double value = capfloor.NPV();
                                double implVol = 0.0;

                                try {
                                    implVol = capfloor.impliedVolatility(value,
                                                                         vars.termStructure,
                                                                         0.10,
                                                                         tolerance,
                                                                         maxEvaluations);
                                } catch (Exception e) {
                                    // couldn't bracket?
                                    capfloor.setPricingEngine(vars.makeEngine(0.0));
                                    double value2 = capfloor.NPV();
                                    if (Math.Abs(value - value2) < tolerance) {
                                        // ok, just skip:
                                        continue;
                                    }

                                    // otherwise, report error
                                    Assert.Fail("implied vol failure: " + typeToString(types[i]) +
                                        "  strike:     " + strikes[j] +
                                        "  risk-free:  " + r +
                                        "  length:     " + lengths[k] + "Y" +
                                        "  volatility: " + v + e.Message);
                                }
                                if (Math.Abs(implVol - v) > tolerance) {
                                    // the difference might not matter
                                    capfloor.setPricingEngine(vars.makeEngine(implVol));
                                    double value2 = capfloor.NPV();
                                    if (Math.Abs(value - value2) > tolerance) {
                                        Assert.Fail(
                                            typeToString(types[i]) + ":"
                                            + "    strike:           "
                                            + strikes[j] + "\n"
                                            + "    risk-free rate:   "
                                            + r + "\n"
                                            + "    length:         "
                                            + lengths[k] + " years\n\n"
                                            + "    original volatility: "
                                            + v + "\n"
                                            + "    price:               "
                                            + value + "\n"
                                            + "    implied volatility:  "
                                            + implVol + "\n"
                                            + "    corresponding price: " + value2);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #13
0
        public void testConsistency()
        {
            CommonVars vars = new CommonVars();

            int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] cap_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] floor_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 };

            Date startDate = vars.termStructure.link.referenceDate();

            for (int i = 0; i < lengths.Length; i++) {
                for (int j = 0; j < cap_rates.Length; j++) {
                    for (int k = 0; k < floor_rates.Length; k++) {
                        for (int l = 0; l < vols.Length; l++) {

                            List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]);
                            Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg,
                                                  cap_rates[j], vols[l]);
                            Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg,
                                                  floor_rates[k], vols[l]);
                            Collar collar = new Collar(leg, new InitializedList<double>(1, cap_rates[j]),
                                          new InitializedList<double>(1, floor_rates[k]));
                            collar.setPricingEngine(vars.makeEngine(vols[l]));

                            if (Math.Abs((cap.NPV() - floor.NPV()) - collar.NPV()) > 1e-10) {
                                Assert.Fail(
                                  "inconsistency between cap, floor and collar:\n"
                                  + "    length:       " + lengths[i] + " years\n"
                                  + "    volatility:   " + vols[l] + "\n"
                                  + "    cap value:    " + cap.NPV()
                                  + " at strike: " + cap_rates[j] + "\n"
                                  + "    floor value:  " + floor.NPV()
                                  + " at strike: " + floor_rates[k] + "\n"
                                  + "    collar value: " + collar.NPV());
                            }
                        }
                    }
                }
            }
        }
Beispiel #14
0
        public void testCachedValue()
        {
            CommonVars vars = new CommonVars();

            Date cachedToday = new Date(14, Month.March, 2002),
                 cachedSettlement = new Date(18, Month.March, 2002);
            Settings.setEvaluationDate(cachedToday);
            vars.termStructure.linkTo(Utilities.flatRate(cachedSettlement, 0.05, new Actual360()));
            Date startDate = vars.termStructure.link.referenceDate();
            List<CashFlow> leg = vars.makeLeg(startDate, 20);
            Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, 0.07, 0.20);
            Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, 0.03, 0.20);

            // par coupon price
            double cachedCapNPV = 6.87570026732,
                   cachedFloorNPV = 2.65812927959;

            // index fixing price
            //Real cachedCapNPV   = 6.87630307745,
            //   cachedFloorNPV = 2.65796764715;

            // test Black cap price against cached value
            if (Math.Abs(cap.NPV() - cachedCapNPV) > 1.0e-11)
                Assert.Fail("failed to reproduce cached cap value:\n"
                            + "    calculated: " + cap.NPV() + "\n"
                            + "    expected:   " + cachedCapNPV);

            // test Black floor price against cached value
            if (Math.Abs(floor.NPV() - cachedFloorNPV) > 1.0e-11)
                Assert.Fail("failed to reproduce cached floor value:\n"
                            + "    calculated: " + floor.NPV() + "\n"
                            + "    expected:   " + cachedFloorNPV);
        }