【譯】Python 金融:算法交易 (1)基礎入門

本文翻譯自2018年最熱門的Python金融教程 Python For Finance: Algorithmic Trading。

這篇 Python 金融教程向您介紹算法交易等內容。
技術已成爲金融領域的一項資產:金融機構已不僅僅是單純的金融機構了,它正向着技術公司演進。除了技術帶來的創新速度和競爭優勢以外,金融交易的速度、頻率和大數據量,使得金融機構對技術的關注度日益提高,技術確已成爲金融業的主要推動力。
在最熱門的金融編程語言中,有R語言、Python,還有C++、C#和Java。在本教程中,你將學習如何開始使用Python進行金融分析,其內容如下:

Python金融入門必備基礎知識:對於那些剛接觸金融的人,首先要了解有關股票和交易策略的知識,什麼是時間序列數據,以及如何設置工作空間。

常見的金融分析方法:介紹時間序列數據和常見的金融分析方法,比如使用Python包Pandas進行移動窗口、波動率計算等等。

簡單的動量策略開發:首先逐步完成開發過程,然後開始編寫簡單的算法交易策略。

回溯測試策略:使用Pandas、zipline和Quantopian回溯測試製定的交易策略。

評估交易策略:優化策略使之獲得更好的表現,並最終評估策略的性能和穩健性。

從這裏下載本教程的 Jupyter notebook 代碼。
Python 金融入門
在進入交易策略學習之前,最好先來了解基礎知識。本教程的第一部分將着重於介紹入門所需的Python基礎知識。但這並不意味着你將完全從零開始:你至少需要完成 DataCamp 的免費課程 Intro to Python for Data Science course,從而學會如何使用Python列表、包和NumPy。此外,儘管不是必需,但仍希望你能瞭解Pandas的基本知識,這是衆所周知的Python數據處理包。
然後我建議你參加DataCamp的課程 Intro to Python for Finance,學習Python金融的基本知識。如果你還想要把新學的Python數據科學技能用於真實的金融數據,可以考慮參加 Importing and Managing Financial Data in Python 課程。
股票和交易
當一家公司想要擴張或承接新項目時,它可以發行股票來募集資金。股票代表在公司所有權中佔的份額,並以金錢兌換的形式發放。股票可以買入和賣出:買賣雙方交易現存的曾發行的股票。賣出股票的價格獨立於公司業績,股價反應的是供需關係。這意味着,每當一隻股票因爲成功、受歡迎等原因被認爲是‘值得的’,那麼它的股價就會上漲。
請注意,股票和債券並不完全相同。債券是公司通過借貸的形式籌集資金,無論是作爲銀行貸款還是發行債券。
正如你剛纔讀到的那樣,買賣或者交易是我們談論股票所不可避免的,但當然不僅限於此:交易是一種買賣資產的行爲,可以是像股票、債券這樣的金融證券,或者是如黃金、石油這樣的有形資產。
股票交易是這樣一個過程:買入股票就是將現金轉換成公司所有權的股份,反之,賣出股票就是將股份換回現金。這一切交易都希望能從中獲取利潤。現在,爲了獲得豐厚的利潤,在市場上要麼做多,要麼做空:要麼你認爲股價會上漲並在將來的高價位上賣出股票,要麼賣出你的股票,期望在低價位上買回而盈利。當你按照固定的計劃在市場上做多或做空時,你就有了一個交易策略。
開發交易策略需要經歷若干階段,就如同構建機器學習模型那樣:首先制定一個策略,並以能在電腦上測試的形式實現它,然後進行初步測試或回溯測試,優化你的策略,最後評估策略的性能和穩健性。
交易策略通常通過回溯測試來驗證:根據策略制定的規則,使用歷史數據,重構過去可能發生的交易。通過這種方式,你能夠了解策略的有效性,並在將其應用於真實市場前,把它作爲策略優化的起點。當然,這通通依賴於以下信念:任何在過去表現良好的策略,也會在將來取得好的成績,同樣,任何在過去表現差勁的策略,在將來也不可能有好的表現。
時間序列數據
時間序列是在連續的、等間距的時間點上取得的一系列數據點。在投資中,時間序列跟蹤選定數據點(如股票價格)的變動,它是在特定的時間跨度內,等間隔地記錄數據點。如果你還是疑惑它到底長什麼樣子,來看看下面的例子:

