一文教你如何用Python預測股票價格,程序員學以致用


最近,A股市場尤其是上證指數走勢凌厲,讓營長有種身在牛市中的錯覺。然而大盤天天漲,營長賬戶中還是那幾百萬,甚至還有所縮水。夜深人靜的時候,營長常常會點着一支菸,思索到底有沒有一個完美的算法,可以預測股價的漲跌,這樣就可以早日實現財務自由,走向人生巔峯。這時,一篇外國友人的文章成功引起了營長的注意,看完後備受啓發,所以我們將其編譯後,分享給大家,尤其是每天編碼的程序員。

在這裏還是要推薦下我自己建的Python開發學習羣:483546416,羣裏都是學Python開發的,如果你正在學習Python ,小編歡迎你加入,大家都是軟件開發黨,不定期分享乾貨(只有Python軟件開發相關的),包括我自己整理的一份2018最新的Python進階資料和高級開發教程,歡迎進階中和進想深入Python的小夥伴

友情提醒:股市有風險,投資需謹慎。營長忘了說,幾十億津巴布韋比。

對數據科學家來說,預測證券市場走勢是一項非常有誘惑力的工作,當然,他們這樣做的目的很大程度上並不是爲了獲取物質回報,而是爲了挑戰自己。證券市場起起伏伏、變幻莫測,試想一下,如果在這個市場裏存在一些我們或者我們的模型可以學習到的既定模式,讓我們可以打敗那些商科畢業的操盤手,將是多麼美妙。當然,當我一開始使用加性模型(additive model)來做時間序列預測時,我不得不先用模擬盤來驗證我的模型在股票市場上的表現。

一衆挑戰者們都希望在每日收益率上能夠跑贏市場,但是大多數都失敗了,我也未能倖免。不過,在這個過程中也學到了大量Python相關知識,包括面向對象編程、數據處理、建模、以及可視化等等。同時,我也認清了一個道理,不要在每日收益率上錙銖必較,學會容忍適當的短期虧損,放長線才能釣大魚。



一天與三十年對比結果:你寧願把錢投在哪裏?

在任何任務中(不只是數據科學),當我們沒有取得立竿見影的成效時,我們都有三個選擇:

1. 調整結果,讓我們看起來像是成功了

2. 隱藏結果,所以沒有人會注意到

3. 公開我們所有的結果和方法,以便其他人(以及我們自己)可以從中吸取經驗和教訓

顯然,不管站在個人還是社會層面,方案三都是最佳選擇,但它同時也是最需要勇氣去實踐的。我可以選擇性地公佈結果,比如當我的模型能夠帶來豐厚的利潤回報時,我也可以掩蓋失敗的事實,假裝自己從來沒有在這項工作上花過時間。這似乎是很天真的想法!我們之所以能夠進步是因爲不斷重複失敗——學習這個過程,而不僅僅是之前的成功。而且,爲有難度的任務編寫Python代碼而付出的努力也並不應該白費!

這篇文章記錄了我使用Python開發的“stock explorer”工具——Stocker的預測功能。此前,我曾展示瞭如何使用Stocker進行分析,並且將完整的代碼貼在GitHub上,以方便大家。

Github代碼地址:

https://github.com/WillKoehrsen/Data-Analysis/tree/master/stocker

實現預測的Stocker工具

Stocker是一款用於探索股票情況的Python工具。一旦我們安裝了所需的庫(查看文檔),我們可以在腳本的同一文件夾中啓動一個Jupyter Notebook,並導入Stocker類:


現在可以訪問這個類了。我們通過傳遞任一有效的股票代碼(粗體是輸出)來創建一個Stocker類的對象:


根據上面的輸出結果,我們有20年的亞馬遜每日股票數據可以用來探索! Stocker對象是建立在Quandl金融庫上,而且擁有3000多隻股票可以使用。我們可以使用plot_stock函數來繪製一個簡單的歷史股價圖:



Stocker的分析功能可以用來發現數據中的整體趨勢和模式,但我們將重點關注預測股票未來的價格上。Stocker中的預測功能是使用一個加性模型來實現的,該模型將時間序列視爲季節性(如每日、每週和每月)的整體趨勢組合。Stocker使用Facebook開發的智能軟件包進行加性建模,用一行代碼就可以創建模型並進行預測:



