상속: VanillaOption
예제 #1
0
        VanillaOption makeOption(StrikedTypePayoff payoff, Exercise exercise, Quote u, YieldTermStructure q,
            YieldTermStructure r, BlackVolTermStructure vol, EngineType engineType, int binomialSteps, int samples)
        {
            GeneralizedBlackScholesProcess stochProcess = makeProcess(u, q, r, vol);

             IPricingEngine engine;
             switch (engineType)
             {
            case EngineType.Analytic:
               engine = new AnalyticEuropeanEngine(stochProcess);
               break;
            case EngineType.JR:
               engine = new BinomialVanillaEngine<JarrowRudd>(stochProcess, binomialSteps);
               break;
            case EngineType.CRR:
               engine = new BinomialVanillaEngine<CoxRossRubinstein>(stochProcess, binomialSteps);
               break;
            case EngineType.EQP:
               engine = new BinomialVanillaEngine<AdditiveEQPBinomialTree>(stochProcess, binomialSteps);
               break;
            case EngineType.TGEO:
               engine = new BinomialVanillaEngine<Trigeorgis>(stochProcess, binomialSteps);
               break;
            case EngineType.TIAN:
               engine = new BinomialVanillaEngine<Tian>(stochProcess, binomialSteps);
               break;
            case EngineType.LR:
               engine = new BinomialVanillaEngine<LeisenReimer>(stochProcess, binomialSteps);
               break;
            case EngineType.JOSHI:
               engine = new BinomialVanillaEngine<Joshi4>(stochProcess, binomialSteps);
               break;
            case EngineType.FiniteDifferences:
               engine = new FDEuropeanEngine(stochProcess, binomialSteps, samples);
               break;
            case EngineType.Integral:
               engine = new IntegralEngine(stochProcess);
               break;
            //case EngineType.PseudoMonteCarlo:
            //  engine = MakeMCEuropeanEngine<PseudoRandom>(stochProcess)
            //      .withSteps(1)
            //      .withSamples(samples)
            //      .withSeed(42);
            //  break;
            //case EngineType.QuasiMonteCarlo:
            //  engine = MakeMCEuropeanEngine<LowDiscrepancy>(stochProcess)
            //      .withSteps(1)
            //      .withSamples(samples);
            //  break;
            default:
               throw new ArgumentException("unknown engine type");
             }

             VanillaOption option = new EuropeanOption(payoff, exercise);
             option.setPricingEngine(engine);
             return option;
        }
