天天看點

同花順選股python開發_量化之路-python繪圖-高仿同花順繪制股票K線圖+均線+成交量+MACD+KDJ(附代碼)...

上一期介紹了k線圖的簡單繪制,可以實作股票趨勢的檢視分析

本期介紹一種用python matplotlib實作高仿同花順界面的繪圖方法

一、話不多說上效果圖(還是以601011寶泰隆為例哈^^)

二、代碼(python 3.7)

# 參考博文:https://blog.csdn.net/PeakGao/article/details/105634317?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.nonecase

# 參考博文部落客:peakgao

# auther:懶兔子

# 程式設計環境:anaconda - Jupyter notebook

import tushare as ts

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt #繪圖

import matplotlib.ticker as ticker #日期刻度定制

import mplfinance as mpf #金融圖形

from matplotlib import colors as mcolors #渲染頂點顔色格式

from matplotlib.collections import LineCollection,PolyCollection

pro = ts.pro_api()

# API括号内,請輸入自己的‘tushare token’哦,申請方法詳見上上篇懶兔子的博文:量化之路-資料采集-從tushareAPI擷取股票資料資訊并導出至excel

# tushare介紹博文連結:https://zhuanlan.zhihu.com/p/149754616

df = pro.daily(ts_code='601011.SH', start_date='20180101', end_date='20200622')

df # 用的Juppyter notebook,此處斷點檢視下擷取的資料狀況

df.drop(df.columns[[0,6,7,8,10]],axis=1,inplace=True) #二維資料兩個括号 剔除多餘的列

df # 用的Juppyter notebook,此處斷點檢視下擷取的資料整理狀況

# 在k線基礎上計算MACD,并将結果存儲在df上面(dif,dea,bar)

def calc_macd(df, fastperiod=12, slowperiod=26, signalperiod=9):

ewma12 = df['close'].ewm(span=fastperiod,adjust=False).mean()

ewma26 = df['close'].ewm(span=slowperiod,adjust=False).mean()

df['dif'] = ewma12-ewma26

df['dea'] = df['dif'].ewm(span=signalperiod,adjust=False).mean()

df['bar'] = (df['dif']-df['dea'])*2

return df

# 在k線基礎上計算KDF,并将結果存儲在df上面(k,d,j)

def calc_kdj(df):

low_list = df['low'].rolling(9, min_periods=9).min()

low_list.fillna(value=df['low'].expanding().min(), inplace=True)

high_list = df['high'].rolling(9, min_periods=9).max()

high_list.fillna(value=df['high'].expanding().max(), inplace=True)

rsv = (df['close'] - low_list) / (high_list - low_list) * 100

df['k'] = pd.DataFrame(rsv).ewm(com=2).mean()

df['d'] = df['k'].ewm(com=2).mean()

df['j'] = 3 * df['k'] - 2 * df['d']

df['kdj'] = 0

series = df['k']>df['d']

df.loc[series[series == True].index, 'kdj'] = 1

df.loc[series[(series == True) & (series.shift() == False)].index, 'kdjcross'] = 1

df.loc[series[(series == False) & (series.shift() == True)].index, 'kdjcross'] = -1

return df

calc_macd(df) #計算MACD

calc_kdj(df) #計算KDJ

df=df.sort_values(by='trade_date',ascending=True)

#兔子提示:tushare擷取資料是倒序的,需要調整順序!!!

df

# 用的Juppyter notebook,此處斷點檢視下擷取的資料整理狀況

# 日期轉換成整數序列

date_tickers=df.trade_date.values

df.trade_date = range(0, len(df)) # 日期改變成序号

matix = df.values # 轉換成繪制蠟燭圖需要的資料格式(date, open, close, high, low, volume)

xdates = matix[:, 0] # X軸資料(這裡用的天數索引)

# 設定外觀效果

plt.rc('font', family='Microsoft YaHei') # 用中文字型,防止中文顯示不出來

plt.rc('figure', fc='k') # 繪圖對象背景圖

plt.rc('text', c='#800000') # 文本顔色

plt.rc('axes', axisbelow=True, xmargin=0, fc='k', ec='#800000', lw=1.5, labelcolor='#800000', unicode_minus=False) # 坐标軸屬性(置底,左邊無空隙,背景色,邊框色,線寬,文本顔色,中文負号修正)

