Ejemplo n.º 1
0
 /// <summary>
 /// AreaSpread describes areas that should be placed on the map
 /// </summary>
 /// <param name="id">Mapped tile id</param>
 /// <param name="flag">Tile flags</param>
 /// <param name="percentage">Percentage of map space covered by this flag</param>
 /// <param name="minSizeInMeter">Minimum size of area in meter</param>
 /// <param name="maxSizeInMeter">Maximum size of area in meter</param>
 /// <param name="useEdgeNoise">Can be used to add aliasing to avoid symmetric areas</param>
 /// <param name="connectEqualFlags">Areas with the same flags will be connected, all free tiles within a give distance will be set to the flag value</param>
 /// <param name="connectDistance">Maximum distance between two areas with the same flag</param>
 /// <param name="spreadType">Geometrical form of the area</param>
 /// <param name="layer">Dicides which generation algorithm will be used</param>
 public AreaSpread(ushort id, byte flag, float percentage, int minSizeInMeter, int maxSizeInMeter, bool useEdgeNoise, bool connectEqualFlags, int connectDistance, SpreadOption spreadType, LayerType layer)
 {
     Id                = id;
     Flag              = flag;
     Percentage        = percentage;
     MinSizeInMeter    = minSizeInMeter;
     MaxSizeInMeter    = maxSizeInMeter;
     UseEdgeNoise      = useEdgeNoise;
     SpreadType        = spreadType;
     Layer             = layer;
     ConnectEqualFlags = connectEqualFlags;
     ConnectDistance   = connectDistance;
 }
Ejemplo n.º 2
0
        private void SpreadOptionBjerksundCalc(string spreadType = "TwoAssetsSpread", Boolean isCall = true, string ValuationDate = "2017-12-26", double vol1 = 0.28, double spot1 = 1.0, double vol2 = 0.30, double spot2 = 2.0,
                                               double vol3       = 0.28, double spot3 = 1.0, double vol4 = 0.28, double spot4 = 1.0, double strike = 1.03, double tol = 1e-8)
        {
            var valuationDate = DateFromStr(ValuationDate);
            var maturityDate  = new Term("176D").Next(valuationDate);
            var calendar      = CalendarImpl.Get("chn");

            var asset1 = "asset1";
            var asset2 = "asset2";
            var asset3 = "asset3";
            var asset4 = "asset4";


            var option = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: (isCall) ? OptionType.Call : OptionType.Put,
                spreadType: ToSpreadType(spreadType),
                strike: strike,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };


            var market = TestMarket(referenceDate: ValuationDate, vol1: vol1, vol2: vol2, vol3: vol3, vol4: vol4, spot1: spot1, spot2: spot2, spot3: spot3, spot4: spot4,
                                    asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);

            var analyticalEngine = new AnalyticalSpreadOptionBjerksundEngine();
            var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All);

            var Engine = new AnalyticalSpreadOptionKirkEngine();
            var Result = Engine.Calculate(option, market, PricingRequest.All);

            Assert.AreEqual(analyticalResult.Pv, Result.Pv, tol);
        }
Ejemplo n.º 3
0
        private void SpreadOptionGreekCalc(double ExpectedPv, string spreadType = "TwoAssetsSpread", string ValuationDate = "2017-12-26")
        {
            var valuationDate = DateFromStr(ValuationDate);
            var maturityDate  = new Term("176D").Next(valuationDate);
            var calendar      = CalendarImpl.Get("chn");

            var asset1 = "asset1";
            var asset2 = "asset2";
            var asset3 = "asset3";
            var asset4 = "asset4";


            var option = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: OptionType.Call,
                spreadType: ToSpreadType(spreadType),
                strike: 1.03,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };


            var market = TestMarket(referenceDate: ValuationDate, asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);

            //var analyticalEngine = new AnalyticalSpreadOptionEngine();
            //var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All);

            var Engine = new AnalyticalSpreadOptionKirkEngine();
            var Result = Engine.Calculate(option, market, PricingRequest.All);

            //Assert.AreEqual(ExpectedPv, analyticalResult.Pv, 1e-8);
            Assert.AreEqual(ExpectedPv, Result.Pv, 1e-8);
        }
