牛股价量探索性分析与趋势指标可视化

01

引言

2020年以来,新冠病毒这只“黑天鹅”在全球肆虐,对宏观经济带来巨大的冲击,也让资本市场动荡不安。但对股票市场而言,所谓“危机”其实是危中有机,截至10月,A股和美股均走出了年初疫情爆发以来的新高。实际上,为了对冲新冠病毒对经济的不利影响,各国央行纷纷放水(印钞票,宽松货币),给市场注入了充沛的流动性。A股方面,由于经济下半年复苏预期较强(全球有望唯一正增长),加上市场流动性宽裕和市场改革(创业板注册制)刺激,形成了2月和7月份的两波上涨行情,不少个股由于题材炒作收益率翻了几倍。

宏观环境和流动性是市场长期走势的重要因素,但对于个股而言,短期影响因素纷繁复杂,充满博弈和投机因素。对于普通投资者没有时间也有没精力去深入挖掘个股背后的基本面因素,而公开透明的基本面信息价值含量较低,因此基于价量的技术分析往往更适合普通个人投资者。那么大牛股的价量和技术指标有什么样的统计特性呢,其预见性价值如何?如何通过经典趋势指标挖掘潜力个股?本文通过对某个时期涨幅排名靠前的个股进行统计分析,对个股的价量和技术指标(其实是基本面指标数据不易获取)进行可视化分析,试图捕捉个股的趋势特征。

02

数据获取

本文使用tushare获取所有A股行情数据,通过构建本地数据库(略)进行数据管理,分析2019年以来所有A股的期间涨幅排名,以前十名为例进行统计分析。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#使用seaborn背景色
plt.style.use('seaborn')
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False

为了方便分析,这里用到了本地数据库,读者可以通过tusahre\ baostock\ akshare 在线获取数据进行替换。

#下面是调用个人本地数据库文件
from update_sql import update_sql
from RPS import get_data
from plot_stock import stock_plot
from base import ts_pro,sql_engine
pro=ts_pro()
engine = sql_engine()
#更新数据库
update_sql(table_name='daily_data')

数据库已更新至20201026日数据

获取2019年1月2日至今数据(2020年10月26日),如没有数据库文件和源代码,可在公众号后台回复“20201026”获取csv格式数据。

#从本地数据库获取2019年至今全市场股价数据
data=get_data(date='20190102')

计算2019年-2020年期间收益率,获取涨幅排名最前(大到小)的十只个股进行统计分析和可视化。涨幅最大的是坚朗五金,上涨了12倍多,粗略看了一下其基本面信息,并不是特别的出众。

#计算
data10=((data.iloc[-1]/data.iloc[0]-1)
        .dropna().sort_values(ascending=False)[:10])
data10.plot.bar(figsize=(8,4))
plt.xticks(rotation=0)
plt.title('2019年以来十大牛股',size=15)
plt.ylabel('累计收益率')
plt.xlabel('')
plt.show()

使用pyfinance对个股风险收益进行评测,实现代码可参见推文《【手把手教你】使用pyfinance进行证券收益分析》,具体指标分析此处不再展开。

#调用了本地脚本画图
stock_plot('坚朗五金').kline_plot()

03

价量探索性分析(EDA)

由于基本面信息较难获取或量化,下面主要以坚朗五金为例,对牛股的价格成交量进行探索性数据分析(Exploratory Data Analysis,简称EDA),观察其在大幅上涨期前或期间是否有较为明显的指示性迹象。

#从本地数据库提取数据,可使用在线数据获取替代
def get_stock_data(code,start='2010'):
    sql=f"select * from daily_data where ts_code='{code}'"
    df=pd.read_sql(sql,engine)
    df.index=pd.to_datetime(df.trade_date)
    df=(df.sort_index()).drop('trade_date',axis=1)
    df['adjclose']=(df.close*df.adj_factor/df.adj_factor.iloc[-1]).values
    return df.loc[start:]

以坚朗五金作为示例。

df=get_stock_data('002791.SZ')
df.head()

定义可视化函数

