用Python快速分析和預測股票價格

  • 2019 年 10 月 8 日
  • 筆記

作者 | 李潔

來源 | Python數據之道

用Python快速分析、可視化和預測股票價格

1 前言

某天,我的一個朋友告訴我說,實現經濟自由的關鍵是股票投資。雖然這是市場繁榮時期的真理,但如今業餘交易股票仍然是一個有吸引力的選擇。由於在線交易平台的便利性,湧現了許多自主價值投資者或家庭主婦交易員。甚至還有一些成功的故事和廣告吹噓有「快速致富計劃」學習如何投資回報率高達 40% 甚至更高的股票。投資已成為當今職場人士的福音。

現在的問題是:哪些股票?如何分析股票?與其他股票相比,所選股票的回報和風險是什麼?

本文的目標是讓你了解使用快速簡單的 Python 代碼分析股票的一種方法。只需花 12 分鐘閱讀這篇文章——最好自己完成一下。然後你就可以快速瀏覽到你的第一份金融分析報告。

為了開始學習和分析股票,我們將從快速查看歷史股票價格開始。這將通過從 Pandas 網絡數據閱讀器和雅虎財經中提取最新的股票數據來實現。然後,我們將嘗試通過探索性分析,如相關性熱圖、Matplotlib 可視化以及使用線性分析和k最近鄰(K Nearest Neighbor,KNN)的預測分析來查看數據。

2 加載雅虎財經數據集

Pandas 網絡數據閱讀器 (Pandas web data reader)是 Pandas 庫的一個擴展,用於與大多數最新的金融數據進行通信,包括雅虎財經、谷歌財經、Enigma 等資源。

我們將使用以下代碼提取 Apple 的股票價格:

import pandas as pd  import datetime  import pandas_datareader.data as web  from pandas import Series, DataFrame    start = datetime.datetime(2010, 1, 1)    end = datetime.datetime(2017, 1, 11)    df = web.DataReader("AAPL", 'yahoo', start, end)    df.tail()

來源於雅虎財經的股票價格

這段代碼將提取從 2010 年 1 月到 2017 年 1 月的 7 年的數據。你可以根據需要調整開始和結束日期。接下來的分析過程,我們將使用收盤價格,即股票在一天交易結束時的最終價格。

3 探索股票的移動平均值和收益率

在這個分析中,我們使用兩個關鍵的測量指標來分析股票:移動平均值和回報率。

3.1 移動平均值:確定趨勢

滾動平均 / 移動平均(MA)通過不斷更新平均價格來平滑價格數據,有助於降低價格表中的「噪音」。此外,該移動平均線可能充當「阻力」,代表着股票的下跌和上升趨勢,你可以從中預期它的未來趨勢,不太可能偏離阻力點。

讓我們開始寫代碼來得到滾動平均值:

close_px = df['Adj Close']    mavg = close_px.rolling(window=100).mean()

最後 10 個移動平均值

這將計算股票收盤價最後 100 個滑窗(100天)的移動平均值,並取每個滑窗的移動平均值。正如你所看到的,移動平均線在滑窗上穩步上升,並不遵循股票價格曲線的鋸齒線。為了更好地理解,讓我們用 Matplotlib 來繪製它。我們將用移動平均線來繪製股票價格表。

%matplotlib inline  import matplotlib.pyplot as plt  from matplotlib import style    # Adjusting the size of matplotlib    import matplotlib as mpl  mpl.rc('figure', figsize=(8, 7))    mpl.__version__    # Adjusting the style of matplotlib    style.use('ggplot')    close_px.plot(label='AAPL')    mavg.plot(label='mavg')    plt.legend()

蘋果股票移動平均價格(mavg)

移動平均使曲線平滑,顯示股票價格的漲跌趨勢。

在這張圖表中,移動平均線顯示了股票價格上升或下降的趨勢。從邏輯上講,你應該在股市低迷時買進,在股市上漲時賣出。

3.2 回報偏差:用於確定風險和收益

