昨天,A股午后重挫,大盘绿油油一片,沪指跌4.50%,深成指跌5.37%,创业板指跌5.93%,254股跌停,A股蒸发3万亿,股民人均亏超2万。
各大机构研报指出市场下跌的原因在于四个方面:
一是今天公布的上半年经济数据较好,二季度增速达到3.2%,明显好于之前市场的一致预期,引发政策边际收紧的担忧;
二是中美关系出现较多扰动;
三是人民日报学习小组质问“变味的茅台”,引发白酒股的大幅调整;
四是中芯国际IPO引发抽血效应,中芯国际单日成交金额近500亿元。
但是事后找跌的原因都是“马后炮”,没什么意义,每个人只能赚到自己认知范围之内的钱,如其依靠别人,不如充实自己。所以你能看懂蚂蚁财富里面上证指数的K线图以及金融分析指标吗?如果不知道,做好接下来才最重要。
教你看懂K线图
K线起源于17世纪日本德川幕府时代,18世纪,日本技术分析中的重要人物本间宗久在进行大米期货交易时,记录并研究大米期货的历史价格信息,同时将战争的策略应用于商场上的交易,在这一过程中发展出来的交易策略逐步演变成为今日用于技术分析的K线形态研究学。19世纪美国K线大师Steve Nison将K线引入西方,成为当今量化技术工具不可或缺的一环。
当收盘价高于开盘价,也就是股价走势呈上升趋势时,我们称这种情况下的K线为阳线,中部的实体以空白或红色表示。这时,上影线的长度表示最高价和收盘价之间的价差,实体的长短代表收盘价与开盘价之间的价差,下影线的长度则代表开盘价和最低价之间的差距。阴线亦同理。
接下来我将使用Tushare财经数据接口教会大家看懂K线图以及金融分析指标。
Tushare是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工到数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据。
Tushare地址:http://tushare.org/
使用前提
建议安装Anaconda(http://www.continuum.io/downloads),一次安装包括了Python环境和全部依赖包,减少问题出现的几率。
下载安装
版本升级 pip install tushare --upgrade
import tushare as ts
import mplfinance as mpf
import matplotlib as mpl # 用于设置曲线参数
from cycler import cycler # 用于定制线条颜色
import pandas as pd
import matplotlib.pyplot as plt
period=30
df = ts.get_hist_data('sh', start='2020-06-16', end='2020-07-16').sort_values(by="date")[-period:]
# 格式化列名,用于之后的绘制
df.rename(columns={'date': 'Date', 'open': 'Open', 'high': 'High', 'low': 'Low', 'close': 'Close', 'volume': 'Volume'}, inplace=True)
df['Date'] = pd.to_datetime(df.index)
# 将日期列作为行索引
df.set_index(['Date'], inplace=True)
print(df.head())
# 设置基本参数
# type:绘制图形的类型,有candle, renko, ohlc, line等
# 此处选择candle,即K线图
# mav(moving average):均线类型,此处设置7,30,60日线
# volume:布尔类型,设置是否显示成交量,默认False
# title:设置标题
# y_label:设置纵轴主标题
# y_label_lower:设置成交量图一栏的标题
# figratio:设置图形纵横比
# figscale:设置图形尺寸(数值越大图像质量越高)
kwargs = dict(
type='candle',
mav=(7, 30, 60),
volume=True,
title='\n%s candle_line' % ('Shanghai Stock Exchange'),
ylabel='SSE Candle',
ylabel_lower='Shares\nTraded Volume',
figratio=(15, 10),
figscale=2)
# 设置marketcolors
# up:设置K线线柱颜色,up意为收盘价大于等于开盘价
# down:与up相反,这样设置与国内K线颜色标准相符
# edge:K线线柱边缘颜色(i代表继承自up和down的颜色),下同。详见官方文档)
# wick:灯芯(上下影线)颜色
# volume:成交量直方图的颜色
# inherit:是否继承,选填
mc = mpf.make_marketcolors(
up='red',
down='green',
edge='i',
wick='i',
volume='in',
inherit=True)
# 设置图形风格
# gridaxis:设置网格线位置
# gridstyle:设置网格线线型
# y_on_right:设置y轴位置是否在右
s = mpf.make_mpf_style(
gridaxis='both',
gridstyle='-.',
y_on_right=False,
marketcolors=mc)
# 设置均线颜色,配色表可见下图
# 建议设置较深的颜色且与红色、绿色形成对比
# 此处设置七条均线的颜色,也可应用默认设置
mpl.rcParams['axes.prop_cycle'] = cycler(
color=['dodgerblue', 'deeppink',
'navy', 'teal', 'maroon', 'darkorange',
'indigo'])
# 设置线宽
mpl.rcParams['lines.linewidth'] = .5
# 图形绘制
# show_nontrading:是否显示非交易日,默认False
# savefig:导出图片,填写文件名及后缀
mpf.plot(df,
**kwargs,
style=s,
show_nontrading=False,
savefig='A_stock-%s %s_candle_line'
% ('sh', period) + '.jpg')
可以看到最近一个月上证指数从2900多点涨到了3450点附近,一口气上涨500多点,直到最近两三天市场才出现大幅调整。那我们怎么知道在什么买入,在什么时候卖出呢?
KDJ(随机指标)又被称为随机指数(The Random Index),是一种用来分析市场中超买和超卖现象的指标,最早用于期货市场,后来在股票分钟被投资者广泛使用。
随机指标(KDJ)由三部分组成,根据特定的周期(默认为9天,也有9周等)内资产的最高价(High)、最低价(Low)和收盘价(Close)以及这三个价格的比例关系,来计算RSV,进而通过移动平均法(MA)来计算K值、D值和J值。然后将这些值在坐标轴上描点。和其他指标一样,KDJ指标计算周期可以按照日,周,年也可以用分钟作为单位。计算RSV的值是求KDJ指标的第一步,那么RSV的公式是:
其中n为时间跨度,如果设定n=9,当期的收盘价为50元,9日内的最高价为90元,最低价为10元,则当期的RSV取值为:RSV=(50-10)/(90-10) * 100=50。
RSV被解读为市场中买盘力量相对强弱,它的取值在0-100之间,RSV越大,说明收盘价在价格区间中的位置较高,市场可能出现超买现象,如果偏低则市场处于超卖行情。
K值由 前一天的K值 和 当期RSV值 经过一定权重调整后相加而得到,一般来说,K值的计算为:
D值是由 前一日的D值 和 当期K值 经过一定权重相加而得到。一般来说,D值的计算为:
J指标是KD指标的辅助指标,进一步反映了K指标和D指标的乖离程度。第t日J值的公式:
KDJ交易策略
import tushare as ts
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 加这个两句 可以显示中文
plt.rcParams['font.sans-serif'] = [u'SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 获取数据
def get_stock_data():
df = ts.get_hist_data("sh", start='2020-01-01', end='2020-07-16')
return df
def clean_data(df):
df.sort_values(by="date", inplace=True)
df.rename(columns={'open': 'Open', 'high': 'High', 'low': 'Low', 'close': 'Close',
'volume': 'Volume'}, inplace=True)
df['Date'] = pd.to_datetime(df.index)
# 将日期列作为行索引
df.set_index(['Date'], inplace=True)
df = df[["Open", "High", "Low", "Close", "Volume"]]
return df
def compute_rsv(df, flag):
# 定义收盘价,最高价,最低价(将这三列分别传到3个series中)
close = df.Close
high = df.High
low = df.Low
# 将close的index字段(日期)date转为Series
date = close.index.to_series()
ndate = len(date)
# 阶段性最高
periodHigh = pd.Series(np.zeros(ndate - 8), index=date.index[8:])
# 阶段性最低
periodLow = pd.Series(np.zeros(ndate - 8), index=date.index[8:])
# 建立一个空Series,用来存放RSV的结果
RSV = pd.Series(np.zeros(ndate - 8), index=date.index[8:])
# 对每个周期内的求RSV
for j in range(8, ndate):
period = date[j - 8:j + 1]
i = date[j]
# 8天内的最高价
periodHigh[i] = high[period].max()
# 8天内的最低价
periodLow[i] = low[period].min()
# 公式
RSV[i] = 100 * (close[i] - periodLow[i]) / (periodHigh[i] - periodLow[i])
periodHigh.name = 'periodHigh'
periodLow.name = 'periodLow'
RSV.name = 'RSV'
# rsv走势曲线
if (flag):
# 大概看下结果
print(periodHigh.head(3))
print(periodLow.head(3))
print(RSV.head())
print(RSV.describe())
close1 = close['2020']
RSV1 = RSV['2020']
Cl_RSV = pd.DataFrame([close1, RSV1]).transpose()
Cl_RSV.plot(subplots=True, figsize=(18, 10))
plt.title('未成熟随机指标RSV')
plt.show()
return date, close, RSV
def compute_kdj(date, close, RSV, flag):
# 创建存储RSV值的数组,前两个值置为50,并把RSV添加到RSV1中
RSV1 = pd.Series([50, 50], index=date[6:8]).append(RSV)
RSV1.name = 'RSV'
# 创建存储K值的数组
KValue = pd.Series(0.0, index=RSV1.index) # 全部默认为0,索引使用的是RSV1的索引
KValue[0] = 50 # K初始第一个值默认为50
# 计算K值
for i in range(1, len(RSV1)):
KValue[i] = 2 / 3 * KValue[i - 1] + RSV1[i] / 3
KValue.name = 'KValue'
print(KValue.head())
# 创建存储D值的数组
DValue = pd.Series(0.0, index=RSV1.index) # 全部默认为0,索引使用的是RSV1的索引
DValue[0] = 50 # D初始第一个值默认为50
# 计算D值
for i in range(1, len(RSV1)):
DValue[i] = 2 / 3 * DValue[i - 1] + KValue[i] / 3
KValue = KValue[1:]
DValue.name = 'DValue'
DValue = DValue[1:]
print(DValue.head())
# 有了K和D,再算J就水到渠成了
JValue = 3 * KValue - 2 * DValue
JValue.name = 'JValue'
if (flag):
plt.figure(figsize=(18, 12))
plt.subplot(211)
plt.title('2020 年 上 证 的 收 盘 价')
plt.plot(close['2020'])
plt.subplot(212)
plt.title('2020 年 上 证 的 RSV 与 KD 线')
#plt.plot(RSV['2020'])
plt.plot(KValue['2020'], linestyle='dashed', label='K')
plt.plot(DValue['2020'], linestyle='-.', label='D')
plt.plot(JValue['2020'], linestyle='--', label='J')
plt.legend(loc='best') # 设置图列位置
plt.savefig("KDJ.jpg")
plt.show()
return KValue, DValue, JValue
if __name__ == "__main__":
df = get_stock_data()
df_clean = clean_data(df)
date, close, RSV = compute_rsv(df_clean, False)
KValue, DValue, JValue = compute_kdj(date, close, RSV, True)
RSI
RSI:相对强弱指标(Relative Strength Index),能够反映出市场在一定时期内的景气程度。在股票市场上,买方和卖方力量的消长会影响股票的价格,如果股票的买入力量大于卖出力量,则股票的价格会上涨,反之则会下跌。RSI的设计是以三条线来反映价格走势的强弱,非常适合做短线差价操作。
RSI的计算:
RS=T天内收市价上涨数之和的平均值/T天内收市价下跌数之和的平均值。
根据RSI的计算过程,可以看出时间跨度T是RSI取值的一个重要影响因素。一些常用的看盘软件设有6日RSI、12日RSI和24日RSI这三个指标。6日近似一周的时间周期,12日可以看作半个月的时间跨度,而24日约为一个月的时间跨度。
import tushare as ts
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 加这个两句 可以显示中文
plt.rcParams['font.sans-serif'] = [u'SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 获取数据
def get_stock_data():
df = ts.get_hist_data("sh", start='2020-01-01', end='2020-07-16')
return df
def clean_data(df):
df.sort_values(by="date", inplace=True)
df.rename(columns={'open': 'Open', 'high': 'High', 'low': 'Low', 'close': 'Close','volume': 'Volume'}, inplace=True)
df['Date'] = pd.to_datetime(df.index)
# 将日期列作为行索引
df.set_index(['Date'], inplace=True)
df = df[["Open", "High", "Low", "Close", "Volume"]]
return df
# 定义一个求rsi的函数
def compute_rsi(price, period=6):
clprcChange = price - price.shift(1)
clprcChange = clprcChange.dropna()
indexprc = clprcChange.index
upPrc = pd.Series(0, index=indexprc)
upPrc[clprcChange > 0] = clprcChange[clprcChange > 0]
downPrc = pd.Series(0, index=indexprc)
downPrc[clprcChange < 0] = -clprcChange[clprcChange < 0]
rsidata = pd.concat([price, clprcChange, upPrc, downPrc], axis=1)
rsidata.columns = ['Close', 'PrcChange', 'upPrc', 'downPrc']
rsidata.dropna(inplace=True)
SMUP = []
SMDOWN = []
for i in range(period, len(upPrc) + 1):
SMUP.append(np.mean(upPrc.values[(i - period):i], dtype=np.float32))
SMDOWN.append(np.mean(downPrc.values[(i - period):i], dtype=np.float32))
rsi = [100 * SMUP[i] / (SMUP[i] + SMDOWN[i]) for i in range(0, len(SMUP))]
indexRsi = indexprc[(period - 1):]
rsi = pd.Series(rsi, index=indexRsi)
return (rsi), SMUP, SMDOWN, indexRsi
def plot(price, SMUP, SMDOWN, indexRsi, rsi):
fig = plt.figure(figsize=(16, 8))
UP = pd.Series(SMUP, index=indexRsi)
DOWN = pd.Series(SMDOWN, index=indexRsi)
# 分为4个子视图展示
plt.subplot(411)
plt.plot(price, 'k')
plt.xlabel('date')
plt.ylabel('Close')
plt.title('RSI相关指标')
plt.subplot(412)
plt.plot(UP, 'b')
plt.ylabel('UP')
plt.subplot(413)
plt.plot(DOWN, 'y')
plt.ylabel('DOWN')
plt.subplot(414)
plt.plot(rsi, 'g')
plt.ylabel('Rsi6')
plt.savefig("RsiIndex.jpg")
plt.show()
def plot_index(rsi):
fig = plt.figure(figsize=(16, 8))
plt.plot(rsi)
plt.title('RSI6指标超买和超卖')
plt.ylim(-10, 110)
plt.axhline(y=80, color='red')
plt.axhline(y=20, color='red')
plt.savefig("Rsi6.jpg")
plt.show()
'''
黄金交叉&死亡交叉
短线超过长线:黄金交叉:买入
短线穿过长线向下:死亡交叉:卖出
'''
def plot_cross(Rsi6, Rsi24):
fig = plt.figure(figsize=(16, 8))
plt.plot(Rsi6['2014-12-12':], label='Rsi6')
plt.plot(Rsi24['2014-12-12':], label='Rsi24', color='red', linestyle='dashed')
plt.title('RSI的黄金交叉与死亡交叉')
plt.ylim(-10, 110)
plt.legend()
plt.savefig("RsiCross.jpg")
plt.show()
if __name__ == "__main__":
df = get_stock_data()
df_clean = clean_data(df)
price = df_clean.Close
Rsi6, SMUP, SMDOWN, indexRsi = compute_rsi(price, period=6)
Rsi24, SMUP24, SMDOWN24, indexRsi24 = compute_rsi(price, period=24)
plot(price,SMUP,SMDOWN,indexRsi,Rsi6)
plot_index(Rsi6)
plot_cross(Rsi6, Rsi24)
通过上面的分析,你能找到哪些点是“黄金交叉”,哪些点是“死亡交叉”吗?