def plot_line(df,lbl='收盘价'):
    short = df.rolling(window=20).mean()
    long = df.rolling(window=100).mean() 
    fig, ax = plt.subplots(figsize=(16,7))
    ax.plot(df.index, df.values, label=lbl)
    ax.plot(short.index, short, label='20日移动均线')
    ax.plot(long.index, long, label='100日移动均线')
    ax.set_xlabel('日期')
    ax.set_ylabel(lbl)
    ax.legend()
    plt.show()

价格和移动均线走势

plot_line(df=df.close)    

将时间周期拉近一年进行观察。在20日均线得到支撑后向上突破。

plot_line(df=df.loc['2019':].close)  

成交量情况:无特别明显的可观察特征。

plot_line(df=df.vol,lbl='成交量')    

最近一年成交量情况

plot_line(df=df.loc['2019':].vol,lbl='成交量')

计算日收益率:收益率波动也看不出明显的特征。

# 计算日收益率和对数收益率
daily_rtn = df.close/df.close.shift(1) - 1
daily_log_rtn = np.log(df.close).diff()
# 另外一种计算日收益率的方式为
# daily_rtn = close.pct_change(1)
#去掉极端值
daily_rtn[daily_rtn>-0.12].plot(figsize=(16,7))
plt.show()

价格和成交量标准差:收益率的移动30日标准差波浪式放大。

daily_rtn[daily_rtn>-0.12].rolling(30).var().plot(figsize=(16,7))
plt.show()

成交量标准差在低位徘徊

df['vol'].rolling(50).var().plot(figsize=(16,7))
plt.show()

04

经典技术指标分析趋势

下面使用三个经典的趋势分析指标RSI、MACD和动量指标对坚朗五金的价格趋势进行刻画,目的是通过观察趋势指标的图形特征来总结牛股的形态特征和考察指标的适用性。

01

RSI- Relative Strength Indicator

RSI即相对强度指标,计算公式如下:

其中14日为默认参数。

AvgUP(t)=(UP(t)+13×AvgUP(t−1))/14

AvgDOWN(t)=(DOWN(t)+13×AvgDOWN(t−1))/14

RSI的计算非常简单,可以理解为某一阶段价格涨幅与跌幅的比。强弱指标值一般分布在30-70(或者20-80)。70—100极强卖出,50—70强买入,30—50弱观望,0—30极弱买入,当然具体情况还得具体分析。

# 计算差分
diff=df.close.diff().dropna()
# Ups
plus=diff.map(lambda x: x if x>0 else 0).rename('Plus')
# Downs
minus=diff.map(lambda x: -1*x if x<0 else 0).rename('Minus')
rsi14=pd.concat([diff,plus,minus],axis=1)
# 14天内平均涨幅
rsi14['AvgUP'] = rsi14.Plus[:14].sum()/14
# 14天内平均跌幅
rsi14['AvgDOWN'] = rsi14.Minus[:14].sum()/14

#计算移动平均
for i in range(14,rsi14.close.size):
    rsi14['AvgUP'].iloc[i]=(rsi14['Plus'].iloc[i] +
             13*rsi14['AvgUP'].iloc[i-1])/14
    rsi14['AvgDOWN'].iloc[i]=(rsi14['Minus'].iloc[i] + 
             13*rsi14['AvgDOWN'].iloc[i-1])/14
rsi14['RSI']=100 - 100 / (1+rsi14['AvgUP']/rsi14['AvgDOWN'])
#查看后5行数据
#rsi14.tail(5)

RSI指标的可视化

#指标可视化
plot_line(df=rsi14['RSI'],lbl='RSI指标')  

02

MACD (Moving Average Convergence-Divergence)

MACD的计算使用了指数移动平均(Exponential Moving Average,简称EMA),具体计算公式为:

MACD line = (s短期价格EMA) – (l长期价格EMA)

MACD Signal = MACD line的p移动平均

其中s、l、p是时间周期,通常默认设置为12天、26天和9天。

MACD线0值是平衡点,当它大于0且呈上升趋势时,表明加速上涨;当它小于0且下降时,表明加速下跌趋势;当它大于0但呈下降趋势时,表明行情可能进入反转;当它小于0但呈下降趋势时,表明行情可能进入反转。

