计算期权策略组合收益_20200521_

计算期权策略组合收益

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')
    

猜你喜欢

转载自blog.csdn.net/weixin_45590329/article/details/106265414