背景介绍:
搭建程序化交易平台的过程需要研究技术指标。
环境:
OS:mac
PYTHON: 3.8
IDE: pycharm
步骤:
第一步:加载库
import pandas as pd
import pandas_datareader as web
from datetime import datetime, timedelta
import talib
import matplotlib.pyplot as plt
from mplfinance.original_flavor import candlestick_ohlc
import matplotlib.ticker as ticker
pandas: 处理股票数据
pandas_datareader:行情数据获取api,也可以用tushare或者从新浪等网站获取
datetime:获取日期
talib:生成技术指标
candlestick_ohlc: 绘制蜡烛图
matplotlib.ticker: 设置x轴刻度,如果不设置,matplotlib会将没有交易的日期也显示出来
第二步:获取数据
def stock(stock_code): #stock_code是股票代码,例子:上市 "600036.ss", 深市 "000001.sz"
start_date = "2019-12-01" #起始日期
today = datetime.date(datetime.now()) #截止日期
stock_info = web.get_data_yahoo(stock_code, start_date, today) #获取行情数据,返回dataframe
stock_info = stock_info.reset_index() #默认index是日期,这里要重置一下,为后面绘图做准备
stock_info = stock_info.astype({"Date": str}) #将Date列的类型设置为str,为绘图做准备
return stock_info
以下是获取招商银行(股票代码 "600036.ss") 的返回结果,一共6列,Date, High, Low, Open, Close, Volumn, Adj Close
第三步:获取技术指标数据
def get_indicators(stock_code):
# 创建dataframe
data = stock(stock_code)
#获取macd
data["macd"], data["macd_signal"], data["macd_hist"] = talib.MACD(data['Close'])
#获取10日均线和30日均线
data["ma10"] = talib.MA(data["Close"], timeperiod=10)
data["ma30"] = talib.MA(data["Close"], timeperiod=30)
#获取rsi
data["rsi"] = talib.RSI(data["Close"])
return data
talib有各种各样的技术指标,这里只获取了均线,macd和rsi,返回dataframe。
第四步:绘图
def plot_chart(data, title):
fig = plt.figure() #创建绘图区,包含四个子图
fig.set_size_inches((20, 16))
ax_candle = fig.add_axes((0, 0.72, 1, 0.32)) #蜡烛图子图
ax_macd = fig.add_axes((0, 0.48, 1, 0.2), sharex=ax_candle) #macd子图
ax_rsi = fig.add_axes((0, 0.24, 1, 0.2), sharex=ax_candle) #rsi子图
ax_vol = fig.add_axes((0, 0, 1, 0.2), sharex=ax_candle) #成交量子图
ohlc = [] #存放行情数据,candlestick_ohlc需要传入固定格式的数据
row_number = 0
for date, row in data.iterrows():
date, highp, lowp, openp, closep = row[:5]
ohlc.append([row_number, openp, highp, lowp, closep])
row_number = row_number+1
date_tickers = data.Date.values #获取Date数据
def format_date(x, pos=None):
# 由于前面股票数据在 date 这个位置传入的都是int
# 因此 x=0,1,2,...
# date_tickers 是所有日期的字符串形式列表
if x < 0 or x > len(date_tickers) - 1:
return ''
return date_tickers[int(x)]
#绘制蜡烛图
ax_candle.plot(data.index, data["ma7"], label="MA7")
ax_candle.plot(data.index, data["ma8"], label="MA8")
ax_candle.plot(data.index, data["ma25"], label="MA25")
candlestick_ohlc(ax_candle, ohlc, colorup="g", colordown="r", width=0.8)
ax_candle.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
ax_candle.xaxis.set_major_locator(ticker.MultipleLocator(6)) #设置间隔为6个交易日
ax_candle.grid(True)
ax_candle.set_title(title, fontsize=20)
ax_candle.legend()
#绘制MACD
ax_macd.plot(data.index, data["macd"], label="macd")
ax_macd.bar(data.index, data["macd_hist"] * 3, label="hist")
ax_macd.plot(data.index, data["macd_signal"], label="signal")
ax_macd.set_title('MACD')
ax_macd.legend()
#绘制RSI
ax_rsi.set_ylabel("(%)")
ax_rsi.plot(data.index, [70] * len(data.index), label="overbought")
ax_rsi.plot(data.index, [30] * len(data.index), label="oversold")
ax_rsi.plot(data.index, data["rsi"], label="rsi")
ax_rsi.set_title('KDJ')
ax_rsi.legend()
#绘制成交量
ax_vol.bar(data.index, data["Volume"] / 1000000)
ax_vol.set_ylabel("(Million)")
#保存图片到本地
fig.savefig("/Users/answer/Desktop/investment/photos/" + title + ".png", bbox_inches="tight")
#这里个人选择不要plt.show(),因为保存图片到本地的
#plt.show()
第五步:批量绘制
def industry(dict):
for key, value in dict.items():
# d.iteritems: an iterator over the (key, value) items
stock_info = get_indicators(key)
plot_chart(stock_info, value)
这里传进去的参数是字典,预先定义了目标股票代码。用字典的好处是,能够把股票名称也传进去。
finance_list = {
"600036.ss": "Zhaoshang Yinhang",
"002142.sz": "Ningbo Yinhang",
"000001.sz": "Pingan Yinhang",
"601318.ss": "Zhongguo Pingan"
}
下面是恒瑞医药的绘制效果。几个指标清晰可见。
其它:
绘图的时候最好把绘图独立窗口关掉
Reference:
那未必, 2017, 使用matplotlib绘制k线图(去掉空白日期), https://www.jianshu.com/p/c10e57ccc7ba
Melina Mackey, 2020, Building a Technical Analysis Chart with Python, https://medium.com/analytics-vidhya/building-a-technical-analysis-chart-with-python-17107b78b297