热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Python量化】如何利用欧奈尔的RPS寻找强势股?

真正的领军股,它们往往是在接近或位于新的股价高点之上时才开始大规模涨势的,而不是在接近新的低点或是从高点巨量跌落之后才转跌为升的。——威廉·欧奈尔《笑傲股市》1引言股票市场经常流传

真正的领军股,它们往往是在接近或位于新的股价高点之上时才开始大规模涨势的,而不是在接近新的低点或是从高点巨量跌落之后才转跌为升的。——威廉·欧奈尔《笑傲股市》

1 引言

股票市场经常流传着一句话:“强者恒强”。最近两个多月A股市场交投火热,大部分股票出现了巨幅反弹甚至创出 2015年以来的新高,尤其是以东方通信为代表的妖股,120日收益率翻了五倍。强者恒强背后的逻辑可以用大家熟知的“马太效应”和“二八法则”来解释。马太效应来自圣经《新约·马太福音》中的一则寓言: “凡有的,还要加给他叫他多余;没有的,连他所有的也要夺过来。”二八法则是意大利经济学家帕累托1897年提出来的,揭示了20%的人占有80%社会财富的一种不平等。同样道理,市场总是朝着阻力最小的路径走,而主力运作个股也需要沿着阻力最小的路径去操作。所以市场20%的股票涨势往往超过80%的股票,80%的资金总是追逐20%的股票。因此,看上去价格高、风险大的股票,反而能够再创新高;而看上去价格低、风险小的股票,则通常继续走低。这也是“强者愈强,弱者愈弱”的表现。那么如何选出“强势股”呢?本文将为大家介绍威廉·欧奈尔的RPS选股方法,重点是如何使用Python实现RPS指标的计算、排序和可视化,筛选出市场的强势股,寻找下一波行情的大黑马。

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

截至2019年3月19日,创业板指数30日收益率接近40%

2 欧奈尔的RPS指标

威廉·欧奈尔是美国股市的传奇人物,驰骋股票市场数十年长盛不衰,并自创了一套投资体系,通过《笑傲股市》一书为广大散户带来了投资希望。电子书可在公众号 Python 金融量化后台回复“笑傲江湖”免费下载。

RPS英文全称 Relative Price Strength Rating,即股价相对强度,该指标是欧奈尔CANSLIM选股法则中的趋势分析,具有很强的实战指导意义。RPS指标是指在一段时间内,个股涨幅在全部股票涨幅排名中的位次值。比如A股共有3500只股票,若某只股票的120日涨幅在所有股票中排名第350位,则该股票的RPS值为:(1-350/3500)*100=90。

RPS的值代表该股的120日涨幅超过其他90%的股票的涨幅。通过该指标可以反映个股股价走势在同期市场中的表现相对强弱。RPS的值介于0-100之间,在过去的一年中,所有股票的涨幅排行中,前1%的股票的RPS值为99至100,前2%的股票的RPS值为98至99,以此类推。RPS时间周期可以自己根据需要进行调整,常用的有60日(3个月)、120日(半年)和250日(一年)等。

3 使用Python计算RPS

RPS的计算公式很简单,难的是对RPS指标的具体应用,需要大量的实战经验积累和严格的操作纪律。下面给出从数据获取、数据处理、指标计算和可视化的Python核心代码。

#先引入后面可能用到的library

importpandasaspd

importtushareasts

importmatplotlib.pyplotasplt

%matplotlib inline

#正常显示画图时出现的中文和负号

frompylabimportmpl

mpl.rcParams[‘font.sans-serif’]=[‘SimHei’]

mpl.rcParams[‘axes.unicode_minus’]=False

#使用之前先输入token,可以从个人主页上复制出来,

#每次调用数据需要先运行该命令

token=’输入你在tushare获得的token’

ts.set_token(token)

pro=ts.pro_api()

数据来源于tushare,首先使用stock_basic获取当前交易日的所有股票代码。截至2019年3月19日,一共有3594只股票。

df = pro.stock_basic(exchange=”, list_status=’L’,

fields=’ts_code,symbol,name,area,industry,list_date’)

print(len(df))

#输出结果:3594

考虑到A股新股上市交易的情况,上市后前一段时间往往会一字涨停,然后出现下跌调整。为了剔除新股次新股的影响,这里选择2017年1月1日前上市的股票作为分析样本,共得到3024只股票。

