使用二叉樹方法在 quantlib 中為期權定價 - 時間表示為一年的一小部分
出於學習目的,我正在嘗試使用Cox-Ross-Rubinstein tree approach使用quantlib為歐洲期權定價。
EquityOption.cpp
作為庫的一部分的文件中提供了一些範例。但是我想給它定價,不使用日期(也就是說,沒有任何日期約定、日曆、到期日期……),但只使用一年的一小部分作為到期日(例如:with
T = 0.5
)。據我所知,所有範例僅考慮日期表示為“真實”日期(例如:2016 年 11 月 1 日)而不表示為到期時間(例如:T=0.1)的情況,即標準教科書案例。
由於該庫嚴重依賴引擎,並且這些引擎主要是用日期設計的,所以我很難擺脫日期。
對於 BS 分析公式,這很容易,因為引擎的核心依賴於與日期無關的BlackScholesCalculator (請參閱此處的完整範例)。
然而,對於二項式的情況,沒有這樣的與日期無關的常式(沒有 BinomialCalculator..),並且
DiscretizedVanillaOption
該類需要一個引擎的變數作為輸入來實例化它。我想到的一個合理的解決方案是找到兩個“假”日期,通過使用偽
.yearFraction(FakeStartDate, FakeEndDate);
函式來找到兩個與我想要的分數相匹配的最佳日期。然後使用這兩個日期來計算價格。然而,對於這樣一個簡單的請求,這種策略似乎很麻煩。如何使用二項式方法計算期權的價值,期限在 quantlib 中表示為一年的分數?
請看下面我到目前為止所做的事情,我堅持實例化
DiscretizedVanillaOption
.Calendar calendar = NullCalendar(); DayCounter dayCounter = SimpleDayCounter(); Date t0(1); Option::Type type = Option::Put; Real S0 = spot_; Real K = strike_; Spread q = dividendYield_; Rate r = interestRate_; Volatility sigma = volatility_; Settings::instance().evaluationDate() = t0; Handle<Quote> underlyingH((boost::static_pointer_cast<Quote>(boost::make_shared<SimpleQuote>(S0)))); Handle<YieldTermStructure> flatDividendTS((boost::static_pointer_cast<YieldTermStructure>(boost::make_shared<FlatForward>(t0, q, dayCounter)))); Handle<YieldTermStructure> flatTermStructure((boost::static_pointer_cast<YieldTermStructure>(boost::make_shared<FlatForward>(t0, r, dayCounter)))); Handle<BlackVolTermStructure> flatVolTS((boost::static_pointer_cast<BlackVolTermStructure>(boost::make_shared<BlackConstantVol>(t0, calendar, sigma, dayCounter)))); boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS)); boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(type, K)); Size timeSteps_ = 200; Time maturity = 0.2; TimeGrid grid(maturity, timeSteps_); boost::shared_ptr<CoxRossRubinstein> tree(new CoxRossRubinstein(bsmProcess, maturity, timeSteps_, payoff->strike())); boost::shared_ptr<BlackScholesLattice<CoxRossRubinstein> > lattice( new BlackScholesLattice<CoxRossRubinstein>(tree, r, maturity, timeSteps_)); DiscretizedVanillaOption option(/* ????*/,bsmProcess, grid);//<--------- First argument Here ? option.initialize(lattice, maturity); double price = option.presentValue();
最後,感謝 Luigi 的回答並通過觀察中的範例,
testsuite
我已經能夠實現它。假的開始日期設置為今天的日期和行使日期如下:Date exDate = today + Integer(timeToMaturity_*360+0.5);
下面是一個使用 CRR 為美式期權定價的工作範例:
double American_CoxRossRubinstein_T(bool IsCall /*if false= put*/, double underlying_, double strike_, double riskfree_, double volatility_, double dividendYield_, double timeToMaturity_) { /*----------------------------------------------------*/ Option::Type optionType =IsCall ? Option::Call : Option::Put ; QuantLib::Date today = QuantLib::Date::todaysDate(); QuantLib::Settings::instance().evaluationDate() = today; QuantLib::DayCounter dayCounter = QuantLib::Actual360(); Calendar calendar = NullCalendar(); Date exDate = today + Integer(timeToMaturity_*360+0.5); Handle<Quote> underlyingH((boost::static_pointer_cast<Quote>(boost::make_shared<SimpleQuote>(underlying_)))); Handle<YieldTermStructure> flatDividendTS((boost::static_pointer_cast<YieldTermStructure>(boost::make_shared<FlatForward>(today, dividendYield_, dayCounter)))); Handle<YieldTermStructure> flatTermStructure((boost::static_pointer_cast<YieldTermStructure>(boost::make_shared<FlatForward>(today,riskfree_, dayCounter)))); Handle<BlackVolTermStructure> flatVolTS((boost::static_pointer_cast<BlackVolTermStructure>(boost::make_shared<BlackConstantVol>(today, calendar, volatility_, dayCounter)))); boost::shared_ptr<Exercise> americanExercise(new AmericanExercise(today, exDate)); boost::shared_ptr<StrikedTypePayoff> payoff(new PlainVanillaPayoff(optionType, strike_)); VanillaOption americanOption(payoff, americanExercise); boost::shared_ptr<BlackScholesMertonProcess> bsmProcess(new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS)); Size timeSteps = static_cast<int>(std::max(700 * timeToMaturity_, 20.0)); americanOption.setPricingEngine(boost::static_pointer_cast<PricingEngine>(boost::make_shared<BinomialVanillaEngine<CoxRossRubinstein>>(bsmProcess, timeSteps ))); Real OptionPrice = americanOption.NPV(); std::cout << std::setprecision(9) << "American_CoxRossRubinstein_T = " << OptionPrice << std::endl; return OptionPrice; }
正如您所提到的,恐怕您將不得不使用假約會。
為了讓這個過程不那麼繁瑣,您可以使用帶有簡單公式的日計數器,例如 Act/360。給定開始日期,將更容易確定相應的結束日期(
startDate+36
對於 T=0.1,startDate+180
對於 T=0.5 等等),而無需與候選人一起玩。