Inheritance: OneAssetOption
        public static Greeks GetOptionOnFutureGreeks(double underlyingPrice, double strike, double riskFreeRate,
                                                     DateTime expirationDate, DateTime calculationDate, string optionType, string exerciseType,
                                                     double optionPrice = double.NaN, double impliedVol = 0.15, string engineName = "baw")
        {
            QLNet.Date ExpirationDateObj  = new QLNet.Date(expirationDate.Day, expirationDate.Month, expirationDate.Year);
            QLNet.Date CalculationDateObj = new QLNet.Date(calculationDate.Day, calculationDate.Month, calculationDate.Year);

            QLNet.DayCounter DayCountObj = new QLNet.Actual365Fixed();
            QLNet.Calendar   CalendarObj = new QLNet.UnitedStates();

            Greeks GreeksOutput = new Greeks();

            QLNet.Option.Type OptionTypeObj;
            QLNet.Exercise    ExerciseObj;
            double            ImpliedVol;
            double            OptionPrice;

            int CalDte = DayCountObj.dayCount(CalculationDateObj, ExpirationDateObj);

            GreeksOutput.CalDte = CalDte;

            if (!double.IsNaN(optionPrice))
            {
                if (optionType.ToUpper() == "C")
                {
                    if (optionPrice + strike - underlyingPrice <= 1.0e-12)
                    {
                        GreeksOutput.Delta = 1;
                        return(GreeksOutput);
                    }
                }
                else if (optionType.ToUpper() == "P")
                {
                    if (optionPrice - strike + underlyingPrice <= 1.0e-12)
                    {
                        GreeksOutput.Delta = -1;
                        return(GreeksOutput);
                    }
                }
            }

            if (CalDte == 0)
            {
                if (optionType.ToUpper() == "C")
                {
                    if (strike <= underlyingPrice)
                    {
                        GreeksOutput.Delta = 1;
                    }
                    else
                    {
                        GreeksOutput.Delta = 0;
                    }
                }
                else if (optionType.ToUpper() == "P")
                {
                    if (strike >= underlyingPrice)
                    {
                        GreeksOutput.Delta = -1;
                    }
                    else
                    {
                        GreeksOutput.Delta = 0;
                    }
                }
                return(GreeksOutput);
            }

            if (optionType.ToUpper() == "C")
            {
                OptionTypeObj = QLNet.Option.Type.Call;
            }
            else if (optionType.ToUpper() == "P")
            {
                OptionTypeObj = QLNet.Option.Type.Put;
            }
            else
            {
                return(GreeksOutput);
            }

            if (exerciseType.ToUpper() == "E")
            {
                ExerciseObj = new QLNet.EuropeanExercise(ExpirationDateObj);
            }
            else if (exerciseType.ToUpper() == "A")
            {
                ExerciseObj = new QLNet.AmericanExercise(CalculationDateObj, ExpirationDateObj);
            }
            else
            {
                return(GreeksOutput);
            }

            QLNet.Settings.setEvaluationDate(CalculationDateObj);

            QLNet.Handle <Quote> UnderlyingObj = new QLNet.Handle <Quote>(new QLNet.SimpleQuote(underlyingPrice));
            QLNet.Handle <YieldTermStructure>    FlatRateObj  = new QLNet.Handle <YieldTermStructure>(new QLNet.FlatForward(CalculationDateObj, riskFreeRate, DayCountObj));
            QLNet.Handle <BlackVolTermStructure> FlatVolTsObj = new QLNet.Handle <BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, impliedVol, DayCountObj));

            QLNet.BlackProcess       BlackProc = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj);
            QLNet.PlainVanillaPayoff PayoffObj = new QLNet.PlainVanillaPayoff(OptionTypeObj, strike);

            QLNet.VanillaOption OptionObj = new QLNet.VanillaOption(PayoffObj, ExerciseObj);

            if (engineName == "baw")
            {
                OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc));
            }
            else if (engineName == "fda")
            {
                OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100));
            }
            else
            {
                return(GreeksOutput);
            }


            if (!double.IsNaN(optionPrice))
            {
                try
                {
                    ImpliedVol = OptionObj.impliedVolatility(targetValue: optionPrice, process: BlackProc, accuracy: 1e-5);
                }
                catch
                {
                    return(GreeksOutput);
                }

                FlatVolTsObj = new QLNet.Handle <BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, ImpliedVol, DayCountObj));
                BlackProc    = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj);

                if (engineName == "baw")
                {
                    OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc));
                }
                else if (engineName == "fda")
                {
                    OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100));
                }
                OptionPrice = optionPrice;
            }
            else
            {
                OptionPrice = OptionObj.NPV();
                ImpliedVol  = impliedVol;
            }

            OptionObj = new QLNet.VanillaOption(PayoffObj, new QLNet.EuropeanExercise(ExpirationDateObj));
            OptionObj.setPricingEngine(new QLNet.AnalyticEuropeanEngine(BlackProc));

            GreeksOutput.Delta       = OptionObj.delta();
            GreeksOutput.Vega        = OptionObj.vega();
            GreeksOutput.Theta       = OptionObj.thetaPerDay();
            GreeksOutput.Gamma       = OptionObj.gamma();
            GreeksOutput.OptionPrice = OptionPrice;
            GreeksOutput.ImpliedVol  = ImpliedVol;

            return(GreeksOutput);
        }
        public override void calculate()
        {
            Utils.QL_REQUIRE(process_.x0() > 0.0, () => "negative or null underlying given");

            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            Utils.QL_REQUIRE(payoff != null, () => "non-striked payoff given");

            Exercise exercise = arguments_.exercise;

            double t = process_.riskFreeRate().link.dayCounter().yearFraction(process_.riskFreeRate().link.referenceDate(),
                                                                              exercise.lastDate());

            double a     = model_.link.parameters()[0];
            double sigma = model_.link.parameters()[1];
            double eta   = process_.blackVolatility().link.blackVol(exercise.lastDate(), payoff.strike());

            double varianceOffset;

            if (a * t > Math.Pow(Const.QL_EPSILON, 0.25))
            {
                double v  = sigma * sigma / (a * a) * (t + 2 / a * Math.Exp(-a * t) - 1 / (2 * a) * Math.Exp(-2 * a * t) - 3 / (2 * a));
                double mu = 2 * rho_ * sigma * eta / a * (t - 1 / a * (1 - Math.Exp(-a * t)));

                varianceOffset = v + mu;
            }
            else
            {
                // low-a algebraic limit
                double v  = sigma * sigma * t * t * t * (1 / 3.0 - 0.25 * a * t + 7 / 60.0 * a * a * t * t);
                double mu = rho_ * sigma * eta * t * t * (1 - a * t / 3.0 + a * a * t * t / 12.0);

                varianceOffset = v + mu;
            }

            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(
                new ShiftedBlackVolTermStructure(varianceOffset, process_.blackVolatility()));

            GeneralizedBlackScholesProcess adjProcess =
                new GeneralizedBlackScholesProcess(process_.stateVariable(),
                                                   process_.dividendYield(),
                                                   process_.riskFreeRate(),
                                                   volTS);

            AnalyticEuropeanEngine bsmEngine = new AnalyticEuropeanEngine(adjProcess);

            VanillaOption option = new VanillaOption(payoff, exercise);

            option.setupArguments(bsmEngine.getArguments());

            bsmEngine.calculate();

            results_ = bsmEngine.getResults() as OneAssetOption.Results;
        }
        public DiscretizedVanillaOption(VanillaOption.Arguments args, StochasticProcess process, TimeGrid grid) {
            arguments_ = args;

            stoppingTimes_ = new InitializedList<double>(args.exercise.dates().Count);
            for (int i=0; i<stoppingTimes_.Count; ++i) {
                stoppingTimes_[i] = process.time(args.exercise.date(i));
                if (!grid.empty()) {
                    // adjust to the given grid
                    stoppingTimes_[i] = grid.closestTime(stoppingTimes_[i]);
                }
            }
        }