預期收益衡量投資收益概率分佈的平均值或預期值。投資組合的預期回報是通過將每項資產的權重乘以其預期回報,再加上每項投資的價值來計算的。(摘自投資百科,investopedia)

你可以參考以下公式:

收益公式

根據這個公式,我們可以畫出收益,如下。

rets = close_px / close_px.shift(1) - 1    rets.plot(label='return')

收益率

從邏輯上講,我們理想的股票收益應該儘可能高且穩定。如果你是風險規避者(像我一樣),你可能希望避開這種股票,因為你看到 2013 年下跌了 10%。這個決定很大程度上取決於你對股票的總體看法和對其他競爭對手股票的分析。

4 分析競爭對手股票

在這部分中,我們將分析一家公司相對於其競爭對手的表現。假設我們對科技公司感興趣,並想比較一下這些巨頭:蘋果(Apple)、通用電氣(GE)、谷歌(Google)、IBM 和微軟(Microsoft)。

dfcomp = web.DataReader(['AAPL', 'GE', 'GOOG', 'IBM', 'MSFT'],'yahoo',start=start,end=end)['Adj Close']

蘋果、通用電氣、谷歌、IBM 和微軟的股價

你將會從雅虎財經的股票價格中得到一張相當整潔平滑的收盤價表。

4.1 相關性分析:競爭對手會互相影響嗎?

我們可以通過運行 pandas 的百分比變化和相關函數來分析競爭關係。百分比變化將定義收益 ,找出與前一天相比價格變化的程度。了解相關性將有助於我們理解收益是否受其他股票收益的影響。

retscomp = dfcomp.pct_change()    corr = retscomp.corr()

讓我們繪製散點圖來觀察 Apple 和 GE 的收益分佈。

plt.scatter(retscomp.AAPL, retscomp.GE)    plt.xlabel('Returns AAPL')    plt.ylabel('Returns GE')

Apple 和 GE 的散點圖

我們可以看到,GE 的收益和 Apple 的收益之間存在着微弱的正相關關係。似乎在大多數情況下, Apple 的回報率越高,GE 的回報率也就越高。

讓我們通過繪製散點矩陣進一步改進我們的分析,以可視化競爭股票之間可能的相關性。在對角點,我們將運行核密度估計(Kernel Density Estimate,KDE)。KDE 是一個基本的數據平滑問題,它基於有限的數據樣本對總體進行推斷。它有助於生成對總體分佈的估計。

pd.scatter_matrix(retscomp, diagonal='kde', figsize=(10, 10))

KDE 圖和散點矩陣

從這裡我們可以得到大多數股票之間的分佈近似正相關。

為了證明正相關關係,我們將使用熱圖來可視化競爭股票之間的相關程度。注意顏色越淺代表這兩隻股票的相關性越強。

plt.imshow(corr, cmap='hot', interpolation='none')  plt.colorbar()    plt.xticks(range(len(corr)), corr.columns)  plt.yticks(range(len(corr)), corr.columns)

競爭股票之間相關性的熱圖

從散點矩陣和熱圖中我們可以發現,競爭股票之間有很大的相關性。然而,這可能並不能說明因果關係,只能說明科技行業的趨勢而不能說明相互競爭的股票是如何相互影響的。

4.2 股票回報率和風險

除了相關性,我們還分析了每支股票的風險和回報。本例中我們提取的是回報的平均值(回報率)和回報的標準差(風險)。

plt.scatter(retscomp.mean(), retscomp.std())  plt.xlabel('Expected returns')    plt.ylabel('Risk')    for label, x, y in zip(retscomp.columns, retscomp.mean(), retscomp.std()):        plt.annotate(label,xy = (x, y), xytext = (20, -20),         textcoords = 'offset points', ha = 'right', va = 'bottom',         bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),         arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))

股票風險與收益的快速散點圖

