使用QuantLib计算DataFrame各行看涨期权价格偏差问题
期权定价与实际价格偏差过大的原因分析
问题背景
用户持有标普500执行价K=500的期权链数据,尝试通过Black-Scholes模型计算看涨期权价格,但计算结果与实际收盘价偏差极大(例如实际价格0.95时,计算值仅0.013527)。
原始期权链数据
date,call_open,call_high,call_low,call_close,put_open,put_high,put_low,put_close,stock_open,stock_high,stock_low,stock_close,stock_volume 2024-01-31 15:30:00,1.03,1.82,0.88,0.95,11.72,12.78,11.34,12.55,488.62,489.09,487.52,487.76,61890.0 2024-01-31 15:30:00,1.03,1.82,0.88,0.95,11.72,12.78,11.34,12.55,488.62,489.09,487.52,487.76,61890.0 2024-01-31 16:00:00,0.95,0.96,0.79,0.84,12.55,13.80,12.47,13.48,487.73,487.83,486.39,486.75,81468.0 2024-01-31 16:00:00,0.95,0.96,0.79,0.84,12.55,13.80,12.47,13.48,487.73,487.83,486.39,486.75,81468.0 2024-01-31 17:00:00,0.84,0.92,0.81,0.86,13.48,13.88,12.76,13.39,486.74,487.48,486.34,486.84,53420.0
计算结果与实际偏差示例
date,call_open,call_high,call_low,call_close,put_open,put_high,put_low,put_close,stock_open,stock_high,stock_low,stock_close,stock_volume,option_pricing 2024-01-31 15:30:00,1.03,1.82,0.88,0.95,11.72,12.78,11.34,12.55,488.62,489.09,487.52,487.76,61890.0,0.013527 2024-01-31 15:30:00,1.03,1.82,0.88,0.95,11.72,12.78,11.34,12.55,488.62,489.09,487.52,487.76,61890.0,0.013527 2024-01-31 16:00:00,0.95,0.96,0.79,0.84,12.55,13.80,12.47,13.48,487.73,487.83,486.39,486.75,81468.0,0.006911 2024-01-31 16:00:00,0.95,0.96,0.79,0.84,12.55,13.80,12.47,13.48,487.73,487.83,486.39,486.75,81468.0,0.006911 2024-01-31 17:00:00,0.84,0.92,0.81,0.86,13.48,13.88,12.76,13.39,486.74,487.48,486.34,486.84,53420.0,0.007350
使用的计算代码
import pandas as pd file_path = "path/expiry_20240214_strike_500.csv" data = pd.read_csv(file_path) data = data.dropna(subset=['stock_close']) data def compute_option_pricing(row): S = row['stock_close'] K = 500 v = data['stock_close'].std() / 100 ri = 0.0528 # 取自美国财政部2024年2月国债利率 date = pd.to_datetime(row['date']) today = ql.Date(date.day, date.month, date.year) expiry = pd.to_datetime("2024-02-14") expiry = ql.Date(expiry.day, expiry.month, expiry.year) # 设置评估日期 ql.Settings.instance().evaluationDate = today # 定义期权工具 option = ql.EuropeanOption(ql.PlainVanillaPayoff(ql.Option.Call, K), ql.EuropeanExercise(expiry)) # 市场参数 u = ql.SimpleQuote(S) r = ql.SimpleQuote(ri) sigma = ql.SimpleQuote(v) riskFreeCurve = ql.FlatForward(0, ql.TARGET(), ql.QuoteHandle(r), ql.Actual365Fixed()) volatility = ql.BlackConstantVol(0, ql.TARGET(), ql.QuoteHandle(sigma), ql.Actual365Fixed()) # 定价模型 process = ql.BlackScholesProcess(ql.QuoteHandle(u), ql.YieldTermStructureHandle(riskFreeCurve), ql.BlackVolTermStructureHandle(volatility)) # 定价引擎 engine = ql.AnalyticEuropeanEngine(process) option.setPricingEngine(engine) return option.NPV() # 应用函数计算期权价格 data['call_option_pricing'] = data.apply(compute_option_pricing, axis=1)
偏差原因分析
1. 波动率参数计算错误
这是核心问题:
- 代码中直接使用
data['stock_close'].std() / 100作为波动率,但该数据集仅包含3个不同的分钟级收盘价,计算出的标准差本身极小(约0.5左右),除以100后得到的波动率仅0.005,远低于标普500实际年化波动率(通常在10%-30%之间)。 - Black-Scholes模型要求输入年化波动率,正确的计算方式应为:
- 计算标的资产的收益率序列(如日度收益率:
(当日收盘价/昨日收盘价)-1) - 取收益率序列的标准差
- 乘以
sqrt(252)(年化因子,假设一年252个交易日)得到年化波动率。
若使用分钟级数据,需乘以sqrt(252*每日交易分钟数)(如美股每日交易390分钟,则sqrt(252*390)≈313)。
- 计算标的资产的收益率序列(如日度收益率:
2. 波动率样本量不足
仅用3个分钟级价格点计算标准差,完全不具备统计意义,无法反映标的资产的真实波动水平。需要至少数月的历史数据来计算合理的波动率。
3. 潜在的标的类型不匹配
若期权标的是标普500期货而非现货,应使用Black模型而非Black-Scholes模型,但此问题对当前偏差的影响远小于波动率错误。
修正建议
- 重新计算波动率:获取至少3个月的标普500日度收盘价数据,计算日度收益率的标准差后乘以
sqrt(252)得到年化波动率,输入模型时无需除以100(若收益率为小数形式)。 - 替换波动率来源:若无法获取足够历史数据,可使用期权市场的隐含波动率(可从期权链数据中通过反向推导Black-Scholes模型得到),这是更贴近实际市场的波动率参数。
内容的提问来源于stack exchange,提问作者user113156
相关产品推荐
相关产品推荐