圖片描述

x軸代表日期,y軸代表價格。在上圖中,“連續的、等間距的時間點” 就是x軸上以14天爲間隔的時間刻度:注意 3/7/2005 和它的下一個點 3/31/2005 之間的差值,以及 4/5/2005 和 4/19/2005 等等。
然而,你常見的股票數據不僅僅只有時間和價格這兩列,大部分時候有5列,包括時間、開盤價、最高價、最低價和收盤價。這意味着,如果時間間隔設置爲天,你將會得到某隻股票那一天的開盤價、收盤價,以及最高、最低價。
現在,你具備了學習完本教程的基本概念。接下來這些概念馬上又會出現,並在後續的學習中變得更深入。
設置工作空間
準備工作空間是一項簡單的工作:基本上只需確保你的系統運行了Python和集成開發環境(IDE)。然而仍有些辦法可以讓你更容易地開始。
以Anaconda爲例,它是Python和R的高性能發行版本,包含了超過100個最受歡迎的Python、R和Scala數據科學包。此外,安裝Anaconda將使你能通過conda輕鬆地安裝超過720個包,這裏conda是集成在Anaconda中的著名管理器,用於管理包、依賴項和環境。除此之外,Anaconda還包含了Jupyter Notebook和Spyder集成開發環境。
聽起來不錯,對吧?
你可以從這裏下載安裝Anaconda,同時不要忘了通過這篇教程Jupyter Notebook Tutorial: The Definitive Guide查看如何設置Jupyter Notebook。
當然,Anaconda並不是你唯一的選擇:你可以嘗試收費的 Canopy Python 發行版本,或者是 Quant Platform。
Quant Platform 相比於 Jupyter 或 Spyder IDE 更有優勢,因爲它向你提供了在瀏覽器中進行金融分析所需的一切。通過 Quant Platform,你可以訪問基於圖形用戶界面的金融工程,進行基於Python的交互式金融分析,以及使用你自己的Python分析庫。更重要的是,你還可以通過論壇與小夥伴們討論問題和解決方案。
Python金融基礎:Pandas
當你使用Python進行金融分析,會經常使用到數據處理包 Pandas。但當你深入時,也會涉及諸如 NumPy、SciPy、Matplotlib 這些包。
現在,讓我們只關注 Pandas 並使用它分析時間序列數據。本節將介紹如何使用 Pandas 導入、探索以及處理數據。最重要的是,你將瞭解如何對導入的數據進行常見的金融分析。
將金融數據導入Python
pandas-datareader包允許從谷歌、雅虎財經、世界銀行等數據源中讀取數據。如果你想知道此函數提供的最新的數據源列表,可參閱此文檔。在本教程中,你將使用pandas-datareader包讀取雅虎財經的數據。首先請確保安裝了此包的最新版本,可通過 pip with pip install pandas-datareader 命令實現。
提示:如果你想安裝最新的開發版本,或者遇到任何問題,都可以在這裏查看安裝說明。

import pandas_datareader as pdr
import datetime 
aapl = pdr.get_data_yahoo('AAPL', 
                          start=datetime.datetime(2006, 10, 1), 
                          end=datetime.datetime(2012, 1, 1))

請注意雅虎API端口最近已更改,如果你已經開始使用該庫,則需要安裝一個臨時的修復補丁,直到該補丁被合併到主幹中才能使用pandas-datareader包從雅虎財經獲取數據。在你開始之前,請確保查閱了此問題 。
無需擔心,在本教程中數據已提前爲你加載好,所以你在使用Pandas學習Python金融時不會遇到任何問題。
即便pandas-datareader提供了向Python導入數據的許多選擇,它也不是唯一能獲取金融數據的包:比如Quandl 庫,就可以獲取谷歌金融數據:

