通過在 Python 中實現 QuantLib,無法使用顯式有限差分法找到亞洲期權的價格
我正在嘗試使用 QuantLib Python 中的有限差分方法來查找連續幾何平均亞洲期權的價格。我無法這樣做。但是,我可以使用封閉式解決方案找到相同選項的價格。這是程式碼:
import QuantLib as ql today = ql.Settings.instance().evaluationDate averageType = ql.Average.Geometric option_type = ql.Option.Call strike = 100.0 exerciseDate = ql.TARGET().advance(today, 90, ql.Days) payoff = ql.PlainVanillaPayoff(option_type, strike) exercise = ql.EuropeanExercise(exerciseDate) option = ql.ContinuousAveragingAsianOption(averageType, payoff, exercise) initialValue = ql.QuoteHandle(ql.SimpleQuote(100)) sigma = 0.3 riskFreeTS = ql.YieldTermStructureHandle(ql.FlatForward(today, 0.03, ql.Actual365Fixed())) volTS = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(today, ql.NullCalendar(), sigma, ql.Actual365Fixed())) stochProcess = ql.BlackScholesProcess(initialValue, riskFreeTS, volTS) engine = ql.AnalyticContinuousGeometricAveragePriceAsianEngine(stochProcess) option.setPricingEngine(engine) price = option.NPV() print(f"Option price: {price}")
任何幫助/建議將不勝感激!!
QuantLib 確實有一個亞洲期權的 FD 定價引擎
ql.FdBlackScholesAsianEngine(stochProcess, tGrid=100, xGrid=100, aGrid=50)
,但我剛剛發現它只為離散的算術收益定價!如果您每天傳遞諸如 which samples之類的內容,則從 Continuous 到 Discrete(在此處記錄)不會對選項的價格產生太大影響。
asianFixingDates = [ql.TARGET().advance(today, x, ql.Days) for x in range(1,91)]
當然,這有點不切實際,但我們可以從分析定價器中恢復該限制內的連續價格(當我進行此更改時,我從原始程式碼中得到 4.187 與 4.184)。不幸的是,在這個選項上執行 FD 定價器會給我這個錯誤:
RuntimeError: Arithmetic averaging supported only
轉向算術平均選項確實會顯著影響定價。但是,如果這對您有任何用處,我已在此答案的底部包含對您的程式碼所需的更改(將平均值更改為
ql.Average.Arithmetic
,並使用離散選項)作為替代方案,如果您需要數值求解器,您可以考慮
ql.MCDiscreteGeometricAPEngine
(在此處記錄)使用 Monte Carlo 來代替幾何選項定價。您仍然需要為離散平均選項定價,但價格非常接近使用以下方法的分析解決方案:rng = "lowdiscrepancy" # could use "pseudorandom" numPaths = 100000 engine = ql.MCDiscreteGeometricAPEngine(stochProcess, rng, requiredSamples=numPaths) option.setPricingEngine(engine) price = option.NPV() print(f"Option price: {price}")
在 QL 中使用 FD 對離散平均算術亞洲進行定價:
import QuantLib as ql today = ql.Settings.instance().evaluationDate averageType = ql.Average.Arithmetic option_type = ql.Option.Call strike = 100.0 exerciseDate = ql.TARGET().advance(today, 90, ql.Days) pastFixings = 0 # Empty because this is a new contract asianFixingDates = [ql.TARGET().advance(today, x, ql.Days) for x in range(1,91)] payoff = ql.PlainVanillaPayoff(option_type, strike) exercise = ql.EuropeanExercise(exerciseDate) option = ql.DiscreteAveragingAsianOption(averageType, 0.0, pastFixings, asianFixingDates, payoff, exercise) initialValue = ql.QuoteHandle(ql.SimpleQuote(100)) sigma = 0.3 riskFreeTS = ql.YieldTermStructureHandle(ql.FlatForward(today, 0.03, ql.Actual365Fixed())) volTS = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(today, ql.NullCalendar(), sigma, ql.Actual365Fixed())) stochProcess = ql.BlackScholesProcess(initialValue, riskFreeTS, volTS) engine = ql.FdBlackScholesAsianEngine(stochProcess, tGrid=100, xGrid=100, aGrid=50) option.setPricingEngine(engine) price = option.NPV() print(f"Option price: {price}")