“五穷六绝”真的存在吗?

技术性调整

五穷六绝七翻身是香港股市在1980年代至1990年代的一个都市传奇,据说这是当时的证券分析师参考历年香港股市的涨跌规律得出的结论:股指每逢5月的时候都会开始跌,到了6月更会大跌,但到了7月却会起死回生。
大洋彼岸,有实证研究表明,美国股票市场具有明显的“1月效应”,即1月份的平均收益率为正,且显著高于其他月份。 该现象最早由Wachtel(1942)发现,但直到1976年Rozef和Kinney才系统地将这一有趣的现象揭示出来,于是美国股市的“1月效应”开始引起金融界的注意。
反观国内,网上随便一搜,分析A股市场“五穷六绝”现象的文章比比皆是。
那么,A股市场真的也存在所谓的“月份效应”吗?

所谓“月份效应”,主要是指股票市场中存在某个或某些特定月份,平均收益率显著地异于其他各月平均收益率的现象。

同样是利用tushare获取数据,我们以上证综指(000001.SH)为例:

def get_data(code,start_date):
    df = pro.index_daily(ts_code = code,start_date = start_date, end_date = '2018-12-31')
    df.index = pd.to_datetime(df.trade_date)
    return df
df = get_data('000001.SH','1993-01-01')

这里有一个小技巧,直接将df的trade_date行通过pd.to_datetime()处理后作为索引,便于后续操作。
修改前df格式(已转置):

0 1 2 3 4
ts_code 000001.SH 000001.SH 000001.SH 000001.SH 000001.SH
trade_date 20171229 20171228 20171227 20171226 20171225
close 3307.17 3296.38 3275.78 3306.12 3280.46
open 3295.25 3272.29 3302.46 3277.84 3296.21
high 3308.22 3304.1 3307.08 3307.3 3312.3
low 3292.77 3263.73 3270.35 3274.33 3270.44
pre_close 3296.38 3275.78 3306.12 3280.46 3297.06
change 10.7874 20.6019 -30.3418 25.6636 -16.602
pct_chg 0.3272 0.6289 -0.9177 0.7823 -0.5035
vol 1.41587e+08 1.75372e+08 1.62675e+08 1.42435e+08 1.46894e+08
amount 1.70357e+08 2.0802e+08 1.98265e+08 1.74679e+08 1.77294e+08

修改后df格式(已转置):

trade_date 2017-12-29 2017-12-28 2017-12-27 2017-12-26 2017-12-25
ts_code 000001.SH 000001.SH 000001.SH 000001.SH 000001.SH
trade_date 20171229 20171228 20171227 20171226 20171225
close 3307.17 3296.38 3275.78 3306.12 3280.46
open 3295.25 3272.29 3302.46 3277.84 3296.21
high 3308.22 3304.1 3307.08 3307.3 3312.3
low 3292.77 3263.73 3270.35 3274.33 3270.44
pre_close 3296.38 3275.78 3306.12 3280.46 3297.06
change 10.7874 20.6019 -30.3418 25.6636 -16.602
pct_chg 0.3272 0.6289 -0.9177 0.7823 -0.5035
vol 1.41587e+08 1.75372e+08 1.62675e+08 1.42435e+08 1.46894e+08
amount 1.70357e+08 2.0802e+08 1.98265e+08 1.74679e+08 1.77294e+08

接下来就可以用收盘价df.close计算收益率了。
这里借鉴了其他文章的思路,用对数化的日收益率推算月收益率与年收益率。
这样做的好处是熨平股价曲线的波动并且没有损失信息。

#计算日对数收益率
def log_ret(df):
    logret = np.log(df/df.shift(1))[1:]
    return logret

#将日收益率转换为月收益率
def month_rate(logret):
    date=[]
    d=list(logret.index)
    for i in range(0,np.size(logret)):
        t=''.join([d[i].strftime("%Y"),d[i].strftime("%m"),"01"])
        date.append(datetime.strptime(t,"%Y%m%d"))
    y=pd.DataFrame(logret.values,date,columns=['月收益率'])
    ret_M=y.groupby(y.index).sum()
    return ret_M