Exemple #4
0
        protected override void performCalculations()
        {
            exerciseDate_ = calendar_.advance(termStructure_.link.referenceDate(), maturity_);
            tau_          = termStructure_.link.timeFromReference(exerciseDate_);
            type_         = strikePrice_ * termStructure_.link.discount(tau_) >=
                            s0_.link.value() * dividendYield_.link.discount(tau_)
                 ? Option.Type.Call
                 : Option.Type.Put;
            StrikedTypePayoff payoff   = new PlainVanillaPayoff(type_, strikePrice_);
            Exercise          exercise = new EuropeanExercise(exerciseDate_);

            option_ = new VanillaOption(payoff, exercise);
            base.performCalculations();
        }
        public override void calculate()
        {
            AmericanExercise ex = arguments_.exercise as AmericanExercise;

            Utils.QL_REQUIRE(ex != null, () => "non-American exercise given");
            Utils.QL_REQUIRE(ex.payoffAtExpiry(), () => "payoff must be at expiry");
            Utils.QL_REQUIRE(ex.dates()[0] <= process_.blackVolatility().link.referenceDate(), () =>
                             "American option with window exercise not handled yet");

            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            Utils.QL_REQUIRE(payoff != null, () => "non-striked payoff given");

            double spot = process_.stateVariable().link.value();

            Utils.QL_REQUIRE(spot > 0.0, () => "negative or null underlying given");

            double variance = process_.blackVolatility().link.blackVariance(ex.lastDate(), payoff.strike());
            double?barrier  = arguments_.barrier;

            Utils.QL_REQUIRE(barrier > 0.0, () => "positive barrier value required");
            Barrier.Type barrierType = arguments_.barrierType;

            // KO degenerate cases
            if ((barrierType == Barrier.Type.DownOut && spot <= barrier) ||
                (barrierType == Barrier.Type.UpOut && spot >= barrier))
            {
                // knocked out, no value
                results_.value       = 0;
                results_.delta       = 0;
                results_.gamma       = 0;
                results_.vega        = 0;
                results_.theta       = 0;
                results_.rho         = 0;
                results_.dividendRho = 0;
                return;
            }

            // KI degenerate cases
            if ((barrierType == Barrier.Type.DownIn && spot <= barrier) ||
                (barrierType == Barrier.Type.UpIn && spot >= barrier))
            {
                // knocked in - is a digital european
                Exercise exercise = new EuropeanExercise(arguments_.exercise.lastDate());

                IPricingEngine engine = new AnalyticEuropeanEngine(process_);

                VanillaOption opt = new VanillaOption(payoff, exercise);
                opt.setPricingEngine(engine);
                results_.value       = opt.NPV();
                results_.delta       = opt.delta();
                results_.gamma       = opt.gamma();
                results_.vega        = opt.vega();
                results_.theta       = opt.theta();
                results_.rho         = opt.rho();
                results_.dividendRho = opt.dividendRho();
                return;
            }

            double riskFreeDiscount = process_.riskFreeRate().link.discount(ex.lastDate());

            AnalyticBinaryBarrierEngine_helper helper = new AnalyticBinaryBarrierEngine_helper(
                process_, payoff, ex, arguments_);

            results_.value = helper.payoffAtExpiry(spot, variance, riskFreeDiscount);
        }
        public static Greeks GetOptionOnFutureGreeks(double underlyingPrice,double strike,double riskFreeRate, 
            DateTime expirationDate, DateTime calculationDate, string optionType, string exerciseType,
            double optionPrice=double.NaN,double impliedVol=0.15,string engineName="baw")
        {
            QLNet.Date ExpirationDateObj = new QLNet.Date(expirationDate.Day, expirationDate.Month, expirationDate.Year);
            QLNet.Date CalculationDateObj = new QLNet.Date(calculationDate.Day, calculationDate.Month, calculationDate.Year);

            QLNet.DayCounter DayCountObj = new QLNet.Actual365Fixed();
            QLNet.Calendar CalendarObj = new QLNet.UnitedStates();

            Greeks GreeksOutput = new Greeks();
            QLNet.Option.Type OptionTypeObj;
            QLNet.Exercise ExerciseObj;
            double ImpliedVol;
            double OptionPrice;

            int CalDte = DayCountObj.dayCount(CalculationDateObj, ExpirationDateObj);
            GreeksOutput.CalDte = CalDte;

            if (!double.IsNaN(optionPrice))
            {
                if (optionType.ToUpper() == "C")
                {
                    if (optionPrice + strike - underlyingPrice <= 1.0e-12)
                    {
                        GreeksOutput.Delta = 1;
                        return GreeksOutput;
                    }
                }
                else if (optionType.ToUpper() == "P")
                {
                    if (optionPrice - strike + underlyingPrice <= 1.0e-12)
                    {
                        GreeksOutput.Delta = -1;
                        return GreeksOutput;
                    }
                }
            }

            if (CalDte == 0)
            {
                if (optionType.ToUpper() == "C")
                {
                    if (strike <= underlyingPrice)
                    {
                        GreeksOutput.Delta = 1;
                    }
                    else
                    {
                        GreeksOutput.Delta = 0;
                    }
                }
                else if (optionType.ToUpper() == "P")
                {
                    if (strike >= underlyingPrice)
                    {
                        GreeksOutput.Delta = -1;
                    }
                    else
                    {
                        GreeksOutput.Delta = 0;
                    }
                }
                return GreeksOutput;
            }

            if (optionType.ToUpper() == "C")
            {
                OptionTypeObj = QLNet.Option.Type.Call;
            }
            else if (optionType.ToUpper() == "P")
            {
                OptionTypeObj = QLNet.Option.Type.Put;
            }
            else
            {
                return GreeksOutput;
            }

            if (exerciseType.ToUpper() == "E")
            {
                ExerciseObj = new QLNet.EuropeanExercise(ExpirationDateObj);
            }
            else if (exerciseType.ToUpper() == "A")
            {
                ExerciseObj = new QLNet.AmericanExercise(CalculationDateObj, ExpirationDateObj);
            }
            else
            {
                return GreeksOutput;
            }

            QLNet.Settings.setEvaluationDate(CalculationDateObj);

            QLNet.Handle<Quote> UnderlyingObj = new QLNet.Handle<Quote>(new QLNet.SimpleQuote(underlyingPrice));
            QLNet.Handle<YieldTermStructure> FlatRateObj = new QLNet.Handle<YieldTermStructure>(new QLNet.FlatForward(CalculationDateObj, riskFreeRate, DayCountObj));
            QLNet.Handle<BlackVolTermStructure> FlatVolTsObj = new QLNet.Handle<BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, impliedVol, DayCountObj));

            QLNet.BlackProcess BlackProc = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj);
            QLNet.PlainVanillaPayoff PayoffObj = new QLNet.PlainVanillaPayoff(OptionTypeObj, strike);

            QLNet.VanillaOption OptionObj = new QLNet.VanillaOption(PayoffObj, ExerciseObj);

            if (engineName == "baw")
            {
                OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc));
            }
            else if (engineName == "fda")
            {
                OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100));
            }
            else
            {
                return GreeksOutput;
            }


            if (!double.IsNaN(optionPrice))
            {
                try
                {

                    ImpliedVol = OptionObj.impliedVolatility(targetValue:optionPrice, process:BlackProc,accuracy:1e-5);
                }
                catch
                {
                    return GreeksOutput;
                }
                
                FlatVolTsObj = new QLNet.Handle<BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, ImpliedVol, DayCountObj));
                BlackProc = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj);

                if (engineName == "baw")
                {
                    OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc));
                }
                else if (engineName == "fda")
                {
                    OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100));
                }
                OptionPrice = optionPrice;
            }
            else
            {
                OptionPrice = OptionObj.NPV();
                ImpliedVol = impliedVol;
            }

            OptionObj = new QLNet.VanillaOption(PayoffObj, new QLNet.EuropeanExercise(ExpirationDateObj));
            OptionObj.setPricingEngine(new QLNet.AnalyticEuropeanEngine(BlackProc));

            GreeksOutput.Delta = OptionObj.delta();
            GreeksOutput.Vega = OptionObj.vega();
            GreeksOutput.Theta = OptionObj.thetaPerDay();
            GreeksOutput.Gamma = OptionObj.gamma();
            GreeksOutput.OptionPrice = OptionPrice;
            GreeksOutput.ImpliedVol = ImpliedVol;

            return GreeksOutput;

        }
