计算期权策略组合收益
import pandas as pd
import os
import numpy as np
import matplotlib.pyplot as plt
import time
plt.rcParams['font.sans-serif']=['simhei']#用于正常显示中文标签
plt.rcParams['axes.unicode_minus']=False#用于正常显示负号
class Option():
"""
计算期权策略组合收益
作者:袁江磊
"""
def __init__(self,stock_price):
"""stock_price为到期股票各种可能价格,比如np.arange(1,100)"""
self.date=time.time()
#self.order()# 记录操作次数
self.info=[]#记录每次新加入期权信息
self.info_order = -1
self.stock_price=stock_price#到期股票各种可能价格,默认从0到100
self.data = pd.DataFrame(self.stock_price, columns=['到期股价'])#数据汇总用于收集记录所增加的投资内容
self.data['总收益']=0
self.make_files()
def make_files(self):
"""生成文件夹用于存放各种生成资料"""
path=os.getcwd()
#生成用于存放图片的文件夹
self.plt_save = False # 决定是否保存图片
self.plt_save_order = 0 # 记录保存图片的顺序
self.path_picture=os.path.join(path,'生成图片')
if os.path.exists(self.path_picture) == False:
os.makedirs(self.path_picture)
def option_data(self, X, cost, number_option, date='某月', name_option='期权', sale='买入', type='看涨', plot='yes'):
"""
生成期权损益数据,X为执行价格,cost为期权费用,number_option为购买的期权数量,name_option为期权名称,date为行权时间如‘date="三月"’
sale为买卖类型,包括买入'买入'和卖出'卖出';type为期权类型,包括看涨'看涨'和看跌'看跌';plot决定是否要绘图,'yes'或者'no'
例如:卖出执行价格为70的看涨期权,费用为4
option_income_data(self,X=70,cost=4,sale='卖出',type='看涨')
"""
#决定买卖方向的系数
if sale=='买入':
c_sale=1
else:
c_sale=-1
#决定看涨看跌的系数
if type=='看涨':
c_type=1
else:
c_type=-1
option_data=number_option*c_sale*(np.array(list(map(lambda x:max(x,0),c_type*(self.stock_price - X))))-cost)#计算到期日各种可能股价下期权收益数据
self.data[sale+name_option+type+date+str(X)]=option_data#将期权数据拼接在数据表之后
self.total()#计算总收益
self.info.append([X, cost, sale, type, number_option, c_sale]) # 将期权信息记录进去系统,[行权价,期权费,买卖方向,期权类型,期权数量,买卖方向]
self.info_order += 1
#是否将数据绘图
if plot=='yes':
self.plot(self.data)
return self.data
def plot(self,data):
plt.figure(figsize=(12,8))
info_order=0
cols_option=[]#记录期权列标题
for col in data.columns[2:]:
plt.plot(data['到期股价'],data[col],label=col)
if col[:2] in ['买入','卖出']:
cols_option.append(col)
#plt.plot(data['到期股价'],data['卖出300ETF看涨6月3700'],label='卖出300ETF看涨6月3700')
info=self.info[info_order]
info_order+=1
plt.plot([info[0]]*2,[0,-1*info[1]*info[4]*info[5]], alpha=0.3,linestyle='--')#绘制短垂线
plt.text(info[0], -1*info[1]*info[4]*info[5], '执行价为'+str(info[0]), size=8, rotation=-40)#, ha='left', va='bottom')
plt.plot(data['到期股价'], data['总收益'], label='总收益',color='red')#绘制总收益曲线
plt.legend(loc='upper right',fontsize=14)
plt.title('到期日投资收益图',fontsize=20)
plt.grid(True,alpha=0.3)
plt.plot(data['到期股价'],[0]*len(data['到期股价']),color='black',linewidth=2,alpha=0.3)#画出0横轴
#为了可以在画图时合适显现盈利曲线,需要计算纵轴最大最小显示刻度
#以最大期权费的五倍(横轴)为最大刻度
cost_options=[]
for info in self.info:
cost_option=info[1]*info[4]
cost_options.append(cost_option)
cost_option_max=max(cost_options)
plt.ylim(-5*cost_option_max,5*cost_option_max)#绘制期权坐标刻度上下限
plt.xticks(fontsize=13)
plt.yticks(fontsize=15)
plt.xlabel('到期股价',fontsize=18)
plt.ylabel('收益',fontsize=18)
#保存生成图片
if self.plt_save==True:
self.plt_save_order += 1
picture_name='图片'+str(self.plt_save_order)+'.jpg'
picture_path=os.path.join(self.path_picture,picture_name)
plt.savefig(picture_path)
def order(self):
self.order = -1 # 记录操作次数
self.order+=1
def total(self):
"""计算总收益"""
columns=self.data.columns.tolist()
columns.remove('到期股价');columns.remove('总收益')
self.data['总收益']=self.data.ix[:,columns].sum(axis=1)
def stock(self,S_0,number_stock,stock_name=''):
"""投资股票,S_0为初始股价,number_stock为所投资股票数量"""
self.stock_order=0
self.data['股票'+stock_name+str(self.stock_order)]=(self.data['到期股价']-S_0)*number_stock
self.stock_order+=1
self.total()
self.plot(self.data)
return self.data
if __name__=='__main__':
option=Option(np.arange(3699.75,3700.25,0.01))#设置到期日股价可能变动范围
option.plt_save = True#另图片保存
option.option_data(3700,0.0249, 200000, '5月', '300ETF', '卖出', '看涨', 'yes')#'卖出300ETF看涨5月3700'
option.option_data(3700.20, 0.0249, 200000, '6月', '300ETF', '买入', '看涨', 'yes') # 买入300ETF看涨6月3700.2
option.stock(3699.90, 200000,'沪深300')
option.stock(3699.94, 200000, '沪深300')
option.stock(3699.98,200000,'沪深300')
option.stock(3700.02, 200000, '沪深300')
option.stock(3700.06, 200000, '沪深300')
option.stock(3700.10, 200000, '沪深300')