量化庫

使用二叉樹方法在 quantlib 中為期權定價 - 時間表示為一年的一小部分

  • February 27, 2017

出於學習目的,我正在嘗試使用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 等等),而無需與候選人一起玩。

引用自:https://quant.stackexchange.com/questions/32544