#将日收益率转换为年收益率
def annual_rate(logret):
    year=[]
    d=list(logret.index)
    for i in range(0,np.size(logret)):
        year.append(d[i].strftime("%Y"))
    y=pd.DataFrame(logret.values,year,columns=['年收益率'])
    ret_Y=np.exp(y.groupby(y.index).sum())-1
    return ret_Y, year

#收益率计算
logret = log_ret(df.close)
ret_M = month_rate(logret)
ret_Y, years = annual_rate(logret)

接下来先看年化收益率,不妨通过matplotlib.pyplot画图更加直观:

#===============画年收益率图===============
fig, ax = plt.subplots()
bar_width = 0.7
opacity = 0.63
ax.axhline(0, color='black', lw=1)
bar1 = ax.bar(ret_Y.index, np.squeeze(ret_Y.values),
              alpha=opacity,
              color = 'r')
ax.set_xlabel('Year')
ax.set_ylabel('logReturns')
ax.set_title('logReturns per year(000001.SH)')
年化对数收益率

描述性统计如下:

def roydescribe():
    print(ret_Y.describe())
    #年收益率最高的五个年份
    print(ret_Y.sort_values('年收益率')[:5].T)
    #年收益率最低的五个年份
    print(ret_Y.sort_values('年收益率',ascending=False)[:5].T)
    #年收益率为正的年份,以及占比
    ratio=int(ret_Y[ret_Y['年收益率']>0].count().values)/len(ret_Y)
    print(f'上涨年份占比{ratio*100}%')

roydescribe()
count mean std min 25% 50% 75% max
年收益率 25.0 0.019707 0.455158 -0.565138 -0.246657 0.016461 0.189655 1.803621

收益率最低的5个年份:

2006 2007 2009 1996 2014
年收益率 -0.565138 -0.484958 -0.420205 -0.414999 -0.37043

收益率最高的5个年份:

2008 2011 2001 1994 2004
年收益率 1.803621 0.314954 0.305373 0.303213 0.220812

总体看来,上证综指收益率为正的的年份占比52.0%

接下来检验月份效应,主要思路是:
(1)取出每年特定月份的月收益率,记为df_m
(2)取出每年去除某特定月份的其他所有月份收益率,记为df_exm
(3)进行两对假设检验(Ha省略):
a. H0: 某月收益率的均值与总体收益率均值显著不同。(单总体t检验ttest_1samp)
b. H0: 某月收益率的均值与除此月外其他所有月收入的均值显著不同。(双总体t检验ttest_ind)

#t检验
t1, p1 = stats.ttest_1samp(df_m, np.mean(ret_M.values))
t2, p2 = stats.ttest_ind(df_m, df_exm,
                         equal_var = True)
t3, p3 = stats.ttest_ind(df_m, df_exm,
                         equal_var = False)
#检验结果写成一个dataframe
testdf = pd.DataFrame([t1, p1, t2, p2,t3, p3],
                      index = ['单样本t检验_t值','单样本t检验_p值','双样本t检验_t值(同方差)','双样本t检验_p值(同方差)','双样本t检验_t值(异方差)','双样本t检验_p值(异方差)'],
                      columns = range(1, 13))
print(testdf.T)

事实上检验b命题需要先检验是否存在异方差,这里由于样本容量小,决定同时检验异方差和同方差存在的情况。具体结果如下。

