我们已经介绍了三篇关于量化投资方面绘图的文章和两篇指标类的推导和介绍的文章,大家有兴趣可以了解一下
由于这一部分主要是给大家介绍指标的数学公式和计算方法,更深入的了解它们,其中有众多的数学公式和理论推导过程,我尽可能排版的工整,方便各位阅读。如果只想看代码实现可以跳到最后面“代码实现”部分
RSI指标的实现其实也很容易上手,计算方式与之前的BOLL指标大同小异,核心计算部分都很容易,大家稍微阅读一下就可以很轻松的理解和使用
大家可以关注我的GitHub:ExileSaber
量化投资这部分内容会在整个包完成并调试后上传,虽然现在还没较高的水平,但是可以一起学习进步
该部分主要参考百度百科的介绍
相对强弱指标,即RSI指标
投资的一般原理认为,投资者的买卖行为是各种因素综合结果的反映,行情的变化最终取决于供求关系,而RSI指标正是根据供求平衡的原理,通过测量某一个期间内股价上涨总幅度占股价变化总幅度平均值的百分比,来评估多空力量的强弱程度,进而提示具体操作。
具体的策略介绍会放在 “量化投资常用技能——决策篇” 中
RSI指标简单来说就是计算N日内收盘涨幅平均值和跌幅平均值
N 日 R S I = N 日 内 收 盘 涨 幅 均 值 N 日 内 收 盘 涨 幅 均 值 + N 日 内 收 盘 跌 幅 均 值 × 100 N日RSI = \frac{N日内收盘涨幅均值}{N日内收盘涨幅均值+N日内收盘跌幅均值} \times100 N日RSI=N日内收盘涨幅均值+N日内收盘跌幅均值N日内收盘涨幅均值×100
通过公式我们可以发现,该指标反映出来的是N日收盘涨幅均值占N日收盘涨跌幅均值的比例。当股票价格持续上涨,向上力道较大时,计算出来的该指标值较大并呈现出上升趋势;当股票价格持续下跌,向下力道较大时,计算出来的该指标值较小并呈现出下降趋势
分为两个部分来讲解,一个是主要的计算部分的代码,学习的同时也可以自己灵活运用在其他地方。另外就是整体的绘图部分,包括烛状图和RSI指标
代码实现如下
rate = np.array(close.pct_change().dropna()) # 计算涨跌幅度
# window是移动平均的窗口大小
for i in range(len(rate) - window + 1):
the_rate = rate[i:i+window] # 提取每一个窗口的数据
up_rate = the_rate[np.where(the_rate > 0)].mean() # 使用np.where函数判断是涨还是跌
down_rate = the_rate[np.where(the_rate < 0)].mean()
rsi.append(100 * up_rate / (up_rate - down_rate))
为了绘图全面,我们将“量化投资常用技能——绘图篇 1:绘制股票收盘价格曲线和ochl烛状图”中绘制烛状图的函数 p l o t plot plot_ o c h l ochl ochl 黏贴到这一部分代码中,即可完成多图绘制。另外在数据方面,我们采用另外一种获取数据的方式(该方法不一定每次都可以有效,需要自己寻找解决方法)。完整代码如下:
缺少的库直接 pip install 安装即可
import numpy as np
import matplotlib.pyplot as plt
import pandas_datareader.data as web
import datetime
from matplotlib.dates import date2num
import mpl_finance as mpf
# ———————————————————— #
# ———— 默认参数设置 ———— #
# ———————————————————— #
__colorup__ = "red"
__colordown__ = "green"
window = 14
start = datetime.datetime(2017, 1, 1)
end = datetime.date.today()
stock = web.DataReader("600519.SS", "yahoo", start, end) # 选择茅台股的数据
# ———————————————————— #
def plot_ochl(data_df, axs=None, show=False):
'''
绘制烛状图
:param data_df: 输入的数据,输入的数据类型目前只支持DataFrame类型
:param axs: 是否在子图上绘制
:param show: 是否显示图像
:return:
'''
if axs is None:
fig, ax = plt.subplots(figsize=(14, 7))
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
drawer = ax
else:
drawer = axs
qutotes = []
# 这部分根据实际表格情况做修改
for index, (d, o, c, h, l) in enumerate(zip(data_df.index, data_df.Open, data_df.Close, data_df.High, data_df.Low)):
d = date2num(d) # 蜡烛图的日期要使用matplotlib.finance.date2num进行转换为特有的数字值
val = (d, o, c, h, l) # 日期,开盘,收盘,最高,最低组成tuple对象val
qutotes.append(val) # 加val加入qutotes
# 使用mpf.candlestick_ochl进行蜡烛绘制,ochl代表:open,close,high,low
mpf.candlestick_ochl(drawer, qutotes, width=0.6, colorup=__colorup__, colordown=__colordown__)
drawer.autoscale_view()
drawer.xaxis_date()
if show:
plt.show()
def rsi(stock_df, window, axs=None, show=False):
'''
计算RSI指标并绘图
:param stock_df: 输入的数据,输入的数据类型目前只支持DataFrame类型
:param window: 计算RSI的窗口大小
:param axs: 是否在子图上绘制
:param show: 是否显示图像
:return:
'''
drawer = plt if axs is None else axs
close = stock_df['Close']
rate = np.array(close.pct_change().dropna()) # 计算涨跌幅度
rsi = []
for i in range(len(rate) - window + 1):
the_rate = rate[i:i+window] # 提取每一个窗口的数据
up_rate = the_rate[np.where(the_rate > 0)].mean() # 使用np.where函数判断是涨还是跌
down_rate = the_rate[np.where(the_rate < 0)].mean()
rsi.append(100 * up_rate / (up_rate - down_rate))
drawer.plot(stock.index, 30 * np.ones(len(stock.index)), 'g--', label='30', alpha=0.6)
drawer.plot(stock.index, 50 * np.ones(len(stock.index)), 'y-.', label='50', alpha=0.5)
drawer.plot(stock.index, 70 * np.ones(len(stock.index)), 'g--', label='70', alpha=0.6)
drawer.plot(stock.index[window:], rsi, label='RSI', alpha=0.8)
drawer.legend()
if show:
plt.show()
fig, ax = plt.subplots(2, 1, figsize=(14, 7))
plot_ochl(data_df=stock, axs=ax[0])
rsi(stock, window, axs=ax[1], show=True)
该部分主要介绍几个常见的研判标准,实际情况并不一定会和研判标准相符合
主要借鉴了百度百科的介绍,放在最后供大家学习代码后也可以了解一下一些RSI指标的研判标准
由公式容易知道, 0 ⪕ R S I ⪕ 100 0 \eqslantless RSI \eqslantless 100 0⪕RSI⪕100, R S I = 50 RSI=50 RSI=50 为强势市场与弱势市场分界点
短期RSI是指参数相对小的RSI,长期RSI是指参数相对较长的RSI。比如,6日RSI和12日RSI中 ,6日RSI即为短期RSI,12日RSI即为长期RSI。长短期RSI线的交叉情况可以作为我们研判行情的方法
在实际运用中若要 缩小这个缺点 ,可以在价格变动幅度较大且涨跌变动较频繁时,将RSI参数设定的小一点;在价格变动幅度较小且涨跌变动不频繁时,将RSI参数设定大一点