#排除掉新股次新股,这里是只考虑2017年1月1日以前上市的股票

df=df[df[&#8216;list_date&#8217;].apply(int).values<20170101]

len(df)

#输出结果:3024

#获取当前所有非新股次新股代码和名称

codes=df.ts_code.values

names=df.name.values

#构建一个字典方便调用

code_name=dict(zip(names,codes))

#使用tushare获取上述股票周价格数据并转换为周收益率

#设定默认起始日期为2018年1月5日,结束日期为2019年3月19日

#日期可以根据需要自己改动

defget_data(code,start=&#8217;20180101&#8242;, end=&#8217;20190319&#8242;):

df=pro.daily(ts_code=code, start_date=start, end_date=end,fields=&#8217;trade_date,close&#8217;)

#将交易日期设置为索引值

df.index=pd.to_datetime(df.trade_date)

df=df.sort_index()

#计算收益率

returndf.close

通过定义的函数获取上述3024只股票自2018年1月5日以来的所有日交易数据,并计算每只股票120日滚动收益率。

#构建一个空的dataframe用来装数据

data=pd.DataFrame()

forname,codeincode_name.items():

data[name]=get_data(code)

#data.to_csv(&#8216;daily_data.csv&#8217;,encoding=&#8217;gbk&#8217;)

#data=pd.read_csv(&#8216;stock_data.csv&#8217;,encoding=&#8217;gbk&#8217;,index_col=&#8217;trade_date&#8217;)

#data.index=(pd.to_datetime(data.index)).strftime(&#8216;%Y%m%d&#8217;)

#计算收益率

defcal_ret(df,w=5):

&#8221;&#8217;w:周5;月20;半年:120; 一年250

&#8221;&#8217;

df=df/df.shift(w)-1

returndf.iloc[w:,:].fillna(0)

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

经过这一轮的大幅上涨,截至2019年3月19日,上述3024只股票中,有49只股票120日收益率超过100%,占比1.68%;收益率在20%-100%之间的股票有1280只,占比达到43.99%;仍有360只股票120日收益率为负数。

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

ret120=cal_ret(data,w=120)

#计算RPS

defget_RPS(ser):

df=pd.DataFrame(ser.sort_values(ascending=False))

df[&#8216;n&#8217;]=range(1,len(df)+1)

df[&#8216;rps&#8217;]=(1-df[&#8216;n&#8217;]/len(df))*100

returndf

#计算每个交易日所有股票滚动w日的RPS

defall_RPS(data):

dates=(data.index).strftime(&#8216;%Y%m%d&#8217;)

RPS={}

foriinrange(len(data)):

RPS[dates[i]]=pd.DataFrame(get_RPS(data.iloc[i]).values,columns=[&#8216;收益率&#8217;,&#8217;排名&#8217;,&#8217;RPS&#8217;],index=get_RPS(data.iloc[i]).index)

returnRPS

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》
《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

rps120=all_RPS(ret120)

#获取所有股票在某个期间的RPS值

defall_data(rps,ret):

df=pd.DataFrame(np.NaN,columns=ret.columns,index=ret.index)

fordateinret.index:

date=date.strftime(&#8216;%Y%m%d&#8217;)

d=rps[date]

forcind.index:

df.loc[date,c]=d.loc[c,&#8217;RPS&#8217;]

returndf

#构建一个以前面收益率为基础的空表

df_new=pd.DataFrame(np.NaN,columns=ret120.columns,index=ret120.index)

计算所有股票在每一个交易日的向前120日滚动RPS值。对股票价格走势和RPS进行可视化。

fordateindf_new.index:

date=date.strftime(&#8216;%Y%m%d&#8217;)

d=rps120[date]

forcind.index:

df_new.loc[date,c]=d.loc[c,&#8217;RPS&#8217;]

defplot_rps(stock):

plt.subplot(211)

data[stock][120:].plot(figsize=(16,16),color=&#8217;r&#8217;)

plt.title(stock+&#8217;股价走势&#8217;,fOntsize=15)

plt.yticks(fOntsize=12)

plt.xticks([])

ax = plt.gca()

ax.spines[&#8216;right&#8217;].set_color(&#8216;none&#8217;)

ax.spines[&#8216;top&#8217;].set_color(&#8216;none&#8217;)

plt.subplot(212)

df_new[stock].plot(figsize=(16,8),color=&#8217;b&#8217;)

plt.title(stock+&#8217;RPS相对强度&#8217;,fOntsize=15)

my_ticks = pd.date_range(&#8216;2018-06-9&#8242;,&#8217;2019-3-31&#8242;,freq=&#8217;m&#8217;)

plt.xticks(my_ticks,fOntsize=12)

plt.yticks(fOntsize=12)

ax = plt.gca()

ax.spines[&#8216;right&#8217;].set_color(&#8216;none&#8217;)

ax.spines[&#8216;top&#8217;].set_color(&#8216;none&#8217;)

plt.show()

查看2018年7月31日-2019年3月19日每月RPS情况。下面仅列出每个月RPS排名前十的股票,里面出现不少熟悉的“妖股”身影。

dates=[&#8216;20180731&#8242;,&#8217;20180831&#8242;,&#8217;20180928&#8242;,&#8217;20181031&#8242;,&#8217;20181130&#8242;,&#8217;20181228&#8242;,&#8217;20190131&#8242;,&#8217;20190228&#8242;,&#8217;20190319&#8217;]

df_rps=pd.DataFrame()

fordateindates:

df_rps[date]=rps120[date].index[:50]

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

东方通信是这一波上涨行情中的最大牛股,主要受益于5G题材的持续炒作。从下图可见,2018年11月,其120日RPS首次出现大于90,然后一直处于高位,具有非常明显的强势股特征。华业资本是本次120日收益率中最低的股票,自2018年8月其其RPS一直下跌,然后持续处于低位,股价一直反弹不起来。顺鑫农业的RPS在2018年6月-11月一直处于高位,然后股价出现了较大的回调。可见RPS的实战意义是,在强势股出现第一波上涨后发现它,然后深入挖掘,判断是否会出现第二、三波的再创新高。

plot_rps(&#8216;东方通信&#8217;)

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

plot_rps(&#8216;华业资本&#8217;)

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

plot_rps(&#8216;顺鑫农业&#8217;)

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》

4 结语

欧奈尔研究了1953年至1993年,500只年度涨幅最大的股票,发现每年涨幅居前的,在他们股价真正大幅度攀升之前,其平均的相对强弱指标RPS为87%。这并不意味着,只要RPS>87%就可以买入该股票呢?其实RPS指标只是对强势股的个一个初步筛选,对于A股而言,RPS大于87%的股票就有400多只,都买进也不太现实,具体运用还需结合个股基本面、题材和整体市场情况分析。RPS实际上是欧奈尔在《笑傲股市》中提出的CANSLIM 七步选股法的一个技术分析。各字母含义如下所示:

C:最近一季度报表显示的盈利(每股收益)

A:每年度每股盈利的增长幅度

N:新产品,新服务,股价创新高

S:该股流通盘大小,市值以及交易量的情况

L:该股票在行业中的低位,是否为龙头

I:该股票有无有实力的庄家,机构大流通股东

M:大盘走势如何,如何判断大盘走向

RPS可以帮助选出创出新高的股票。牛股一定创新高,但是新高不一定是牛股。所以关键是将RPS结合基本面进一步选择,基本面情况好,销售额和盈利增长很快,且这种增长是由公司推出的新产品或新服务带来的。本文主要分享了欧奈尔RPS指标的原理和Python计算方法,受篇幅所限,文中只给出了核心代码,如需完整代码可通过加入知识星球,向博主索要。文中提及股票不构成任何投资建议,投资有风险,入市需谨慎!

关于Python金融量化

专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取30多g的量化投资视频资料、公众号文章Python完整源码、量化投资前沿分析框架,与博主直接交流、结识圈内朋友等。

《【Python量化】如何利用欧奈尔的RPS寻找强势股?》


推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • EPPlus绘制刻度线的方法及示例代码
    本文介绍了使用EPPlus绘制刻度线的方法,并提供了示例代码。通过ExcelPackage类和List对象,可以实现在Excel中绘制刻度线的功能。具体的方法和示例代码在文章中进行了详细的介绍和演示。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • importjava.util.ArrayList;publicclassPageIndex{privateintpageSize;每页要显示的行privateintpageNum ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
author-avatar
Jacky麦麦9
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有