Ejemplo n.º 4
0
        private void SpreadOptionGreekTest(double vol1       = 0.28, double vol2 = 0.30, double vol3 = 0.40, double spot1 = 4900, double spot2 = 1500, double spot3 = 1500,
                                           string spreadType = "TwoAssetsSpread", string t0 = "2017-12-26", string t1 = "2017-12-27", double volMove = 0.10, double mktMove = 1e-4, double toleranceInPct = 2)
        {
            var valuationDate = DateFromStr(t0);
            var maturityDate  = new Term("176D").Next(valuationDate);
            var calendar      = CalendarImpl.Get("chn");
            var spot1New      = spot1 + spot1 * mktMove;
            var spot2New      = spot2 + spot2 * mktMove;
            var spot3New      = spot3 + spot3 * mktMove;
            var vol1New       = vol1 + volMove;
            var vol2New       = vol2 + volMove;
            var vol3New       = vol3 + volMove;
            var T0            = DateFromStr(t0);
            var T1            = DateFromStr(t1);


            var valuationDay    = t0;
            var valuationDayNew = t1;

            var asset1 = "asset1";
            var asset2 = "asset2";
            var asset3 = "asset3";
            var asset4 = "asset4";
            var option = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: OptionType.Call,
                spreadType: ToSpreadType(spreadType),
                strike: 1000,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };

            var market = TestMarket(referenceDate: t0, vol1: vol1, vol2: vol2, vol3: vol3, spot1: spot1, spot2: spot2, spot3: spot3,
                                    asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);
            var marketNew = TestMarket(referenceDate: t1, vol1: vol1New, vol2: vol2New, vol3: vol3New, spot1: spot1New, spot2: spot2New, spot3: spot3New,
                                       asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);
            var marketPI = TestMarket(referenceDate: t0, vol1: vol1, vol2: vol2, vol3: vol3, spot1: spot1New, spot2: spot2New, spot3: spot3New,
                                      asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);
            var marketVI = TestMarket(referenceDate: t0, vol1: vol1New, vol2: vol2New, vol3: vol3New, spot1: spot1, spot2: spot2, spot3: spot3,
                                      asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);
            var marketPVC = TestMarket(referenceDate: t0, vol1: vol1New, vol2: vol2New, vol3: vol3New, spot1: spot1New, spot2: spot2New, spot3: spot3New,
                                       asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);

            var engine = new AnalyticalSpreadOptionKirkEngine();

            var result    = engine.Calculate(option, market, PricingRequest.All);
            var resultNew = engine.Calculate(option, marketNew, PricingRequest.All);
            var resultPI  = engine.Calculate(option, marketPI, PricingRequest.All);
            var resultVI  = engine.Calculate(option, marketVI, PricingRequest.All);
            var resultPVC = engine.Calculate(option, marketPVC, PricingRequest.All);

            var actualPL = resultNew.Pv - result.Pv;

            //price Impact
            //PI = PV(t-1, priceNew) - Pv(t-1)
            var basePv  = result.Pv;
            var PI      = resultPI.Pv - basePv;
            var thetapl = result.Theta * (T1 - T0);

            //vol impact
            //VI = PV(t-1. volNew) - Pv (t-1)
            var VI = resultVI.Pv - basePv;

            //price vol cross impact
            //PVC = PV(t-1. volNew, PriceNew) - Pv (t-1) - (PI+VI)
            var PVC = resultPVC.Pv - basePv - PI - VI;

            var newEstimate    = PI + VI + PVC + thetapl;
            var newUnexplained = actualPL - newEstimate;

            //Time impact
            //TI = PV(t, all OldInfo) - Pv(t-1)

            //TODO:
            //Time/ price cross Impact
            //TPC = PV(t, priceNew) - pv(t-1) - (TI +PI)

            //Time/vol cross impact
            //TVC = PV(t, volNew) - pv(t-1) -(TI+VI)


            //TODO:
            //in case of big move ( vol and spot), we need high order risk to explain pnl
            //var diff = actualPL - esimstatedPL;
            //Assert.AreEqual(true, Math.Abs(diff / actualPL) * 100.0 < toleranceInPct); //pnl well explained in not too extreme moves
            Assert.AreEqual(true, Math.Abs(newUnexplained / actualPL) * 100.0 < toleranceInPct);
        }