plt.rc('xtick', c='#d43221') # x軸刻度文字顔色

plt.rc('ytick', c='#d43221') # y軸刻度文字顔色

plt.rc('grid', c='#800000', alpha=0.9, ls=':', lw=0.8) # 網格屬性(顔色,透明值,線條樣式,線寬)

plt.rc('lines', lw=0.8) # 全局線寬

# 建立繪圖對象和4個坐标軸

fig = plt.figure(figsize=(16, 8))

left, width = 0.05, 0.9

ax1 = fig.add_axes([left, 0.6, width, 0.35]) # left, bottom, width, height

ax2 = fig.add_axes([left, 0.45, width, 0.15], sharex=ax1) # 共享ax1軸

ax3 = fig.add_axes([left, 0.25, width, 0.2], sharex=ax1) # 共享ax1軸

ax4 = fig.add_axes([left, 0.05, width, 0.2], sharex=ax1) # 共享ax1軸

plt.setp(ax1.get_xticklabels(), visible=False) # 使x軸刻度文本不可見,因為共享,不需要顯示

plt.setp(ax2.get_xticklabels(), visible=False) # 使x軸刻度文本不可見,因為共享,不需要顯示

plt.setp(ax3.get_xticklabels(), visible=False) # 使x軸刻度文本不可見,因為共享,不需要顯示

# 繪制蠟燭圖

def format_date(x, pos=None): return '' if x<0 or x>len(date_tickers)-1 else date_tickers[int(x)] # 日期格式化函數,根據天數索引取出日期值

ax1.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) # 設定自定義x軸格式化日期函數

ax1.xaxis.set_major_locator(ticker.MultipleLocator(max(int(len(df)/15), 5))) # 橫向最多排15個左右的日期,最少5個,防止日期太擁擠

opens, closes, highs, lows = matix[:, 1], matix[:, 2], matix[:, 3], matix[:, 4] # 取出ochl值

avg_dist_between_points = (xdates[-1] - xdates[0]) / float(len(xdates)) # 計算每個日期之間的距離

delta = avg_dist_between_points / 4.0 # 用于K線實體(矩形)的偏移坐标計算

barVerts = [((date - delta, open), (date - delta, close), (date + delta, close), (date + delta, open)) for date, open, close in zip(xdates, opens, closes) ] # 生成K線實體(矩形)的4個頂點坐标

rangeSegLow = [ ((date, low), (date, min(open, close))) for date, low, open, close in zip(xdates, lows, opens, closes) ] # 生成下影線頂點清單

rangeSegHigh = [ ((date, high), (date, max(open, close))) for date, high, open, close in zip(xdates, highs, opens, closes) ] # 生成上影線頂點清單

rangeSegments = rangeSegLow + rangeSegHigh # 上下影線頂點清單

cmap = {True: mcolors.to_rgba('#000000', 1.0), False: mcolors.to_rgba('#54fcfc', 1.0)} # K線實體(矩形)中間的背景色(True是上漲顔色,False是下跌顔色)

inner_colors = [ cmap[opn < cls] for opn, cls in zip(opens, closes) ] # K線實體(矩形)中間的背景色清單

cmap = {True: mcolors.to_rgba('#ff3232', 1.0), False: mcolors.to_rgba('#54fcfc', 1.0)} # K線實體(矩形)邊框線顔色(上下影線和後面的成交量顔色也共用)

updown_colors = [ cmap[opn < cls] for opn, cls in zip(opens, closes) ] # K線實體(矩形)邊框線顔色(上下影線和後面的成交量顔色也共用)清單

ax1.add_collection(LineCollection(rangeSegments, colors=updown_colors, linewidths=0.5, antialiaseds=False)) # 生成上下影線的頂點資料(顔色,線寬,反鋸齒,反鋸齒關閉好像沒效果)

ax1.add_collection(PolyCollection(barVerts, facecolors=inner_colors, edgecolors=updown_colors, antialiaseds=False, linewidths=0.5)) # 生成多邊形(矩形)頂點資料(背景填充色,邊框色,反鋸齒,線寬)

# 均線