現在你可以看到這張關於競爭股票的風險和收益比較的清晰的圖表。從邏輯上講,你想要將風險最小化,並使收益最大化。因此,您需要為您的風險回報容忍度畫一條線(紅線)。然後,你將創建規則——購買紅線以下的股票(微軟、通用電氣和 IBM),賣出紅線以上的股票(蘋果和谷歌)。這條紅線顯示了您的期望值閾值和買進/賣出決策的基線。

5 預測股票價格

5.1 特徵工程

我們將使用這三個機器學習模型來預測股票:簡單線性分析、二次判別分析(Quadratic Discriminant Analysis,QDA)和 K近鄰(K Nearest Neighbor,KNN)。但首先我們需要設計一些特徵:高-低百分比和百分比變化。

dfreg = df.loc[:,['Adj Close','Volume']]    dfreg['HL_PCT'] = (df['High'] — df['Low']) / df['Close'] * 100.0    dfreg['PCT_change'] = (df['Close'] — df['Open']) / df['Open'] * 100.0

生成的最終數據幀

5.2 預處理和交叉驗證

在將數據放入預測模型之前,我們將按照以下步驟對數據進行清洗和處理:

1.刪除缺失值

2.分離標籤,我們要預測 Adjclose

3.縮放 X ,使每個樣本都可以具有相同的線性回歸分佈。

4.最後,我們要找到近期 X 和早期 X (用於訓練)的數據序列,用於模型生成和評估。

5.分離標籤並標識為 Y。

6.分別通過交叉驗證訓練模型和測試

請參考以下的代碼。

# Drop missing value  dfreg.fillna(value=-99999, inplace=True)    # We want to separate 1 percent of the data to forecast  forecast_out = int(math.ceil(0.01 * len(dfreg)))    # Separating the label here, we want to predict the AdjClose    forecast_col = 'Adj Close'  dfreg['label'] = dfreg[forecast_col].shift(-forecast_out)    X = np.array(dfreg.drop(['label'], 1))    # Scale the X so that everyone can have the same distribution for linear regression  X = preprocessing.scale(X)    # Finally We want to find Data Series of late X and early X (train) for model generation and evaluation  X_lately = X[-forecast_out:]  X = X[:-forecast_out]    # Separate label and identify it as y  y = np.array(dfreg['label'])  y = y[:-forecast_out]

5.3 模型生成-預測過程有意思的地方開始了

首先,讓我們為我們的 SciKit-Learn 庫 的導入添加以下代碼:

from sklearn.linear_model import LinearRegression  from sklearn.neighbors import KNeighborsRegressor  from sklearn.linear_model import Ridge  from sklearn.preprocessing import PolynomialFeatures  from sklearn.pipeline import make_pipeline

5.4 簡單線性分析和二次判別分析

簡單線性分析給出兩個或多個變量之間的線性關係。當我們在兩個變量中畫關係圖時,我們會得到一條直線。二次判別分析類似於簡單線性分析,只是模型允許多項式(例如: x 平方)的生成並會產生曲線。

線性回歸預測因變量(Y)為輸出而自變量(X)為輸入。在繪製過程中,我們會得到一條直線,如下圖所示:

簡單線性回歸

以下是一篇相當乾貨的文章,它對線性回歸進行了全面的回顧。

A beginner』s guide to Linear Regression in Python with Scikit-Learn https://towardsdatascience.com/a-beginners-guide-to-linear-regression-in-python-with-scikit-learn-83a8f7ae2b4f

我們將導入並使用現有的 SciKit 庫,並通過選擇 X 和 Y 訓練集來訓練模型。代碼如下。

# Linear regression  clfreg = LinearRegression(n_jobs=-1)  clfreg.fit(X_train, y_train)    # Quadratic Regression 2  clfpoly2 = make_pipeline(PolynomialFeatures(2), Ridge())  clfpoly2.fit(X_train, y_train)    # Quadratic Regression 3  clfpoly3 = make_pipeline(PolynomialFeatures(3), Ridge())  clfpoly3.fit(X_train, y_train)

5.5 K最近鄰(KNN)

KNN利用特徵相似性來預測數據點的值。這保證了分配的新點與數據集中的點相似。為了找出相似點,我們提取這些點間的最小距離(例如:歐氏距離)。

