zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

案例1:金融数据分析----code知识点详解版

2023-04-18 14:27:29 时间

1.引言

金融案例分析是金融领域研究的重要组成部分,可以帮助人们深入理解金融市场中的运作和交易流程,分析金融风险和机会,制定投资和风险管理策略等。本篇文章将以Python为工具,介绍一种基于Python的金融案例分析方法,以帮助读者更好地理解金融领域知识。

1.1案例分析目标

本篇文章的案例分析目标是,以股票市场为例,介绍如何利用Python进行金融数据分析。具体包括:

  • 1.利用Python获取股票数据;
  • 2.对股票数据进行数据清洗和处理;
  • 3.利用Python进行股票数据可视化;
  • 4.利用Python进行股票市场分析和预测。

1.2涉及知识点

本篇文章的案例分析将涉及以下知识点:

  • 1.Python基础语法;
  • 2.数据清洗和处理;
  • 3.数据可视化;
  • 4.机器学习基础。

1.3案例分析流程

本篇文章的案例分析流程包括以下步骤:

  • 1.加载包:代码的第一部分是加载数据分析过程中所需要的包,具体加载方法可参见2.4.4包的导入
  • 2.数据获取:利用Python获取股票数据,并对数据进行存取,数据的存取见3.python数据的存取
  • 3.数据清洗和处理:对股票数据进行数据清洗和处理,包括缺失值处理、异常值处理、数据标准化等,常用的操作命令见5.dataframe数据清洗
  • 3.数据可视化:利用Python进行股票数据可视化,相关知识点见8.dataframe数据可视化
  • 4.建立模型:利用Python建立股票市场分析和预测模型;
  • 5.模型评估和优化:对模型进行评估和优化;
  • 6.结论和展望:对案例分析结果进行结论和展望。
    下面将分别介绍每个步骤的具体实现。

2.数据获取

涉及知识点:


2.1安装tushare库

首先需要安装tushare库。可以在命令行中运行以下命令来安装:

pip install tushare

2.2获取Token

使用tushare需要申请Token,申请方法如下:

访问tushare官网,注册账号并登录

在个人中心页面获取token

2.3导入tushare库并设置Token

导入tushare库并设置Token,代码如下:

import tushare as ts

ts.set_token('你的Token')

2.4获取数据

tushare接口示例:

以获取中国平安(601318.SH)2015年至今的股票数据为例,代码如下:

import tushare as ts #加载包

mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False

ts.set_token('填入你自己的Token!!!!!')# 设置Token

pro = ts.pro_api()# 初始化pro接口

df = pro.daily(ts_code='601318.SH', start_date='20150101')# 获取中国平安(601318.SH)2015年至今的股票数据

print(df.head())# 打印前5行数据

以上代码实现的功能是从tushare获取中国平安(601318.SH)2015年至今的股票数据,并打印前5行数据。

2.6保存数据

df.to_csv('./data/sh601318.csv', index=False)
  • 需要注意的是,tushare的数据接口有一定的限制,包括每天请求次数和请求数据量等。如果需要更多数据,可以考虑购买tushare的付费服务。

3.数据预处理

涉及知识点:


在获取了股票数据后,我们需要对数据进行清洗和处理,以保证后续分析的准确性。具体实现代码如下:

3.1读取已有数据

import pandas as pd

# 读取CSV文件
df = pd.read_csv('./data/sh601318.csv')

# 查看数据基本信息
print(df.info())

3.2清理数据

#删除不需要的列
df.drop(['ts_code'], axis=1, inplace=True) # 删除code列

#重命名dataframe数据列名
df.rename(columns={'trade_date':'Date', 'open':'Open', 'close':'Close', 'high':'High', 'low':'Low', 'volume':'Volume'}, inplace=True) # 重命名列

#将dataframe时间列由int转换为datetime格式
df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d') # 将Date列转换为datetime格式

#设置索引列
df.set_index('Date', inplace=True) # 将Date列设为行索引

#按指定列的升序/降序排列
df.sort_index(inplace=True) # 按日期排序

#保存已处理完毕的数据
df.to_csv('./data/sh601318_processed.csv')

# 从某dataframe中提取一个只包含某些列的子数据框
df_601318 = df[['Close']]
df_601318.head()

如果是下次重新分析,可考虑通过读取已处理好的数据开始后续分析:

