示例#1
0
        public void testDeltaValues()
        {
            // Testing delta calculator values

            DeltaData[] values =
            {
                // Values taken from parallel implementation in R
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Spot,     1.421,  0.997306,  0.992266,  0.1180654, 1.608080,    0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaSpot,   1.421,  0.997306,  0.992266,  0.1180654, 1.600545,    0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Fwd,      1.421,  0.997306,  0.992266,  0.1180654, 1.609029,    0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaFwd,    1.421,  0.997306,  0.992266,  0.1180654, 1.601550,    0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Spot,   122.121, 0.9695434, 0.9872347,  0.0887676, 119.8031,    0.67),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaSpot, 122.121, 0.9695434, 0.9872347,  0.0887676, 117.7096,    0.67),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Fwd,    122.121, 0.9695434, 0.9872347,  0.0887676, 120.0592,    0.67),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaFwd,  122.121, 0.9695434, 0.9872347,  0.0887676, 118.0532,    0.67),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.Spot,    3.4582,   0.99979, 0.9250616,  0.3199034, 4.964924,  -0.821),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.PaSpot,  3.4582,   0.99979, 0.9250616,  0.3199034, 3.778327,  -0.821),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.Fwd,     3.4582,   0.99979, 0.9250616,  0.3199034,  4.51896,  -0.821),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.PaFwd,   3.4582,   0.99979, 0.9250616,  0.3199034,  3.65728, -0.8219),
                // JPYUSD Data taken from Castagnas "FX Options and Smile Risk" (Wiley 2009)
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.Spot,    103.00,   0.99482,   0.98508, 0.07247845,    97.47,   -0.25),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.PaSpot,  103.00,   0.99482,   0.98508, 0.07247845,    97.22, -0.25)
            };

            Option.Type             currOt;
            DeltaVolQuote.DeltaType currDt;
            double currSpot;
            double currdDf;
            double currfDf;
            double currStdDev;
            double currStrike;
            double expected;
            double currDelta;
            double calculated;
            double error;
            double tolerance;

            for (int i = 0; i < values.Length; i++)
            {
                currOt     = values[i].ot;
                currDt     = values[i].dt;
                currSpot   = values[i].spot;
                currdDf    = values[i].dDf;
                currfDf    = values[i].fDf;
                currStdDev = values[i].stdDev;
                currStrike = values[i].strike;
                currDelta  = values[i].value;

                BlackDeltaCalculator myCalc = new BlackDeltaCalculator(currOt, currDt, currSpot, currdDf, currfDf, currStdDev);

                tolerance = 1.0e-3;

                expected   = currDelta;
                calculated = myCalc.deltaFromStrike(currStrike);
                error      = Math.Abs(calculated - expected);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Delta-from-strike calculation failed for delta. \n"
                                 + "Iteration: " + i + "\n"
                                 + "Calculated Strike:" + calculated + "\n"
                                 + "Expected   Strike:" + expected + "\n"
                                 + "Error: " + error);
                }

                tolerance = 1.0e-2;
                // tolerance not that small, but sufficient for strikes in
                // particular since they might be results of a numerical
                // procedure

                expected   = currStrike;
                calculated = myCalc.strikeFromDelta(currDelta);
                error      = Math.Abs(calculated - expected);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Strike-from-delta calculation failed for delta. \n"
                                 + "Iteration: " + i + "\n"
                                 + "Calculated Strike:" + calculated + "\n"
                                 + "Expected   Strike:" + expected + "\n"
                                 + "Error: " + error);
                }
            }
        }