在 KNN 模型可視化中,你將會以 k 個數量的元素對問題元素進行分組

有關模型的詳細資料,請參閱以下鏈接。這對加深你的理解非常有用。

Introduction to k-Nearest Neighbors: Simplified (with implementation in Python) https://www.analyticsvidhya.com/blog/2018/03/introduction-k-neighbours-algorithm-clustering/

# KNN Regression  clfknn = KNeighborsRegressor(n_neighbors=2)  clfknn.fit(X_train, y_train)

5.6 評估

一種簡單、快速、粗略的評估方法是在每個訓練過的模型中使用 score 方法。score 可以得到測試數據集的 self.predict(X) 與 y 的平均精度。

confidencereg = clfreg.score(X_test, y_test)  confidencepoly2 = clfpoly2.score(X_test,y_test)  confidencepoly3 = clfpoly3.score(X_test,y_test)  confidenceknn = clfknn.score(X_test, y_test)    # results    ('The linear regression confidence is ', 0.96399641826551985)    ('The quadratic regression 2 confidence is ', 0.96492624557970319)    ('The quadratic regression 3 confidence is ', 0.9652082834532858)    ('The knn regression confidence is ', 0.92844658034790639)

結果顯示大多數模型的精確性評分(>0.95)。然而,這並不意味着我們可以盲目地持有這些股票。仍然有許多問題需要考慮,特別是對於不同的公司來說,隨着時間的推移,它們的價格走勢也會不同。

為了進行全面的測試,讓我們輸出一些股票的預測。

forecast_set = clf.predict(X_lately)    dfreg['Forecast'] = np.nan    #result    (array([ 115.44941187,  115.20206522,  116.78688393,  116.70244946,            116.58503739,  115.98769407,  116.54315699,  117.40012338,            117.21473053,  116.57244657,  116.048717  ,  116.26444966,            115.78374093,  116.50647805,  117.92064806,  118.75581186,            118.82688731,  119.51873699]), 0.96234891774075604, 18)

6 繪製預測圖

根據預測值,我們將用現有的歷史數據來可視化繪圖。這將有助於我們可視化模型如何預測未來股票價格。

last_date = dfreg.iloc[-1].name    last_unix = last_date    next_unix = last_unix + datetime.timedelta(days=1)    for i in forecast_set:        next_date = next_unix      next_unix += datetime.timedelta(days=1)      dfreg.loc[next_date] = [np.nan for _ in range(len(dfreg.columns)-1)]+[i]    dfreg['Adj Close'].tail(500).plot()  dfreg['Forecast'].tail(500).plot()  plt.legend(loc=4)  plt.xlabel('Date')  plt.ylabel('Price')  plt.show()

圖形表示預測值

如圖所示,藍線顯示了基於回歸的股票價格預測。預測表明,經濟衰退不會持續太久,然後就會復蘇。因此,我們可以在經濟低迷時買進股票,在經濟好轉時賣出。

7 未來的改進/挑戰

為了進一步分析股票,這裡有一些你可以實現的想法。這些想法將有助於對股票進行更全面的分析。如果需要更多的說明,請隨時通知我。

  • 分析經濟定性因素,如新聞(新聞來源和情感分析)
  • 分析經濟定量因素,如某個國家的HPI、公司起源之間的經濟不平等

代碼

在公眾號『Python數據之道』後台回復 「code」,可以獲取本文的代碼文件

文章來源:https://towardsdatascience.com/in-12-minutes-stocks-analysis-with-pandas-and-scikit-learn-a8d8a7b50ee7 本文原作者 Vincent Tatan 的聲明: 免責聲明:本免責聲明告知讀者,本文中表達的觀點、想法和意見僅屬於作者本人,並不一定屬於作者的僱主、組織、委員會或其他團體或個人。參考文獻是從列表中挑選出來的,與其他作品的任何相似之處都純屬巧合。 本文寫作純粹是作者的副業,沒有任何其他隱藏的動機。