import quandl 
aapl = quandl.get("WIKI/AAPL", start_date="2006-10-01", end_date="2012-01-01")

更多關於如何使用 Quandl 獲取金融數據的信息,可參考此網頁。
最後,如果你已經在金融領域工作了一段時間,你可能知道最常用的數據處理工具是Excel。在這種情況下,你需要了解如何將Excel集成到Python中。
查看 DataCamp 的教程 Python Excel Tutorial: The Definitive Guide ,獲取更多相關知識。
使用時間序列數據
當你最終將數據導入工作空間後,首先要做的事情就是將手弄髒(指清洗、整理數據——譯者注)。然而,現在要處理的是時間序列數據,這看起來可能不那麼簡單,因爲索引是日期時間數據。
即便如此也不用擔心。讓我們一步步來,首先使用函數來探索數據。如果你先前已經有R或者Pandas的編程經驗,那麼對於這些函數就不陌生了。
沒關係,你將發現這很容易!
如上述代碼塊所示,使用pandas_datareader將數據導入工作空間。所得到的對象 aapl 是數據框,一個二維數據結構,其每一列可以是不同類型的數據。現在當你手頭有了一個常規的數據框時,首先要做的事情之一是運行 head() 和 tail() 函數來查看開始和結束的幾行數據。幸運的是,當你使用時間序列數據時,這一點並不會改變。
提示:請務必使用 describe() 函數來查看數據的統計摘要信息。

# 查看`aapl`數據的前幾行
print(aapl.head())

                 High        Low       Open      Close     Volume  Adj Close
Date                                                                        
2006-10-02  10.838572  10.614285  10.728572  10.694285  178159800   7.161565
2006-10-03  10.707143  10.455714  10.635715  10.582857  197677200   7.086947
2006-10-04  10.780000  10.451428  10.585714  10.768572  207270700   7.211311
2006-10-05  10.880000  10.590000  10.647142  10.690000  170970800   7.158698
2006-10-06  10.720000  10.544286  10.631429  10.602858  116739700   7.100338

# 查看`aapl`數據的最後幾行
print(aapl.tail())

                 High        Low       Open      Close    Volume  Adj Close
Date                                                                       
2011-12-23  57.655716  57.070000  57.098572  57.618572  67349800  38.585011
2011-12-27  58.441429  57.574287  57.585712  58.075714  66269000  38.891148
2011-12-28  58.321430  57.334286  58.127144  57.520000  57165500  38.519012
2011-12-29  57.950001  57.215714  57.628571  57.874287  53994500  38.756252
2011-12-30  58.040001  57.641430  57.644287  57.857143  44915500  38.744774

# 查看`aapl` 數據的統計信息
print(aapl.describe())

              High          Low         Open        Close        Volume  \
count  1323.000000  1323.000000  1323.000000  1323.000000  1.323000e+03   
mean     29.237566    28.507684    28.901012    28.889151  1.882896e+08   
std      14.199012    14.029758    14.123131    14.119734  1.027007e+08   
min      10.568571    10.371428    10.488571    10.461429  3.937360e+07   
25%      17.752857    17.182143    17.457857    17.431429  1.122037e+08   
50%      25.642857    24.725714    25.260000    25.120001  1.629866e+08   
75%      39.132858    38.351429    38.777143    38.699999  2.316230e+08   
max      60.957142    59.427143    60.251427    60.320000  8.432424e+08 



         Adj Close  
count  1323.000000  
mean     19.345990  
std       9.455460  
min       7.005628  
25%      11.673178  
50%      16.821934  
75%      25.915947  
max      40.394054