单样本t检验_t值 单样本t检验_p值 双样本t检验_t值(同方差) 双样本t检验_p值(同方差) 双样本t检验_t值(异方差) 双样本t检验_p值(异方差)
0.021206 0.983257 0.028681 0.977138 0.022565 0.982166
-2.401039 0.024454 -1.023598 0.306855 -2.080191 0.041892
-0.516011 0.610568 -0.582992 0.560340 -0.542541 0.591769
-1.163957 0.255882 -1.387305 0.166385 -1.228705 0.229646
0.633335 0.532504 0.719484 0.472407 0.666184 0.510794
1.474966 0.153221 1.659263 0.098115 1.550275 0.132371
-0.411840 0.684111 -0.335063 0.737813 -0.418050 0.678707
0.015390 0.987848 0.023460 0.981299 0.016476 0.986981
0.625214 0.537731 0.402170 0.687847 0.609384 0.545949
0.375261 0.710762 0.262375 0.793213 0.371749 0.712311
0.534583 0.597856 -0.485051 0.627996 -0.550306 0.586153
0.636998 0.530156 0.720739 0.471635 0.669826 0.508497
t检验p值情况图

经检验可以看出,只有2月份的收益率与所有月份组成的总体均值(异方差假设下的其他月份均值)之间的差异具有5%水平的统计显著性。通过画出1993-2018月收益变化图我们可以看出,2月份的收益率总体上是小于0的,这可能与2月是春节所在月份,资金周期性紧张有关。


1993-2018月收益变化

综上,通过统计检验可以看出,A股并不存在明显的所谓的“五穷六绝七翻身”现象。与主要发达国家的股票市场不同,A股运营时间短,市场不成熟的特点可能对股指造成扭曲,其中存在的趋势还有待进一步挖掘。


百度搜索“五穷六绝”
百度搜索“五穷六绝”

事实上亚洲金融风暴后,“五穷六绝”这个词,香港同胞已经很少提起了。

参考文章:https://www.jianshu.com/p/71a5e315d2c1

完整代码如下:

# -*- coding: UTF-8 -*-
import pandas as pd
import numpy as np
import tushare as ts
from datetime import datetime
from pylab import mpl
import matplotlib.pyplot as plt
import scipy.stats as stats

#正常显示画图时出现的中文和负号
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
pro = ts.pro_api()

#获取数据函数
def get_data(code,start_date):
    df = pro.index_daily(ts_code = code,start_date = start_date, end_date = '2018-12-31')
    print(df.head().T)
    df.index = pd.to_datetime(df.trade_date)
    print(df.head().T)
    return df

#计算日对数收益率
def log_ret(df):
    logret = np.log(df/df.shift(1))[1:]
    return logret

#将日收益率转换为月收益率
def month_rate(logret):
    date=[]
    d=list(logret.index)
    for i in range(0,np.size(logret)):
        t=''.join([d[i].strftime("%Y"),d[i].strftime("%m"),"01"])
        date.append(datetime.strptime(t,"%Y%m%d"))
    y=pd.DataFrame(logret.values,date,columns=['月收益率'])
    ret_M=y.groupby(y.index).sum()
    return ret_M

#将日收益率转换为年收益率
def annual_rate(logret):
    year=[]
    d=list(logret.index)
    for i in range(0,np.size(logret)):
        year.append(d[i].strftime("%Y"))
    y=pd.DataFrame(logret.values,year,columns=['年收益率'])
    ret_Y=np.exp(y.groupby(y.index).sum())-1
    return ret_Y, year

#获取数据
df = get_data('000001.SH','1993-01-01')
#对数收益率
logret = log_ret(df.close)
#对数月收益率
ret_M = month_rate(logret)
#对数年收益率
ret_Y, years = annual_rate(logret)

#===============画年收益率图===============
fig, ax = plt.subplots()
bar_width = 0.7
opacity = 0.63
ax.axhline(0, color='black', lw=1)
bar1 = ax.bar(ret_Y.index, np.squeeze(ret_Y.values),
              alpha=opacity,
              color = 'r')
ax.set_xlabel('年份')
ax.set_ylabel('收益率')
ax.set_title('年化对数收益率(000001.SH)')

