double uo_put_ql(const Date& todaysDate_,
	const Date& settlementDate_,
	const Date& maturity_,
	Real spot_,
	Real strike,
	Real barrier_,
	Real rebate_,
	Spread dividendYield,
	Rate riskFreeRate,
	Volatility volatility
	)
{
	// set up dates
	Calendar calendar = TARGET();
	Date todaysDate = todaysDate_;
	Date settlementDate = settlementDate_;
	Date maturity = maturity_;

	Settings::instance().evaluationDate() = todaysDate_;

	DayCounter dc = Actual360();

	Real barrier = barrier_;
	Real rebate = rebate_;

	Handle <Quote > spot(boost::shared_ptr<SimpleQuote>(new SimpleQuote(spot_)));

	Handle<YieldTermStructure> qTS(boost::shared_ptr<YieldTermStructure>(
		new FlatForward(settlementDate, dividendYield, dc)));

	Handle<YieldTermStructure> rTS(boost::shared_ptr<YieldTermStructure>(
		new FlatForward(settlementDate, riskFreeRate, dc)));

	Handle<BlackVolTermStructure> volTS(boost::shared_ptr<BlackVolTermStructure>(
		new BlackConstantVol(settlementDate, calendar, volatility, dc)));

	boost::shared_ptr<BlackScholesMertonProcess> stochProcess(new BlackScholesMertonProcess(spot, qTS, rTS, volTS));

	boost::shared_ptr<PricingEngine> engine(
		new AnalyticBarrierEngine(stochProcess));


	Option::Type type = Option::Put;

	boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(type, strike));

	boost::shared_ptr<Exercise> exercise(new EuropeanExercise(maturity));

	BarrierOption option(
		Barrier::UpOut,
		barrier,
		rebate,
		payoff,
		exercise);

	option.setPricingEngine(engine);

	return option.NPV();
}
    void AnalyticBSMHullWhiteEngine::calculate() const {

        QL_REQUIRE(process_->x0() > 0.0, "negative or null underlying given");

        const boost::shared_ptr<StrikedTypePayoff> payoff =
            boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
        QL_REQUIRE(payoff, "non-striked payoff given");

        const boost::shared_ptr<Exercise> exercise = arguments_.exercise;

        Time t = process_->riskFreeRate()->dayCounter().yearFraction(
                                    process_->riskFreeRate()->referenceDate(),
                                    exercise->lastDate());

        const Real a = model_->params()[0];
        const Real sigma = model_->params()[1];
        const Real eta =
            process_->blackVolatility()->blackVol(exercise->lastDate(),
                                                  payoff->strike());

        Real varianceOffset;
        if (a*t > std::pow(QL_EPSILON, 0.25)) {
            const Real v = sigma*sigma/(a*a)
                *(t + 2/a*std::exp(-a*t) - 1/(2*a)*std::exp(-2*a*t) - 3/(2*a));
            const Real mu = 2*rho_*sigma*eta/a*(t-1/a*(1-std::exp(-a*t)));

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

            varianceOffset = v + mu;
        }

        Handle<BlackVolTermStructure> volTS(
             boost::shared_ptr<BlackVolTermStructure>(
              new ShiftedBlackVolTermStructure(varianceOffset,
                                               process_->blackVolatility())));

        boost::shared_ptr<GeneralizedBlackScholesProcess> adjProcess(
                new GeneralizedBlackScholesProcess(process_->stateVariable(),
                                                   process_->dividendYield(),
                                                   process_->riskFreeRate(),
                                                   volTS));

        boost::shared_ptr<AnalyticEuropeanEngine> bsmEngine(
                                      new AnalyticEuropeanEngine(adjProcess));

        VanillaOption(payoff, exercise).setupArguments(
                                                   bsmEngine->getArguments());
        bsmEngine->calculate();

        results_ = *dynamic_cast<const OneAssetOption::results*>(
                                                    bsmEngine->getResults());
    }