正如介紹中所述,這一數據包含四列,分別是蘋果股票每天的開盤價、收盤價,以及最高、最低價。此外還有另外兩列,成交量和調整的收盤價。
成交量(Volume)這一列記錄每天交易的股票數量。調整的收盤價(Adj Close)是將當天的收盤價進行調整,以包含第二天開盤前的任何舉措。可以使用此列檢查或深入分析歷史回報情況。
注意索引或行標籤如何包含日期,以及列或列標籤如何包含數值。
提示:可以使用Pandas中的 to_csv() 函數將該數據保存爲csv文檔,並且通過 read_csv() 函數將數據重新讀回到Python中。當因雅虎API端口被更改而無法獲取數據時,這一方法是非常方便的。

import pandas as pd
aapl.to_csv('data/aapl_ohlc.csv')  # 注意事先要在當前工作目錄下創建data文件夾
df = pd.read_csv('data/aapl_ohlc.csv', header=0, index_col='Date', parse_dates=True)

現在你已經簡單地查看了數據的前幾行以及一些統計信息,是時候更深入一些了。
一種方法是檢查索引和列,並選擇某列的最後10行數據。後者被稱爲構造子集,因爲你選擇了數據中的一小部分。構造子集得到一個序列(Series),它是一個可以存儲任何數據類型的一維數組。
請記住數據框結構是一個二維數組,它的每一列可以存儲不同的數據類型。
讓我們在接下來的練習中檢查上面所說的一切。首先,使用 index 和 columns 屬性來查看數據的索引和列。接着選取數據集中 Close 列的最後10個觀測量。使用方括號 [] 挑出最後10個數值。你也許從其他編程語言(比如R語言)中獲知了這一構造子集的方法。最後,將後者指定給變量 ts,並使用 type() 函數查看 ts 的類型。

# 查看索引 
aapl.index

DatetimeIndex(['2006-10-02', '2006-10-03', '2006-10-04', '2006-10-05',
               '2006-10-06', '2006-10-09', '2006-10-10', '2006-10-11',
               '2006-10-12', '2006-10-13',
               ...
               '2011-12-16', '2011-12-19', '2011-12-20', '2011-12-21',
               '2011-12-22', '2011-12-23', '2011-12-27', '2011-12-28',
               '2011-12-29', '2011-12-30'],
              dtype='datetime64[ns]', name='Date', length=1323, freq=None)

# 查看列
aapl.columns

Index(['High', 'Low', 'Open', 'Close', 'Volume', 'Adj Close'], dtype='object')

# 選擇Close列的最後10個數值
ts = aapl['Close'][-10:]
print(ts)

Date
2011-12-16    54.431427
2011-12-19    54.601429
2011-12-20    56.564285
2011-12-21    56.635715
2011-12-22    56.935715
2011-12-23    57.618572
2011-12-27    58.075714
2011-12-28    57.520000
2011-12-29    57.874287
2011-12-30    57.857143
Name: Close, dtype: float64

# 查看ts的類型
type(ts)

pandas.core.series.Series

方括號可以很好的對數據取子集,但它可能不是Pandas中最慣用的方法。這就是你還需學習 loc() 和 iloc() 函數的原因:前者用於基於標籤的索引,後者用於位置索引。
實際上,這意味着你可以將行標籤,如 2007 和 2006-11-01 傳遞給 loc() 函數,而將整數 22 和 43 傳遞給 iloc() 函數。
完成下面的練習來了解 loc() 和 iloc() 的工作方式。

查看2006年11、12月數據的前幾行

print(aapl.loc[pd.Timestamp('2006-11-01'):pd.Timestamp('2006-12-31')].head())

                 High        Low       Open      Close     Volume  Adj Close
Date                                                                        
2006-11-01  11.625714  11.194285  11.585714  11.308572  152798100   7.572930
2006-11-02  11.331429  11.214286  11.274285  11.282857  116370800   7.555712
2006-11-03  11.361428  11.112857  11.337143  11.184286  107972200   7.489699
2006-11-06  11.437143  11.204286  11.278571  11.387143  108644200   7.625546
2006-11-07  11.571428  11.447143  11.492857  11.501429  131483100   7.702079

