online gambling singapore online gambling singapore online slot malaysia online slot malaysia mega888 malaysia slot gacor live casino malaysia online betting malaysia mega888 mega888 mega888 mega888 mega888 mega888 mega888 mega888 mega888 用Python 淺析股票數據

摘要: 本文將使用Python來可視化股票數據,比如繪製K線圖,並且探究各項指標的含義和關係,最後使用移動平均線方法初探投資策略。


大數據

本文將使用Python來可視化股票數據,比如繪製K線圖,並且探究各項指標的含義和關係,最後使用移動平均線方法初探投資策略。

 

數據導入

這裡將股票數據存儲在stockData.txt文本文件中,我們使用pandas.read_table()函數將文件數據讀入成DataFrame格式。

其中參數usecols=range(15)限制只讀取前15列數據,parse_dates=[0]表示將第一列數據解析成時間格式,index_col=0則將第一列數據指定為索引。

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) #設置繪圖尺寸

#讀取數據

stock = pd.read_table('stockData.txt', usecols=range(15), parse_dates=[0], index_col=0)

stock = stock[::-1] #逆序排列

stock.head()

 

大數據

以上顯示了前5行數據,要得到數據的更多信息,可以使用.info()方法。它告訴我們該數據一共有20行,索引是時間格式,日期從2015年1月5日到2015年1月30日。總共有14列,並列出了每一列的名稱和數據格式,並且沒有缺失值。

 

stock.info()

DatetimeIndex: 20 entries, 2015-01-05 to 2015-01-30

Data columns (total 14 columns):

open 20 non-null float64

high 20 non-null float64

close 20 non-null float64

low 20 non-null float64

volume 20 non-null float64

price_change 20 non-null float64

p_change 20 non-null float64

ma5 20 non-null float64

ma10 20 non-null float64

ma20 20 non-null float64

v_ma5 20 non-null float64

v_ma10 20 non-null float64

v_ma20 20 non-null float64

turnover 20 non-null float64

dtypes: float64(14)

memory usage: 2.3 KB

在觀察每一列的名稱時,我們發現'open'的列名前面似乎與其它列名不太一樣,為了更清楚地查看,使用.columns得到該數據所有的列名如下:

stock.columns

Index([' open', 'high', 'close', 'low', 'volume', 'price_change',

'p_change', 'ma5', 'ma10', 'ma20', 'v_ma5', 'v_ma10', 'v_ma20',

'turnover'],

dtype='object')

於是發現'open'列名前存在多餘的空格,我們使用如下方法修正列名。

stock.rename(columns={' open':'open'}, inplace=True)

至此,我們完成了股票數據的導入和清洗工作,接下來將使用可視化的方法來觀察這些數據。

數據觀察

首先,我們觀察數據的列名,其含義對應如下:

 

大數據

這些指標總體可分為兩類:

 

價格相關指標

當日價格:開盤、收盤價,最高、最低價

價格變化:價格變動和漲跌幅

均價:5、10、20日均價

成交量相關指標

成交量

換手率:成交量/發行總股數×100%

成交量均量:5、10、20日均量

由於這些指標都是隨時間變化的,所以讓我們先來觀察它們的時間序列圖。

時間序列圖

以時間為橫坐標,每日的收盤價為縱坐標,做折線圖,可以觀察股價隨時間的波動情況。這裡直接使用DataFrame數據格式自帶的做圖工具,其優點是能夠快速做圖,並自動優化圖形輸出形式。

stock['close'].plot(grid=True)

 

大數據

如果我們將每日的開盤、收盤價和最高、最低價以折線的形式繪製在一起,難免顯得凌亂,也不便於分析。那麼有什麼好的方法能夠在一張圖中顯示出這四個指標?答案下面揭曉。

 

K線圖

相傳K線圖起源於日本德川幕府時代,當時的商人用此圖來記錄米市的行情和價格波動,後來K線圖被引入到股票市場。每天的四項指標數據用如下蠟燭形狀的圖形來記錄,不同的顏色代表漲跌情況。

 

大數據

 

圖片來源:http://wiki.mbalib.com/wiki/K線理論

Matplotlib.finance模塊提供了繪製K線圖的函數candlestick_ohlc(),但如果要繪製比較美觀的K線圖還是要下點功夫的。下面定義了pandas_candlestick_ohlc()函數來繪製適用於本文數據的K線圖,其中大部分代碼都是在設置坐標軸的格式。

from matplotlib.finance import candlestick_ohlc

from matplotlib.dates import DateFormatter, WeekdayLocator, DayLocator, MONDAY

def pandas_candlestick_ohlc(stock_data, otherseries=None):

# 設置繪圖參數,主要是坐標軸

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)

# 創建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, horizo​​ntalalignment='right')

plt.show()

pandas_candlestick_ohlc(stock)

 

大數據

這里紅色代表上漲,綠色代表下跌。

 

相對變化量

股票中關注的不是價格的絕對值,而是相對變化量。有多種方式可以衡量股價的相對值,最簡單的方法就是將股價除以初始時的價格。

 

大數據

 

stock['return'] = stock['close'] / stock.close.iloc[0]

stock['return'].plot(grid=True)

 

大數據

第二種方法是計算每天的漲跌幅,但計算方式有兩種:

 

 

大數據

這兩者可能導致不同的分析結果,樣例數據中的漲跌幅使用的是第一個公式,並乘上了100%。

 

stock['p_change'].plot(grid=True).axhline(y=0, color='black', lw=2)

 

大數據