注意,表示預測結果的綠線包含了相對應的置信區間,這代表在模型預測的不確定性。在這種情況下,如果將置信區間寬度設置爲80%,這意味着我們預計這個範圍將包含實際值的可能性爲80%。置信區間將隨着時間進一步擴大,這是因爲隨着預測時間距離現有數據的時間越來越遠,預測值將面臨更多的不確定性。任何時候我們做這樣的預測,都必須包含一個置信區間。儘管大多數人傾向於一個確定的值,但我們的預測結果必須反映出我們生活在一個充滿不確定性的世界!

任何人都可以做股票預測:簡單地選擇一個數字,而這就是你的估測(我可能是錯的,但我敢肯定,這是華爾街所有人都會做的)。爲了讓我們的模型具有可信度,我們需要評估它的準確性。Stocker工具中有許多用於評估模型準確度的方法。

▌評估預測結果

爲了計算準確率,我們需要一個測試集和一個訓練集。我們需要知道測試集的答案,也就是實際的股價,所以我們將使用過去一年的歷史數據(本例中爲2017年)。訓練時,我們不選用2014-2016的數據來作爲訓練集。監督學習的基本思想是模型從訓練集中學習到數據中的模式和關係,然後能夠在測試數據上正確地重現結果。

我們需要量化我們的準確率,所以我們使用了測試集的預測結果和實際值,我們計算的指標包括測試集和訓練集的美元平均誤差、正確預測價格變化趨勢的時間百分比、以及實際價格落在預測結果80%置信區間內的時間百分比。所有這些計算都由Stocker自動完成,而且可視化效果很好:



可以看到,預測結果真是糟糕透了,還不如直接拋硬幣。如果我們根據這個預測結果來投資,那麼我們最好是買買彩票,這樣比較明智。但是,不要放棄這個模型,第一個模型通常比較糟糕,因爲我們使用的是默認參數(稱爲超參數)。如果我們最初的嘗試不成功,那麼我們可以調整這些參數來獲得一個更好的模型。在Prophet模型中有許多不同的參數設置需要調整,最重要的是變點先驗尺度(changepoint prior scale),它控制着模型在數據趨勢上的偏移量。

▌變點先驗(Changepoint Prior)的選擇

變點代表時間序列從增加到減少,或者從緩慢增加到越來越快(反之亦然)。它們出現在時間序列變化率最大的地方。變點先驗尺度表示在模型中給予變點的偏移量。這是用來控制過度擬合與欠擬合的(也被稱爲偏差與方差間的權衡)。

一個更高的先驗能創造一個更多變點權重和更具彈性的模型,但這可能會導致過擬合,因爲該模型將嚴格遵守訓練數據的規律,而不能將它泛化到新的測試數據中。降低先驗會減少模型的靈活性,而這又可能會導致相反的問題:欠擬合,當我們的模型沒有完全遵循訓練數據,而沒有學習到底層模式時,這種情況就會發生。如何找出適當的參數以達到正確的平衡,這更多的是一個工程問題而不是理論問題,在這裏,我們只能依靠經驗結果。Stocker類有兩種不同的方式來選擇適當的先驗:可視化和量化。 我們可以從可視化方法開始:



在這裏,我們使用三年的數據進行訓練,然後顯示了六個月的預測結果。我們沒有量化這裏的預測結果,因爲我們只是試圖去理解變點先驗值的作用。這個圖表很好地說明了過擬合與欠擬合!代表最小先驗的藍線與代表訓練數據的黑線值並不是非常接近,就好像它有自己的一套模式,並在數據的附近隨便選了一條路線。相比之下,代表最大先驗的黃線,則與訓練觀察結果非常貼近。變點先驗的默認值是0.5,它落在兩個極值之間的某處。

我們還要注意先驗值不同帶來的不確定性(陰影區間)方面的差異。最小的先驗值在訓練數據上表現有最大的不確定性,但在測試數據上的不確定性卻是最小。相比之下,最大的先驗值在訓練數據上具有最小的不確定性,但在測試數據上卻有最大的不確定性。先驗值越高,對訓練數據的擬合就越好,因爲它緊跟每次的觀察值。但是,當使用測試數據時,過擬合模型就會因爲沒有任何數據點來定位而迷失掉。由於股票具有相當多的變化性,我們可能需要比默認模型更靈活的模型,這樣才能夠捕捉儘可能多的模式信息。

現在我們對先驗值帶來的影響有了一個概念,我們可以使用訓練集和驗證集對數值進行評估:


