本文將使用Python來可視化股票數(shù)據(jù),比如繪制K線圖,并且探究各項指標(biāo)的含義和關(guān)系,最后使用移動平均線方法初探投資策略。
數(shù)據(jù)導(dǎo)入
這里將股票數(shù)據(jù)存儲在stockData.txt文本文件中讶舰,我們使用pandas.read_table()函數(shù)將文件數(shù)據(jù)讀入成DataFrame格式。
其中參數(shù)usecols=range(15)限制只讀取前15列數(shù)據(jù)需了,parse_dates=[0]表示將第一列數(shù)據(jù)解析成時間格式跳昼,index_col=0則將第一列數(shù)據(jù)指定為索引。
import?pandas?as?pd
import?numpy?as?np
import?matplotlib.pyplot?as?plt
%matplotlib?inline
%config?InlineBackend.figure_format?=?'retina'
%pylab?inline
pylab.rcParams['figure.figsize']?=?(10,?6)?#設(shè)置繪圖尺寸
#讀取數(shù)據(jù)
stock?=?pd.read_table('stockData.txt',?usecols=range(15),?parse_dates=[0],?index_col=0)
stock?=?stock[::-1]#逆序排列
stock.head()
以上顯示了前5行數(shù)據(jù)肋乍,要得到數(shù)據(jù)的更多信息鹅颊,可以使用.info()方法。它告訴我們該數(shù)據(jù)一共有20行墓造,索引是時間格式挪略,日期從2015年1月5日到2015年1月30日√显溃總共有14列杠娱,并列出了每一列的名稱和數(shù)據(jù)格式,并且沒有缺失值谱煤。
stock.info()
DatetimeIndex:?20?entries,?2015-01-05?to?2015-01-30
Data?columns?(total?14?columns):
open20?non-null?float64
high20?non-null?float64
close?20?non-null?float64
low?20?non-null?float64
volume20?non-null?float64
price_change20?non-null?float64
p_change20?non-null?float64
ma5?20?non-null?float64
ma1020?non-null?float64
ma2020?non-null?float64
v_ma5?20?non-null?float64
v_ma1020?non-null?float64
v_ma2020?non-null?float64
turnover20?non-null?float64
dtypes:?float64(14)
memory?usage:?2.3?KB
在觀察每一列的名稱時摊求,我們發(fā)現(xiàn)’open’的列名前面似乎與其它列名不太一樣,為了更清楚地查看刘离,使用.columns得到該數(shù)據(jù)所有的列名如下:
stock.columns
Index(['????open',?'high',?'close',?'low',?'volume',?'price_change',
?'p_change',?'ma5',?'ma10',?'ma20',?'v_ma5',?'v_ma10',?'v_ma20',
?'turnover'],
dtype='object')
于是發(fā)現(xiàn)’open’列名前存在多余的空格室叉,我們使用如下方法修正列名睹栖。
stock.rename(columns={'????open':'open'},?inplace=True)
至此,我們完成了股票數(shù)據(jù)的導(dǎo)入和清洗工作茧痕,接下來將使用可視化的方法來觀察這些數(shù)據(jù)野来。
數(shù)據(jù)觀察
首先,我們觀察數(shù)據(jù)的列名踪旷,其含義對應(yīng)如下:
openhighcolselowvolumeprice_changep_change
開盤價最高價收盤價最低價成交量價格變動漲跌幅
ma5ma10ma20v_ma5v_ma10v_ma20turnover
5日均價10日均價20日均價5日均量10日均量20日均量換手率
這些指標(biāo)總體可分為兩類:
價格相關(guān)指標(biāo)
當(dāng)日價格:開盤曼氛、收盤價,最高令野、最低價
價格變化:價格變動和漲跌幅
均價:5舀患、10、20日均價
成交量相關(guān)指標(biāo)
成交量
換手率:成交量/發(fā)行總股數(shù)×100%
成交量均量:5气破、10聊浅、20日均量
由于這些指標(biāo)都是隨時間變化的,所以讓我們先來觀察它們的時間序列圖现使。
時間序列圖
以時間為橫坐標(biāo)低匙,每日的收盤價為縱坐標(biāo),做折線圖碳锈,可以觀察股價隨時間的波動情況努咐。這里直接使用DataFrame數(shù)據(jù)格式自帶的做圖工具,其優(yōu)點是能夠快速做圖殴胧,并自動優(yōu)化圖形輸出形式。
stock['close'].plot(grid=True)
如果我們將每日的開盤佩迟、收盤價和最高团滥、最低價以折線的形式繪制在一起,難免顯得凌亂报强,也不便于分析灸姊。那么有什么好的方法能夠在一張圖中顯示出這四個指標(biāo)?答案下面揭曉秉溉。
K線圖
相傳K線圖起源于日本德川幕府時代力惯,當(dāng)時的商人用此圖來記錄米市的行情和價格波動,后來K線圖被引入到股票市場召嘶。每天的四項指標(biāo)數(shù)據(jù)用如下蠟燭形狀的圖形來記錄父晶,不同的顏色代表漲跌情況。
圖片來源:http://wiki.mbalib.com/wiki/K線理論
Matplotlib.finance模塊提供了繪制K線圖的函數(shù)candlestick_ohlc()弄跌,但如果要繪制比較美觀的K線圖還是要下點功夫的甲喝。下面定義了pandas_candlestick_ohlc()函數(shù)來繪制適用于本文數(shù)據(jù)的K線圖,其中大部分代碼都是在設(shè)置坐標(biāo)軸的格式铛只。
from?matplotlib.finance?import?candlestick_ohlc
from?matplotlib.dates?import?DateFormatter,?WeekdayLocator,?DayLocator,?MONDAY
def?pandas_candlestick_ohlc(stock_data,?otherseries=None):????
# 設(shè)置繪圖參數(shù)埠胖,主要是坐標(biāo)軸
mondays?=?WeekdayLocator(MONDAY)
alldays?=?DayLocator()??
dayFormatter?=?DateFormatter('%d')
fig,?ax?=?plt.subplots()
fig.subplots_adjust(bottom=0.2)
if?stock_data.index[-1]?-?stock_data.index[0]?<?pd.Timedelta('730 days'):
weekFormatter?=?DateFormatter('%b %d')??
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
else:
weekFormatter?=?DateFormatter('%b %d, %Y')
ax.xaxis.set_major_formatter(weekFormatter)
ax.grid(True)
# 創(chuàng)建K線圖??
stock_array?=?np.array(stock_data.reset_index()[['date','open','high','low','close']])
stock_array[:,0]?=?date2num(stock_array[:,0])
candlestick_ohlc(ax,?stock_array,?colorup?=?"red",?colordown="green",?width=0.4)
# 可同時繪制其他折線圖
if?otherseries?is?not?None:
for?each?in?otherseries:
plt.plot(stock_data[each],?label=each)????????????
plt.legend()
ax.xaxis_date()
ax.autoscale_view()
plt.setp(plt.gca().get_xticklabels(),?rotation=45,?horizontalalignment='right')
plt.show()
pandas_candlestick_ohlc(stock)
這里紅色代表上漲糠溜,綠色代表下跌。
相對變化量
股票中關(guān)注的不是價格的絕對值直撤,而是相對變化量非竿。有多種方式可以衡量股價的相對值,最簡單的方法就是將股價除以初始時的價格谋竖。
stock['return']?=?stock['close']?/?stock.close.iloc[0]
stock['return'].plot(grid=True)
第二種方法是計算每天的漲跌幅红柱,但計算方式有兩種:
這兩者可能導(dǎo)致不同的分析結(jié)果,樣例數(shù)據(jù)中的漲跌幅使用的是第一個公式圈盔,并乘上了100%豹芯。
stock['p_change'].plot(grid=True).axhline(y=0,?color='black',?lw=2)
為了解決第二種方法中的兩難選擇,我們引入第三種方法驱敲,就是計算價格的對數(shù)之差铁蹈,公式如下:
close_price?=?stock['close']
log_change?=?np.log(close_price)?-?np.log(close_price.shift(1))
log_change.plot(grid=True).axhline(y=0,?color='black',?lw=2)
相關(guān)關(guān)系
在觀察了價格的走勢之后,我們來看看各指標(biāo)之間的關(guān)系众眨。下面挑選了部分代表性的指標(biāo)握牧,并使用pandas.scatter_matrix()函數(shù),將各項指標(biāo)數(shù)據(jù)兩兩關(guān)聯(lián)做散點圖娩梨,對角線是每個指標(biāo)數(shù)據(jù)的直方圖沿腰。
small?=?stock[['close',?'price_change',?'ma20','volume',?'v_ma20',?'turnover']]
_?=?pd.scatter_matrix(small)
圖中可以明顯發(fā)現(xiàn)成交量(volume)和換手率(turnover)有非常明顯的線性關(guān)系,其實換手率的定義就是:成交量除以發(fā)行總股數(shù)狈定,再乘以100%颂龙。所以下面的分析中我們將換手率指標(biāo)去除,這里使用了相關(guān)性關(guān)系來實現(xiàn)數(shù)據(jù)降維纽什。
上面的散點圖看著有些眼花繚亂措嵌,我們可以使用numpy.corrcof()來直接計算各指標(biāo)數(shù)據(jù)間的相關(guān)系數(shù)。
small?=?stock[['close',?'price_change',?'ma20','volume',?'v_ma20']]
cov?=?np.corrcoef(small.T)
cov
array([[?1.,0.30308764,0.10785519,0.91078009,?-0.37602193],
?[?0.30308764,1.,?-0.45849273,0.3721832?,?-0.25950305],
?[?0.10785519,?-0.45849273,1.,?-0.06002202,0.51793654],
?[?0.91078009,0.3721832?,?-0.06002202,1.,?-0.37617624],
?[-0.37602193,?-0.25950305,0.51793654,?-0.37617624,1.]])
如果覺得看數(shù)字還是不夠方便芦缰,我們繼續(xù)將上述相關(guān)性矩陣轉(zhuǎn)換成圖形企巢,如下圖所示,其中用顏色來代表相關(guān)系數(shù)让蕾。我們發(fā)現(xiàn)位于(0浪规,3)位置的相關(guān)系數(shù)非常大,查看數(shù)值達到0.91探孝。這兩個強烈正相關(guān)的指標(biāo)是收盤價和成交量笋婿。
img?=?plt.matshow(cov,cmap=plt.cm.winter)
plt.colorbar(img,?ticks=[-1,0,1])
plt.show()
以上我們用矩陣圖表的方式在多個指標(biāo)中迅速找到了強相關(guān)的指標(biāo)。接著做出收盤價和成交量的折線圖顿颅,因為它們的數(shù)值差異很大萌抵,所以我們采用兩套縱坐標(biāo)體系來做圖。
1stock[['close','volume']].plot(secondary_y='volume',?grid=True)
觀察這兩個指標(biāo)的走勢,在大部分時候股價上漲绍填,成交量也上漲霎桅,反之亦然。但個別情況下則不成立讨永,可能是成交量受到前期的慣性影響滔驶,或者還有其他因素。
移動平均線
吳軍老師曾講述他的投資經(jīng)驗卿闹,大意是說好的投資方式不是做預(yù)測揭糕,而是能在合適的時機做出合適的應(yīng)對和決策。同樣股市也沒法預(yù)測锻霎,我們能做的是選擇恰當(dāng)?shù)牟呗詰?yīng)對不同的情況著角。
好的指標(biāo)是能驅(qū)動決策的吏口。在上面的分析中我們一直沒有使用的一類指標(biāo)是5、10产徊、20日均價,它們又稱為移動平均值舟铜,下面我們就使用這項指標(biāo)來演示一個簡單的股票交易策略。(警告:這里僅僅是演示說明谆刨,并非投資建議。)
為了得到更多的數(shù)據(jù)來演示痊夭,我們使用pandas_datareader直接從雅虎中下載最近一段時間的谷歌股票數(shù)據(jù)。
import?datetime
import?pandas_datareader.data?as?web
# 設(shè)置股票數(shù)據(jù)的時間跨度
start?=?datetime.datetime(2016,10,1)
end?=?datetime.date.today()
# 從yahoo中獲取google的股價數(shù)據(jù)。
goog?=?web.DataReader("GOOG",?"yahoo",?start,?end)
#修改索引和列的名稱难捌,以適應(yīng)本文的分析
goog.index.rename('date',?inplace=True)
goog.rename(columns={'Open':'open',?'High':'high',?'Low':'low',?'Close':'close'},?inplace=True)
goog.head()
數(shù)據(jù)中只有每天的價格和成交量膝宁,所以我們需要自己算出5日均價和10日均價,并將均價的折線圖(也稱移動平均線)與K線圖畫在一起根吁。
goog["ma5"]?=?np.round(goog["close"].rolling(window?=?5,?center?=?False).mean(),?2)
goog["ma20"]?=?np.round(goog["close"].rolling(window?=?20,?center?=?False).mean(),?2)
goog?=?goog['2017-01-01':]
pandas_candlestick_ohlc(goog,?['ma5','ma20'])
觀察上圖员淫,我們發(fā)現(xiàn)5日均線與K線圖較為接近,而20日均線則更平坦击敌,可見移動平均線具有抹平短期波動的作用介返,更能反映長期的走勢。比較5日均線和20日均線,特別是關(guān)注它們的交叉點圣蝎,這些是交易的時機刃宵。移動平均線策略,最簡單的方式就是:當(dāng)5日均線從下方超越20日均線時徘公,買入股票牲证,當(dāng)5日均線從上方越到20日均線之下時,賣出股票关面。
為了找出交易的時機坦袍,我們計算5日均價和20日均價的差值,并取其正負號等太,作于下圖捂齐。當(dāng)圖中水平線出現(xiàn)跳躍的時候就是交易時機。
goog['ma5-20']?=?goog['ma5']?-?goog['ma20']
goog['diff']?=?np.sign(goog['ma5-20'])
goog['diff'].plot(ylim=(-2,2)).axhline(y=0,?color='black',?lw=2)
為了更方便觀察缩抡,上述計算得到的均價差值奠宜,再取其相鄰日期的差值,得到信號指標(biāo)缝其。當(dāng)信號為1時挎塌,表示買入股票;當(dāng)信號為-1時内边,表示賣出股票榴都;當(dāng)信號為0時,不進行任何操作漠其。
goog['signal']?=?np.sign(goog['diff']?-?goog['diff'].shift(1))
goog['signal'].plot(ylim=(-2,2))
從上圖中看出嘴高,從今年初到現(xiàn)在,一共有兩輪買進和賣出的時機和屎。到目前為止拴驮,似乎一切順利,那么讓我們看下這兩輪交易的收益怎么樣吧套啤。
trade?=?pd.concat([
pd.DataFrame({"price":?goog.loc[goog["signal"]?==?1,?"close"],
"operation":?"Buy"}),
pd.DataFrame({"price":?goog.loc[goog["signal"]?==?-1,?"close"],
"operation":?"Sell"})????
])
trade.sort_index(inplace=True)
trade
上述表格列出了交易日期潜沦、操作和當(dāng)天的價格唆鸡。但很遺憾地發(fā)現(xiàn)争占,這兩輪交易的賣出價都小于買入價,實際上按上述方法交易我們虧本了2蟆6号浴片效!
你是否很憤怒呢淀衣?原來分析到現(xiàn)在召调,都是假的呀唠叛!我之前就警告過,這里的分析只是演示移動平均線策略的思想册舞,而并非真正的投資建議调鲸。股票市場是何其的復(fù)雜多變挽荡,又如何是一個小小的策略所能戰(zhàn)勝的呢定拟?
那么這個策略就一無是處嗎?非也株依!如果考慮更長的時間跨度勺三,比如5年需曾、10年呆万,并考慮更長的均線,比如將20日均線和50日均線比較牡彻;雖然過程中也有虧損的時候庄吼,但贏的概率更大严就。也就是說梢为,在更長的時間尺度上該策略也是可行的铸董。但即使你賺了,又能跑贏大盤嗎蕴忆?這時候還需用到其他方法孽文,比如合理配置投資比例等芋哭。
還是那句話郁副,股市有風(fēng)險存谎,投資需謹慎既荚。本文不是分析股票的文章,而是借用股票數(shù)據(jù)來說明數(shù)據(jù)分析的基本方法句各,以及演示什么樣的指標(biāo)是好的指標(biāo)。