import pandas as pd
df = pd.read_csv('./data/sh601318_processed.csv')
df_601318 = df[['Close']]

# 将Date列转换为datetime格式
df_601318.index = pd.to_datetime(df_601318.index, format='%Y-%m-%d') 

print(df_601318.head())

4.数据可视化

涉及知识点:


数据可视化是金融分析的重要手段,可以帮助我们更好地理解数据特征和趋势。在Python中,dataframe数据的可视化可参见(dataframe数据可视化)。具体实现代码如下:

import matplotlib.pyplot as plt

# 绘制中国平安收盘价折线图
plt.figure(figsize=(15, 6))
plt.plot(df_601318['Close'])
plt.title('ZGPA Closing Prices')
plt.xlabel('Date')
plt.ylabel('Price')
plt.show()

上述绘图中的图标题,以及横纵坐标或图例的标签均是英文,若将其直接改成中文则无法显示,需要设置绘制时的字符,具体实现如下:

# 如前面已加载过相同的包,此处可省略下面包的加载代码
import matplotlib.pyplot as plt

#中文字符设定 plt.rcParams属性总结
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

# 绘制中国平安收盘价折线图
plt.figure(figsize=(15, 6))
plt.plot(df_601318['Close'])
plt.title('中国平安收盘价格')
plt.xlabel('日期')
plt.ylabel('收盘价')
plt.show()

5.基本走势分析

涉及知识点:


5.1描述性统计分析

进行金融案例分析时,描述性统计分析是非常重要的,它可以帮助我们更好地理解数据的基本特征和趋势。在Python中,我们可以使用pandas库来进行描述性统计分析。具体实现代码如下:

# 描述性统计分析
print(df_601318.describe())

5.2历史走势分析

  • 计算每日收益率
# 计算每日收益率
df_601318['daily_return'] = df_601318['Close'].pct_change()

df.pct_change()是一个Pandas DataFrame方法,用于计算每个元素与前一个元素之间的百分比变化。用股票收盘价计算得到的便是某股票的每日收益率,其数学表达式为:
( d f − d f . s h i f t ( 1 ) ) / d f . s h i f t ( 1 ) (df - df.shift(1)) / df.shift(1) (dfdf.shift(1))/df.shift(1)

其中, d f . s h i f t ( 1 ) df.shift(1) df.shift(1)表示将DataFrame向下移动1行,以便计算当前元素与前一个元素之间的变化。然后,用当前DataFrame减去向下移动后的DataFrame,再除以向下移动后DataFrame,即可得到每个元素与前一个元素之间的百分比变化。

  • 计算移动平均收盘价
# 计算移动平均线
df_601318['ma5'] = df_601318['Close'].rolling(5).mean()#周平均收盘价
df_601318['ma10'] = df_601318['Close'].rolling(10).mean()#半月平均收盘价
df_601318['ma20'] = df_601318['Close'].rolling(20).mean()#月平均收盘价
  • 计算月平均收益率的布林带
# 计算月平均收益率的布林带-95%的置信区间
df_601318['std20'] = df_601318['Close'].rolling(20).std()
df_601318['upper_band20'] = df_601318['ma20'] + 2 * df_601318['std20']
df_601318['lower_band20'] = df_601318['ma20'] - 2 * df_601318['std20']
  • 可视化操作
#中文字符设定
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

plt.rcParams 的属性是全局生效的,因此一般建议在程序开头设置一次即可

# 绘制收益率曲线
df_601318['daily_return'].plot(figsize=(10,6))
plt.title('中国平安日度收益率')
plt.xlabel('日期')
plt.ylabel('收益率')
plt.show()

# 绘制收益率的直方图
df_601318['daily_return'].hist(bins=50, figsize=(10,6))
plt.title('Distribution of Daily Return of ZGPA')
plt.xlabel('Return')
plt.ylabel('Frequency')
plt.show()

# 绘制移动平均线和布林带
plt.figure(figsize=(10,6))
plt.plot(df_601318['Close'])
plt.plot(df_601318['ma5'])
plt.plot(df_601318['ma10'])
plt.plot(df_601318['ma20'])
plt.plot(df_601318['upper_band20'])
plt.plot(df_601318['lower_band20'])
plt.title('Moving Averages and Bollinger Bands of ZGPA')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend(['Close', 'MA5', 'MA10', 'MA20', 'Upper Band20', 'Lower Band20'])
plt.show()

6.周期效应分析