예제 #2
0
        public override void calculate()
        {
            PlainVanillaPayoff payoff = arguments_.payoff as PlainVanillaPayoff;

            Utils.QL_REQUIRE(payoff != null, () => "non-plain payoff given");
            Utils.QL_REQUIRE(payoff.strike() > 0.0, () => "strike must be positive");

            double K = payoff.strike();
            double S = process_.x0();

            Utils.QL_REQUIRE(S >= 0.0, () => "negative or null underlying given");
            Utils.QL_REQUIRE(!triggered(S), () => "barrier touched");

            DoubleBarrier.Type barrierType = arguments_.barrierType;
            Utils.QL_REQUIRE(barrierType == DoubleBarrier.Type.KnockOut ||
                             barrierType == DoubleBarrier.Type.KnockIn, () =>
                             "only KnockIn and KnockOut options supported");

            double L      = arguments_.barrier_lo.GetValueOrDefault();
            double H      = arguments_.barrier_hi.GetValueOrDefault();
            double K_up   = Math.Min(H, K);
            double K_down = Math.Max(L, K);
            double T      = residualTime();
            double rd     = riskFreeRate();
            double dd     = riskFreeDiscount();
            double rf     = dividendYield();
            double df     = dividendDiscount();
            double vol    = volatility();
            double mu     = rd - rf - vol * vol / 2.0;
            double sgn    = mu > 0 ? 1.0 :(mu < 0 ? -1.0: 0.0);
            //rebate
            double R_L = arguments_.rebate.GetValueOrDefault();
            double R_H = arguments_.rebate.GetValueOrDefault();

            //european option
            EuropeanOption europeanOption         = new EuropeanOption(payoff, arguments_.exercise);
            IPricingEngine analyticEuropeanEngine = new AnalyticEuropeanEngine(process_);

            europeanOption.setPricingEngine(analyticEuropeanEngine);
            double european = europeanOption.NPV();

            double barrierOut = 0;
            double rebateIn   = 0;

            for (int n = -series_; n < series_; n++)
            {
                double d1      = D(S / H * Math.Pow(L / H, 2.0 * n), vol * vol + mu, vol, T);
                double d2      = d1 - vol * Math.Sqrt(T);
                double g1      = D(H / S * Math.Pow(L / H, 2.0 * n - 1.0), vol * vol + mu, vol, T);
                double g2      = g1 - vol * Math.Sqrt(T);
                double h1      = D(S / H * Math.Pow(L / H, 2.0 * n - 1.0), vol * vol + mu, vol, T);
                double h2      = h1 - vol * Math.Sqrt(T);
                double k1      = D(L / S * Math.Pow(L / H, 2.0 * n - 1.0), vol * vol + mu, vol, T);
                double k2      = k1 - vol * Math.Sqrt(T);
                double d1_down = D(S / K_down * Math.Pow(L / H, 2.0 * n), vol * vol + mu, vol, T);
                double d2_down = d1_down - vol * Math.Sqrt(T);
                double d1_up   = D(S / K_up * Math.Pow(L / H, 2.0 * n), vol * vol + mu, vol, T);
                double d2_up   = d1_up - vol * Math.Sqrt(T);
                double k1_down = D((H * H) / (K_down * S) * Math.Pow(L / H, 2.0 * n), vol * vol + mu, vol, T);
                double k2_down = k1_down - vol * Math.Sqrt(T);
                double k1_up   = D((H * H) / (K_up * S) * Math.Pow(L / H, 2.0 * n), vol * vol + mu, vol, T);
                double k2_up   = k1_up - vol * Math.Sqrt(T);

                if (payoff.optionType() == Option.Type.Call)
                {
                    barrierOut += Math.Pow(L / H, 2.0 * n * mu / (vol * vol)) *
                                  (df * S * Math.Pow(L / H, 2.0 * n) * (f_.value(d1_down) - f_.value(d1))
                                   - dd * K * (f_.value(d2_down) - f_.value(d2))
                                   - df * Math.Pow(L / H, 2.0 * n) * H * H / S * Math.Pow(H / S, 2.0 * mu / (vol * vol)) * (f_.value(k1_down) - f_.value(k1))
                                   + dd * K * Math.Pow(H / S, 2.0 * mu / (vol * vol)) * (f_.value(k2_down) - f_.value(k2)));
                }
                else if (payoff.optionType() == Option.Type.Put)
                {
                    barrierOut += Math.Pow(L / H, 2.0 * n * mu / (vol * vol)) *
                                  (dd * K * (f_.value(h2) - f_.value(d2_up))
                                   - df * S * Math.Pow(L / H, 2.0 * n) * (f_.value(h1) - f_.value(d1_up))
                                   - dd * K * Math.Pow(H / S, 2.0 * mu / (vol * vol)) * (f_.value(g2) - f_.value(k2_up))
                                   + df * Math.Pow(L / H, 2.0 * n) * H * H / S * Math.Pow(H / S, 2.0 * mu / (vol * vol)) * (f_.value(g1) - f_.value(k1_up)));
                }
                else
                {
                    Utils.QL_FAIL("option type not recognized");
                }

                double v1 = D(H / S * Math.Pow(H / L, 2.0 * n), -mu, vol, T);
                double v2 = D(H / S * Math.Pow(H / L, 2.0 * n), mu, vol, T);
                double v3 = D(S / L * Math.Pow(H / L, 2.0 * n), -mu, vol, T);
                double v4 = D(S / L * Math.Pow(H / L, 2.0 * n), mu, vol, T);
                rebateIn += dd * R_H * sgn * (Math.Pow(L / H, 2.0 * n * mu / (vol * vol)) * f_.value(sgn * v1) - Math.Pow(H / S, 2.0 * mu / (vol * vol)) * f_.value(-sgn * v2))
                            + dd * R_L * sgn * (Math.Pow(L / S, 2.0 * mu / (vol * vol)) * f_.value(-sgn * v3) - Math.Pow(H / L, 2.0 * n * mu / (vol * vol)) * f_.value(sgn * v4));
            }

            //rebate paid at maturity
            if (barrierType == DoubleBarrier.Type.KnockOut)
            {
                results_.value = barrierOut;
            }
            else
            {
                results_.value = european - barrierOut;
            }

            results_.additionalResults["vanilla"]    = european;
            results_.additionalResults["barrierOut"] = barrierOut;
            results_.additionalResults["barrierIn"]  = european - barrierOut;
        }