作业季露露

上次那个代码有很多问题,大改了一下

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 加载ETF数据
df = pd.read_csv("C:/Users/z'z'z/Desktop/50ETF_daily.csv")

# 数据清理,移除非日期格式的行
df = df[pd.to_datetime(df['日期'], errors='coerce').notna()]

# 将'日期'列转换为datetime类型
df['日期'] = pd.to_datetime(df['日期'], format='%Y/%m/%d')

# 按日期排序
df = df.sort_values('日期')

# 生成完整日期范围
date_range = pd.date_range(df['日期'].min(),df['日期'].max() , freq='D')
full_dates = pd.DataFrame(date_range, columns=['日期'])
# 合并原始数据和完整日期表
df = pd.merge(full_dates, df, on='日期', how='left')
# 填充缺失的数据(这里假设用前一天的数据填充)
df.fillna(method='ffill', inplace=True)
# 设定均线长度
short_window = 20  # 短期均线
long_window = 50   # 长期均线
# 计算均线
df['短期均线'] = df['收盘'].rolling(window=short_window, min_periods=1).mean()
df['长期均线'] = df['收盘'].rolling(window=long_window, min_periods=1).mean()
# 生成买卖信号
df['信号'] = 0.0

df.loc[short_window:, '信号'] = (df['短期均线'] > df['长期均线']).astype(float)
df.loc[short_window:, '信号'] = df.loc[short_window:, '信号'].replace({True: 1.0, False: -1.0})