# 查看2007年數據的前幾行
print(aapl.loc['2007'].head())

                 High        Low       Open      Close     Volume  Adj Close
Date                                                                        
2007-01-03  12.368571  11.700000  12.327143  11.971429  309579900   8.016820
2007-01-04  12.278571  11.974286  12.007143  12.237143  211815100   8.194759
2007-01-05  12.314285  12.057143  12.252857  12.150000  208685400   8.136404
2007-01-08  12.361428  12.182858  12.280000  12.210000  199276700   8.176582
2007-01-09  13.282857  12.164286  12.350000  13.224286  837324600   8.855811

# 查看2006年11月數據的前幾行
print(aapl.iloc[22:43].head())

                 High        Low       Open      Close     Volume  Adj Close
Date                                                                        
2006-11-01  11.625714  11.194285  11.585714  11.308572  152798100   7.572930
2006-11-02  11.331429  11.214286  11.274285  11.282857  116370800   7.555712
2006-11-03  11.361428  11.112857  11.337143  11.184286  107972200   7.489699
2006-11-06  11.437143  11.204286  11.278571  11.387143  108644200   7.625546
2006-11-07  11.571428  11.447143  11.492857  11.501429  131483100   7.702079

# 查看2006-11-01 和 2006-12-01 兩天的開盤價和收盤價
print(aapl.iloc[[22,43], [2, 3]])

                 Open      Close
Date                            
2006-11-01  11.585714  11.308572
2006-12-01  13.114285  13.045714

提示:如果仔細查看子集數據,你會發現某些天的數據是缺失的;如果你更仔細地觀察其模式,你會發現經常是缺失兩或三天;這些天是週末或者假日,所以並不包含在你的數據中。沒什麼可擔心的:這很正常,也無需填補缺失的日期。
除了索引,你可能還想研究其他技術來更好的瞭解數據。你永遠不知道還會發生什麼。讓我們嘗試從數據集中採集20行數據樣本,然後按月而不是天對數據 aapl 進行重新採樣。可以使用 sample() 和 resample() 函數來實現:

# 採樣20行數據
sample = aapl.sample(20)

# 輸出`sample`
print(sample)

                 High        Low       Open      Close     Volume  Adj Close
Date                                                                        
2011-08-15  54.995716  54.012856  54.232857  54.772858  115136000  36.679344
2007-03-19  13.078571  12.798572  12.891429  13.018572  178240300   8.718055
2007-11-28  25.799999  25.049999  25.260000  25.745714  287728000  17.240946
2010-09-17  39.708572  39.097141  39.669998  39.338570  158619300  26.343573
2010-03-11  32.214287  31.902857  31.987143  32.214287  101425100  21.572710
2007-01-18  13.158571  12.721429  13.157143  12.724286  591151400   8.520981
2007-06-05  17.527143  17.214285  17.344286  17.524286  230196400  11.735363
2011-03-04  51.470001  51.107143  51.438572  51.428570  113316700  34.439796
2009-12-15  28.215714  27.610001  27.975714  27.738571  104864900  18.575493
2006-12-15  12.745714  12.475715  12.717143  12.531428  184984800   8.391831
2007-08-27  19.237143  18.871429  19.055714  18.892857  176859900  12.651844
2009-01-16  12.054286  11.485714  12.042857  11.761429  261906400   7.876194
2007-03-01  12.615714  11.964286  12.004286  12.437143  353882200   8.328694
2010-05-05  36.877144  35.532856  36.147144  36.570000  220775800  24.489573
2010-09-08  37.770000  37.014286  37.111427  37.560001  131637800  25.152536
2009-07-16  21.145714  20.795713  20.822857  21.074286   98392700  14.112666
2007-06-06  17.721428  17.421429  17.471428  17.662857  278060300  11.828161
2009-05-05  18.980000  18.731428  18.821428  18.958570   99563800  12.695851
2011-09-28  57.677143  56.644287  57.169998  56.715714  107409400  37.980404
2007-04-19  13.035714  12.832857  12.884286  12.895715  106478400   8.635779