Ejemplo n.º 5
0
        private void SpreadVanillaCalc(string spreadType = "TwoAssetsSpread", string ValuationDate = "2017-12-26",
                                       double spot1      = 4500, double spot2 = 2500, double strike = 2000, double vol1 = 0.5, double vol2 = 0.5, double rho12 = 0.5)
        {
            var valuationDate = DateFromStr(ValuationDate);
            var maturityDate  = new Term("176D").Next(valuationDate);
            var calendar      = CalendarImpl.Get("chn");

            var asset1 = "asset1";
            var asset2 = "asset2";
            var asset3 = "asset3";
            var asset4 = "asset4";

            var option = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: OptionType.Call,
                spreadType: ToSpreadType(spreadType),
                strike: strike,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };

            var option1 = new VanillaOption(
                valuationDate,
                maturityDate,
                OptionExercise.European,
                OptionType.Call,
                2.0 * strike,
                InstrumentType.EquityIndex,
                calendar,
                new Act365(),
                CurrencyCode.CNY,
                CurrencyCode.CNY,
                new[] { maturityDate },
                new[] { maturityDate }
                );

            var option2 = new VanillaOption(
                valuationDate,
                maturityDate,
                OptionExercise.European,
                OptionType.Put,
                strike,
                InstrumentType.EquityIndex,
                calendar,
                new Act365(),
                CurrencyCode.CNY,
                CurrencyCode.CNY,
                new[] { maturityDate },
                new[] { maturityDate }
                );

            var market = TestMarket(referenceDate: ValuationDate, vol1: vol1, vol2: vol2, vol3: 0.0, spot1: spot1, spot2: spot2, spot3: 0.0,
                                    asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4, rho12: rho12, rho23: 0.0, rho13: 0.0);
            var market1 = GetMarket(referenceDate: ValuationDate, vol: vol1, spot: spot1);
            var market2 = GetMarket(referenceDate: ValuationDate, vol: vol2, spot: spot2);

            var analyticalEngine  = new AnalyticalSpreadOptionKirkEngine();
            var analyticalEngine2 = new AnalyticalVanillaEuropeanOptionEngine();
            var result            = analyticalEngine.Calculate(option, market, PricingRequest.All);
            var result1           = analyticalEngine2.Calculate(option1, market1, PricingRequest.All);
            var result2           = analyticalEngine2.Calculate(option2, market2, PricingRequest.All);

            Assert.AreEqual(true, result1.Pv + result2.Pv - result.Pv > 0);
        }
Ejemplo n.º 6
0
        private void SpreadOptionParity(string ValuationDate = "2017-12-26", double vol1 = 0.28, double spot1 = 1.0, double vol2 = 0.30, double spot2 = 2.0, double vol3 = 0.30, double spot3 = 2.0, double strike = 1.03)
        {
            var valuationDate = DateFromStr(ValuationDate);
            var maturityDate  = new Term("176D").Next(valuationDate);
            var calendar      = CalendarImpl.Get("chn");

            var asset1 = "asset1";
            var asset2 = "asset2";
            var asset3 = "asset3";
            var asset4 = "asset4";

            var option1 = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: OptionType.Call,
                spreadType: SpreadType.ThreeAssetsSpread,
                strike: strike,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };


            var option2 = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: OptionType.Call,
                spreadType: SpreadType.FourAssetsSpread,
                strike: strike,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };

            var option3 = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: OptionType.Call,
                spreadType: SpreadType.ThreeAssetsSpreadBasket,
                strike: strike,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };


            var option4 = new SpreadOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: OptionType.Call,
                spreadType: SpreadType.FourAssetsSpreadBasketType1,
                strike: strike,
                weights: new double[] { 1.0, 1.0, 1.0, 1.0 },
                underlyingInstrumentType: InstrumentType.EquityIndex,
                calendar: calendar,
                dayCount: new Act365(),
                payoffCcy: CurrencyCode.CNY,
                settlementCcy: CurrencyCode.CNY,
                exerciseDates: new[] { maturityDate },
                observationDates: new[] { maturityDate },
                underlyingTickers: new[] { asset1, asset2, asset3, asset4 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 }
            };

            var market = TestMarket(referenceDate: ValuationDate, vol1: vol1, vol2: vol2, vol3: vol3, spot1: spot1, spot2: spot2, spot3: spot3,
                                    asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4);

            var analyticalEngine = new AnalyticalSpreadOptionKirkEngine();
            var result1          = analyticalEngine.Calculate(option1, market, PricingRequest.All);
            var result2          = analyticalEngine.Calculate(option2, market, PricingRequest.All);
            var result3          = analyticalEngine.Calculate(option3, market, PricingRequest.All);
            var result4          = analyticalEngine.Calculate(option4, market, PricingRequest.All);

            var Engine  = new AnalyticalSpreadOptionBjerksundEngine();
            var result5 = Engine.Calculate(option1, market, PricingRequest.All);
            var result6 = Engine.Calculate(option2, market, PricingRequest.All);
            var result7 = Engine.Calculate(option3, market, PricingRequest.All);
            var result8 = Engine.Calculate(option4, market, PricingRequest.All);

            Assert.AreEqual(result1.Pv, result2.Pv, 1.0e-8);
            Assert.AreEqual(result3.Pv, result4.Pv, 1.0e-8);
            //Assert.AreEqual(result5.Pv, result6.Pv, 1.0e-8);
            Assert.AreEqual(result7.Pv, result8.Pv, 1.0e-8);
        }
