在QuantLib里的VanillaOption是经过Instrument, Option, OneAssetOption类多层继承而来的,为了简单起见,这里给出的例子让VanillaOption直接继承Instrument。
class VanillaOption : public Instrument {
public:
class arguments;
class results;
class engine;
VanillaOption(const boost::shared_ptr<Payoff>&, const boost::shared_ptr<Exercise>&);
bool isExpired() const;
bool setupArguments(Arguments*) const;
bool fetchResults(const Results*) const;
Real delta() const;
Real gamma() const;
Real theta() const;
// more greeks ...
protected:
void setupExpired() const;
boost::shared_ptr<Payoff> payoff_;
boost::shared_ptr<Exercise> exercise_;
mutable Real delta_;
mutable Real gamma_;
mutable Real theta_;
// ... more
};
class VanillaOption::arguments : public PricingEngine::arguments {
public:
arguments();
void validate() const;
boost::shared_ptr<Payoff> payoff;
boost::shared_ptr<Exercise> exercise;
};
class Greeks : public virtual PricingEngine::results {
public:
Greeks();
Real delta, gamma, theta, vega, rho, dividendRho;
};
class VanillaOption::results : public Instrument::results, public Greeks {
public:
void reset();
};
class VanillaIOption::engine : public GenericEngine<VanillaOption::arguments, VanillaOption::results> {};
VanillaOption::VanillaOption(const boost::shared_ptr<StrikedTypePayoff> &off, const boost::shared_ptr<Exercise> &exercise) : payoff_(payoff), exercise_(exercise) {}
bool VanillaOption::isExpired() const {
Date today = Settings::instance().evaluationDate();
return exercise_->lastDate() < today;
}
void VanillaOption::setupExpired() const {
Instrument::setupExpired();
// delta_ = gamma_ = theta_ = 0;
}
void VanillaOption::setupArguments(PricingEngine::arguments *args) const {
VanillaOption::arguments *arguments = dynamic_cast<VanillaOption::arguments*>(args);
QL_REQUIRE(arguments != 0, "wrong argument type");
arguments->exercise = exercise_;
arguments->payoff = payoff_;
}
void VanillaOption::fetchResults(const PricingEngine::results *r) const {
Instrument::fetchResults(r);
const VanillaOption::results *results = dynamic_cast<const VanillaOption::results*>(r);
QL_ENSURE(results != 0, "wrong result type");
delta_ = results->delta;
// more greeks...
}
class AnalyticEuropeanEngine : public VanillaOption::engine {
public:
AnalyticEuropeanEngine(const shared_ptr<GeneralizedBlackScholesProcess> &process) : process_(process) {
registerWith(process);
}
void calculate() const {
QL_REQUIRE(arguments_.exercise->type() = Exercise::European, "not an European option");
boost::shared_ptr<PlainVanillaPayoff> payoff = boost::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
QL_REQUIRE(process, "Black-Scholes process needed");
// ...other requirements
Real spot = process_->stateVariable()->value();
// ...other needed quantities
BlackCalculator black(payoff, forwardPrice, stdDev, discount);
results_.value = black.value();
results_.delta = black.delta(spot);
// ...other greeks
}
private:
boost::shared_ptr<GeneralizedBlackSchloesProcess> process_;
};
cont