涉及知识点:


基于上述数据,我们可以进行周期效应分析。在Python中,我们可以使用pandas库和statsmodels库来进行周期效应分析。具体实现代码如下:

6.1周度效应

6.1.1整体周效应分析

  • Step1:整体周效应计算
# 将数据添加周标记
df_601318['Weekday']=df_601318.index.weekday

#全部数据按周几分组并计算周一至周五的平均收盘价
weekday_mean=df_601318.groupby('Weekday')['Close'].mean()

#周一至周五的均值与整体均值的比值
weekday_mean_ratio = weekday_mean / weekday_mean.mean()

#大于1表示高于均值,小于1低于均值
print(weekday_mean_ratio)
  • Step2:整体周效应可视化
#绘制折线图
plt.figure(figsize=(10, 6))
plt.plot(weekday_mean_ratio.values)
plt.axhline(1.0, color='gray', linewidth=1)
plt.xticks(range(5), ['星期一', '星期二', '星期三', '星期四', '星期五'])
plt.title('中国平安周效应分析')
plt.xlabel('星期')
plt.ylabel('平均收盘价比值')
plt.show()
  • Step3:整体周效应均值检验
from scipy.stats import ttest_ind
# 计算整体周效应的t检验 周一与周五有无显著差异
weekday_0 = df_601318[df_601318['Weekday'] == 0]['Close']
weekday_4 = df_601318[df_601318['Weekday'] == 4]['Close']
t, p = ttest_ind(weekday_0, weekday_4, equal_var=False)
print('t-test between Monday and Friday: t = {:.4f}, p = {:.4f}'.format(t, p))

6.1.2年度周效应分析

  • Step1:年度周效应计算
# 将数据添加年度标记
df_601318['Year'] = df_601318.index.year

#计算每年周一至周五各自的平均收盘价
year_weekly_df=df_601318.groupby(['Year', 'Weekday'])['Close'].mean().unstack()

#计算每年的平均收盘价
year_df=df_601318.groupby('Year')['Close'].mean().values.reshape(-1, 1)

#计算年度周效应比值
year_weekly_mean_ratio = year_weekly_df/year_df

#列名重命名
year_weekly_mean_ratio.rename(columns = {0:'Monday', 
                                         1:'Tuesday', 
                                         2:'Wednesday', 
                                         3:'Thursday', 
                                         4:'Friday'},inplace=True)
  • Step2:年度周效应可视化

绘制折线图

#绘制周效应的年度变化图表
plt.figure(figsize=(10, 6))
year_weekly_mean_ratio.plot()
plt.axhline(1.0, color='gray', linewidth=1)
plt.title('年度周效应')
plt.xlabel('年份')
plt.ylabel('平均收盘价比值')
plt.show()

折线图结果看得并不明显,可考虑绘制热力图,为了让结果对比更清楚,可考虑先对数据重新赋值,将原来每年周一至周五的数据变换为按照比值大小排列的定序数据,从小到大依次赋值为1,2,3,4,5。代码实现如下所示:

import seaborn as sns
# 对每行的数据重新赋值,按大小排序
year_weekly_new = year_weekly_mean_ratio.apply(lambda row: pd.Series(row).rank(method='dense'), axis=1)
# 绘制热力图
sns.heatmap(year_weekly_new, cmap='coolwarm', annot=True)

6.2月度效应

除了周度周期效应,我们还可以进行月度周期效应分析。具体实现代码如下:

6.2.1整体月效应分析

#整体月效应计算
df_601318['Month']=df_601318.index.month# 将数据添加月标记
month_mean=df_601318.groupby('Month')['Close'].mean()#全部数据按月分组并计算每月的平均收盘价
month_mean_ratio = month_mean / month_mean.mean()#每月均值与整体均值的比值
print(month_mean_ratio)#大于1表示高于均值,小于1低于均值

# 整体月效应可视化
plt.figure(figsize=(10, 6))
plt.plot(month_mean_ratio.values)
plt.axhline(1.0, color='gray', linewidth=1)
plt.xticks(range(12), ['一月','二月', '三月', '四月', '五月','六月','七月', '八月', '九月', '十月', '十一月','十二月'])
plt.title('中国平安月效应分析')
plt.xlabel('月份')
plt.ylabel('平均月度收盘价比值')
plt.show()

