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()
        {
            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;

        }
Esempio n. 4
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 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();
			}
        }