Example #1
0
        private void RainbowOptionGreekCalc(double ExpectedPv, string rainbowType = "Max", string ValuationDate = "2017-12-18", double vol = 0.28, double spot = 1.0, double volNew = 0.30, double spotNew = 2.0,
                                            double strike1 = 1.03, double strike2 = 1.05, Boolean isCall = true)
        {
            var valuationDate = DateFromStr(ValuationDate);
            var maturityDate  = new Term("176D").Next(valuationDate);
            var calendar      = CalendarImpl.Get("chn");

            var asset1 = "asset1";
            var asset2 = "asset2";

            var option = new RainbowOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: isCall ? OptionType.Call : OptionType.Put,
                rainbowType: ToRainbowType(rainbowType),
                strikes: new double[] { strike1, strike2 },
                cashAmount: 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 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2 }
            };

            var market = TestMarket(referenceDate: ValuationDate, vol: vol, volNew: volNew, spot: spot, spotNew: spotNew, asset1: asset1, asset2: asset2);

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

            Assert.AreEqual(ExpectedPv, analyticalResult.Pv, 1e-8);
        }
Example #2
0
        private void RainbowOptionGreekTest(double vol     = 0.28, double spot       = 1.0, double volNew           = 0.30, double spotNew = 2.0,
                                            double strike1 = 1.03, double strike2    = 1.05, Boolean isCall         = true, Boolean isBest = true,
                                            string t0      = "2015-03-19", string t1 = "2015-03-20", 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 spot2         = spot + spot * mktMove;
            var spotNew2      = spotNew + spotNew * mktMove;
            var vol2          = vol + volMove;
            var volNew2       = volNew + volMove;
            var T0            = DateFromStr(t0);
            var T1            = DateFromStr(t1);


            var valuationDay    = t0;
            var valuationDayNew = t1;

            var asset1 = "asset1";
            var asset2 = "asset2";
            var option = new RainbowOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: isCall ? OptionType.Call : OptionType.Put,
                rainbowType: isBest ? RainbowType.Max : RainbowType.Min,
                strikes: new double[] { strike1, strike2 },
                cashAmount: 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 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2 }
            };
            var market    = TestMarket(referenceDate: t0, vol: vol, volNew: volNew, spot: spot, spotNew: spotNew, asset1: asset1, asset2: asset2);
            var marketNew = TestMarket(referenceDate: t1, vol: vol2, volNew: volNew2, spot: spot2, spotNew: spotNew2, asset1: asset1, asset2: asset2);
            var marketPI  = TestMarket(referenceDate: t0, vol: vol, volNew: volNew, spot: spot2, spotNew: spotNew2, asset1: asset1, asset2: asset2);
            var marketVI  = TestMarket(referenceDate: t0, vol: vol2, volNew: volNew2, spot: spot, spotNew: spotNew, asset1: asset1, asset2: asset2);
            var marketPVC = TestMarket(referenceDate: t0, vol: vol2, volNew: volNew2, spot: spot2, spotNew: spotNew2, asset1: asset1, asset2: asset2);

            var engine = new AnalyticalRainbowOptionEngine();

            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);
        }
Example #3
0
        private void RainbowOptionParity(string ValuationDate = "2017-12-18", double vol = 0.28, double spot    = 1.0, double volNew   = 0.30, double spotNew = 2.0,
                                         double strike1       = 1.03, double strike2     = 1.05, Boolean isCall = true, Boolean isBest = true)
        {
            var valuationDate = DateFromStr(ValuationDate);
            var maturityDate  = new Term("176D").Next(valuationDate);
            var calendar      = CalendarImpl.Get("chn");

            var asset1 = "asset1";
            var asset2 = "asset2";

            var option1 = new RainbowOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: isCall ? OptionType.Call : OptionType.Put,
                rainbowType: isBest ? RainbowType.Max : RainbowType.Min,
                strikes: new double[] { strike1, strike2 },
                cashAmount: 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 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2 }
            };


            var option2 = new RainbowOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: isCall ? OptionType.Put : OptionType.Call,
                rainbowType: isBest ? RainbowType.Max : RainbowType.Min,
                strikes: new double[] { strike1, strike2 },
                cashAmount: 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 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2 }
            };


            var option = new RainbowOption(
                startDate: valuationDate,
                maturityDate: maturityDate,
                exercise: OptionExercise.European,
                optionType: isCall ? OptionType.Call : OptionType.Put,
                rainbowType: isBest ? RainbowType.Max : RainbowType.Min,
                strikes: new double[] { 1e-8, 0 },
                cashAmount: 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 }
                )
            {
                UnderlyingTickers = new string[] { asset1, asset2 }
            };
            var market = TestMarket(referenceDate: ValuationDate, vol: vol, volNew: volNew, spot: spot, spotNew: spotNew, asset1: asset1, asset2: asset2);

            var analyticalEngine = new AnalyticalRainbowOptionEngine();
            var result1          = analyticalEngine.Calculate(option1, market, PricingRequest.All);
            var result2          = analyticalEngine.Calculate(option2, market, PricingRequest.All);
            var result           = analyticalEngine.Calculate(option, market, PricingRequest.All);
            var r = market.DiscountCurve.Value.ZeroRate(market.ValuationDate, maturityDate);
            var T = option1.DayCount.CalcDayCountFraction(market.ValuationDate, maturityDate);

            Assert.AreEqual(0.0, (result1.Pv + strike1 * Math.Exp(-r * T) - result2.Pv - result.Pv), 1.0e-6);
        }