# 四月与八月差异最大,利用t检验从统计学意义上看看二者有无显著差异
month_4 = df_601318[df_601318['Month'] == 4]['Close']
month_8 = df_601318[df_601318['Month'] == 8]['Close']
t, p = ttest_ind(month_4, month_8, equal_var=False)
print('t-test between April and August: t = {:.4f}, p = {:.4f}'.format(t, p))

6.2.2年度月效应分析

#年度月效应计算
# df_601318['Year'] = df_601318.index.year# 将数据添加年度标记
year_monthly_df=df_601318.groupby(['Year', 'Month'])['Close'].mean().unstack()#计算每年周一至周五各自的平均收盘价
year_df=df_601318.groupby('Year')['Close'].mean().values.reshape(-1, 1)#计算每年的平均收盘价
year_monthly_mean_ratio = year_monthly_df/year_df#计算年度周效应比值

#2023年只有一、二月份的数据,可考虑删除2023年的数据
year_monthly_mean_ratio = year_monthly_mean_ratio.drop(2023, axis=0)  # 删除索引为 2023的行
print(year_monthly_mean_ratio)


#年度月效应可视化

# 绘制折线图
plt.figure(figsize=(10, 6))
year_monthly_mean_ratio.plot()
plt.axhline(1.0, color='gray', linewidth=1)
plt.title('年度月效应')
plt.xlabel('年份')
plt.ylabel('平均月度收盘价比值')
plt.show()

# 对每行的数据重新赋值,按大小排序
year_monthly_new = year_monthly_mean_ratio.apply(lambda row: pd.Series(row).rank(method='dense'), axis=1)
# 绘制热力图
sns.heatmap(year_monthly_new, cmap='coolwarm', annot=True)

从分解图中可以看出,中国平安股票价格存在明显的月度周期效应,即每个月的收盘价存在重复的规律性变化。这对于投资者来说是非常有用的信息,可以帮助他们更好地制定投资策略。

6.3季度效应

除了周度和月度周期效应,我们还可以进行季度周期效应分析。具体实现代码如下:

6.3.1整体季度效应分析

#整体季度效应分析
df_601318['Quarter']=df_601318.index.quarter# 将数据添加月标记

quarterly_mean=df_601318.groupby('Quarter')['Close'].mean()#全部数据按月分组并计算每月的平均收盘价
quarterly_mean_ratio = quarterly_mean / quarterly_mean.mean()#每月均值与整体均值的比值
print(quarterly_mean_ratio)#大于1表示高于均值,小于1低于均值

# 整体季度效应可视化
plt.figure(figsize=(10, 6))
plt.plot(quarterly_mean_ratio.values)
plt.axhline(1.0, color='gray', linewidth=1)
plt.xticks(range(4), ['一季度','二季度', '三季度', '四季度'])
plt.title('中国平安季度效应分析')
plt.xlabel('季度')
plt.ylabel('平均季度收盘价比值')
plt.show()

# 二季度与三季度差异最大,利用t检验从统计学意义上看看二者有无显著差异
quarter_2 = df_601318[df_601318['Quarter'] == 2]['Close']
quarter_3 = df_601318[df_601318['Quarter'] == 3]['Close']
t, p = ttest_ind(quarter_2, quarter_3, equal_var=False)
print('t-test between Quarter2 and Quarter3: t = {:.4f}, p = {:.4f}'.format(t, p))

6.3.2年度季效应分析

#年度季效应计算
# df_601318['Year'] = df_601318.index.year# 将数据添加年度标记
year_quarterly_df=df_601318.groupby(['Year', 'Quarter'])['Close'].mean().unstack()#计算每年周一至周五各自的平均收盘价
year_df=df_601318.groupby('Year')['Close'].mean().values.reshape(-1, 1)#计算每年的平均收盘价
year_quarterly_mean_ratio = year_quarterly_df/year_df#计算年度周效应比值

#2023年只有一、二月份的数据,可考虑删除2023年的数据
year_quarterly_mean_ratio = year_quarterly_mean_ratio.drop(2023, axis=0)  # 删除索引为 2023的行
print(year_quarterly_mean_ratio)


#年度季效应可视化

# 绘制折线图
plt.figure(figsize=(10, 6))
year_quarterly_mean_ratio.plot()
plt.axhline(1.0, color='gray', linewidth=1)
plt.title('年度季效应')
plt.xlabel('年份')
plt.ylabel('平均季度收盘价比值')
plt.show()

