def delta_hedge_svi(hedge_date, liquidition_date, daycounter, calendar, spot_c, spot_h, spot_l, black_var_surface, calibrated_params, orgnized_data_l, orgnized_data_h, rfs, optiontype): hedge_error_Ms = {} hedge_error_pct_Ms = {} if optiontype == ql.Option.Call: iscall = True else: iscall = False for nbr_month in range(4): params_Mi = calibrated_params[nbr_month] rf = rfs.get(nbr_month) moneyness_l, strikes_l, close_prices_l, expiration_date_l = orgnized_data_l.get( nbr_month) moneyness_h, strikes_h, close_prices_h, expiration_date_h = orgnized_data_h.get( nbr_month) temp_date = calendar.advance(liquidition_date, ql.Period(5, ql.Days)) if expiration_date_l <= temp_date: continue hedge_errors = [] hedge_errors_pct = [] moneyness = [] ttm = daycounter.yearFraction(hedge_date, expiration_date_h) svi = svimodel(ttm, params_Mi) discount = math.exp(-rf * ttm) forward = spot_c / math.exp(-rf * ttm) for idx_k, k in enumerate(strikes_h): if k in close_prices_l.keys(): close_l = close_prices_l.get(k) else: continue close_h = close_prices_h.get(k) # No arbitrage condition if close_h < k * math.exp(-rf * ttm) - spot_h: continue if close_h < 0.0001: continue #delta = hedge_util.calculate_delta_svi(black_var_surface, hedge_date, daycounter, calendar, # spot_c, rf, k, expiration_date_h, optiontype) dSigma_dK = svi.calculate_dSigma_dK(k, forward, ttm) stdDev = svi.svi_iv_function(math.log(k / forward, math.e)) * math.sqrt(ttm) black = blackcalculator(k, forward, stdDev, discount, iscall) delta = black.delta_total(spot_c, dSigma_dK) #delta = hedge_util.calculate_effective_delta_svi(hedge_date,daycounter,calendar,params_Mi,spot_c,rf,k,expiration_date_h,optiontype) #cash_on_hedge_date = hedge_util.calculate_cash_position(hedge_date, close_h, spot_h, delta) #hedge_error = hedge_util.calculate_hedging_error(hedge_date, liquidition_date, daycounter, spot_l, close_l, delta, # cash_on_hedge_date, rf) t = daycounter.yearFraction(hedge_date, liquidition_date) cash_h = close_h - delta * spot_h pnl = delta * spot_l + cash_h * math.exp(rf * t) - close_l pnl_pct = pnl / close_h if abs(pnl_pct) > 10: #print(liquidition_date, ',', nbr_month, ',', k, 'too large error', pnl_pct) continue hedge_error = round(pnl, 4) pnl_pct = round(pnl_pct, 4) hedge_errors.append(hedge_error) hedge_errors_pct.append(pnl_pct) moneyness.append(round(spot_h / k, 4)) hedge_error_Ms.update({nbr_month: [moneyness, hedge_errors]}) hedge_error_pct_Ms.update({nbr_month: [moneyness, hedge_errors_pct]}) return hedge_error_Ms, hedge_error_pct_Ms
vols = {2.2: 0.2449897447635236, 2.25: 0.22837076995826824, 2.3: 0.21949149068217633, 2.35: 0.20985304700906196, 2.4: 0.2041719266214876, 2.45: 0.20033927445461783, 2.5: 0.19807488063669001, 2.55: 0.19085764979481112, 2.6: 0.19159774017588876, 2.65: 0.1919016701828232, 2.7: 0.1934624432856883, 2.75: 0.19404949435809657} ttm = (maturitydt-hedge_date).days/365 discount = math.exp(-rf*ttm) dS = 0.001 iscall = False engineType = 'AnalyticEuropeanEngine' print('spot = ',spot) print('='*100) print("%10s %25s %25s %25s " % ("Strike","delta_total","delta_eff ","delta_constant_vol ")) print('-'*100) underlying_ql = ql.SimpleQuote(spot) daycounter = ql.ActualActual() calendar = ql.China() svi = svimodel(ttm,params) for strike in vols.keys(): #option_call = OptionPlainVanilla(strike, to_ql_date(maturitydt), ql.Option.Call).get_european_option() vol = vols.get(strike) #process = evaluation.get_bsmprocess_cnstvol(daycounter,calendar, underlying_ql, vol) #engine = OptionEngine(process, engineType).engine #option_call.setPricingEngine(engine) stdDev = vol * math.sqrt(ttm) forward = spot/discount black = blackcalculator(strike,forward,stdDev,discount,iscall) delta = black.delta(spot) # 隐含波动率对行权价的一阶倒数 dSigma_dK = svi.calculate_dSigma_dK(strike,forward,ttm) # 全Delta delta_total = black.delta_total(spot,ttm,dSigma_dK)
# Example strike = 2.4 dS = 0.001 iscall = True curve = get_curve_treasury_bond(date_ql, daycounter) yield_ts = util.get_yield_ts(date_ql, curve, maturitydt, daycounter) dividend_ts = util.get_dividend_ts(date_ql, daycounter) print('strike = ', strike, ', option type : call') print('=' * 100) print("%10s %25s %25s %25s %25s" % ("Spot", "delta_total", "delta_eff", "delta_constant_vol ", "diff")) print('-' * 100) svi_c = svimodel(ttm, params_c) call_delta_total = [] call_delta_cnst = [] call_delta_eff = [] call_diff = [] #index=['data_total','data_const'] result = pd.DataFrame() for spot in np.arange(2, 3.5, 0.025): forward = spot / discount x = math.log(strike / forward, math.e) vol = svi_c.svi_iv_function(x) stdDev = vol * math.sqrt(ttm) black = blackcalculator(strike, forward, stdDev, discount, iscall) delta = black.delta(spot)