用python的matplotlib和numpy庫繪製股票K線均線和成交量的整合效果(含量化驗證交易策略程式碼)
在用python的matplotlib和numpy庫繪製股票K線均線的整合效果(含從網路介面爬取資料和驗證交易策略程式碼)一文裡,我講述了通過爬蟲介面得到股票資料並繪製出K線均線圖形的方式,在本文裡,將在此基礎上再引入成交量效果圖,並結合量價理論,給出並驗證一些交易策略。
1 成交量對量化分析的意義
美國的股市分析家葛蘭碧(Joe Granville)在他所著的《股票市場指標》一書裡提出著名的“量價理論”。“量價理論”的核心思想是,任何對股價的分析,如果離開了對成交量的分析,都將是無本之木,無水之源,因為成交量的增加或萎縮都表現出一定的股價趨勢。
成交量是指時間單位內已經成交的股數或總手數。成交量能反應出股市交易中的供求關係,其中道理是比較淺顯易懂的,當股票供不應求時,大家爭相購買,成交量就很大了,反之當供過於求時,則說明市場交易冷淡,成交量必然萎縮。
廣義的成交量包括成交股數(Volumn或Vol)、成交金額(AMOUNT,時間單位內已經成交的總金額數)和換手率(TUN,股票每天成交量除以股票的流通總股本所得的比率),而狹義則是指成交股數。我們用yahoo介面得到的資料裡,有表示成交股數的Volumn列,其中的單位是“手”,一手為100股,在本部分裡,我們是通過Volumn列資料繪製股票的成交量資訊。
2 引入成交量
在K線和均線整合成交量的效果圖裡,出於美觀的考慮,我們對整合的效果提出瞭如下三點要求。
第一,繪製上下兩個子圖,上圖放K線和均線,下圖放成交量效果。
第二,上下兩個子圖共享x軸,也就是說,兩者x軸的刻度標籤和間隔應該是一樣的。
第三,通過柱狀圖來繪製成交量圖,如果當天股票上漲,成交量圖是紅色,下跌則是綠色。
在如下的drawKMAAndVol.py案例,我們將實現增加成交量圖的效果。
1 #!/usr/bin/env python 2 #coding=utf-8 3 import pandas as pd 4 import matplotlib.pyplot as plt 5 from mpl import candlestick_ochl 6 from matplotlib import MultipleLocator 7 #根據指定程式碼和時間範圍,獲取股票資料 8 df = pd.read_csv('D:/stockData/ch7/600895.csv',encoding='gbk') 9 #設定大小,共享x座標軸 10 figure,(axPrice, axVol) = plt.subplots(2, sharex=True, figsize=(15,8)) 11 #呼叫方法,繪製K線圖 12 candlestick_ochl(ax = axPrice, opens=df["Open"].values, closes=df["Close"].values, highs=df["High"].values, lows=df["Low"].values, 13 width=0.75, colorup='red', colordown='green') 14 axPrice.set_title("600895張江高科K線圖和均線圖")#設定子圖示題 15 df['Close'].rolling(window=3).plot(ax=axPrice,color="red",label='3天均線') 16 df['Close'].rolling(window=5).plot(ax=axPrice,color="blue",label='5天均線') 17 df['Close'].rolling(window=10).plot(ax=axPrice,color="green",label='10天均線') 18 axPrice.legend(loc='best') #繪製圖例 19 axPrice.set_ylabel("價格(單位:元)") 20 axPrice.grid(True) #帶網格線 21 #如下繪製成交量子圖 22 #直方圖表示成交量,用for迴圈處理不同的顏色 23 for index, row in df.iterrows(): 24 if(row['Close'] >= row['Open']): 25 axVol.bar(row['Date'],row['Volume']/1000000,width = 0.5,color='red') 26 else: 27 axVol.bar(row['Date'],row['Volume']/1000000,width = 0.5,color='green') 28 axVol.set_ylabel("成交量(單位:億手)")#設定y軸標題 29 axVol.set_title("600895張江高科成交量")#設定子圖的標題 30 axVol.set_ylim(0,df['Volume'].max()/100000000*1.2)#設定y軸範圍 31 xmajorLocator = MultipleLocator(5) #將x軸主刻度設定為5的倍數 32 axVol.xaxis.set_major_locator(xmajorLocator) 33 axVol.grid(True) #帶網格線 34 #旋轉x軸的展示文字角度 35 for xtick in axVol.get_xticklabels(): 36 xtick.set_rotation(15) 37 plt.rcParams['font.sans-serif']=['SimHei'] 38 plt.show()
從第8行到第20行,我們一方面是從csv檔案裡讀取資料,另一方面在第一個子圖裡繪製了K線和均線圖。這部分的程式碼和之前很相似,不過請大家注意兩個點。
第一,在第10行裡,不僅設定了繪圖區域的大小,更通過sharex=True語句,設定了axPrice和axVol這兩個子圖共享x軸。
第二,第二,在第14、18、19和第20行,由於是在K線圖和均線圖的axPrice子圖裡操作,所以若干方法的呼叫主體是axPrice物件,而不是之前的pyplot.plt物件。
從第23行到第36行裡,我們在axVol子圖裡繪製了成交量圖的效果。請大家注意第23行到第27行的for迴圈,在其中,我們通過第24行的if語句,比較收盤價和開盤價,以判斷當天股票是漲是跌,在此基礎上,通過第25行或第27行的bar方法,設定當日成交量圖的填充顏色。從上述程式碼能看出,成交量是在自於csv檔案裡的Volume列。
在繪製成交量圖的時候有兩個細節請大家注意一下。
第一,在第25行、第27行和第30行裡,當我們設定y軸的刻度值和範圍時,我們除以了一個相同的數,這是因為在第28行我們設定y軸文字時,指定了y軸成交量的單位是“億手“。
第二, 本次是通過第35行和第36行的for迴圈,設定了“x軸文字旋轉”的效果,從程式碼裡我們能看到,本案例中的旋轉角度是15度。
上述程式碼的執行效果如下圖所示,從中大家能看兩個x軸刻度一致的子圖,且在成交量子圖裡,上漲日和下跌日的成交量填充色分別是紅色和綠色。
3 成交量與股價的關係
成交量和股價間也存在著八大規律,通過下圖,我們能感受到這些規律,其中縱座標表示價(即股價),橫座標表示量(即成交量)。
我們能看出量價之間的八種關係,即量增價平、量增價升、量平價升、量縮價升、量減價平、量縮價跌、量平價跌、量跌價升,隨著上述週期過程,股價也完成了一個從漲到跌的完整迴圈,下面我們來具體解釋一下。
1.量增價平:股價經過持續下跌進入到低位狀態,出現了成交量增加但股價平穩的現象,此時不同天的成交量高度落差可能比較明顯,這說明該股在底部積聚上漲動力。
2.量增價升:成交量在低價位區持續上升,同時伴隨著股價上漲趨勢,這說明股價上升得到了成交量的支撐,後市將繼續看好,這是中短線的買入訊號。
3.量平價升:在股價持續上漲的過程中,如果多日的成交量保持等量水平,建議在這一階段中可以適當增加倉位。
4.量縮價升:成交量開始減少,但股價依然在上升,此時應該視情況繼續持股。但如果還沒有買入的投資者就不宜再重倉介入,因為股價已經有了一定的漲幅,價位開始接近上限。
5.量減價平:股價經長期大幅度上漲後,成交量顯著減少,股價也開始橫向調整不再上升,這是高位預警的訊號。這個階段裡一旦有風吹草動,比如突然拉出大陽線和大陰線,建議應出貨離場,做到落袋為安。
6.量縮價跌:成交量在高位繼續減少,股價也開始進入下降通道,這是明確的賣出訊號。如果還出現縮量陰跌,這說明股價底部尚遠,不會輕易止跌。
7.量平價跌:成交量停止減少,但股價卻出現急速下滑現象,這說明市場並沒有形成一致看空的共識。股諺有“多頭不死,跌勢不止“的說法,出現“量平價跌”的情況,說明主力開始逐漸退出市場,這個階段裡,應繼續觀望或者出貨,別輕易去買入以所謂的“搶反彈”。
8. 量增價跌:股價經長期大幅下跌之後,有可能出現成交量增加的情況,此時的操作原則是建議賣出,或者空倉觀望。如果低價區成交量有增加,則說明有資金在此價位區間接盤,預示後期有望形成底部並出現反彈。但如果出現量增價跌,則建議應清倉出局。
在下文裡,我們將通過Python語言驗證量價理論中的兩個規則。
4 驗證“量增價平“的買點
在如下的calBuyPointByVol.py案例中,我們將驗證“量增價平“的買點。在這段程式碼裡我們做了三件事,第一是通過yahoo介面得到了指定股票指定範圍內的交易資料,第二通過pandas介面儲存得到的資料,以便日後驗證,第三通過遍歷dataframe物件,計算量和價的關係,從而獲得買點日期。
1 #!/usr/bin/env python 2 #coding=utf-8 3 import pandas_datareader 4 import pandas as pd 5 import numpy as np 6 #漲幅是否大於指定比率 7 def isMoreThanPer(lessVal,highVal,per): 8 if np.abs(highVal-lessVal)/lessVal>per/100: 9 return True 10 else: 11 return False 12 #漲幅是否小於指定比率 13 def isLessThanPer(lessVal,highVal,per): 14 if np.abs(highVal-lessVal)/lessVal<per/100: 15 return True 16 else: 17 return False 18 code='600895.ss' 19 stock = pandas_datareader.get_data_yahoo(code,'2018-09-01','2018-12-31') 20 #刪除最後一行,因為get_data_yahoo會多取一天資料 21 stock.drop(stock.index[len(stock)-1],inplace=True) 22 #儲存在本地 23 stock.to_csv('D:\\stockData\ch7\\60089520181231.csv') 24 #從檔案裡得到資料 25 df = pd.read_csv('D:/stockData/ch7/60089520181231.csv',encoding='gbk') 26 cnt=0 27 while cnt<=len(df)-1: 28 try: 29 #規則1,連續三天收盤價變動不超過3% 30 if isLessThanPer(df.iloc[cnt]['Close'],df.iloc[cnt+1]['Close'],3) and isLessThanPer(df.iloc[cnt]['close'],df.iloc[cnt+2]['Close'],3) : 31 #規則2,連續三天成交量漲幅超過75% 32 if isMoreThanPer(df.iloc[cnt]['Volume'],df.iloc[cnt+1]['volume'],75) and isMoreThanPer(df.iloc[cnt]['Volume'],df.iloc[cnt+2]['Volume'],75) : 33 print("Buy Point on:" + df.iloc[cnt]['Date']) 34 except: 35 pass 36 cnt=cnt+1
在第7行定義的isMoreThanPer方法裡,我們比較了高價和低價,以判斷是否超過由引數per指定的漲幅。在第13行的isLessThanPer方法裡,我們判斷了跌幅是否超過per指定的範圍。由於這兩個功能經常會用到,所以我們把它們封裝成函式。
從第18行到第25行,我們完成了獲取並儲存資料的動作,並用df物件儲存了待遍歷的股票資料(即張江高科2018-09-01到2018-12-31的資料)。
在第27行到第36行按日期遍歷股票資料時,我們制定瞭如下規則,連續三天股票的收盤價變動範圍不超過5%(即價平)且3天成交量的漲幅過75%(即量增),把滿足條件的日期打印出來。執行後,我們能看到11月2日這個買點。
在之前程式碼基礎上改寫下,把時間範圍改成2018-09-01到2018-12-31,再執行下,能看到如下圖所示的效果。
從中我們能看到驗證後的結果:在11月2日之後,股票的漲幅比較明顯,確實是個合適的買點,從中我們能看出 “量增價平”的指導意義。
5 驗證“量減價平“的賣點
在如下calSellPointByVol.py案例中,我們同樣是分析張江高科2018-09-01到2018-12-31的交易資料,本次我們制定的策略是,第一,還是連續三天股票的收盤價變動範圍不超過5%(即價平),第二,較第一日相比,第二日和第三日的成交量下降幅度超過75%(即量減)。
1 #!/usr/bin/env python 2 #coding=utf-8 3 import pandas_datareader 4 import pandas as pd 5 import numpy as np 6 #漲幅是否大於指定比率 7 def isMoreThanPer(lessVal,highVal,per): 8 if np.abs(highVal-lessVal)/lessVal>per/100: 9 return True 10 else: 11 return False 12 #漲幅是否小於指定比率 13 def isLessThanPer(lessVal,highVal,per): 14 if np.abs(highVal-lessVal)/lessVal<per/100: 15 return True 16 else: 17 return False 18 #本次直接從檔案裡得到資料 19 df = pd.read_csv('D:/stockData/ch7/60089520181231.csv',encoding='gbk') 20 cnt=0 21 while cnt<=len(df)-1: 22 try: 23 #規則1,連續三天收盤價變動不超過3% 24 if isLessThanPer(df.iloc[cnt]['Close'],df.iloc[cnt+1]['Close'],3) and isLessThanPer(df.iloc[cnt]['Close'],df.iloc[cnt+2]['close'],3) : 25 #規則2,連續三天成交量跌幅超過75% 26 if isMoreThanPer(df.iloc[cnt+1]['Volume'],df.iloc[cnt]['Volume'],75) and isMoreThanPer(df.iloc[cnt+2]['Volume'],df.loc[cnt]['Volume'],75) : 27 print("Sell Point on:" + df.iloc[cnt]['Date']) 28 except: 29 pass 30 cnt=cnt+1
上述程式碼和之前calBuyPointByVol.py案例很相似,只不過我們適當變更了第26行判斷“成交量”的if條件。上述程式碼執行後,我們能得到的賣點是2018-12-05,從上圖裡我們能看出,在這段時間之後的若干交易日裡,張江高科的股價確實有下跌現象。
6 求推薦,後文預告與版權說明
在本系列的後面文章中,將陸續通過python繪製成交量、KDJ、MACD、RSI,BIAS和OBV等指標,而且還會用Python編寫針對這些指標的交易策略,敬請關注。
本文用了我將近2個小時,如果大家感覺好,請幫忙推薦下。
關於轉載有如下的說明。
1 本文文字和程式碼均屬原創,可轉載,但謝絕用於商業使用者。
2 轉載時請用連結的方式,給出原文出處,同時寫明原作者是hsm_computer。
3 在轉載時,請原文轉載 ,如要在轉載修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利於轉載者的目