Exemple #7
0
        public override void calculate(DateTime calcDate, FP_Parameter fp_parameter)
        {
            // master data load

            this.indexOptionDAO_.SelectOwn();

            // market data load
            
            // index data
            clsHDAT_MARKETDATA_TB clstb = new clsHDAT_MARKETDATA_TB();

            string calcDateStr = calcDate.ToString("yyyyMMdd");
            QLNet.Settings.setEvaluationDate(calcDate);

            clstb.REF_DT = calcDateStr;
            clstb.INDEX_CD = this.indexOptionDAO_.UNDERLYING_INDEX_CD;

            int checkNum = clstb.SelectOwn();

            if (checkNum == 0) { throw new Exception("market data does not exist : " + calcDateStr + " " + clstb.INDEX_CD); }

            double indexData = clstb.LAST;

            // curveData --------------------------------------------------

            string curve_cd = "IRSKRW";
            
            YieldCurve curveManager = new YieldCurve();

            curveManager.loadCurveData(calcDate,curve_cd,clsHDAT_CURVEDATA_TB.RATE_TYP_Type.YTM);
            QLNet.YieldTermStructure yield_ts = curveManager.yieldCurve();

            // calculate

            string maturityDateStr = this.indexOptionDAO_.MATURITY_DT;

            System.Globalization.CultureInfo us
                = new System.Globalization.CultureInfo("en-US");

            DateTime maturityDate = DateTime.ParseExact(maturityDateStr, "yyyyMMdd", us);

            DayCounter dc = new Actual365Fixed();
            Calendar cal = new NullCalendar();

            double vol = 0.3;

            double strike = this.indexOptionDAO_.STRIKE;
            PlainVanillaPayoff strikePayoff = new PlainVanillaPayoff(Option.Type.
                Call, strike);

            Exercise exercise = new EuropeanExercise(maturityDate);

            VanillaOption q_option = new VanillaOption(strikePayoff,exercise);

            Handle<Quote> x0 = new Handle<Quote>(new SimpleQuote(indexData));
            FlatForward flatForward = new FlatForward(calcDate,0.01,dc);
            Handle<YieldTermStructure> dividendTS = new Handle<YieldTermStructure>(flatForward);
            Handle<YieldTermStructure> riskFreeTS = new Handle<YieldTermStructure>(yield_ts);
            BlackConstantVol blackConstVol = new BlackConstantVol(calcDate,cal,vol,dc);
            Handle<BlackVolTermStructure> blackVolTS = new Handle<BlackVolTermStructure>(blackConstVol);

            GeneralizedBlackScholesProcess process =new GeneralizedBlackScholesProcess(x0 ,dividendTS,riskFreeTS,blackVolTS);
            
            AnalyticEuropeanEngine europeanEngine = new AnalyticEuropeanEngine(process);

            q_option.setPricingEngine(europeanEngine);

            double value = q_option.NPV(); 
            double indexMultiplier = this.indexOptionDAO_.INDEX_MULTIPLIER;
            int quantity = this.indexOptionDAO_.QUANTITY;

            clsHITM_FP_GREEKRESULT_TB result_tb = new clsHITM_FP_GREEKRESULT_TB();

            result_tb.FP_GREEKRESULT_ID = IDGenerator.getNewGreekResultID(this.indexOptionDAO_.INSTRUMENT_ID,calcDateStr);
            result_tb.CALC_DT = calcDateStr;
            result_tb.INSTRUMENT_ID = this.indexOptionDAO_.INSTRUMENT_ID;
            result_tb.INSTRUMENT_TYP = this.indexOptionDAO_.INSTRUMENT_TYP;
            result_tb.UNDERLYING_ID = "KOSPI200";
            result_tb.UNDERLYING_VALUE = indexData;
            //result_tb.SEQ = 1;
            result_tb.DELTA = (q_option.delta() * indexData / 100) * indexMultiplier * quantity; // 1% Delta
            result_tb.GAMMA = 0.5 * (q_option.gamma() * indexData / 100) * indexMultiplier * quantity; // 1% Gamma
            result_tb.VEGA = q_option.vega() / 100 * indexMultiplier * quantity; // 1% point Vega
            result_tb.CALC_PRICE = value * indexMultiplier * quantity;
            result_tb.CALCULATED_FLAG = (int)clsHITM_FP_GREEKRESULT_TB.CALCULATED_FLAG_Type.CALCULATED;
            result_tb.CALCULATED_TIME = DateTime.Now.ToString("HHmmss"); ;
            result_tb.CALCULATE_TYP = (int)clsHITM_FP_GREEKRESULT_TB.CALCULATE_TYP_Type.ANALYTICS;

            // price

            if (result_tb.UpdateDateResult() == 0)
            { throw new Exception("update result fail. no exist , calcDate : " + calcDate.ToString("yyyyMMdd") + " , inst_id : " + result_tb.INSTRUMENT_ID); }

            // delta

            // gamma and others : no exist ?


        }
        //static void Main(string[] args) 
        //{
        //    List<double> xGrid = Enumerable.Range(0, 100).Select(x => x / 10.0).ToList();
        //    List<double> yGrid = Enumerable.Range(0, 100).Select(x => x / 10.0).ToList();

        //    //List<double> xGrid = Enumerable.Range(0, 100);
        //    CubicInterpolation cubic = new CubicInterpolation(xGrid, xGrid.Count, yGrid, 
        //                                                      CubicInterpolation.DerivativeApprox.Kruger, true,
        //                                                      CubicInterpolation.BoundaryCondition.SecondDerivative , 0.0,
        //                                                      CubicInterpolation.BoundaryCondition.SecondDerivative , 0.0);

            
        //}

        static void Main(string[] args)
        {

            DateTime timer = DateTime.Now;

            // set up dates
            Calendar calendar = new TARGET();
            Date todaysDate = new Date(15, Month.May, 1998);
            Date settlementDate = new Date(17, Month.May, 1998);
            Settings.setEvaluationDate(todaysDate);

            // our options
            Option.Type type = Option.Type.Put;
            double underlying = 36;
            double strike = 40;
            double dividendYield = 0.00;
            double riskFreeRate = 0.06;
            double volatility = 0.20;
            Date maturity = new Date(17, Month.May, 1999);
            DayCounter dayCounter = new Actual365Fixed();

            Console.WriteLine("Option type = " + type);
            Console.WriteLine("Maturity = " + maturity);
            Console.WriteLine("Underlying price = " + underlying);
            Console.WriteLine("Strike = " + strike);
            Console.WriteLine("Risk-free interest rate = {0:0.000000%}", riskFreeRate);
            Console.WriteLine("Dividend yield = {0:0.000000%}", dividendYield);
            Console.WriteLine("Volatility = {0:0.000000%}", volatility);
            Console.Write("\n");

            string method;

            Console.Write("\n");

            // write column headings
            int[] widths = new int[] { 35, 14, 14, 14 };
            Console.Write("{0,-" + widths[0] + "}", "Method");
            Console.Write("{0,-" + widths[1] + "}", "European");
            Console.Write("{0,-" + widths[2] + "}", "Bermudan");
            Console.WriteLine("{0,-" + widths[3] + "}", "American");

            List<Date> exerciseDates = new List<Date>(); ;
            for (int i = 1; i <= 4; i++)
                exerciseDates.Add(settlementDate + new Period(3 * i, TimeUnit.Months));

            Exercise europeanExercise = new EuropeanExercise(maturity);
            Exercise bermudanExercise = new BermudanExercise(exerciseDates);
            Exercise americanExercise = new AmericanExercise(settlementDate, maturity);

            Handle<Quote> underlyingH = new Handle<Quote>(new SimpleQuote(underlying));

            // bootstrap the yield/dividend/vol curves
            var flatTermStructure = new Handle<YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            var flatDividendTS = new Handle<YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            var flatVolTS = new Handle<BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));
            StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);
            var bsmProcess = new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

            // options
            VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise);
            VanillaOption bermudanOption = new VanillaOption(payoff, bermudanExercise);
            VanillaOption americanOption = new VanillaOption(payoff, americanExercise);


            // Analytic formulas:

            // Black-Scholes for European
            method = "Black-Scholes";
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + "}", "N/A");

            europeanOption.theta();

            // Barone-Adesi and Whaley approximation for American
            method = "Barone-Adesi/Whaley";
            americanOption.setPricingEngine(new BaroneAdesiWhaleyApproximationEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + "}", "N/A");
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());


            // Bjerksund and Stensland approximation for American
            method = "Bjerksund/Stensland";
            americanOption.setPricingEngine(new BjerksundStenslandApproximationEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + "}", "N/A");
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Integral
            method = "Integral";
            europeanOption.setPricingEngine(new IntegralEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + "}", "N/A");


            // Finite differences
            int timeSteps = 801;
            method = "Finite differences";
            europeanOption.setPricingEngine(new FDEuropeanEngine(bsmProcess, timeSteps, timeSteps - 1));
            bermudanOption.setPricingEngine(new FDBermudanEngine(bsmProcess, timeSteps, timeSteps - 1));
            americanOption.setPricingEngine(new FDAmericanEngine(bsmProcess, timeSteps, timeSteps - 1));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Jarrow-Rudd
            method = "Binomial Jarrow-Rudd";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<JarrowRudd>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<JarrowRudd>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<JarrowRudd>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());


            method = "Binomial Cox-Ross-Rubinstein";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Additive equiprobabilities
            method = "Additive equiprobabilities";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Trigeorgis
            method = "Binomial Trigeorgis";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<Trigeorgis>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<Trigeorgis>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<Trigeorgis>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Tian
            method = "Binomial Tian";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<Tian>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<Tian>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<Tian>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Leisen-Reimer
            method = "Binomial Leisen-Reimer";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<LeisenReimer>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<LeisenReimer>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<LeisenReimer>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Joshi
            method = "Binomial Joshi";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<Joshi4>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<Joshi4>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<Joshi4>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());


            // Monte Carlo Method: MC (crude)
            timeSteps = 1;
            method = "MC (crude)";
            ulong mcSeed = 42;
            IPricingEngine mcengine1 = new MakeMCEuropeanEngine<PseudoRandom>(bsmProcess)
                                            .withSteps(timeSteps)
                                            .withAbsoluteTolerance(0.02)
                                            .withSeed(mcSeed)
                                            .value();
            europeanOption.setPricingEngine(mcengine1);
            // Real errorEstimate = europeanOption.errorEstimate();
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", "N/A");


            // Monte Carlo Method: QMC (Sobol)
            method = "QMC (Sobol)";
            int nSamples = 32768;  // 2^15

            IPricingEngine mcengine2 = new MakeMCEuropeanEngine<LowDiscrepancy>(bsmProcess)
                                            .withSteps(timeSteps)
                                            .withSamples(nSamples)
                                            .value();
            europeanOption.setPricingEngine(mcengine2);
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", "N/A");

            // Monte Carlo Method: MC (Longstaff Schwartz)
            method = "MC (Longstaff Schwartz)";
            IPricingEngine mcengine3 = new MakeMCAmericanEngine<PseudoRandom>(bsmProcess)
                                        .withSteps(100)
                                        .withAntitheticVariate()
                                        .withCalibrationSamples(4096)
                                        .withAbsoluteTolerance(0.02)
                                        .withSeed(mcSeed)
                                        .value();
            americanOption.setPricingEngine(mcengine3);
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", "N/A");
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // End test
            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
        public void calculate(GBMParaViewModel para)
        {
            // set up dates
            Calendar calendar = new TARGET();
            //Date todaysDate = new Date(DateTime.Now);
            Date settlementDate = new Date(para.ReferenceDate_);
            Settings.setEvaluationDate(settlementDate);

            // our options
            Option.Type type = this.callPutEnum_;

            double underlying = para.CurrentPrice_;
            double strike = this.strike_;
            double dividendYield = para.Dividend_ / 100;
            double riskFreeRate = para.Drift_ / 100;
            double volatility = 0.0;

            if (this.callPutEnum_ == Option.Type.Call)
            {
                try
                {
                    volatility = para.Call_Interpolation_.value(this.strike_) / 100;
                    this.imVolCal_ = Math.Round(para.Call_Interpolation_.value(this.strike_), 1);
                }
                catch (Exception)
                {
                    volatility = para.Call_Interpolation_.value(this.strike_, true) / 100;
                    this.imVolCal_ = Math.Round(para.Call_Interpolation_.value(this.strike_,true), 1);
                }
                
            }
            else if (this.callPutEnum_ == Option.Type.Put)
            {
                try
                {
                    volatility = para.Call_Interpolation_.value(this.strike_) / 100;
                    this.imVolCal_ = Math.Round(para.Put_Interpolation_.value(this.strike_), 1);
                }
                catch (Exception)
                {
                    volatility = para.Call_Interpolation_.value(this.strike_, true) / 100;
                    this.imVolCal_ = Math.Round(para.Put_Interpolation_.value(this.strike_,true), 1);
                }
                
            }

            

            Date maturity = new Date(this.maturiry_);

            DayCounter dayCounter = new Actual365Fixed();

            //// write column headings
            //int[] widths = new int[] { 35, 14, 14, 14 };
            //Console.Write("{0,-" + widths[0] + "}", "Method");
            //Console.Write("{0,-" + widths[1] + "}", "European");
            //Console.Write("{0,-" + widths[2] + "}", "Bermudan");
            //Console.WriteLine("{0,-" + widths[3] + "}", "American");

            //List<Date> exerciseDates = new List<Date>(); ;
            //for (int i = 1; i <= 4; i++)
            //    exerciseDates.Add(settlementDate + new Period(3 * i, TimeUnit.Months));

            Exercise europeanExercise = new EuropeanExercise(maturity);
            //Exercise bermudanExercise = new BermudanExercise(exerciseDates);
            //Exercise americanExercise = new AmericanExercise(settlementDate, maturity);

            Handle<Quote> underlyingH = new Handle<Quote>(new SimpleQuote(underlying));

            // bootstrap the yield/dividend/vol curves
            var flatTermStructure = new Handle<YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            var flatDividendTS = new Handle<YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            var flatVolTS = new Handle<BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));
            StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);
            var bsmProcess = new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

            // options
            VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise);

            // Analytic formulas:
            // Black-Scholes for European
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));
            
            this.npv_ = Math.Round(europeanOption.NPV(),6);
            this.deltaCal_ = Math.Round(europeanOption.delta(),6);
            this.gammaCal_= Math.Round(europeanOption.gamma(),6);
            this.vegaCal_ = Math.Round(europeanOption.vega()/ 100, 6);
            this.thetaCal_= Math.Round(europeanOption.theta()/ 365,6) ;
            this.rhoCal_ = Math.Round(europeanOption.rho() / 100, 6);

        }
        //public override void calculate(Excel_instrumentViewModel excel_inst)
        //{
        //    //#region Setting
		 
        //    //Excel_compositeOptionViewModel compOptionVM = excel_interface as Excel_compositeOptionViewModel;

        //    //if (compOptionVM == null)
        //    //{
        //    //    //error
        //    //}

        //    //Calendar calendar = new TARGET();

        //    //Date todaysDate = todaysDate = ProgramVariable.ReferenceDate_;

        //    //Date settlementDate = todaysDate;
            
        //    //Settings.setEvaluationDate(todaysDate);

        //    //DayCounter dayCounter = new Actual365Fixed();

        //    //if (this.Excel_underlyingCalcInfo_paraViewModel_.Excel_underlyingInfo_paraViewModel_.Count == 0)
        //    //{ 
        //    //    //error
        //    //}

        //    //Excel_geometricBMViewModel gbm = this.Excel_underlyingCalcInfo_paraViewModel_.Excel_underlyingInfo_paraViewModel_[0].Excel_underlyingModel_paraViewModel_ as Excel_geometricBMViewModel;

        //    //double currentValue = Convert.ToDouble(gbm.CurrentValue_);

        //    //SimpleQuote quote = new SimpleQuote(currentValue);
        //    //Handle<Quote> underlyingH = new Handle<Quote>(quote);

        //    //double drift = Convert.ToDouble(gbm.Drift_);
        //    //double dividendYield = Convert.ToDouble(gbm.Dividend_);

        //    //double volatility = Convert.ToDouble(gbm.Volatility_);

        //    //SimpleQuote volQuote = new SimpleQuote(volatility);
        //    //Handle<Quote> volH = new Handle<Quote>(volQuote);

        //    //var flatTermStructure = new Handle<YieldTermStructure>(new FlatForward(settlementDate, drift, dayCounter));
        //    //var flatDividendTS = new Handle<YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
        //    //Handle<BlackVolTermStructure> flatVolTS = new Handle<BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volH, dayCounter));

        //    //BlackScholesMertonProcess bsmProcess = new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

        //    //double value = 0.0;

        //    //DateTime exDate = compOptionVM.ExerciseDate_;

        //    //List<QLNet.OneAssetOption> optionList = new List<QLNet.OneAssetOption>();

        //    //foreach (Excel_compositeOption_subtypeViewModel item in compOptionVM.Excel_compositeOption_subtypeViewModelList_)
        //    //{
        //    //    optionList.Add(this.option(item, bsmProcess, exDate));
        //    //}
            
        //    ////------------------------------------------------

        //    //foreach (var item in optionList)
        //    //{
        //    //    value = value + item.NPV();
        //    //}

        //    //if (this.Separable_)
        //    //{
        //    //    double matrutiryPayAmt = 0.0;

        //    //    Excel_yieldCurveViewModel e_ycvm
        //    //        = this.Excel_discountCurve_paraViewModel_.discountYieldCurve("KRW");

        //    //    QLNet.YieldTermStructure yts = e_ycvm.yieldCurve();

        //    //    value += matrutiryPayAmt;
        //    //}
            
        //    //#endregion
            
        //    //#region Calculation

        //    //quote.setValue(currentValue*1.01);
        //    //double sup = optionList[0].NPV();

        //    //quote.setValue(currentValue * 0.99);
        //    //double sdown = optionList[0].NPV();

        //    //double delta = (sup - sdown) / (currentValue * 0.02);

        //    //double gamma = (sup * sup - 2 * value + sdown * sdown) / (currentValue * 0.01 * currentValue * 0.01);

        //    //quote.setValue(currentValue);

        //    //volQuote.setValue(volatility - 0.01);
        //    //double voldown = optionList[0].NPV();

        //    //volQuote.setValue(volatility + 0.01);
        //    //double volup = optionList[0].NPV();

        //    //double vega = (volup - voldown) / 2;

        //    //#endregion

        //    //#region Result

        //    //this.Excel_resultViewModel_.Price_ = value.ToString();

        //    //double baseUnderlyingValue = Convert.ToDouble(
        //    //    excel_interface.Excel_underlyingCalcInfoViewModel_.Excel_underlyingInfoViewModel_[0].BasePrice_);

        //    //this.Excel_resultViewModel_.PercentPrice_ = (100 * value / baseUnderlyingValue).ToString();

        //    //double notional = Convert.ToDouble(excel_interface.Excel_issueInfoViewModel_.Notional_);

        //    //this.Excel_resultViewModel_.EvalAmount_ = ( notional * ( value / baseUnderlyingValue) ).ToString();

        //    //#endregion

        //    //double gamma = optionList[0].gamma();
        //    //double vega = optionList[0].vega();
            
        //}

        private QLNet.OneAssetOption option(Excel_compositeOption_subtypeViewModel compositeOptionVM, 
                                        BlackScholesMertonProcess bsmProcess, 
                                        DateTime exDate)
        {

            Date exerciseDate = new Date(exDate);

            if (compositeOptionVM.Excel_Type_.ToUpper() == "EXCEL_VANILLACALLPUT")
            {
                Excel_vanillaCallPutViewModel e_vcpvm = compositeOptionVM as Excel_vanillaCallPutViewModel;

                QLNet.PlainVanillaPayoff payoff = new PlainVanillaPayoff(Option.Type.Call, e_vcpvm.StrikeValue_);

                QLNet.EuropeanExercise ex = new EuropeanExercise(exerciseDate);

                QLNet.VanillaOption vanillaOption = new VanillaOption(payoff, ex);
                
                return vanillaOption;

            }
            else if (compositeOptionVM.Excel_Type_.ToUpper() == "EXCEL_UPINOUTCALL" ||
                     compositeOptionVM.Excel_Type_.ToUpper() == "EXCEL_DOWNINOUTCALL" )
            {
                Excel_upInOutCallViewModel e_uiocvm = compositeOptionVM as Excel_upInOutCallViewModel;

                Barrier.Type type = Barrier.Type.UpOut;

                if (e_uiocvm.InOut_.ToString() == "IN")
                {
                    type = Barrier.Type.UpIn;
                }

                double strikeValue = e_uiocvm.StrikeValue_;
                double barrierValue = e_uiocvm.BarrierValue_;
                double partiRate = Convert.ToDouble(e_uiocvm.PartiRate_)/100.0;
                double rebateValue = Convert.ToDouble(e_uiocvm.RebateCouponValue_);

                QLNet.PlainVanillaPayoff payoff = new PlainVanillaPayoff(Option.Type.Call, strikeValue);

                QLNet.EuropeanExercise ex = new EuropeanExercise(exerciseDate);

                QLNet.BarrierOption barrierOption = new QLNet.BarrierOption(type, barrierValue, partiRate, rebateValue, payoff, ex);

                QLNet.AnalyticBarrierWithPartiRateEngine engine = new AnalyticBarrierWithPartiRateEngine(bsmProcess);

                barrierOption.setPricingEngine(engine);

                return barrierOption;
            }
            else if (compositeOptionVM.Excel_Type_.ToUpper() == "")
            {
                Barrier.Type type = Barrier.Type.DownOut;

                QLNet.PlainVanillaPayoff payoff = new PlainVanillaPayoff(Option.Type.Call, 261.4);

                QLNet.EuropeanExercise ex = new EuropeanExercise(exerciseDate);

                QLNet.BarrierOption barrierOption = new QLNet.BarrierOption(type, 313.68, 0.32, 0.0, payoff, ex);

                QLNet.AnalyticBarrierWithPartiRateEngine engine = new AnalyticBarrierWithPartiRateEngine(bsmProcess);

                barrierOption.setPricingEngine(engine);

                return barrierOption;
            }
            else
            {
                throw new Exception("unknown compositeOptionType");
            }
            

        }
        public void calculate(double[] p, GBMParaViewModel para)
        {

            this.xData_ = p;
            this.yData_ = new double[p.Length];

            double sellBuySign = 1.0;

            if (this.sellBuy_ == "매도")
            {
                sellBuySign = -1.0;
            }
            else
            { 
            }

            // set up dates
            Calendar calendar = new TARGET();
            //Date todaysDate = new Date(DateTime.Now);
            Date settlementDate = new Date(para.ReferenceDate_);
            Settings.setEvaluationDate(settlementDate);

            // our options
            Option.Type type = this.callPutEnum_;

            double underlying = para.CurrentPrice_;
            double strike = this.strike_;
            double dividendYield = para.Dividend_ / 100;
            double riskFreeRate = para.Drift_ / 100;

            if (this.callPutEnum_ == Option.Type.Call)
            {
                this.imVol_ = para.Call_Interpolation_.value(this.strike_);
            }
            else if (this.callPutEnum_ == Option.Type.Put)
            {
                this.imVol_ = para.Put_Interpolation_.value(this.strike_);
            }

            double volatility = (this.imVol_ ) / 100;

            Date maturity = new Date(this.maturiry_.AddDays(1));
            

            if (this.callPutEnum_ == 0)
            {
                this.deltaCal_ = 1.0;
                this.gammaCal_ = 0.0;
                this.vegaCal_ = 0.0;
                this.thetaCal_ = 0.0;
                this.rhoCal_ = 0.0;

                this.deltaPosition_ = sellBuySign * this.unit_ * 500000 * underlying;

                this.deltaRisk_ = this.deltaPosition_ * 0.09;
                this.gammaRisk_ = 0.0;
                this.vegaRisk_ = 0.0;

                this.totalRisk_ = this.deltaRisk_ + this.gammaRisk_ + this.vegaRisk_;
                this.deepOTM_ = 0.0;

                //this.remainDays_ = maturity - settlementDate;
                this.remainDays_ = (this.maturiry_ - para.ReferenceDate_).Days + 1;

                return;
            }

            DayCounter dayCounter = new Actual365Fixed();

            Exercise europeanExercise = new EuropeanExercise(maturity);

            SimpleQuote quote = new SimpleQuote(underlying);

            Handle<Quote> underlyingH = new Handle<Quote>(quote);

            // bootstrap the yield/dividend/vol curves
            var flatTermStructure = new Handle<YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            var flatDividendTS = new Handle<YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            var flatVolTS = new Handle<BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));
            StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);
            var bsmProcess = new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

            // options
            VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise);

            // Analytic formulas:
            // Black-Scholes for European
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));

            this.npv_ = Math.Round(europeanOption.NPV(), 6);
            this.deltaCal_ = sellBuySign * Math.Round(europeanOption.delta(), 6);
            this.gammaCal_ = sellBuySign * Math.Round(europeanOption.gamma(), 6);
            this.vegaCal_ = sellBuySign * Math.Round(europeanOption.vega() / 100, 6);
            this.thetaCal_ = sellBuySign * Math.Round(europeanOption.theta() / 365, 6);
            this.rhoCal_ = sellBuySign * Math.Round(europeanOption.rho() / 100, 6);

            this.deltaPosition_ = Math.Round(this.deltaCal_ * this.unit_ * 500000 * underlying,0);
            this.deltaRisk_ = Math.Round(this.deltaPosition_ * 0.09,0);
            this.gammaRisk_ = Math.Round(0.5 * this.gammaCal_ * (underlying * underlying * 0.08 * 0.08) * this.unit_ * 500000, 0);
            this.vegaRisk_ = Math.Round(this.vegaCal_ * this.imVol_ * 0.25 * this.unit_ * 500000, 0);
            
            this.totalRisk_ = this.deltaRisk_ + this.gammaRisk_ + this.vegaRisk_;

            this.deepOTM_ = 0.0;
            //this.remainDays_ = maturity - settlementDate;
            this.remainDays_ = (this.maturiry_ - para.ReferenceDate_).Days + 1;


            for (int i = 0; i < this.xData_.Length; i++)
			{
                quote.setValue(this.xData_[i]);
                this.yData_[i] = 500000.0 * (double)this.unit_ * europeanOption.NPV();
			}
        }