# 按月重新採樣
monthly_aapl = aapl.resample('M').mean()

# 輸出 `monthly_aapl` 的前幾行
print(monthly_aapl.head())

                 High        Low       Open      Close        Volume  \
Date                                                                   
2006-10-31  11.123766  10.893117  11.002922  11.017987  1.634995e+08   
2006-11-30  12.314626  12.028980  12.161565  12.192109  1.647010e+08   
2006-12-31  12.546500  12.205571  12.415857  12.353071  2.111349e+08   
2007-01-31  12.880857  12.522572  12.722357  12.697357  3.401223e+08   
2007-02-28  12.382932  12.111804  12.252105  12.246842  1.805573e+08   

            Adj Close  
Date                   
2006-10-31   7.378336  
2006-11-30   8.164602  
2006-12-31   8.272392  
2007-01-31   8.502948  
2007-02-28   8.201255  

非常直截了當,不是嗎?
resample() 函數使用頻繁,因爲它爲時間序列的頻率轉換提供了精細而靈活的控制:除了指定新的時間間隔,處理缺失數據以外,還能選擇對數據重新採樣的方式,如上述代碼所示。asfreq() 方法與之類似,不過只能實現前兩項功能。
提示:在 IPython 控制檯中嘗試代碼 aapl.asfreq("M", method="bfill"),並查看其輸出結果。
最後,在進行數據可視化和常見的金融分析這些進階的數據探索之前,你可能已經開始計算每天開盤價和收盤價之間的差值了。在Pandas的幫助下,可以輕易地實現這一算數運算;只需將 aapl 數據的 Open 列數值減去該數據的 Close 列數值即可。換言之,就是從 aapl.Open 中減去 aapl.Close。將結果存入 aapl 數據框中新的一列 diff 中,另外可以使用 del 將其刪除:

# 在`aapl` 中新增一列`diff`
aapl['diff'] = aapl.Open - aapl.Close

# 刪除`diff` 列
#del aapl['diff']

提示:請確保註釋掉最後一行代碼,這樣 aapl 數據框的新列不會被刪除,並且你可以檢查算術運算的結果!
當然,瞭解絕對收益可幫助你知道自己是否做了一個好的投資。但是作爲一名定量分析者,你可能對使用相對方法衡量股票價值更感興趣,比如某隻股票上漲或下跌的幅度。計算每日的百分比變化便是這樣一種方法。
現在知道這一點很好,不過也不用擔心,接下來你將會越來越深入地進行了解。
本節介紹了在開始預分析之前,進行數據探索的一些方法。但是仍有可提高的餘地,如果你想了解更多,可閱讀 Python Exploratory Data Analysis 這篇教程。
可視化時間序列數據
在使用 head(), tail(),索引等方法探索數據之後,你大概想要可視化時間序列數據。多虧了Pandas的繪圖功能整合了 Matplotlib 包,使這項任務變得容易了;只要使用 plot() 函數並傳遞給它相關的參數即可。另外,也可以使用 grid 參數來爲圖片添加網格背景。
讓我們檢查並運行以下代碼,看看如何繪製這樣一幅圖!

# 導入Matplotlib包的`pyplot` 模塊,簡寫爲 `plt`
import matplotlib.pyplot as plt

# 繪製收盤價曲線
aapl['Close'].plot(grid=True)

# 顯示繪圖
plt.show()

圖片描述

如果你想進一步瞭解 Matplotlib 包,並學習如何開始使用它,那麼可以查看 DataCamp的課程 Intermediate Python for Data Science。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章