示例#2
0
        public void testAtmCalcs()
        {
            // Testing delta-neutral ATM quotations
            SavedSettings backup = new SavedSettings();

            DeltaData[] values =
            {
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Spot,     1.421,  0.997306,  0.992266,  0.1180654, 1.608080,   0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaSpot,   1.421,  0.997306,  0.992266,  0.1180654, 1.600545,   0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Fwd,      1.421,  0.997306,  0.992266,  0.1180654, 1.609029,   0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaFwd,    1.421,  0.997306,  0.992266,  0.1180654, 1.601550,   0.15),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Spot,   122.121, 0.9695434, 0.9872347,  0.0887676, 119.8031,   0.67),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaSpot, 122.121, 0.9695434, 0.9872347,  0.0887676, 117.7096,   0.67),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Fwd,    122.121, 0.9695434, 0.9872347,  0.0887676, 120.0592,   0.67),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.PaFwd,  122.121, 0.9695434, 0.9872347,  0.0887676, 118.0532,   0.67),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.Spot,    3.4582,   0.99979, 0.9250616,  0.3199034, 4.964924, -0.821),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.PaSpot,  3.4582,   0.99979, 0.9250616,  0.3199034, 3.778327, -0.821),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.Fwd,     3.4582,   0.99979, 0.9250616,  0.3199034,  4.51896, -0.821),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.PaFwd,   3.4582,   0.99979, 0.9250616,  0.3199034,  3.65728, -0.821),
                // Data taken from Castagnas "FX Options and Smile Risk" (Wiley 2009)
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.Spot,    103.00,   0.99482,   0.98508, 0.07247845,    97.47,  -0.25),
                new DeltaData(Option.Type.Put,  DeltaVolQuote.DeltaType.PaSpot,  103.00,   0.99482,   0.98508, 0.07247845,    97.22,  -0.25),
                // Extreme case: zero vol, ATM Fwd strike
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Fwd,     103.00,   0.99482,   0.98508,        0.0, 101.0013,    0.5),
                new DeltaData(Option.Type.Call, DeltaVolQuote.DeltaType.Spot,    103.00,   0.99482,   0.98508,        0.0, 101.0013, 0.99482 * 0.5)
            };

            DeltaVolQuote.DeltaType currDt;
            double currSpot;
            double currdDf;
            double currfDf;
            double currStdDev;
            double expected;
            double calculated;
            double error;
            double tolerance = 1.0e-2; // not that small, but sufficient for strikes
            double currAtmStrike;
            double currCallDelta;
            double currPutDelta;
            double currFwd;

            for (int i = 0; i < values.Length; i++)
            {
                currDt     = values[i].dt;
                currSpot   = values[i].spot;
                currdDf    = values[i].dDf;
                currfDf    = values[i].fDf;
                currStdDev = values[i].stdDev;
                currFwd    = currSpot * currfDf / currdDf;

                BlackDeltaCalculator myCalc = new BlackDeltaCalculator(Option.Type.Call, currDt, currSpot, currdDf,
                                                                       currfDf, currStdDev);

                currAtmStrike = myCalc.atmStrike(DeltaVolQuote.AtmType.AtmDeltaNeutral);
                currCallDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Put);
                currPutDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Call);

                expected   = 0.0;
                calculated = currCallDelta + currPutDelta;
                error      = Math.Abs(calculated - expected);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Delta neutrality failed for spot delta in Delta Calculator. \n"
                                 + "Iteration: " + i + "\n"
                                 + "Calculated Delta Sum: " + calculated + "\n"
                                 + "Expected Delta Sum:   " + expected + "\n"
                                 + "Error: " + error);
                }

                myCalc.setDeltaType(DeltaVolQuote.DeltaType.Fwd);
                currAtmStrike = myCalc.atmStrike(DeltaVolQuote.AtmType.AtmDeltaNeutral);
                currCallDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Put);
                currPutDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Call);

                expected   = 0.0;
                calculated = currCallDelta + currPutDelta;
                error      = Math.Abs(calculated - expected);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Delta neutrality failed for forward delta in Delta Calculator. \n"
                                 + "Iteration: " + i + "\n"
                                 + "Calculated Delta Sum: " + calculated + "\n"
                                 + "Expected Delta Sum:   " + expected + "\n"
                                 + "Error: " + error);
                }

                myCalc.setDeltaType(DeltaVolQuote.DeltaType.PaSpot);
                currAtmStrike = myCalc.atmStrike(DeltaVolQuote.AtmType.AtmDeltaNeutral);
                currCallDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Put);
                currPutDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Call);

                expected   = 0.0;
                calculated = currCallDelta + currPutDelta;
                error      = Math.Abs(calculated - expected);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Delta neutrality failed for premium-adjusted spot delta in Delta Calculator. \n"
                                 + "Iteration: " + i + "\n"
                                 + "Calculated Delta Sum: " + calculated + "\n"
                                 + "Expected Delta Sum:   " + expected + "\n"
                                 + "Error: " + error);
                }


                myCalc.setDeltaType(DeltaVolQuote.DeltaType.PaFwd);
                currAtmStrike = myCalc.atmStrike(DeltaVolQuote.AtmType.AtmDeltaNeutral);
                currCallDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Put);
                currPutDelta = myCalc.deltaFromStrike(currAtmStrike);
                myCalc.setOptionType(Option.Type.Call);

                expected   = 0.0;
                calculated = currCallDelta + currPutDelta;
                error      = Math.Abs(calculated - expected);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Delta neutrality failed for premium-adjusted forward delta in Delta Calculator. \n"
                                 + "Iteration: " + i + "\n"
                                 + "Calculated Delta Sum: " + calculated + "\n"
                                 + "Expected Delta Sum:   " + expected + "\n"
                                 + "Error: " + error);
                }

                // Test ATM forward Calculations
                calculated = myCalc.atmStrike(DeltaVolQuote.AtmType.AtmFwd);
                expected   = currFwd;
                error      = Math.Abs(expected - calculated);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Atm forward test failed. \n"
                                 + "Calculated Value: " + calculated + "\n"
                                 + "Expected   Value: " + expected + "\n"
                                 + "Error: " + error);
                }

                // Test ATM 0.50 delta calculations
                myCalc.setDeltaType(DeltaVolQuote.DeltaType.Fwd);
                double atmFiftyStrike = myCalc.atmStrike(DeltaVolQuote.AtmType.AtmPutCall50);
                calculated = Math.Abs(myCalc.deltaFromStrike(atmFiftyStrike));
                expected   = 0.50;
                error      = Math.Abs(expected - calculated);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Atm 0.50 delta strike test failed. \n"
                                 + "Iteration:" + i + "\n"
                                 + "Calculated Value: " + calculated + "\n"
                                 + "Expected   Value: " + expected + "\n"
                                 + "Error: " + error);
                }
            }
        }