Ejemplo n.º 7
0
        public void testKirkEngine()
        {
            // Testing Kirk approximation for spread options

            /* The example data below are from "complete guide to option
             * pricing formulas", Espen Gaarder Haug, p 60
             *
             * Expected values of option theta were calculated using automatic
             * differentiation of the pricing function. The engine uses closed-form
             * formula */

            Case[] cases =
            {
                new Case(28.0,   20.0, 7.0, 0.05, 0.29, 0.36, 0.42,  90,  2.1670,  3.0431),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.20, -0.5,  36,  4.7530, 25.5905),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.20,  0.0,  36,  3.7970, 20.8841),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.20,  0.5,  36,  2.5537, 14.7260),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.20, -0.5, 180, 10.7517, 10.0847),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.20,  0.0, 180,  8.7020,  8.2619),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.20,  0.5, 180,  6.0257,  5.8661),
                new Case(122.0, 120.0, 3.0, 0.10, 0.25, 0.20, -0.5,  36,  5.4275, 28.9013),
                new Case(122.0, 120.0, 3.0, 0.10, 0.25, 0.20,  0.0,  36,  4.3712, 23.7133),
                new Case(122.0, 120.0, 3.0, 0.10, 0.25, 0.20,  0.5,  36,  3.0086, 16.9864),
                new Case(122.0, 120.0, 3.0, 0.10, 0.25, 0.20, -0.5, 180, 12.1941, 11.3603),
                new Case(122.0, 120.0, 3.0, 0.10, 0.25, 0.20,  0.0, 180,  9.9340,  9.3589),
                new Case(122.0, 120.0, 3.0, 0.10, 0.25, 0.20,  0.5, 180,  7.0067,  6.7463),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.25, -0.5,  36,  5.4061, 28.7963),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.25,  0.0,  36,  4.3451, 23.5848),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.25,  0.5,  36,  2.9723, 16.8060),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.25, -0.5, 180, 12.1483, 11.3200),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.25,  0.0, 180,  9.8780,  9.3091),
                new Case(122.0, 120.0, 3.0, 0.10, 0.20, 0.25,  0.5, 180,  6.9284, 6.6761)
            };

            for (int i = 0; i < cases.Length; ++i)
            {
                // First step: preparing the test values
                // Useful dates
                DayCounter dc           = new Actual360();
                Date       today        = Date.Today;
                Date       exerciseDate = today + cases[i].length;

                // Futures values
                SimpleQuote F1 = new SimpleQuote(cases[i].F1);
                SimpleQuote F2 = new SimpleQuote(cases[i].F2);

                // Risk-free interest rate
                double             riskFreeRate = cases[i].r;
                YieldTermStructure forwardRate  = Utilities.flatRate(today, riskFreeRate, dc);

                // Correlation
                Quote rho = new SimpleQuote(cases[i].rho);

                // Volatilities
                double vol1 = cases[i].sigma1;
                double vol2 = cases[i].sigma2;
                BlackVolTermStructure volTS1 = Utilities.flatVol(today, vol1, dc);
                BlackVolTermStructure volTS2 = Utilities.flatVol(today, vol2, dc);

                // Black-Scholes Processes
                // The BlackProcess is the relevant class for futures contracts
                BlackProcess stochProcess1 = new BlackProcess(new Handle <Quote>(F1),
                                                              new Handle <YieldTermStructure>(forwardRate),
                                                              new Handle <BlackVolTermStructure>(volTS1));

                BlackProcess stochProcess2 = new BlackProcess(new Handle <Quote>(F2),
                                                              new Handle <YieldTermStructure>(forwardRate),
                                                              new Handle <BlackVolTermStructure>(volTS2));

                // Creating the pricing engine
                IPricingEngine engine = new KirkSpreadOptionEngine(stochProcess1,
                                                                   stochProcess2, new Handle <Quote>(rho));

                // Finally, create the option:
                Option.Type        type     = Option.Type.Call;
                double             strike   = cases[i].X;
                PlainVanillaPayoff payoff   = new PlainVanillaPayoff(type, strike);
                Exercise           exercise = new EuropeanExercise(exerciseDate);

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

                // And test the data
                double value     = option.NPV();
                double theta     = option.theta();
                double tolerance = 1e-4;

                if (Math.Abs(value - cases[i].value) > tolerance)
                {
                    REPORT_FAILURE("value",
                                   payoff, exercise,
                                   cases[i].value, value, tolerance, today);
                }

                if (Math.Abs(theta - cases[i].theta) > tolerance)
                {
                    REPORT_FAILURE("theta",
                                   payoff, exercise,
                                   cases[i].theta, theta, tolerance, today);
                }
            }
        }