mav_colors = ['#ffffff', '#d4ff07', '#ff80ff', '#00e600', '#02e2f4', '#ffffb9', '#2a6848'] # 均線循環顔色

mav_period = [5, 10, 20, 30, 60, 120, 180] # 定義要繪制的均線周期,可增減

n = len(df)

for i in range(len(mav_period)):

if n >= mav_period[i]:

mav_vals = df['close'].rolling(mav_period[i]).mean().values

ax1.plot(xdates, mav_vals, c=mav_colors[i%len(mav_colors)], label='MA'+str(mav_period[i]))

ax1.set_title('K線圖') # 标題

ax1.grid(True) # 畫網格

ax1.legend(loc='upper right') # 圖例放置于右上角

ax1.xaxis_date() # 好像要不要效果一樣?

# 成交量和成交量均線(5日,10日)

# ax2.bar(xdates, matix[:, 5], width= 0.5, color=updown_colors) # 繪制成交量柱狀圖

barVerts = [((date - delta, 0), (date - delta, vol), (date + delta, vol), (date + delta, 0)) for date, vol in zip(xdates, matix[:,5]) ] # 生成K線實體(矩形)的4個頂點坐标

ax2.add_collection(PolyCollection(barVerts, facecolors=inner_colors, edgecolors=updown_colors, antialiaseds=False, linewidths=0.5)) # 生成多邊形(矩形)頂點資料(背景填充色,邊框色,反鋸齒,線寬)

if n>=5: # 5日均線,作法類似前面的均線

vol5 = df['vol'].rolling(5).mean().values

ax2.plot(xdates, vol5, c='y', label='VOL5')

if n>=10: # 10日均線,作法類似前面的均線

vol10 = df['vol'].rolling(10).mean().values

ax2.plot(xdates, vol10, c='w', label='VOL10')

ax2.yaxis.set_ticks_position('right') # y軸顯示在右邊

ax2.legend(loc='upper right') # 圖例放置于右上角

ax2.grid(True) # 畫網格

# ax2.set_ylabel('成交量') # y軸名稱

# MACD

difs, deas, bars = matix[:, 6], matix[:, 7], matix[:, 8] # 取出MACD值

ax3.axhline(0, ls='-', c='g', lw=0.5) # 水準線

ax3.plot(xdates, difs, c='w', label='DIFF') # 繪制DIFF線

ax3.plot(xdates, deas, c='y', label='DEA') # 繪制DEA線

# ax3.bar(xdates, df['bar'], width= 0.05, color=bar_colors) # 繪制成交量柱狀圖(發現用bar繪制,線的粗細不一緻,故使用下面的直線清單)

cmap = {True: mcolors.to_rgba('r', 1.0), False: mcolors.to_rgba('g', 1.0)} # MACD線顔色,大于0為紅色,小于0為綠色

bar_colors = [ cmap[bar > 0] for bar in bars ] # MACD線顔色清單

vlines = [ ((date, 0), (date, bars[date])) for date in range(len(bars)) ] # 生成MACD線頂點清單

ax3.add_collection(LineCollection(vlines, colors=bar_colors, linewidths=0.5, antialiaseds=False)) # 生成MACD線的頂點資料(顔色,線寬,反鋸齒)

ax3.legend(loc='upper right') # 圖例放置于右上角

ax3.grid(True) # 畫網格

# KDJ

K, D, J = matix[:, 9], matix[:, 10], matix[:, 11] # 取出KDJ值

ax4.axhline(0, ls='-', c='g', lw=0.5) # 水準線

ax4.yaxis.set_ticks_position('right') # y軸顯示在右邊

ax4.plot(xdates, K, c='y', label='K') # 繪制K線

ax4.plot(xdates, D, c='c', label='D') # 繪制D線

ax4.plot(xdates, J, c='m', label='J') # 繪制J線

ax4.legend(loc='upper right') # 圖例放置于右上角

ax4.grid(True) # 畫網格

# set useblit = True on gtkagg for enhanced performance

from matplotlib.widgets import Cursor # 處理滑鼠

cursor = Cursor(ax1, useblit=True, color='w', linewidth=0.5, linestyle='--')

plt.show()

大功告成!

參考博文部落客:peakgao