# 对每行的数据重新赋值,按大小排序
year_quarterly_new = year_quarterly_mean_ratio.apply(lambda row: pd.Series(row).rank(method='dense'), axis=1)
# 绘制热力图
sns.heatmap(year_quarterly_new, cmap='coolwarm', annot=True)

7.节日效应分析

涉及知识点:


节日效应分析可以帮助我们了解特定日期的股票价格变化是否具有规律性。在Python中,我们可以使用pandas库和statsmodels库来进行节日效应分析。具体实现代码如下:

7.1春节效应

Step1:获取春节日期数据

import pandas as pd
#手动添加数据研究时段每年的春节开始和结束时间(国家法定假期:除夕至初六)
spring_dates_dict = { '2015': ('2015-02-18', '2015-02-24'), 
                     '2016': ('2016-02-06', '2016-02-12'), 
                     '2017': ('2017-01-27', '2017-02-02'), 
                     '2018': ('2018-02-15', '2018-02-21'), 
                     '2019': ('2019-02-04', '2019-02-10'), 
                     '2020': ('2020-01-24', '2020-01-30'), 
                     '2021': ('2021-02-11', '2021-02-17'), 
                     '2022': ('2022-01-31', '2022-02-06'),
                    '2023': ('2023-01-21', '2023-01-27')}

# 将字典转化为DataFrame
spring_dates_df = pd.DataFrame.from_dict(spring_dates_dict, orient='index', columns=['start', 'end'])

# 将start和end列提取出来,组成新的DataFrame
spring_dates = pd.DataFrame({'start': pd.to_datetime(spring_dates_df['start']), 
                             'end': pd.to_datetime(spring_dates_df['end'])})

Step2:获取春节假期前后交易日历

每年春节放假前20个交易日数据和春节假期结束后15个交易日数据

# 根据spring_dates得到每年春节放假前20个交易日和假期结束后15个交易日的日期列表
spring_start_dates = []
spring_end_dates = []

for i in range(len(spring_dates['start'])):
    start_date2=spring_dates['start'][i]
    start_date1 = pd.to_datetime(start_date2) - pd.Timedelta('20 days')
    end_date1=spring_dates['end'][i]
    end_date2 = pd.to_datetime(end_date1) + pd.Timedelta('15 days')
    pre20_list = (pd.date_range(start=start_date1, end=start_date2)).strftime('%Y-%m-%d').tolist()
    pos15_list = (pd.date_range(start=end_date1, end=end_date2)).strftime('%Y-%m-%d').tolist()
    spring_start_dates+=pre20_list
    spring_end_dates+=pos15_list

# 取出df_601318中存在对应交易日的所有数据保存到新的dataframe变量df_spring中
df_spring_pre = df_601318[df_601318.index.isin(spring_start_dates)]

df_spring_pos = df_601318[df_601318.index.isin(spring_end_dates) ]

Step3:计算春节前后收益率

# 计算每年放假前20个交易日的收益率和平均收益率及标准差
df_spring_pre['Return']=df_spring_pre['Close'].pct_change()#计算日收益率
df_spring_pre.dropna(subset=['Return'], inplace=True)#删除Return列空值所对应的行
df_spring_pre['Year'] = df_spring_pre.index.year# 将数据添加年度标记
df_spring_pre_returns=df_spring_pre.groupby('Year')['Return'].agg(['mean', 'std'])#求每年日收益率的均值和标准差

#类似上面,计算每年假期结束后15个交易日的收益率和平均收益率及标准差
df_spring_pos['Return']=df_spring_pos['Close'].pct_change()
df_spring_pos.dropna(subset=['Return'], inplace=True)
df_spring_pos['Year'] = df_spring_pos.index.year
df_spring_pos_returns=df_spring_pos.groupby('Year')['Return'].agg(['mean', 'std'])

Step4:可视化分析

# 可视化分析
plt.figure(figsize=(12, 6))
plt.subplot(2, 2, 1)
df_spring_pre_returns['mean'].plot(kind='bar', label='20 Days Before')
plt.legend()
plt.title('春节前20天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')

plt.subplot(2, 2, 2)
df_spring_pre_returns['std'].plot(kind='bar', label='20 Days Before')
plt.legend()
plt.title('春节前20天日平均收益率标准差')
plt.xlabel('年份')
plt.ylabel('日平均收益率标准差')

