文章目录
- 备兑看涨期权(Covered Call)
- 保护看跌期权(protective put)
- 牛市价差套利
- 熊市价差套利
- 写在后面
本文所有代码基于windAPI,复现前先下载客户端并注册账号
备兑看涨期权(Covered Call)
构成:标的资产的多头 + 欧式看涨期权空头
损益:当标的资产市场价格上涨时,标的资产多头获利,看涨期权空头不行权。
当标的资产价格下降时,标的资产多头亏损,看涨期权行权获利弥补多头方损失。
头寸 | 损益 |
---|---|
标的资产多头 | S T − S 0 S_{T}-S_{0} ST−S0 |
看涨期权空头 | C − m a x ( S T − K , 0 ) C-max(S_{T}-K,0) C−max(ST−K,0) |
整体策略 | S T − S 0 − m a x ( S T − K , 0 ) + C S_{T}-S_{0}-max(S_{T}-K,0)+C ST−S0−max(ST−K,0)+C |
其中 S T S_{T} ST表示T时刻的市价,K表示执行价,C表示看涨期权价格。损益图如下所示。
代码实现:
def CoveredCall(UnderlyingCode, OptionCode,StartTime):
'''
UndelyingCode:标的资产代码
OptionCode:对冲期权的代码
StartTime:开始回测时间
'''
error_code, wsd_data = w.wsd(OptionCode, "exe_price,exe_enddate,close,exe_ratio", StartTime, StartTime, usedf=True)
StrikePrice = wsd_data['EXE_PRICE'][0]
StrikeTime = wsd_data['EXE_ENDDATE'][0]
OptionPrice = wsd_data['CLOSE'][0]
Ratio = wsd_data['EXE_RATIO'][0]
# 取当前系统时间
current_time = datetime.datetime.now()
# 比较行权日和当前,如果行权日晚于当前时间,只能回测到当前时间,否则可以回测到行权日。
if current_time > StrikeTime:
BacktestTime = StrikeTime
else:
BacktestTime = current_time
# 定义合约份数
N_ETF = 10000
N_option = 1
# 取行情数据
error_code, etf_data = w.wsd(UnderlyingCode, "close", StartTime, BacktestTime, usedf=True)
S0 = etf_data['CLOSE'][0]
Payoff = (etf_data - S0) * N_ETF + N_option * OptionPrice - np.max(etf_data - StrikePrice, 0) * Ratio
Payoff.plot(legend=None)
plt.xlabel('Time', fontsize=8)
plt.xticks(rotation=45)
plt.ylabel('Payoff', fontsize=8)
plt.show()
if __name__ == "__main__":
UnderlyingCode = "510050.SH"
OptionCode = "10005337.SH"
StartTime = "2023-04-27"
CoveredCall(UnderlyingCode, OptionCode, StartTime)
随着到期日临近,策略损益变化如下图:
保护看跌期权(protective put)
构成:标的资产多头+看跌期权多头
损益:当标的资产市场价格上涨时,标的资产多头获利,看跌期权多头不行权,损失期权费。
当标的资产价格下降时,标的资产多头亏损,看跌期权行权获利弥补空头方损失。
头寸 | 损益 |
---|---|
标的资产多头 | S T − S 0 S_{T}-S_{0} ST−S0 |
看跌期权多头 | m a x ( K − S T , 0 ) − C max(K-S_{T},0)-C max(K−ST,0)−C |
整体策略 | S T − S 0 + m a x ( S T − K , 0 ) − C S_{T}-S_{0}+max(S_{T}-K,0)-C ST−S0+max(ST−K,0)−C |
代码实现:
def ProtectedPut(UnderlyingCode, OptionCode,StartTime):
'''
UndelyingCode:标的资产代码
OptionCode:对冲期权的代码
StartTime:开始回测时间
'''
error_code, wsd_data = w.wsd(OptionCode, "exe_price,exe_enddate, close,exe_ratio", StartTime, StartTime, usedf=True)
StrikePrice = wsd_data['EXE_PRICE'][0]
StrikeTime = wsd_data['EXE_ENDDATE'][0]
OptionPrice = wsd_data['CLOSE'][0]
Ratio = wsd_data['EXE_RATIO'][0]
# 取当前系统时间
current_time = datetime.datetime.now()
# 比较行权日和当前,如果行权日晚于当前时间,只能回测到当前时间,否则可以回测到行权日。
if current_time > StrikeTime:
BacktestTime = StrikeTime
else:
BacktestTime = current_time
# 定义合约份数
N_etf = 10000
N_option = 1
# 取现货价格序列
error_code, etf_data = w.wsd(UnderlyingCode, "close", StartTime, BacktestTime, usedf=True)
S0 = etf_data['CLOSE'][0]
payoff = -N_option * OptionPrice + N_option * np.max(StrikePrice - etf_data) * Ratio + (etf_data - S0) * N_etf
payoff.plot(legend=None)
plt.xlabel('Time', fontsize=8)
plt.xticks(rotation=45)
plt.ylabel('Payoff', fontsize=8)
plt.show()
if __name__ == "__main__":
OptionCode = "10005338.SH"
UnderlyingCode = "510050.SH"
StartTime = "2023-04-27"
ProtectedPut(UnderlyingCode, OptionCode, StartTime)
随着到期日临近,策略损益变化如下图:
牛市价差套利
构成:买入行权价低的看涨期权/看跌期权,卖出行权价高的看涨期权/看跌期权,即低买高卖。
损益:以看涨期权为例,当标的资产价格上涨时,看涨期权的多头方获利,空头方亏损。
头寸 | 损益 |
---|---|
低行权价看涨期权多头 | m a x ( S t − K l o w , 0 ) − C 1 max(S_{t}-K_{low},0)-C1 max(St−Klow,0)−C1 |
高行权价看涨期权空头 | C 2 − m a x ( S t − K h i g h , 0 ) C2-max(S_{t}-K_{high},0) C2−max(St−Khigh,0) |
整体策略 | C 2 − C 1 + m a x ( S t − K l o w , 0 ) − m a x ( S t − K h i g h , 0 ) C2-C1+max(S_{t}-K_{low},0)-max(S_{t}-K_{high},0) C2−C1+max(St−Klow,0)−max(St−Khigh,0) |
整体损益情况如下图所示:
代码实现:
############################ BullSpread
def BullSpread(UnderlyingCode, code_high_strike, code_low_strike):
'''
UnderlyingCode:标的资产代码
code_high_strike:行权价高的期权代码
code_low_strike:行权价低的期权代码
:return:
'''
# 取期权基本数据
error_code, wss_data = w.wss(code_high_strike, "startdate,lasttradingdate", usedf=True) # 取期权的上市时间及结束时间
StartDate = wss_data['STARTDATE'][0]
EndDate = wss_data['LASTTRADINGDATE'][0]
# 取期权价格及执行价
error_code, high_strike_data = w.wsd(code_high_strike, "exe_price,close,exe_ratio,exe_mode", StartDate, StartDate, usedf=True)
error_code, low_strike_data = w.wsd(code_low_strike, "exe_price,close,exe_ratio,exe_mode", StartDate, StartDate, usedf=True)
K_high = high_strike_data['EXE_PRICE'][0]
K_low = low_strike_data['EXE_PRICE'][0]
OptionPrice_high_strike = high_strike_data['CLOSE'][0]
OptionPrice_low_strike = low_strike_data['CLOSE'][0]
Type = high_strike_data['EXE_MODE'][0]
Ratio_high_strike = high_strike_data['EXE_RATIO'][0]
Ratio_low_strike = low_strike_data['EXE_RATIO'][0]
# 取标的资产价格数据
error_code, etf_data = w.wsd(UnderlyingCode, "close", StartDate, EndDate, usedf=True)
# 定义合约份数
N_option = 1
# 判断期权是看涨还是看跌
if Type == "认购":
Payoff = N_option * OptionPrice_high_strike - np.maximum(etf_data - K_high, 0) * Ratio_high_strike - N_option * OptionPrice_low_strike + np.maximum(etf_data - K_low, 0) * Ratio_low_strike
elif Type == "认沽":
Payoff = N_option * OptionPrice_high_strike - np.maximum(K_high - etf_data, 0) * Ratio_high_strike - N_option * OptionPrice_low_strike + np.maximum(K_low - etf_data, 0) * Ratio_low_strike
else:
print("期权类型判断有误")
Payoff.plot(legend=None)
plt.xlabel('Time', fontsize=8)
plt.xticks(rotation=45)
plt.ylabel('Payoff', fontsize=8)
plt.show()
if __name__ == "__main__":
code_high_strike = "10006371.SH"
code_low_strike = "10006365.SH"
UnderlyingCode = "510050.SH"
BullSpread(UnderlyingCode, code_high_strike, code_low_strike)
随着到期日临近,策略损益变化如下图:
熊市价差套利
构成:卖出行权价低的看涨期权/看跌期权,买入行权价高的看涨期权/看跌期权,即低买高卖。
损益:以看涨期权为例,当标的资产价格上涨时,看涨期权的多头方获利,空头方亏损。
头寸 | 损益 |
---|---|
低行权价看涨期权空头 | C 1 − m a x ( S t − K l o w , 0 ) C1-max(S_{t}-K_{low},0) C1−max(St−Klow,0) |
高行权价看涨期权多头 | m a x ( S t − K h i g h , 0 ) − C 2 max(S_{t}-K_{high},0)-C2 max(St−Khigh,0)−C2 |
整体策略 | C 1 − C 2 + m a x ( S t − K h i g h , 0 ) − m a x ( S t − K l o w , 0 ) C1-C2+max(S_{t}-K_{high},0)-max(S_{t}-K_{low},0) C1−C2+max(St−Khigh,0)−max(St−Klow,0) |
整体损益情况如下图所示:
代码实现:
def BearSpread(UnderlyingCode, code_high_strike, code_low_strike):
'''
UnderlyingCode:标的资产代码
code_high_strike:行权价高的期权代码
code_low_strike:行权价低的期权代码
:return:
'''
# 取期权基本数据
error_code, wss_data = w.wss(code_high_strike, "startdate,lasttradingdate", usedf=True) # 取期权的上市时间及结束时间
StartDate = wss_data['STARTDATE'][0]
EndDate = wss_data['LASTTRADINGDATE'][0]
# 取期权价格及执行价
error_code, high_strike_data = w.wsd(code_high_strike, "exe_price,close,exe_ratio,exe_mode", StartDate, StartDate, usedf=True)
error_code, low_strike_data = w.wsd(code_low_strike, "exe_price,close,exe_ratio,exe_mode", StartDate, StartDate, usedf=True)
K_high = high_strike_data['EXE_PRICE'][0]
K_low = low_strike_data['EXE_PRICE'][0]
OptionPrice_high_strike = high_strike_data['CLOSE'][0]
OptionPrice_low_strike = low_strike_data['CLOSE'][0]
Type = high_strike_data['EXE_MODE'][0]
Ratio_high_strike = high_strike_data['EXE_RATIO'][0]
Ratio_low_strike = low_strike_data['EXE_RATIO'][0]
# 取标的资产价格数据
error_code, etf_data = w.wsd(UnderlyingCode, "close", StartDate, EndDate, usedf=True)
# 定义合约份数
N_option = 1
# 判断期权是看涨还是看跌
if Type == "认购":
Payoff = N_option * OptionPrice_low_strike - np.maximum(etf_data - K_low, 0) * Ratio_low_strike - N_option * OptionPrice_high_strike + np.maximum(etf_data - K_high, 0) * Ratio_high_strike
elif Type == "认沽":
Payoff = N_option * OptionPrice_low_strike - np.maximum(K_low - etf_data, 0) * Ratio_low_strike - N_option * OptionPrice_high_strike + np.maximum(K_high - etf_data, 0) * Ratio_high_strike
else:
print("期权类型判断有误")
Payoff.plot(legend=None)
plt.xlabel('Time', fontsize=8)
plt.xticks(rotation=45)
plt.ylabel('Payoff', fontsize=8)
plt.show()
if __name__ == "__main__":
code_high_strike = "10006371.SH"
code_low_strike = "10006365.SH"
UnderlyingCode = "510050.SH"
BearSpread(UnderlyingCode, code_high_strike, code_low_strike)
随着到期日临近,策略损益变化如下图:
写在后面
最近和做期权的朋友交流发现,实际应用这些策略是很复杂的。由于期权买方卖方权利和义务的特点,Covered Call在卖看涨期权时需要缴纳保证金,一旦标的资产价格迅速上涨,期权端可能会被强平。所以可能根本就熬不到合约到期,也就不会有上述的收益曲线了。
Protective Put策略也是一样。如果盘中隐含波动率急速上涨,期权价格上涨,此时将看跌期权平仓会获得不小的收益,根本不用持有到期…
所以期权的策略其实是非常复杂的,不光光只考虑初始时间点的期权价格,更要考虑盘中期权价格的变动。这里只是为了复现FRM中提出的策略,还有很多不严谨的地方。