示例#3
0
        public void testDeltaPriceConsistency()
        {
            // Testing premium-adjusted delta price consistency

            // This function tests for price consistencies with the standard
            // Black Scholes calculator, since premium adjusted deltas can be calculated
            // from spot deltas by adding/subtracting the premium.

            SavedSettings backup = new SavedSettings();

            // actually, value and tol won't be needed for testing
            EuropeanOptionData[] values =
            {
                //        type, strike,   spot,    rd,    rf,    t,  vol,   value,    tol
                new EuropeanOptionData(Option.Type.Call, 0.9123, 1.2212, 0.0231, 0.0000, 0.25, 0.301, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 0.9234, 1.2212, 0.0231, 0.0000, 0.35, 0.111, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 0.9783, 1.2212, 0.0231, 0.0000, 0.45, 0.071, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 1.0000, 1.2212, 0.0231, 0.0000, 0.55, 0.082, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 1.1230, 1.2212, 0.0231, 0.0000, 0.65, 0.012, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 1.2212, 1.2212, 0.0231, 0.0000, 0.75, 0.129, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 1.3212, 1.2212, 0.0231, 0.0000, 0.85, 0.034, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 1.3923, 1.2212, 0.0131, 0.2344, 0.95, 0.001, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Call, 1.3455, 1.2212, 0.0000, 0.0000, 1.00, 0.127, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  0.9123, 1.2212, 0.0231, 0.0000, 0.25, 0.301, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  0.9234, 1.2212, 0.0231, 0.0000, 0.35, 0.111, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  0.9783, 1.2212, 0.0231, 0.0000, 0.45, 0.071, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  1.0000, 1.2212, 0.0231, 0.0000, 0.55, 0.082, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  1.1230, 1.2212, 0.0231, 0.0000, 0.65, 0.012, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  1.2212, 1.2212, 0.0231, 0.0000, 0.75, 0.129, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  1.3212, 1.2212, 0.0231, 0.0000, 0.85, 0.034, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  1.3923, 1.2212, 0.0131, 0.2344, 0.95, 0.001, 0.0, 0.0),
                new EuropeanOptionData(Option.Type.Put,  1.3455, 1.2212, 0.0000, 0.0000, 1.00, 0.127, 0.0, 0.0),
                // extreme case: zero vol
                new EuropeanOptionData(Option.Type.Put,  1.3455, 1.2212, 0.0000, 0.0000, 0.50, 0.000, 0.0, 0.0),
                // extreme case: zero strike
                new EuropeanOptionData(Option.Type.Put,  0.0000, 1.2212, 0.0000, 0.0000, 1.50, 0.133, 0.0, 0.0),
                // extreme case: zero strike+zero vol
                new EuropeanOptionData(Option.Type.Put,  0.0000, 1.2212, 0.0000, 0.0000, 1.00, 0.133, 0.0, 0.0),
            };

            DayCounter dc       = new Actual360();
            Calendar   calendar = new TARGET();
            Date       today    = Date.Today;

            // Start setup of market data

            double discFor       = 0.0;
            double discDom       = 0.0;
            double implVol       = 0.0;
            double expectedVal   = 0.0;
            double calculatedVal = 0.0;
            double error         = 0.0;

            SimpleQuote    spotQuote  = new SimpleQuote(0.0);
            Handle <Quote> spotHandle = new Handle <Quote>(spotQuote);

            SimpleQuote        qQuote  = new SimpleQuote(0.0);
            Handle <Quote>     qHandle = new Handle <Quote>(qQuote);
            YieldTermStructure qTS     = new FlatForward(today, qHandle, dc);

            SimpleQuote        rQuote  = new SimpleQuote(0.0);
            Handle <Quote>     rHandle = new Handle <Quote>(qQuote);
            YieldTermStructure rTS     = new FlatForward(today, rHandle, dc);

            SimpleQuote           volQuote  = new SimpleQuote(0.0);
            Handle <Quote>        volHandle = new Handle <Quote>(volQuote);
            BlackVolTermStructure volTS     = new BlackConstantVol(today, calendar, volHandle, dc);

            BlackScholesMertonProcess stochProcess;
            IPricingEngine            engine;
            StrikedTypePayoff         payoff;
            Date     exDate;
            Exercise exercise;
            // Setup of market data finished

            double tolerance = 1.0e-10;

            for (int i = 0; i < values.Length; ++i)
            {
                payoff   = new PlainVanillaPayoff(values[i].type, values[i].strike);
                exDate   = today + timeToDays(values[i].t);
                exercise = new EuropeanExercise(exDate);

                spotQuote.setValue(values[i].s);
                volQuote.setValue(values[i].v);
                rQuote.setValue(values[i].r);
                qQuote.setValue(values[i].q);

                discDom = rTS.discount(exDate);
                discFor = qTS.discount(exDate);
                implVol = Math.Sqrt(volTS.blackVariance(exDate, 0.0));

                BlackDeltaCalculator myCalc = new BlackDeltaCalculator(values[i].type, DeltaVolQuote.DeltaType.PaSpot,
                                                                       spotQuote.value(), discDom, discFor, implVol);

                stochProcess = new BlackScholesMertonProcess(spotHandle,
                                                             new Handle <YieldTermStructure>(qTS),
                                                             new Handle <YieldTermStructure>(rTS),
                                                             new Handle <BlackVolTermStructure>(volTS));

                engine = new AnalyticEuropeanEngine(stochProcess);

                EuropeanOption option = new EuropeanOption(payoff, exercise);
                option.setPricingEngine(engine);

                calculatedVal = myCalc.deltaFromStrike(values[i].strike);
                expectedVal   = option.delta() - option.NPV() / spotQuote.value();
                error         = Math.Abs(expectedVal - calculatedVal);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Premium-adjusted spot delta test failed. \n"
                                 + "Calculated Delta: " + calculatedVal + "\n"
                                 + "Expected Value:   " + expectedVal + "\n"
                                 + "Error: " + error);
                }

                myCalc.setDeltaType(DeltaVolQuote.DeltaType.PaFwd);

                calculatedVal = myCalc.deltaFromStrike(values[i].strike);
                expectedVal   = expectedVal / discFor; // Premium adjusted Fwd Delta is PA spot without discount
                error         = Math.Abs(expectedVal - calculatedVal);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Premium-adjusted forward delta test failed. \n"
                                 + "Calculated Delta: " + calculatedVal + "\n"
                                 + "Expected Value:   " + expectedVal + "\n"
                                 + "Error: " + error);
                }


                // Test consistency with BlackScholes Calculator for Spot Delta
                myCalc.setDeltaType(DeltaVolQuote.DeltaType.Spot);

                calculatedVal = myCalc.deltaFromStrike(values[i].strike);
                expectedVal   = option.delta();
                error         = Math.Abs(calculatedVal - expectedVal);

                if (error > tolerance)
                {
                    QAssert.Fail("\n spot delta in BlackDeltaCalculator differs from delta in BlackScholesCalculator. \n"
                                 + "Calculated Value: " + calculatedVal + "\n"
                                 + "Expected Value:   " + expectedVal + "\n"
                                 + "Error: " + error);
                }
            }
        }