df['仓位'] = df['信号'].diff()
signal_df = df[['日期', '信号']]
# 生成完整日期范围
date_range = pd.date_range(df['日期'].min(),df['日期'].max()  , freq='D')
full_dates = pd.DataFrame(date_range, columns=['日期'])
# 合并信号表和完整日期表
merged_df = pd.merge(full_dates, signal_df, on='日期', how='left')
# 填充缺失的信号值(这里假设缺失的信号为0.0)
merged_df['信号'] = merged_df['信号'].fillna(0.0)
output_file = r"C:\Users\z'z'z\Desktop\ETF_signal_output.xlsx"
merged_df.to_excel(output_file, index=False)
# 在这之后继续进行后续的信号处理和投资组合交易记录的逻辑
print(f"买卖信号已导出到文件:{output_file}")
# 加载期权数据
option_df = pd.read_csv("C:/Users/z'z'z/Desktop/50ETF期权日收盘行情2016.csv")
option_df['交易日期'] = pd.to_datetime(option_df['交易日期'], format='%Y-%m-%d')
option_df['收盘价'] = pd.to_numeric(option_df['收盘价'], errors='coerce')
option_df['成交量(手)'] = pd.to_numeric(option_df['成交量(手)'], errors='coerce')
option_df['到期日'] = pd.to_datetime(option_df['到期日'], format='%Y-%m-%d')
option_df['行权价'] = pd.to_numeric(option_df['行权价'], errors='coerce')
# 初始化资金
initial_funds = 1000000
current_funds = initial_funds
investment_amount = 1  # 每次投资数量(固定金额或固定比例)
# 构造投资组合并记录交易和每日收益率
portfolio = []
daily_returns = []  # 记录每日收益率
cumulativ_return=[]
# 根据信号选择期权合约并记录交易
for index, row in merged_df.iterrows():
    #print(1)
    signal = row['信号']
    date = row['日期']
    current_funds_prev = current_funds
    profit = 0
    cash_value = 0  #当日产生的全部损益
    cash=0
    portfolio_value=0
    new_portfolio=[]
    # 对冲之前构造的期权策略
    # 清除牛市价差策略
    # 处理投资组合
    for holding in portfolio:
            if (signal == -1.0 and holding['信号'] == 1.0) or (signal == 1.0 and holding['信号'] == -1.0):
                portfolio.remove(holding)
                option_type = '购' if signal == -1.0 else '沽'
                options = option_df[(option_df['交易日期'] == date) & (option_df['合约名称'].str.contains(option_type))]
                if not options.empty:
                    # 找到对应的买入和卖出期权合约
                    option1 = options[options['合约名称'] == holding['买入合约名称']].iloc[0]
                    option2 = options[options['合约名称'] == holding['卖出合约名称']].iloc[0]
                     # 对于找不到期权的情况,输出警告并跳过对冲操作
                    if option1.empty or option2.empty:
                       print(f"未找到对应的期权合约进行对冲,日期:{date}")
                       new_portfolio.append(holding)
                       continue
                    else:                                                                                                                                                        
                       sell_price = option1['收盘价']
                       buy_price = option2['收盘价']
                       cash = (sell_price - buy_price) * investment_amount * 10000
                       cash_value +=  cash  # 更新现金损益
    if signal!=0:
        option_type = '购' if signal == 1.0 else '沽'
        options = option_df[(option_df['交易日期'] == date) & (option_df['合约名称'].str.contains(option_type))]
        if not options.empty:
            # 选择较低执行价的看涨期权
           if option_type =='购':
            option1 = options.sort_values(by=['行权价']).iloc[0]
            # 选择与较低执行价期权到期日相同且执行价较高的看涨期权
            options = options[(options['行权价'] > option1['行权价']) & (options['到期日'] == option1['到期日'])]
           else:
            # 选择较高执行价的看跌期权
            option1 = options.sort_values(by=['行权价'], ascending=False).iloc[0]
            # 选择与较高执行价期权到期日相同且执行价较低的看跌期权
            options = options[(options['行权价'] < option1['行权价']) & (options['到期日'] == option1['到期日'])]
           if not options.empty:
                option2 = options.sort_values(by=['行权价']).iloc[0]
                buy_price = option1['收盘价']
                sell_price = option2['收盘价']
                cash= (sell_price - buy_price) * investment_amount * 10000 #负的
                if current_funds >= -cash:          
                    cash_value+=cash
                    portfolio.append({
                        '交易日期': date,
                        '买入合约名称':option1['合约名称'],
                        '买入价格': buy_price,
                        '行权价1': option1['行权价'],
                        '卖出合约名称': option2['合约名称'],
                        '卖出价格': sell_price,
                        '行权价2': option2['行权价'],
                        '信号': signal,
                        '到期日': option1['到期日']
                    })
    else:
        portfolio.append({
                        '交易日期': date,
                        '买入合约名称':'',
                        '买入价格': '',
                        '行权价1': '',
                        '卖出合约名称': '',
                        '卖出价格': '',
                        '行权价2': '',
                        '信号': signal,
                        '到期日': ''
                        })
    cash=0 #、今日到期,单个期权组合行权后现金损益
    value=0 #未到期,未被清除单个期权组合价值
    for holding in portfolio:
            price = df[df['日期'] == date]['收盘'].values[0]
            if holding['信号'] == 1.0:
                if price <= holding['行权价1']:
                    value=cash = 0
                elif price >= holding['行权价2']:
                    value=cash = (holding['行权价2'] - holding['行权价1'])*10000 
                else:
                    value=cash = (price - holding['行权价1'])*10000
            elif holding['信号'] == -1.0:
                if price >= holding['行权价2']:
                    value=cash =0
                elif price <= holding['行权价1']:
                    value=cash = (holding['行权价1'] - holding['行权价2'])*10000 
                else:
                    value=cash = (holding['行权价2'] - price)*10000 
            if holding['到期日'] ==date: 
               portfolio.remove(holding)
               cash_value+=cash # 今日到期,单个期权组合行权后现金损益的加总
            else:
               portfolio_value+= value #未到期,未被清除期权组合价值的加总
    current_funds=current_funds_prev +cash_value
    value=current_funds+portfolio_value
    b=(value-initial_funds)/initial_funds
    a=(current_funds-initial_funds)/initial_funds
    cumulativ_return.append({'日期':date,'累计收益率':b})
    
# 转换为DataFrame
returns_df = pd.DataFrame(cumulativ_return)
# 导出投资组合和收益率
portfolio_df = pd.DataFrame(portfolio)
portfolio_df.to_excel(r"C:\Users\z'z'z\Desktop\Portfolio.xlsx", index=False)
returns_df.to_excel(r"C:\Users\z'z'z\Desktop\Returns.xlsx", index=False) 
print(f"投资组合和收益率已导出到文件:Portfolio.xlsx 和 Returns.xlsx")
# 绘制收益率图表
plt.figure(figsize=(14, 7))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  .plot(returns_df['日期'], returns_df['累计收益率'], label='策略累计收益率')
plt.title('策略累计收益率')
plt.xlabel('日期')
plt.ylabel('累计收益率')
plt.legend()
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值