#===============年收益率的描述性统计===============
def roydescribe():
    print(ret_Y.describe().T)
    #年收益率最高的五个年份
    print(ret_Y.sort_values('年收益率')[:5].T)
    #年收益率最低的五个年份
    print(ret_Y.sort_values('年收益率',ascending=False)[:5].T)
    #年收益率为正的年份,以及占比
    ratio=int(ret_Y[ret_Y['年收益率']>0].count().values)/len(ret_Y)
    print(f'上涨年份占比{ratio*100}%')

roydescribe()


#===============月份效应检验===============
'''
# 所谓“月份效应”,主要是指股票市场中存在某个或某些特定月份的平均收益率年复一年显著地异于其他各月平均收益率的现象。
# 有实证研究表明,美国股票市场表现为“1月效应”,即1月份的平均收益率为正,且显著高于其他月份的平均收益。
# 该现象最早由Wachte1(1942)发现,但直到1976年Rozef和Kinney系统地将这一异象揭示出来,“1月效应”才引起金融界的注意。
# 美国等发达国家对“月份效应”的讨论和研究已走向成熟,但是由于A股运行时间较短,并且由于文化差异(节假日安排)导致的交易时间不一致,其“月份效应”特征可能异于我国,因此仍有必要进一步挖掘和探讨。
# 检验思路:(1)将数据分成两组:m月份和其他月份;(2)检验两组数据的平均值是否相等
'''

#每年不同月份收益率
df_m = pd.DataFrame()
df_exm=pd.DataFrame()
for i in range (1, 13):
    ret = ret_M[ret_M.index.month == i]
    df_m[str(i)+'月份'] = ret['月收益率'].values

#月收益率描述性统计
print(df_m.describe().round(3))
#除了i月以外,剩余月份收益率
for i in range (1,13):
    ret=ret_M[ret_M.index.month!=i]
    df_exm['ex'+str(i)]=ret['月收益率'].values


#历年月收益率变化图
def drawret(ro, co, mo):
    axs[ro, co].axhline(0, color='black', lw=1)
    axs[ro, co].plot(range(1993, 2018), df_m[str(mo) + '月份'], color='b', alpha=0.7)
    axs[ro, co].set(title=str(mo) + '月份')
    axs[ro, co].grid()

fig, axs = plt.subplots(3, 4, sharey= True)
j=1
for a in range(0, 3):
    for b in range(0, 4):
        drawret(a, b, j)
        j += 1
plt.tight_layout()

#t检验
#检验H0:df_m = 0
t1, p1 = stats.ttest_1samp(df_m, np.mean(ret_M.values))
#检验H0:df_m = df_exm
t2, p2 = stats.ttest_ind(df_m, df_exm,
                         equal_var = True)

t3, p3 = stats.ttest_ind(df_m, df_exm,
                         equal_var = False)

#检验结果写成一个dataframe
testdf = pd.DataFrame([t1, p1, t2, p2,t3, p3],
                      index = ['单样本t检验_t值','单样本t检验_p值','双样本t检验_t值(同方差)','双样本t检验_p值(同方差)','双样本t检验_t值(异方差)','双样本t检验_p值(异方差)'],
                      columns = range(1, 13))
print(testdf.T)

#t检验p值情况图
fig, ax = plt.subplots()
plt.title('t检验p值情况图')
plt.plot(range(1, 13), p1, label = 'p(H0:MEAN(df_m) = MEAN(ret_M.values))')
plt.plot(range(1, 13), p2, label = 'p(H0:MEAN(df_m) = MEAN(df_exm),equal_var = True))')
plt.plot(range(1, 13), p3, label = 'p(H0:MEAN(df_m) = MEAN(df_exm),equal_var = False))')
plt.plot(range(1, 13), [0.05 for _ in range(1, 13)], label = 'p = 0.05', lw = 0.5)
plt.plot(range(1, 13), [0.10 for _ in range(1, 13)], label = 'p = 0.05', lw = 0.5)
plt.legend()
plt.show()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352