ema_short = df.close.ewm(span=12, adjust=False).mean()
ema_long = df.close.ewm(span=26, adjust=False).mean()
macd_line = ema_short - ema_long
macd_signal = macd_line.ewm(span=9, adjust=False).mean()
#画图
fig, ax = plt.subplots(figsize=(16,7))
ax.plot(macd_line.index, macd_line, label='MACD Line')
ax.plot(macd_signal.index, macd_signal, label='MACD Signal')
ax.set_xlabel('Date')
ax.set_ylabel('MACD')
ax.legend()
plt.show()

03

动量指标(momentum)

动量显示收盘价格有多大变化,它表明趋势有多强。动量是指当前收盘价与n天前收盘价的差值:即
Momentum = Close - Close(n日前)

momentum = df.close.diff(20)
momentum.plot(figsize=(16,7))
plt.show()

将上述三个技术指标与价格走势进行可视化。

def plot_all(close=df.close,rsi=rsi14['RSI'],
             macd=macd_signal,momentum=momentum):
    fig = plt.figure(constrained_layout=True,figsize=(20,16))
    gs = fig.add_gridspec(10, 1)
    ax1 = fig.add_subplot(gs[:4, 0])
    ax1.set_title('收盘价')
    ax1.plot(close.index, close, label='收盘价')
    ax2 = fig.add_subplot(gs[4:6,0])
    ax2.set_title('RSI指标')
    ax2.plot(rsi.index, rsi)
    ax2.axhline(y=30,linewidth=0.5, color='blue')
    ax2.axhline(y=70,linewidth=0.5, color='red')
    ax3 = fig.add_subplot(gs[6:8,0])
    ax3.set_title('MACD指标')    
    ax3.plot(macd.index, macd)
    ax3.axhline(y=0,linewidth=0.5, color='black')
    ax4 = fig.add_subplot(gs[8:,0])
    ax4.set_title('动量指标')
    ax4.plot(momentum.index, momentum)
    ax4.axhline(y=0,linewidth=0.5, color='black')
    plt.show()
plot_all()

最近一年的价格趋势与技术指标可视化。

start = '20191026'
plot_all(close=df.loc[start:].close,
         rsi=rsi14.loc[start:]['RSI'],
         macd=macd_signal.loc[start:],
         momentum=momentum.loc[start:])

最后,将数据获取和技术指标可视化封装成类,便于对不同个股或多只个股进行分析和比较。这里使用了talib计算RSI、MACD和动量指标(指标计算分别使用一句代码即可搞掂)。由于代码较长,此处省略,完整代码见知识星球分享

import talib as ta
class TrendIndicator(object):
    def __init__(self,stock,n=200):
        pass
    def get_code(self):
        pass
    def get_stock_data(self):
        pass
    def plot_all(self):
        pass

坚朗五金近一年的价格与技术指标走势

TrendIndicator('坚朗五金').plot_all()

英科医疗近一年的价格与技术指标走势

TrendIndicator('英科医疗').plot_all()

春风动力近一年的价格与技术指标走势

TrendIndicator('春风动力').plot_all()

05

结语

本文以2019年涨幅居前的个股为例,对个股价量进行了探索性分析,同时简要阐述了三个经典技术指标RSI、MACD和动量的基本原理和计算过程,利用Python对指标进行了计算和可视化。文中并没有对这些强势个股的趋势指标图形展开分析,也没有对牛股的形态特征和上涨前趋势指标的表现进行统计分析和归纳总结,这一步留给读者自己完成。技术指标有一定的局限性,特别是在不同的市场阶段(牛\熊\震荡),其适用性可能不同,盲目照搬照套容易吃市场的亏。本文的目的是为大家学习如何使用Python对个股进行量化分析提供一个参考实例,希望能起到抛砖引玉的作用,同时为大家理解和分析市场提供一个研判视角,文中关于市场或个股的理解存在一定的局限性,不构成任何投资参考。

关于Python金融量化

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

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值