在這裏,我們必須注意到,我們的驗證集和測試集是不一樣的數據。如果它們是一樣的,那麼我們會得到在測試數據上效果最好的模型,但是它只是在測試數據上過擬合了,而我們的模型也不能用於現實世界的數據。總的來說,就像在數據科學中通常所做的那樣,我們正在使用三組不同的數據:訓練集(2013-2015)、驗證集(2016)和測試集(2017)。

我們用四個指標來評估四個先驗值:訓練誤差、訓練範圍(置信區間)、測試誤差和測試範圍(置信區間),所有的值都以美元爲單位。正如我們在圖中看到的那樣,先驗值越高,訓練誤差越低,訓練數據的不確定性越低。我們也可以看到,更高的先驗能降低我們的測試錯誤。爲了在測試集上獲得更高的準確率,作爲交換,隨着先驗的增長,我們在測試數據上得到了更大範圍的不確定性。

Stocker先驗驗證還可以通過兩條線來闡述這些點:



基於不同變點先驗尺度下,訓練和測試準確性曲線和不確定性曲線

既然最高的先驗值產生了最低的測試誤差率,我們應該嘗試再增加先驗值來看看是否能得到更好的結果。我們可以通過在驗證中加入其它值的方法來優化我們的搜索:



改進後的訓練和測試曲線

當先驗值爲0.5時,測試集的錯誤率將最小化。因此我們將重新設置Stocker對象的變點先驗值。


我們可以調整模型的其他參數,比如我們期望看到的模式,或者模型使用的訓練數據。找到最佳組合只需要重複上述過程,並使用一些不同的值。請隨意嘗試任意的參數!

評估改進的模型

現在我們的模型已經優化好了,我們可以再次評估它:



現在看起來好多了! 這顯示了模型優化的重要性。使用默認值可以提供第一次合理猜測,但是我們需要確定,我們正在使用正確的模型“設置”,就像我們試圖通過調整平衡和淡入淡出來優化立體聲的聲音那樣(很抱歉引用了一個過時的例子)。

▌玩轉股票市場

股票預測是一個有趣的實踐,但真正的樂趣在於觀察這些預測結果在實際市場中會發揮多好的作用。使用evaluate_prediction函數,我們可以在評估期間使用我們的模型“玩一玩”股票市場。我們將使用模型預測給出的策略,與我們在整個期間簡單地購買和持有股票的策略進行一個對比。

我們的策略規則很簡單,如下:

1、當模型預測股價會上漲的那一天,我們開始買入,並在一天結束時賣出。當模型預測股價下跌時,我們就不買入任何股票;

2、如果我們購買股票的價格在當天上漲,那麼我們就把股票上漲的幅度乘以我們購買的股票的數量;

3、如果我們購買的股票價格下跌,我們就把下跌的幅度乘以股票的數量,計作我們的損失。

在整個評估期間,也就是2017年,我們每天以這樣的方式進行股票操作。將股票的數量添加進模型回饋裏面,Stocker就會以數字和圖表顯示的方式告訴我們這個策略是如何進行的:



上圖告訴了我們一個非常寶貴的策略:買入並持有!雖然我們可以在策略上再作出相當大的調整,但更好的選擇是長期投資。

我們可以嘗試其他的測試時間段,看看有沒有什麼時候我們的模型給出的策略能勝過買入和持有的方法。我們的策略是比較保守的,因爲當我們預測市場下跌的時候我們不進行操作,所以當股票下跌的時候,我們期待有比持有策略更好的方法。


一直用虛擬貨幣實驗

我就知道我們的模型可以做到這一點!不過,我們的模型只有在已經有了當天的數據時才能戰勝市場,也就是說還只是事後諸葛亮。

▌對股票未來價格的預測

現在我們有了一個像樣的模型,然後就可以使用predict_future()函數來對股票未來價格的進行預測。




預測接下來10天和100天的股票價格趨勢

這個模型和大多數“專業人士”一樣,總體上看好Amazon這支股票。另外,我們按照預期做出的估計,不確定性會進一步增加。實際上,如果我們使用這個模型策略進行交易,那我們每天都可以訓練一個新的模型,並且提前預測最多一天的價格。

雖然我們可能沒有從Stocker工具中獲得豐厚的收益,但是重點在於開發過程而不是最終結果! 在我們嘗試之前,我們實際上不知道自己是否能解決這樣一個問題,就算最終失敗,也好過從不嘗試!任何有興趣檢查代碼或使用Stocker工具的人,都可以在GitHub上找到代碼。


發佈了35 篇原創文章 · 獲贊 75 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章