replicatingvarianceswapengine.hpp
来自「有很多的函数库」· HPP 代码 · 共 219 行
HPP
219 行
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2006 Warren Chou
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
/*! \file replicatingvarianceswapengine.hpp
\brief Replicating engine for variance swaps
*/
#ifndef quantlib_replicating_varianceswap_engine_hpp
#define quantlib_replicating_varianceswap_engine_hpp
#include <ql/instruments/varianceswap.hpp>
#include <ql/instruments/europeanoption.hpp>
#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
namespace QuantLib {
//! Variance-swap pricing engine using replicating cost,
/*! as described in Demeterfi, Derman, Kamal & Zou,
"A Guide to Volatility and Variance Swaps", 1999
\ingroup forwardengines
\test returned fair variances verified against results from literature
*/
class ReplicatingVarianceSwapEngine : public VarianceSwap::engine {
public:
typedef std::vector<Real> StrikesType;
// constructor
ReplicatingVarianceSwapEngine(
const Real dk = 5.0,
const StrikesType& callStrikes = StrikesType(),
const StrikesType& putStrikes = StrikesType(),
const boost::shared_ptr<PricingEngine>& engine =
boost::shared_ptr<PricingEngine>());
void calculate() const;
protected:
// helper methods
void computeOptionWeights(const StrikesType&,
const Option::Type) const;
Real computeLogPayoff(const Real, const Real) const;
Real computeReplicatingPortfolio() const;
Rate riskFreeRate() const;
DiscountFactor riskFreeDiscount() const;
Real underlying() const;
Time residualTime() const;
private:
const Real dk_;
const StrikesType callStrikes_;
const StrikesType putStrikes_;
boost::shared_ptr<PricingEngine> optionEngine_;
};
// inline definitions
inline ReplicatingVarianceSwapEngine::ReplicatingVarianceSwapEngine(
const Real dk,
const StrikesType& callStrikes,
const StrikesType& putStrikes,
const boost::shared_ptr<PricingEngine>& engine)
: dk_(dk), callStrikes_(callStrikes), putStrikes_(putStrikes),
optionEngine_(engine) {
QL_REQUIRE(!callStrikes.empty() && !putStrikes.empty(),
"no strike(s) given");
QL_REQUIRE(*std::min_element(putStrikes.begin(),putStrikes.end())>0.0,
"min put strike must be positive");
QL_REQUIRE(*std::min_element(callStrikes.begin(), callStrikes.end())==
*std::max_element(putStrikes.begin(), putStrikes.end()),
"min call and max put strikes differ");
if (!engine)
optionEngine_ = boost::shared_ptr<PricingEngine>(
new AnalyticEuropeanEngine);
}
inline void ReplicatingVarianceSwapEngine::computeOptionWeights(
const StrikesType& availStrikes,
const Option::Type type) const {
if (availStrikes.empty()) return;
StrikesType strikes = availStrikes;
// add end-strike for piecewise approximation
switch (type) {
case Option::Call:
std::sort(strikes.begin(), strikes.end());
strikes.push_back(strikes.back() + dk_);
break;
case Option::Put:
std::sort(strikes.begin(), strikes.end(), std::greater<Real>());
strikes.push_back(std::max(strikes.back() - dk_, 0.0));
break;
default:
QL_FAIL("invalid option type");
}
// remove duplicate strikes
StrikesType::iterator last =
std::unique(strikes.begin(), strikes.end());
strikes.erase(last, strikes.end());
// compute weights
Real f = strikes.front();
Real slope, prevSlope = 0.0;
for (StrikesType::const_iterator k=strikes.begin();
// added end-strike discarded
k<strikes.end()-1;
k++) {
slope = std::fabs((computeLogPayoff(*(k+1), f) -
computeLogPayoff(*k, f))/
(*(k+1) - *k));
boost::shared_ptr<StrikedTypePayoff> payoff(
new PlainVanillaPayoff(type, *k));
if ( k == strikes.begin() )
results_.optionWeights.push_back(std::make_pair(payoff,slope));
else
results_.optionWeights.push_back(
std::make_pair(payoff, slope - prevSlope));
prevSlope = slope;
}
}
inline Real ReplicatingVarianceSwapEngine::computeLogPayoff(
const Real strike,
const Real callPutStrikeBoundary) const {
Real f = callPutStrikeBoundary;
return (2.0/residualTime()) * (((strike - f)/f) - std::log(strike/f));
}
inline
Real ReplicatingVarianceSwapEngine::computeReplicatingPortfolio() const {
boost::shared_ptr<Exercise> exercise(
new EuropeanExercise(arguments_.maturityDate));
Real optionsValue = 0.0;
for (results_.iterator=results_.optionWeights.begin();
results_.iterator<results_.optionWeights.end();
results_.iterator++) {
boost::shared_ptr<StrikedTypePayoff> payoff =
results_.iterator->first;
EuropeanOption option(arguments_.stochasticProcess,
payoff,
exercise);
option.setPricingEngine(optionEngine_);
Real weight = results_.iterator->second;
optionsValue += option.NPV() * weight;
}
Real f = results_.optionWeights.front().first->strike();
return 2.0 * riskFreeRate() -
2.0/residualTime() *
(((underlying()/riskFreeDiscount() - f)/f) +
std::log(f/underlying())) +
optionsValue/riskFreeDiscount();
}
// calculate fair variance via replicating portfolio
inline void ReplicatingVarianceSwapEngine::calculate() const {
computeOptionWeights(callStrikes_, Option::Call);
computeOptionWeights(putStrikes_, Option::Put);
results_.fairVariance = computeReplicatingPortfolio();
}
inline Real ReplicatingVarianceSwapEngine::underlying() const {
return arguments_.stochasticProcess->stateVariable()->value();
}
inline Time ReplicatingVarianceSwapEngine::residualTime() const {
return arguments_.stochasticProcess->time(arguments_.maturityDate);
}
inline Rate ReplicatingVarianceSwapEngine::riskFreeRate() const {
boost::shared_ptr<GeneralizedBlackScholesProcess> process =
boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
arguments_.stochasticProcess);
QL_REQUIRE(process, "Black-Scholes process required");
return process->riskFreeRate()->zeroRate(residualTime(), Continuous,
NoFrequency, true);
}
inline
DiscountFactor ReplicatingVarianceSwapEngine::riskFreeDiscount() const {
boost::shared_ptr<GeneralizedBlackScholesProcess> process =
boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
arguments_.stochasticProcess);
QL_REQUIRE(process, "Black-Scholes process required");
return process->riskFreeRate()->discount(residualTime());
}
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?