plt.subplot(2, 2, 3)
df_spring_pos_returns['mean'].plot(kind='bar', label='15 Days After')
plt.legend()
plt.title('春节后15天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')

plt.subplot(2, 2, 4)
df_spring_pos_returns['std'].plot(kind='bar', label='15 Days After')
plt.legend()
plt.title('春节后15天日平均收益率标准差')
plt.xlabel('年份')
plt.ylabel('日平均收益率标准差')
plt.tight_layout()
plt.show()

# 绘制春节前20天和春节后15天的收益率图表
plt.figure(figsize=(10, 6))
plt.plot(df_spring_pre['Return'], label='20 Days Before')
plt.plot(df_spring_pos['Return'], label='15 Days After')
plt.legend()
plt.title('春节前20天和后15天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')
plt.show()

实际应用中为了获得更准确的分析结果,还应该考虑其他可能影响股票价格的因素,例如市场趋势、行业变化、政治和经济事件等。

7.2国庆效应

Step1:获得每年国庆假期起始时间

#添加每年国庆假期起始时间
nationalday_dates_dict = {str(year): (f"{year}-10-01", f"{year}-10-07") for year in range(2010, 2023)}

# 将字典转化为DataFrame
nationalday_dates_df = pd.DataFrame.from_dict(nationalday_dates_dict, orient='index', columns=['start', 'end'])

# 将start和end列提取出来,组成新的DataFrame
nationalday_dates = pd.DataFrame({'start': pd.to_datetime(nationalday_dates_df['start']), 
                             'end': pd.to_datetime(nationalday_dates_df['end'])})

Step2:根据nationalday_dates得到每年国庆前后10个交易日的日期列表

nationalday_start_dates = []
nationalday_end_dates = []

for i in range(len(nationalday_dates['start'])):
    start_date2=nationalday_dates['start'][i]
    start_date1 = pd.to_datetime(start_date2) - pd.Timedelta('10 days')
    end_date1=nationalday_dates['end'][i]
    end_date2 = pd.to_datetime(end_date1) + pd.Timedelta('10 days')
    pre10_list = (pd.date_range(start=start_date1, end=start_date2)).strftime('%Y-%m-%d').tolist()
    pos10_list = (pd.date_range(start=end_date1, end=end_date2)).strftime('%Y-%m-%d').tolist()
    nationalday_start_dates+=pre10_list
    nationalday_end_dates+=pos10_list

# 取出df_601318中存在对应交易日的所有数据保存到新的dataframe变量df_spring中
df_nationalday_pre = df_601318[df_601318.index.isin(nationalday_start_dates)]

df_nationalday_pos = df_601318[df_601318.index.isin(nationalday_end_dates) ]

Step3:计算每年国庆前后10个交易日的收益率和平均收益率

df_nationalday_pre['Return']=df_nationalday_pre['Close'].pct_change()
df_nationalday_pre.dropna(subset=['Return'], inplace=True)
df_nationalday_pre['Year'] = df_nationalday_pre.index.year
df_nationalday_pre_returns=df_nationalday_pre.groupby('Year')['Return'].agg(['mean', 'std'])

df_nationalday_pos['Return']=df_nationalday_pos['Close'].pct_change()
df_nationalday_pos.dropna(subset=['Return'], inplace=True)
df_nationalday_pos['Year'] = df_nationalday_pos.index.year
df_nationalday_pos_returns=df_nationalday_pos.groupby('Year')['Return'].agg(['mean', 'std'])

Step4:可视化分析

plt.figure(figsize=(12, 6))
plt.subplot(2, 2, 1)
df_nationalday_pre_returns['mean'].plot(kind='bar', label='10 Days Before')
plt.legend()
plt.title('国庆节前10天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')

plt.subplot(2, 2, 2)
df_nationalday_pre_returns['std'].plot(kind='bar', label='10 Days Before')
plt.legend()
plt.title('国庆节前10天日平均收益率标准差')
plt.xlabel('年份')
plt.ylabel('日平均收益率标准差')

plt.subplot(2, 2, 3)
df_nationalday_pos_returns['mean'].plot(kind='bar', label='10 Days After')
plt.legend()
plt.title('国庆节后10天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')

plt.subplot(2, 2, 4)
df_nationalday_pos_returns['std'].plot(kind='bar', label='10 Days After')
plt.legend()
plt.title('国庆节后10天日平均收益率标准差')
plt.xlabel('年份')
plt.ylabel('日平均收益率标准差')

