期權
求解隱含波動率 Vega 卡在 0 (Python)
所以我的目標是用盡可能少的手動輸入來計算選項希臘語。我設法通過金錢選項獲得了 IV,但是當我嘗試進一步的 OTM 罷工時,我的結果完全被搞砸了。
我執行這個循環來估計 IV:
def find_vol(target_value, call_put, S, K, T, r): MAX_ITERATIONS = 200 PRECISION = 0.01 sigma = 0.01 s = {} for i in range(0, MAX_ITERATIONS): price = bs_price(call_put, S, K, T, r, sigma) vega = bs_vega(call_put, S, K, T, r, sigma) price = price diff = target_value - price # our root print({'sigma':sigma,'vega':vega,'price':price, 'target_value':target_value,'diff':diff}) if abs(diff) < PRECISION: return sigma sigma = sigma + diff/vega s[diff]=sigma mindiff =min(list(s.keys()),key=abs) sigma = s[mindiff] # value wasn't found, return best guess so far return sigma
我的問題是,對於某些選項,循環會卡住,因為 Vega 變為 0,然後這條線不再有意義: sigma = sigma + diff/Vega 當問題發生時,它看起來像這樣:
問題可能是因為我在美式期權上使用了 BS 模型,這顯然是錯誤的,但我不確定使用二項式時我的結果是否會有所改善。建議將不勝感激!
完整的工作程式碼:‘‘‘python
import datetime from scipy.stats import norm from math import exp, log,sqrt import quantsbin.derivativepricing as qbdp def find_vol(target_value, call_put, S, K, T, r): MAX_ITERATIONS = 200 PRECISION = 0.01 sigma = 0.5 s = {} for i in range(0, MAX_ITERATIONS): price = bs_price(call_put, S, K, T, r, sigma) vega = bs_vega(call_put, S, K, T, r, sigma) price = price diff = target_value - price # our root #print({'sigma':sigma,'vega':vega,'price':price, 'target_value':target_value,'diff':diff}) if abs(diff) < PRECISION: return sigma sigma = sigma + diff/vega # f(x) / f'(x) s[diff]=sigma mindiff =min(list(s.keys()),key=abs) #print(mindiff) sigma = s[mindiff] #print(sigma) # value wasn't found, return best guess so far return sigma n = norm.pdf N = norm.cdf def bs_price(cp_flag,S,K,T,r,v,q=0.0): d1 = (log(S/K)+(r+v*v/2.)*T)/(v*sqrt(T)) d2 = d1-v*sqrt(T) if cp_flag == 'c': price = S*exp(-q*T)*N(d1)-K*exp(-r*T)*N(d2) else: price = K*exp(-r*T)*N(-d2)-S*exp(-q*T)*N(-d1) return price def bs_vega(cp_flag,S,K,T,r,v,q=0.0): d1 = (log(S/K)+(r+v*v/2.)*T)/(v*sqrt(T)) return S * sqrt(T)*n(d1) def calculate_iv_greeks(price_market,strike,expiration,date_calc,spot_underlying,rfr,kind,div_yield=0): exp_y,exp_m,exp_d = expiration calc_y, calc_m, calc_d = date_calc expiration = datetime.date(exp_y, exp_m, exp_d) date_calc = datetime.date(calc_y, calc_m, calc_d) T = (expiration - date_calc).days / 365. #T = (expiration - date_calc).days r = ((rfr/100)/365)*(expiration - date_calc).days iv = find_vol(price_market,kind,spot_underlying,strike,T,r) if kind =='C': type = 'Call' else: type = 'Put' expiration = datetime.date(exp_y,exp_m,exp_d).strftime("%Y%m%d") date_calc = datetime.date(calc_y, calc_m, calc_d).strftime("%Y%m%d") equity_option1 = qbdp.EqOption(option_type=type, strike=strike, expiry_date=str(expiration)) if div_yield != 0: eq1_engine = equity_option1.engine(model='Binomial', pricing_date=str(date_calc), spot0=spot_underlying, rf_rate=rfr/100, volatility=iv, yield_div=div_yield) print('Engine:Binomial') else: eq1_engine = equity_option1.engine(model='BSM', pricing_date=str(date_calc), spot0=spot_underlying, rf_rate=rfr/100, volatility=iv) print('Engine:BSM') D,G,TH,V,R,P = eq1_engine.risk_parameters().values() print(eq1_engine.risk_parameters()) return eq1_engine.valuation(),iv, D,TH V_market = 5.85 K = 285 S = 289.85 cp = 'c' greeks=calculate_iv_greeks(price_market=V_market,strike=K,expiration=. [2019,5,1],date_calc=[2019,4,17], spot_underlying=S,rfr=2.41,kind=cp,div_yield=0) print(greeks) print('Broker values: ', {'IV':0.1217 ,'Delta':0.765 })
’’’
您的 vega 偏離了 100 倍。將其更改為 sigma = sigma + diff/vega/100。
import datetime from scipy.stats import norm from math import exp, log,sqrt import quantsbin.derivativepricing as qbdp def find_vol(target_value, call_put, S, K, T, r): MAX_ITERATIONS = 200 PRECISION = 0.01 sigma = 0.5 s = {} for i in range(0, MAX_ITERATIONS): price = bs_price(call_put, S, K, T, r, sigma) vega = bs_vega(call_put, S, K, T, r, sigma) price = price diff = target_value - price # our root #print({'sigma':sigma,'vega':vega,'price':price, 'target_value':target_value,'diff':diff}) if abs(diff) < PRECISION: return sigma sigma = sigma + diff/vega/100 # f(x) / f'(x) s[diff]=sigma mindiff =min(list(s.keys()),key=abs) #print(mindiff) sigma = s[mindiff] #print(sigma) # value wasn't found, return best guess so far return sigma n = norm.pdf N = norm.cdf def bs_price(cp_flag,S,K,T,r,v,q=0.0): d1 = (log(S/K)+(r+v*v/2.)*T)/(v*sqrt(T)) d2 = d1-v*sqrt(T) if cp_flag == 'c': price = S*exp(-q*T)*N(d1)-K*exp(-r*T)*N(d2) else: price = K*exp(-r*T)*N(-d2)-S*exp(-q*T)*N(-d1) return price def bs_vega(cp_flag,S,K,T,r,v,q=0.0): d1 = (log(S/K)+(r+v*v/2.)*T)/(v*sqrt(T)) return S * sqrt(T)*n(d1) def calculate_iv_greeks(price_market,strike,expiration,date_calc,spot_underlying,rfr,kind,div_yield=0): exp_y,exp_m,exp_d = expiration calc_y, calc_m, calc_d = date_calc expiration = datetime.date(exp_y, exp_m, exp_d) date_calc = datetime.date(calc_y, calc_m, calc_d) T = (expiration - date_calc).days / 365 #T = (expiration - date_calc).days r = ((rfr/100)/365)*(expiration - date_calc).days iv = find_vol(price_market,kind,spot_underlying,strike,T,r) if kind =='C': type = 'Call' else: type = 'Put' expiration = datetime.date(exp_y,exp_m,exp_d).strftime("%Y%m%d") date_calc = datetime.date(calc_y, calc_m, calc_d).strftime("%Y%m%d") equity_option1 = qbdp.EqOption(option_type=type, strike=strike, expiry_date=str(expiration)) if div_yield != 0: eq1_engine = equity_option1.engine(model='Binomial', pricing_date=str(date_calc), spot0=spot_underlying, rf_rate=rfr/100, volatility=iv, yield_div=div_yield) print('Engine:Binomial') else: eq1_engine = equity_option1.engine(model='BSM', pricing_date=str(date_calc), spot0=spot_underlying, rf_rate=rfr/100, volatility=iv) print('Engine:BSM') D,G,TH,V,R,P = eq1_engine.risk_parameters().values() print(eq1_engine.risk_parameters()) return eq1_engine.valuation(),iv, D,TH V_market = 5.85 K = 285 S = 289.85 cp = 'c' expiration = datetime.date(2019, 5, 1) date_calc = datetime.date(2019, 4, 17) sig = find_vol(V_market, cp, S, K, T = (expiration - date_calc).days / 365, r=.0241) print("Estimated implied vol: " + str(np.round(sig*100,2)))