為了解決第二種方法中的兩難選擇,我們引入第三種方法,就是計算價格的對數之差,公式如下:

 

 

大數據

 

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)

 

大數據
大數據

相關關係

 

在觀察了價格的走勢之後,我們來看看各指標之間的關係。下面挑選了部分代表性的指標,並使用pandas.scatter_matrix()函數,將各項指標數據兩兩關聯做散點圖,對角線是每個指標數據的直方圖。

small = stock[['close', 'price_change', 'ma20','volume', 'v_ma20', 'turnover']]

_ = pd.scatter_matrix(small)

 

大數據

圖中可以明顯發現成交量(volume)和換手率(turnover)有非常明顯的線性關係,其實換手率的定義就是:成交量除以發行總股數,再乘以100%。所以下面的分析中我們將換手率指標去除,這裡使用了相關性關係來實現數據降維。

 

上面的散點圖看著有些眼花繚亂,我們可以使用numpy.corrcof()來直接計算各指標數據間的相關係數。

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. ]])

如果覺得看數字還是不夠方便,我們繼續將上述相關性矩陣轉換成圖形,如下圖所示,其中用顏色來代表相關係數。我們發現位於(0,3)位置的相關係數非常大,查看數值達到0.91。這兩個強烈正相關的指標是收盤價和成交量。

img = plt.matshow(cov,cmap=plt.cm.winter)

plt.colorbar(img, ticks=[-1,0,1])

plt.show()

 

大數據

以上我們用矩陣圖表的方式在多個指標中迅速找到了強相關的指標。接著做出收盤價和成交量的折線圖,因為它們的數值差異很大,所以我們採用兩套縱坐標體係來做圖。

 

stock[['close','volume']].plot(secondary_y='volume', grid=True)

 

大數據

觀察這兩個指標的走勢,在大部分時候股價上漲,成交量也上漲,反之亦然。但個別情況下則不成立,可能是成交量受到前期的慣性影響,或者還有其他因素。

 

移動平均線

吳軍老師曾講述他的投資經驗,大意是說好的投資方式不是做預測,而是能在合適的時機做出合適的應對和決策。同樣股市也沒法預測,我們能做的是選擇恰當的策略應對不同的情況。

好的指標是能驅動決策的。在上面的分析中我們一直沒有使用的一類指標是5、10、20日均價,它們又稱為移動平均值,下面我們就使用這項指標來演示一個簡單的股票交易策略。(警告:這裡僅僅是演示說明,並非投資建議。)

為了得到更多的數據來演示,我們使用pandas_datareader直接從雅虎中下載最近一段時間的谷歌股票數據。

import datetime

import pandas_datareader.data as web

# 設置股票數據的時間跨度

start = datetime.datetime(2016,10,1)

end = datetime.date.today()

# 從yahoo中獲取google的股價數據。

goog = web.DataReader("GOOG", "yahoo", start, end)

#修改索引和列的名稱,以適應本文的分析

goog.index.rename('date', inplace=True)

goog.rename(columns={'Open':'open', 'High':'high', 'Low':'low', 'Close':'close'}, inplace=True)

goog.head()

 

大數據

數據中只有每天的價格和成交量,所以我們需要自己算出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'])

 

大數據

觀察上圖,我們發現5日均線與K線圖較為接近,而20日均線則更平坦,可見移動平均線具有抹平短期波動的作用,更能反映長期的走勢。比較5日均線和20日均線,特別是關注它們的交叉點,這些是交易的時機。移動平均線策略,最簡單的方式就是:當5日均線從下方超越20日均線時,買入股票,當5日均線從上方越到20日均線之下時,賣出股票。

 

為了找出交易的時機,我們計算5日均價和20日均價的差值,並取其正負號,作於下圖。當圖中水平線出現跳躍的時候就是交易時機。

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)

 

大數據

為了更方便觀察,上述計算得到的均價差值,再取其相鄰日期的差值,得到信號指標。當信號為1時,表示買入股票;當信號為-1時,表示賣出股票;當信號為0時,不進行任何操作。

 

goog['signal'] = np.sign(goog['diff'] - goog['diff'].shift(1))

goog['signal'].plot(ylim=(-2,2))

 

大數據

從上圖中看出,從今年初到現在,一共有兩輪買進和賣出的時機。到目前為止,似乎一切順利,那麼讓我們看下這兩輪交易的收益怎麼樣吧。

 

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

 

大數據

上述表格列出了交易日期、操作和當天的價格。但很遺憾地發現,這兩輪交易的賣出價都小於買入價,實際上按上述方法交易我們虧本了!!!

 

你是否很憤怒呢?原來分析到現在,都是假的呀!我之前就警告過,這裡的分析只是演示移動平均線策略的思想,而並非真正的投資建議。股票市場是何其的複雜多變,又如何是一個小小的策略所能戰勝的呢?

那麼這個策略就一無是處嗎?非也!如果考慮更長的時間跨度,比如5年、10年,並考慮更長的均線,比如將20日均線和50日均線比較;雖然過程中也有虧損的時候,但贏的概率更大。也就是說,在更長的時間尺度上該策略也是可行的。但即使你賺了,又能跑贏大盤嗎?這時候還需用到其他方法,比如合理配置投資比例等。

還是那句話,股市有風險,投資需謹慎。本文不是分析股票的文章,而是藉用股票數據來說明數據分析的基本方法,以及演示什麼樣的指標是好的指標。

來源:魚心DrFish

轉貼自: 36大數據


留下你的回應

以訪客張貼回應

0

在此對話中的人們

YOU MAY BE INTERESTED