plt.tight_layout()
plt.show()


# 绘制国庆节前10天和国庆节后10天的收益率图表
plt.figure(figsize=(10, 6))
plt.plot(df_nationalday_pre['Return'], label='10 Days Before')
plt.plot(df_nationalday_pos['Return'], label='10 Days After')
plt.legend()
plt.title('国庆节前10天和后10天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')
plt.show()

7.3劳动节效应

Step1:获得每年劳动节假期起始时间

#添加每年劳动节假期起始时间
laborday_dates_dict = {str(year): (f"{year}-05-01", f"{year}-05-03") for year in range(2010, 2023)}

# 将字典转化为DataFrame
laborday_dates_df = pd.DataFrame.from_dict(laborday_dates_dict, orient='index', columns=['start', 'end'])

# 将start和end列提取出来,组成新的DataFrame
laborday_dates = pd.DataFrame({'start': pd.to_datetime(laborday_dates_df['start']), 
                             'end': pd.to_datetime(laborday_dates_df['end'])})

Step2:根据laborday_dates得到每年劳动节前后5个交易日的日期列表

laborday_start_dates = []
laborday_end_dates = []

for i in range(len(laborday_dates['start'])):
    start_date2=laborday_dates['start'][i]
    start_date1 = pd.to_datetime(start_date2) - pd.Timedelta('5 days')
    end_date1=laborday_dates['end'][i]
    end_date2 = pd.to_datetime(end_date1) + pd.Timedelta('5 days')
    pre5_list = (pd.date_range(start=start_date1, end=start_date2)).strftime('%Y-%m-%d').tolist()
    pos5_list = (pd.date_range(start=end_date1, end=end_date2)).strftime('%Y-%m-%d').tolist()
    laborday_start_dates+=pre5_list
    laborday_end_dates+=pos5_list

# 取出df_601318中存在对应交易日的所有数据保存到新的dataframe变量df_laborday中
df_laborday_pre = df_601318[df_601318.index.isin(laborday_start_dates)]

df_laborday_pos = df_601318[df_601318.index.isin(laborday_end_dates) ]

Step3:计算每年劳动节前后5个交易日的收益率和平均收益率

df_laborday_pre['Return']=df_laborday_pre['Close'].pct_change()
df_laborday_pre.dropna(subset=['Return'], inplace=True)
df_laborday_pre['Year'] = df_laborday_pre.index.year
df_laborday_pre_returns=df_laborday_pre.groupby('Year')['Return'].agg(['mean', 'std'])

df_laborday_pos['Return']=df_laborday_pos['Close'].pct_change()
df_laborday_pos.dropna(subset=['Return'], inplace=True)
df_laborday_pos['Year'] = df_laborday_pos.index.year
df_laborday_pos_returns=df_laborday_pos.groupby('Year')['Return'].agg(['mean', 'std'])

Step4:可视化分析

plt.figure(figsize=(12, 6))
plt.subplot(2, 2, 1)
df_laborday_pre_returns['mean'].plot(kind='bar', label='5 Days Before')
plt.legend()
plt.title('劳动节前5天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')

plt.subplot(2, 2, 2)
df_laborday_pre_returns['std'].plot(kind='bar', label='5 Days Before')
plt.legend()
plt.title('劳动节前5天日平均收益率标准差')
plt.xlabel('年份')
plt.ylabel('日平均收益率标准差')

plt.subplot(2, 2, 3)
df_laborday_pos_returns['mean'].plot(kind='bar', label='5 Days After')
plt.legend()
plt.title('劳动节后5天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')

plt.subplot(2, 2, 4)
df_laborday_pos_returns['std'].plot(kind='bar', label='5 Days After')
plt.legend()
plt.title('劳动节后5天日平均收益率标准差')
plt.xlabel('年份')
plt.ylabel('日平均收益率标准差')

plt.tight_layout()
plt.show()


# 绘制劳动节前5天和后5天的收益率图表
plt.figure(figsize=(10, 6))
plt.plot(df_nationalday_pre['Return'], label='5 Days Before')
plt.plot(df_nationalday_pos['Return'], label='5 Days After')
plt.legend()
plt.title('劳动节前5天和后5天日平均收益率')
plt.xlabel('年份')
plt.ylabel('日平均收益率')
plt.show()

–未完待续–