1. 程式人生 > >用python的matplotlib和numpy庫繪製股票K線均線和成交量的整合效果(含量化驗證交易策略程式碼)

用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 在轉載時,請原文轉載 ,如要在轉載修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利於轉載者的目