示例#4
0
        public void testPutCallParity()
        {
            // Testing put-call parity for deltas

            // Test for put call parity between put and call deltas.

            SavedSettings backup = new SavedSettings();

            /* The data below are from
             * "Option pricing formulas", E.G. Haug, McGraw-Hill 1998
             * pag 11-16
             */

            EuropeanOptionData[] values =
            {
                // pag 2-8
                //        type, strike,   spot,    q,    r,    t,  vol,   value,    tol
                new EuropeanOptionData(Option.Type.Call,  65.00,  60.00, 0.00, 0.08, 0.25, 0.30,  2.1334, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,   95.00, 100.00, 0.05, 0.10, 0.50, 0.20,  2.4648, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,   19.00,  19.00, 0.10, 0.10, 0.75, 0.28,  1.7011, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call,  19.00,  19.00, 0.10, 0.10, 0.75, 0.28,  1.7011, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call,   1.60,   1.56, 0.08, 0.06, 0.50, 0.12,  0.0291, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,   70.00,  75.00, 0.05, 0.10, 0.50, 0.35,  4.0870, 1.0e-4),
                // pag 24
                new EuropeanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.15,  0.0205, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8734, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.15,  9.9413, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.25,  0.3150, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1217, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.25, 10.3556, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.35,  0.9474, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3693, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.35, 11.1381, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.15,  0.8069, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0232, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.15, 10.5769, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.25,  2.7026, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.6997, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.25, 12.7857, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.35,  4.9329, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.3679, 1.0e-4),
                new EuropeanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.35, 15.3086, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.15,  9.9210, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8734, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.15,  0.0408, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.25, 10.2155, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1217, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.25,  0.4551, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.35, 10.8479, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3693, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.35,  1.2376, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.15, 10.3192, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0232, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.15,  1.0646, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.25, 12.2149, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.6997, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.25,  3.2734, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.35, 14.4452, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.3679, 1.0e-4),
                new EuropeanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.35,  5.7963, 1.0e-4),
                // pag 27
                new EuropeanOptionData(Option.Type.Call,  40.00,  42.00, 0.08, 0.04, 0.75, 0.35,  5.0975, 1.0e-4)
            };

            DayCounter dc       = new Actual360();
            Calendar   calendar = new TARGET();
            Date       today    = Date.Today;

            double discFor        = 0.0;
            double discDom        = 0.0;
            double implVol        = 0.0;
            double deltaCall      = 0.0;
            double deltaPut       = 0.0;
            double expectedDiff   = 0.0;
            double calculatedDiff = 0.0;
            double error          = 0.0;
            double forward        = 0.0;

            SimpleQuote spotQuote = new SimpleQuote(0.0);

            SimpleQuote        qQuote  = new SimpleQuote(0.0);
            Handle <Quote>     qHandle = new Handle <Quote>(qQuote);
            YieldTermStructure qTS     = new FlatForward(today, qHandle, dc);

            SimpleQuote        rQuote  = new SimpleQuote(0.0);
            Handle <Quote>     rHandle = new Handle <Quote>(qQuote);
            YieldTermStructure rTS     = new FlatForward(today, rHandle, dc);

            SimpleQuote           volQuote  = new SimpleQuote(0.0);
            Handle <Quote>        volHandle = new Handle <Quote>(volQuote);
            BlackVolTermStructure volTS     = new BlackConstantVol(today, calendar, volHandle, dc);

            StrikedTypePayoff payoff;
            Date     exDate;
            Exercise exercise;

            double tolerance = 1.0e-10;

            for (int i = 0; i < values.Length; ++i)
            {
                payoff   = new PlainVanillaPayoff(Option.Type.Call, values[i].strike);
                exDate   = today + timeToDays(values[i].t);
                exercise = new EuropeanExercise(exDate);

                spotQuote.setValue(values[i].s);
                volQuote.setValue(values[i].v);
                rQuote.setValue(values[i].r);
                qQuote.setValue(values[i].q);
                discDom = rTS.discount(exDate);
                discFor = qTS.discount(exDate);
                implVol = Math.Sqrt(volTS.blackVariance(exDate, 0.0));
                forward = spotQuote.value() * discFor / discDom;

                BlackDeltaCalculator myCalc = new BlackDeltaCalculator(Option.Type.Call, DeltaVolQuote.DeltaType.Spot,
                                                                       spotQuote.value(), discDom, discFor, implVol);

                deltaCall = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Put);
                deltaPut = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Call);

                expectedDiff   = discFor;
                calculatedDiff = deltaCall - deltaPut;
                error          = Math.Abs(expectedDiff - calculatedDiff);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Put-call parity failed for spot delta. \n"
                                 + "Calculated Call Delta: " + deltaCall + "\n"
                                 + "Calculated Put Delta:  " + deltaPut + "\n"
                                 + "Expected Difference:   " + expectedDiff + "\n"
                                 + "Calculated Difference: " + calculatedDiff);
                }
                myCalc.setDeltaType(DeltaVolQuote.DeltaType.Fwd);

                deltaCall = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Put);
                deltaPut = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Call);

                expectedDiff   = 1.0;
                calculatedDiff = deltaCall - deltaPut;
                error          = Math.Abs(expectedDiff - calculatedDiff);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Put-call parity failed for forward delta. \n"
                                 + "Calculated Call Delta: " + deltaCall + "\n"
                                 + "Calculated Put Delta:  " + deltaPut + "\n"
                                 + "Expected Difference:   " + expectedDiff + "\n"
                                 + "Calculated Difference: " + calculatedDiff);
                }

                myCalc.setDeltaType(DeltaVolQuote.DeltaType.PaSpot);

                deltaCall = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Put);
                deltaPut = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Call);

                expectedDiff   = discFor * values[i].strike / forward;
                calculatedDiff = deltaCall - deltaPut;
                error          = Math.Abs(expectedDiff - calculatedDiff);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Put-call parity failed for premium-adjusted spot delta. \n"
                                 + "Calculated Call Delta: " + deltaCall + "\n"
                                 + "Calculated Put Delta:  " + deltaPut + "\n"
                                 + "Expected Difference:   " + expectedDiff + "\n"
                                 + "Calculated Difference: " + calculatedDiff);
                }

                myCalc.setDeltaType(DeltaVolQuote.DeltaType.PaFwd);

                deltaCall = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Put);
                deltaPut = myCalc.deltaFromStrike(values[i].strike);
                myCalc.setOptionType(Option.Type.Call);

                expectedDiff   = values[i].strike / forward;
                calculatedDiff = deltaCall - deltaPut;
                error          = Math.Abs(expectedDiff - calculatedDiff);

                if (error > tolerance)
                {
                    QAssert.Fail("\n Put-call parity failed for premium-adjusted forward delta. \n"
                                 + "Calculated Call Delta: " + deltaCall + "\n"
                                 + "Calculated Put Delta:  " + deltaPut + "\n"
                                 + "Expected Difference:   " + expectedDiff + "\n"
                                 + "Calculated Difference: " + calculatedDiff);
                }
            }
        }
示例#5
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(BlackDeltaCalculator obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }