金融/证券/会计/公司治理等方向的编程课程
股票技术术语中有很多重要的指标,例如 ma
macd
kdj
rsi
等
接下来, 介绍如何构造 ma
与 macd
这两个指标
为避免现金分红带来的影响, 我们以未分红过的新股为例进行演示
先看一下最终效果
从上交所抓取某个未分红过的新股
请注意该教程仅做教学演示, 不做任何个股分析
因为抓取数据的过程在第五课已经讲过, 这里仅提供代码, 不再重复讲解
这些的代码只是一个函数, 无法直接运行, 如果想亲自测试, 请使用最后提供的完整代码
def download():
response = requests.get(
'http://yunhq.sse.com.cn:32041/v1/sh1/dayk/603713?callback=jQuery111205234775875526079_1542185571865&select=date%2Copen%2Chigh%2Clow%2Cclose%2Cvolume&begin=-5000&end=-1&_=1542185571881',
headers={'Referer': 'http://www.sse.com.cn/market/price/trends/'}
)
# 针对结果进行格式处理
json_str = response.text[42:-1]
data = json.loads(json_str)
return data['kline']
def init_df(kline):
''' 根据K线数据,创建含有日期与收盘价的矩阵 '''
df = pd.DataFrame({})
df['date'] = [x[0] for x in kline]
df['close'] = [x[4] for x in kline]
return df
ma其实就是 Moving average, 移动平均线
我们需要使用pandas的rolling方法, 获取一定长度的移动窗口, 然后计算其平均值即可
如果我们有一系列数据, 只要计算出总和与长度, 做除法就是平均值
# 一系列数字
prices = [5, 8, 4, 3]
# 5 + 8 + 4 + 3 = 20
# 20 / 4 = 5
average = sum(prices) / len(prices)
获取移动窗口时, 需要提供窗口大小
df['close'].rolling(5).apply(lambda x: sum(x) / len(x))
这里的rolling中的5就是窗口大小,说明要以连续的5条数据作为一个移动窗口
每次会把5个数字作为一个数组, 交给apply, 在apply中通过一个函数接收并处理
在python中使用lambda表达式可以很方便地写函数, 这里的x就是这个数组, 冒号后面就是要返回的数据
因为ma有窗口周期的概念, 一般都以 5 10 20 60 作为几个重要的窗口周期, 因为分别代表了 一周, 半月, 一月, 一季
所以我们循环生成这些ma指标
def ma_lines(df, windows):
for window in windows:
name = 'ma%s' % (window)
df[name] = df['close'].rolling(window).apply(lambda x: sum(x) / len(x), raw=True)
return df
注意, apply是最万能的办法,可以实现自己的任意需求, 如果为了简单, 也可以使用mean实现, 效果一样
df[name] = df['close'].rolling(window).mean()
平滑异同移动平均线 (Moving Average Convergence Divergence)
百度百科
智库百科
指数移动平均数指标(Exponential Moving Average,EXPMA或EMA)
智库百科
EMA =(当日收盘价-上日EMA)/N+上日EMA
macd的概念很清晰, 但是有很多不同的说法
本教程采用的说法与概念的对应关系如下
短期ema
ema(close, 12)长期ema
ema(close, 26)离差值
dif = ema(close, 12) - ema(close, 26)离差平均值
dea = ema(dif, 9)柱
histogram = (dif - dea) * 2快速/慢速/短期/长期
因为ema(close,12)比ema(close, 26)的变化要快, dif比dea的变化也要快, 所以有些地方会混淆快
与短
, 慢
与长
只说快速线,很难知道是ema(close, 12) 还是dif
macd到底是谁
dea的别名
histogram的别名
不只是说法不统一, 计算ema初值与 histogram的公式也不统一
ema初值
重要参数 12 26 9这几个参数是在追踪经验上发现比较合适的, 也是最主流的用法
2倍的 dif - dea 按理说, 差值已经体现了两条线的关系, 不需要再乘以2
不过, 很多地方都约定俗成, 乘以2来放大差距,方便观察
如何生成ema指标
直接使用pandas提供的ewm
def ema_lines(df, from_label, N):
line = df[from_label].ewm(alpha=2/(N+1), adjust=False).mean()
# 为了与多数平台保持一致,保留3位小数
return round(line, 3)
生成macd的指标们
def macd_lines(df):
df['ema12'] = ema_lines(df, 'close', 12)
df['ema26'] = ema_lines(df, 'close', 26)
df['dif'] = df['ema12'] - df['ema26']
df['dea'] = ema_lines(df, 'dif', 9)
df['histogram'] = (df['dif'] - df['dea']) * 2
return df
这一步的实现细节不是关键, 参考最后的代码即可
# 股票的各种指标
# macd
# http://www.forexabode.com/forex-school/technical-indicators/macd/
# 有些股票涉及到分红, 价格变成了负数
import os # 操作系统库
import json # 处理json格式的数据
import requests # 发起网络请求
import pandas as pd # 优秀的分析数据工具
import numpy as np # 处理数字的工具
import matplotlib.pyplot as plt # 强大的画图工具
def run():
''' 主程序, 用来调度各个重要流程 '''
print('正在下载')
kline = download()
df = init_df(kline)
windows = [5, 10, 20, 60]
df = ma_lines(df, windows)
df = macd_lines(df)
draw(df, windows)
df.to_csv('lesson7.csv', index=False)
def download():
response = requests.get(
'http://yunhq.sse.com.cn:32041/v1/sh1/dayk/603713?callback=jQuery111205234775875526079_1542185571865&select=date%2Copen%2Chigh%2Clow%2Cclose%2Cvolume&begin=-5000&end=-1&_=1542185571881',
headers={'Referer': 'http://www.sse.com.cn/market/price/trends/'}
)
# 针对结果进行格式处理
json_str = response.text[42:-1]
data = json.loads(json_str)
return data['kline']
def init_df(kline):
''' 根据K线数据,创建含有日期与收盘价的矩阵 '''
df = pd.DataFrame({})
df['date'] = [x[0] for x in kline]
df['close'] = [x[4] for x in kline]
return df
def ma_lines(df, windows):
for window in windows:
name = 'ma%s' % (window)
df[name] = df['close'].rolling(window).apply(lambda x: sum(x) / len(x), raw=True)
return df
def macd_lines(df):
df['ema12'] = ema_lines(df, 'close', 12)
df['ema26'] = ema_lines(df, 'close', 26)
df['dif'] = df['ema12'] - df['ema26']
df['dea'] = ema_lines(df, 'dif', 9)
df['histogram'] = (df['dif'] - df['dea']) * 2
return df
def ema_lines(df, from_label, N):
line = df[from_label].ewm(alpha=2/(N+1), adjust=False).mean()
# 为了与多数平台保持一致,保留3位小数
return round(line, 3)
def draw(df, windows):
''' 画图 '''
# 创建画板
plt.figure(figsize=(7, 4))
# 准备横坐标
count = df.count()['close']
index = np.arange(count)
df['index'] = index
# 设置横坐标的刻度与显示标签
limit = 20
plt.subplot(211)
plt.xticks(index[::limit], df['date'][::limit])
# 画收盘价曲线
plt.xlabel('date')
plt.ylabel('close')
l_close, = plt.plot(index, df['close'], 'black', label='close')
legend_handles_close = [l_close]
for window in windows:
name = 'ma%s' % (window)
l_ma, = plt.plot(index, df[name], label=name)
legend_handles_close.append(l_ma)
plt.legend(handles=legend_handles_close)
plt.subplot(212)
plt.xticks(index[::limit], df['date'][::limit])
plt.xlabel('date')
plt.ylabel('macd')
macd_labels = ['ema12', 'ema26', 'dif', 'dea', 'histogram']
l_dif, = plt.plot(index, df['dif'], label='dif')
l_dea, = plt.plot(index, df['dea'], label='dea')
plt.bar(index, df['histogram'])
legend_handles_macd = [l_dif, l_dea]
plt.legend(handles=legend_handles_macd)
plt.show()
if __name__ == '__main__':
run()
我近期一边整理免费课程,也会推出更多的免费视频,方便大家结合查看学习
如果你对我的课程感兴趣,欢迎与我联系,提供一对一教学,也可以帮助实现特定程序
了解清楚目标后,第一次可以先听课后付款
如果有概念没有理解清楚,随时可以询问,不再收费