如何用字典替代列表计算期权希腊值?如何用apply/assign替代循环?
期权希腊值计算:字典实现与无循环方案
样本DataFrame df
Date Expiry Strike Price LTP Open Int Underlying Value Days 2019-06-04 2019-06-27 12500 19.9 1945425 12021.65 23 2019-06-10 2019-06-27 12500 6.5 2708100 11922.70 17
原计算代码(可正常运行)
def greek(underlyingprice,strikeprice,interestrate,expirationdate,callprice): x = mibian.BS([underlyingprice,strikeprice,interestrate,expirationdate], callPrice=callprice) IV = x.impliedVolatility c = mibian.BS([underlyingprice,strikeprice,interestrate,expirationdate], volatility = IV) delta = c.callDelta theta = c.callTheta rho = c.callRho vega = c.vega gamma = c.gamma return [delta,theta,rho,vega,gamma,IV] underlyingprice = df['Underlying Value'].values strikeprice = df['Strike Price'].values expirationdate = df['Days'].values interestrate = 7.3 callprice = df['LTP'].values final = [] for i, j, k, l in zip(underlyingprice, strikeprice, expirationdate, callprice): final.append(greek(i,j,interestrate,k, l)) final = pd.DataFrame(np.array(final)) final.columns = ['Delta','Theta','Rho','Vega','Gamma','Implied Volatility'] final[['Underlying Value','Strike Price','LTP']] = df[['Underlying Value','Strike Price','LTP']] final.reset_index(inplace=True) final.head()
输出结果
Delta Theta Rho Vega Gamma Implied Volatility Underlying Value Strike Price LTP 0.118572 -1.772300 0.885692 5.985913 0.000574 11.459351 12021.65 12500 19.9 0.050060 -1.076517 0.274938 2.656285 0.000327 12.268066 11922.70 12500 6.5
问题1:改用字典实现存储结果
直接在循环中生成字典列表,每个字典的键对应最终DataFrame的列名,值为计算得到的希腊值或原数据,之后直接将字典列表转为DataFrame即可,无需后续手动设置列名和合并数据:
方案1:修改函数直接返回字典
def greek_dict(underlyingprice, strikeprice, interestrate, expirationdate, callprice): x = mibian.BS([underlyingprice, strikeprice, interestrate, expirationdate], callPrice=callprice) IV = x.impliedVolatility c = mibian.BS([underlyingprice, strikeprice, interestrate, expirationdate], volatility=IV) return { 'Delta': c.callDelta, 'Theta': c.callTheta, 'Rho': c.callRho, 'Vega': c.vega, 'Gamma': c.gamma, 'Implied Volatility': IV, 'Underlying Value': underlyingprice, 'Strike Price': strikeprice, 'LTP': callprice } interestrate = 7.3 final_dict = [] for idx, row in df.iterrows(): res = greek_dict(row['Underlying Value'], row['Strike Price'], interestrate, row['Days'], row['LTP']) final_dict.append(res) final_df = pd.DataFrame(final_dict) final_df.reset_index(inplace=True) final_df.head()
方案2:基于原函数结果构建字典
如果不想修改原greek函数,可基于返回的列表构建字典:
final_dict = [] for i,j,k,l in zip(underlyingprice, strikeprice, expirationdate, callprice): greek_vals = greek(i,j,interestrate,k,l) res_dict = { 'Delta': greek_vals[0], 'Theta': greek_vals[1], 'Rho': greek_vals[2], 'Vega': greek_vals[3], 'Gamma': greek_vals[4], 'Implied Volatility': greek_vals[5], 'Underlying Value': i, 'Strike Price': j, 'LTP': l } final_dict.append(res_dict) final_df = pd.DataFrame(final_dict)
问题2:不使用for循环,用apply实现逐行计算
利用pandas.DataFrame.apply(),指定axis=1实现逐行处理,将每行的对应字段传入修改后的函数,返回包含所有希腊值的Series,直接与原DataFrame合并:
def greek_series(row, interestrate): x = mibian.BS([row['Underlying Value'], row['Strike Price'], interestrate, row['Days']], callPrice=row['LTP']) IV = x.impliedVolatility c = mibian.BS([row['Underlying Value'], row['Strike Price'], interestrate, row['Days']], volatility=IV) return pd.Series({ 'Delta': c.callDelta, 'Theta': c.callTheta, 'Rho': c.callRho, 'Vega': c.vega, 'Gamma': c.gamma, 'Implied Volatility': IV }) interestrate = 7.3 # 合并原DataFrame与计算结果 final_apply = df.join(df.apply(greek_series, axis=1, args=(interestrate,))) final_apply.reset_index(inplace=True) final_apply.head()
如果需要单独生成某几个列,也可以用assign配合lambda(效率略低于一次性返回Series):
def calculate_delta(row, interestrate): x = mibian.BS([row['Underlying Value'], row['Strike Price'], interestrate, row['Days']], callPrice=row['LTP']) IV = x.impliedVolatility c = mibian.BS([row['Underlying Value'], row['Strike Price'], interestrate, row['Days']], volatility=IV) return c.callDelta # 按需添加其他希腊值计算函数 final_assign = df.assign( Delta=lambda df: df.apply(calculate_delta, axis=1, args=(7.3,)), # Theta=lambda df: df.apply(calculate_theta, axis=1, args=(7.3,)), # ...其他列同理 )
注意:apply本质仍是逐行循环,但代码更简洁、符合pandas API风格;由于mibian.BS不支持向量化输入,这是最简洁的无显式循环方案。
内容的提问来源于stack exchange,提问作者Raagib khan
相关产品推荐
相关产品推荐

