這篇文章裡,我們將會學習如何利用python來分析金融資料。我們主要會利用mpl_finance、pandas與matplotlib三個套件庫
我們先匯入需要用到的套件庫
import pandas as pd import matplotlib.pyplot as plt from matplotlib import dates as mdates from matplotlib import ticker as mticker from mpl_finance import candlestick_ohlc from matplotlib.dates import DateFormatter import datetime as dt
這邊我們使用yahoo finance的台積電股票資料,檔案可在這邊下載到 https://drive.google.com/open?id=189v3i7aAfC4zqF0h26-2QFtfmVWFc91fhttps://drive.google.com/open?id=189v3i7aAfC4zqF0h26-2QFtfmVWFc91fhttps://drive.google.com/open?id=189v3i7aAfC4zqF0h26-2QFtfmVWFc91f https://reurl.cc/AzeqY
建立一個python筆記本或是腳本後,將腳本放在與股票資料同一個資料夾。我們就可以用以下的程式碼將股票資料讀為pandas.DataFrame格式
匯入資料,把csv檔(連結下方)放到與程式檔同一資料夾
df = pd.read_csv(‘file.csv’,parse_dates=[‘Date’],index_col=0).dropna() df = df[(df.index > ‘2018-06-01’)] df_plot = df[[‘Open’,‘High’,‘Low’,‘Close’]]
這邊我們用read_csv(pandas提供的指令)讀入csv檔案,並選取2018年6月後的股票資料,為了等一下畫股價圖的需求,我們另外建立一個DataFrame,並取名為df_plot
接下來我們來計算MA與KD線,我們的計畫畫兩個子圖,一個子圖顯示日線與交易量,另一個子圖顯示KD線,其中MA線的計算相當簡單,我們使用pandas裡面內建的rolling方法即可回傳一個MA線的DataFrame. 我們將計算的過程包裝成一個函數。
#計算MA線 def moving_average(data,period): return data[‘Close’].rolling(period).mean()
另一方面,計算KD線的規則相對複雜,我們先看一下程式瑪
#計算KD線 ''' Step1:計算RSV:(今日收盤價-最近9天的最低價)/(最近9天的最高價-最近9天的最低價) Step2:計算K: K = 2/3 X (昨日K值) + 1/3 X (今日RSV) Step3:計算D: D = 2/3 X (昨日D值) + 1/3 X (今日K值) ''' def KD(data): data_df = data.copy() data_df[‘min’] = data_df[‘Low’].rolling(9).min() data_df[‘max’] = data_df[‘High’].rolling(9).max() data_df[‘RSV’] = (data_df[‘Close’] - data_df[‘min’])/(data_df[‘max’] - data_df[‘min’]) data_df = data_df.dropna() # 計算K # K的初始值定為50 K_list = [50] for num,rsv in enumerate(list(data_df[‘RSV’])): K_yestarday = K_list[num] K_today = 2/3 * K_yestarday + 1/3 * rsv K_list.append(K_today) data_df[‘K’] = K_list[1:] # 計算D # D的初始值定為50 D_list = [50] for num,K in enumerate(list(data_df[‘K’])): D_yestarday = D_list[num] D_today = 2/3 * D_yestarday + 1/3 * K D_list.append(D_today) data_df[‘D’] = D_list[1:] use_df = pd.merge(data,data_df[[‘K’,‘D’]],left_index=True,right_index=True,how=‘left’) return use_df
第一部份:計算出RSV 我們需要先計算RSV,根據定義,我們要將最近9天的最低價與最高價計算出,這邊我們使用pandas的rolling方法配合max,min即可計算出,我們將其存到新的一欄。有了max以及min欄位,我們就可以計算出RSV欄位。 第二部份:計算K線 我們先令K的初始值為50,然後要根據定義去迭代。我想把計算的K值存到一個列表中,所以先建了一個列表K_list,並填入第一個元素為50,接下來我們對RSV欄位跑迴圈,因為每次進入這個迴圈我們都能得到當天的RSV值,我們從K_list中取得昨天的K值並能計算出今天的K值,我們最後再把計算出的K值存回DataFrame一個新的column中,計算D線也是用同樣的邏輯。
有了KD線的計算函數之後,我們要來畫圖了!在這邊,我們要用mpl_finance這個套件,這是原本的matplotlib finance裡面獨立出來的一個套件,可以使用pip安裝,我們將要使用mpl_finance裡面的candlestick_ohlc函數來畫蠟燭圖,為了滿足格式需要(有時間、開盤價、收盤價、最高價與最低價排列好的DataFrame),我們想要新生成一個DataFrame,所以我們寫下以下的函數
def prepare_data(data): data_df = data.copy() data_df[‘DateTime’] = data_df.index data_df = data_df.reset_index() data_df = data_df[[‘DateTime’,‘Open’,‘High’,‘Low’,‘Close’]] data_df[‘DateTime’] = mdates.date2num(data_df[‘DateTime’].astype(dt.date)) return data_df
這個函數會將我們的原本的DataFrame抓出DateTime、Open、High、Low以及Close這幾個欄位排列好,並將原本是日期格式的日期,轉為需要candlestick_ohlc使用mdates.date2num格式。接下來就是繪製的主程式。
畫股價圖
顏色:https://matplotlib.org/users/colors.html
#畫股價線圖與蠟燭圖 def plot_stock_price(data): Ma_10 = moving_average(data,10) Ma_50 = moving_average(data,50) Length = len(data[‘DateTime’].values[50-1:]) fig = plt.figure(facecolor=‘white’,figsize=(15,10)) ax1 = plt.subplot2grid((6,4), (0,0),rowspan=4, colspan=4, facecolor=‘w’) candlestick_ohlc(ax1, data.values[-Length:],width=0.6,colorup=‘red’,colordown=‘green’) Label1 = ‘10 MA Line’ Label2 = ‘50 MA Line’ ax1.plot(data.DateTime.values[-Length:],Ma_10[-Length:],‘black’,label=Label1, linewidth=1.5) ax1.plot(data.DateTime.values[-Length:],Ma_50[-Length:],‘navy’,label=Label2, linewidth=1.5) ax1.legend(loc=‘upper center’, ncol=2) ax1.grid(True, color=‘black’) ax1.xaxis.set_major_formatter(mdates.DateFormatter(‘%Y-%m-%d’)) ax1.yaxis.label.set_color(“black”) ax1.tick_params(axis=‘y’, colors=‘black’) ax1.tick_params(axis=‘x’, colors=‘black’) plt.ylabel(‘Stock price and Volume’) plt.suptitle(‘Stock Code:2330’,color=‘black’,fontsize=16) #畫交易量 ax1v = ax1.twinx() ax1v.fill_between(data.DateTime.values[-Length:],0, df.Volume.values[-Length:], facecolor=‘navy’, alpha=.4) ax1v.axes.yaxis.set_ticklabels([]) ax1v.grid(False) ax1v.set_ylim(0, 3*df.Volume.values.max()) ax1v.tick_params(axis=‘x’, colors=‘black’) ax1v.tick_params(axis=‘y’, colors=‘black’) #加入KD線在下方 ax2 = plt.subplot2grid((6,4), (4,0), sharex=ax1, rowspan=1, colspan=4, facecolor=‘white’) ax2.plot(daysreshape.DateTime.values[-Length:], df.K[-Length:],color=‘black’) ax2.plot(daysreshape.DateTime.values[-Length:], df.D[-Length:],color=‘navy’) plt.ylabel(‘KD Value’, color=‘black’)
首先,我們利用我們寫好的計算移動平均的函數先計算出10天與50天的移動平均,接下來我們新增一張畫布(fig),然後畫第一張子圖(ax1),裡面我們先利用candlestick_ohlc將股價圖畫在ax1上,接下來在將兩條MA線畫上,我們也將x軸的日期格式在轉回日期表示。 接下來我們畫交易量,交易量因為要跟股價圖分享同一個x軸,所以我們輸入指令ax1v = ax1.twinx(),然後我們使用fill_between畫出交易量。 最後我們加入KD線的子圖(ax2),並將K值與D值畫在上面。
最後我們執行
daysreshape = prepare_data(df_plot) plot_stock_price(daysreshape) plt.show()
即可看到成品
