2. 獲取並管理金融數據

qteasy是一個完全本地化部署和運行的量化交易分析工具包,具備以下功能:

  • 金融數據的獲取、清洗、存儲以及處理、可視化、使用

  • 量化交易策略的創建,並提供大量內置基本交易策略

  • 向量化的高速交易策略回測及交易結果評價

  • 交易策略參數的優化以及評價

  • 交易策略的部署、實盤運行

通過本系列教程,您將會通過一系列的實際示例,充分了解qteasy的主要功能以及使用方法。

2.1. 開始前的準備工作

在開始本教程前,請完成以下工作:

  • 完成qteasy的安裝並升級到最新版本

  • 数据通道(二选一或组合)

    • 使用 Tushare:注册tushare pro账户并确保有一定的积分(大多数高级数据需要较多积分才能下载),在qteasy.cfg中配置tushare_token

    • 使用 AKShare 或其他通道:安装 pip install akshare(若选 AKShare),无需 Tushare token;部分表覆盖范围小于 Tushare,详见数据通道文档

  • 完成mysql数据库的配置,并将数据库配置写入qteasy.cfg可选项

  • 完成ta-lib的安裝 (可選項)

上一篇教程中,我介紹瞭如何新建一個虛擬環境,並在新的虛擬環境中安裝並初始化qteasy,如果還沒有完成這一步的朋友,請移步前一篇教程完成qteasy的安裝和基礎配置。

另外,爲了方便後續圖表等功能的使用,建議使用jupyter notebook來進行開發,您可以在新建的虛擬環境中運行以下命令安裝jupyter notebook

(bash): pip install notebook

安裝完成後,可以使用下面命令啓動jupyter notebook

(bash): jupyter notebook

啓動後,就可以在瀏覽器中的一個交互式開發環境中運行代碼了,如下圖所示:

在這裏插入圖片描述

如果不使用jupyter notebook,也可以使用ipython

(bash): pip install ipython

ipython 運行在terminal中,但是對圖表的支持沒有那麼好

2.2. 獲取基礎數據以及價格數據

如上一篇教程介紹,剛剛初始化的qteasy是無法調用任何歷史數據的,所有歷史數據都必須首先下載到本地,保存到一個稱爲Datasource的數據倉庫之後,才能完成後續所有需要數據的工作,例如調用歷史數據,進行策略的回測和優化等等。

qteasy需要使用的數據種類很多,所有的數據都是保存在一些預定義的數據表中,Datasource就是一系列數據表的集合。其中最基礎的數據表包括:

  • trade_calendar - 交易日曆數據,包括不同交易所的開市、閉市日期計劃,每年底更新下一年的交易日曆

  • stock_basics - 股票基礎資訊,包括滬深股市所有股票的基本資訊,包括代碼、名稱、全稱、上市日期、分類等等基礎資訊

  • index_basics - 指數基礎資訊,包括滬深股市所有指數的基本資訊,包括代碼、名稱、全稱等等資訊

在配置好tushare_token以後,第一次導入qteasy時,如果系統未找到交易日曆數據,會顯示資訊提示交易日曆無法讀取。

關於DataSource數據源對象的更多資訊,請參見DataSource Reference

>>> import qteasy as qt

提示資訊:

UserWarning: trade calendar is not loaded, some utility functions may not work properly, to download trade calendar, run 
"qt.refill_data_source(tables='trade_calendar')"

qteasy提供了一個函數get_table_overview()來顯示本地存儲的數據資訊,運行這個函數,可以列印出本地保存的數據表的清單,存儲的數據量、佔用的磁盤空間大小、以及數據範圍等等。

>>> qt.get_table_overview()

數據表分析過程可能會花費幾分鐘時間,其間會顯示進度條顯示分析進度。分析完成以後,會顯示本地數據源的數據表清單,以及數據表的數據範圍等資訊。

如果當前數據源中沒有任何數據,會輸出如下:

Analyzing local data source tables... depending on size of tables, it may take a few minutes
Analyzing completed!
Analyzing tables: 100%|█████████████████████████| 104/104 [00:00<00:00, 9107.58it/s]

Finished analyzing datasource: 
file://csv@qt_root/data/
0 table(s) out of 104 contain local data as summary below, to view complete list, print returned DataFrame
===============================tables with local data===============================
Empty DataFrame
Columns: [has_data, size, records, min2, max2]
Index: []

如果本地數據源中沒有數據,將會顯示上面的內容。此時需要下載數據到本地數據源。

下載交易日曆和基礎數據

我们可以调用refill_data_source函数下载交易日历和基础数据。这个函数是qteasy的标准数据下载接口函数,所有的历史数据类型均可以通过此接口下载。这个函数的基本参数是tables,传入数据表的名称即可下载相应的数据到本地存储了。使用refill_data_source下载交易数据时,qteasy会自动进行数据清洗,排除重复数据,去除错误数据,发生错误自动重试,并将下载的数据合并到本地数据表中。

qteasy支持通过 tushareakshareeastmoneysina 等多个内置通道下载数据(参数 channel,未指定时默认为 tushare)。不同通道支持的表范围与前置条件不同,切换方式与能力对照见数据通道文档

要下载前面提到的交易日历、股票和指数的基本信息,只需要运行下面的代码(默认使用 Tushare,需已配置 tushare_token):

>>> qt.refill_data_source(tables='trade_calendar, stock_basic, index_basic')

數據下載過程中會顯示進度條顯示下載進度。

輸出如下:

Filling data source file://csv@qt_root/data/ ...
into 3 table(s) (parallely): {'trade_calendar', 'index_basic', 'stock_basic'}
<trade_calendar> 72609 wrn: 100%|███████████████| 8/8 [00:03<00:00,  2.39task/s]
<index_basic> 12456 wrn: 100%|██████████████████| 8/8 [00:00<00:00,  9.68task/s]
<stock_basic> 5484 wrn: 100%|███████████████████| 4/4 [00:00<00:00,  5.45task/s]

Data refill completed! 90549 rows written into 3/3 table(s)!

下載完成後,再次運行qt.get_table_overview()函數

>>> qt.get_table_overview()

可以看到數據已經成功下載到本地:

Analyzing local data source tables... depending on size of tables, it may take a few minutes
Analyzing tables: 100%|████████████████████████| 104/104 [00:00<00:00, 967.60it/s]
Analyzing completed!

Finished analyzing datasource: 
file://fth@qt_root/data/
3 table(s) out of 104 contain local data as summary below, to view complete list, print returned DataFrame
===============================tables with local data===============================
               Has_data Size_on_disk Record_count Record_start Record_end
table                                                                    
trade_calendar   True       1.3MB         73K         CFFEX       SZSE   
stock_basic      True       651KB          5K          None       None   
index_basic      True       1.1MB         12K          None       None   

可以看到,三張數據表已經被下載到本地數據源,數據源的類型爲"file://csv@qt_root/data/"類型(即數據以csv文件形式存儲在qt根路徑的/data/路徑下),包含三張數據表,其中交易日曆的範圍涵蓋到2024年年底。

查看股票和指數的基礎數據

上面的基礎數據下載好之後,建議重新啓動IDE,重新導入qteasy。這時,我們就可以使用qteasy篩選和查找股票/指數了。

查找股票/指數詳細資訊可以使用get_stock_info()或者get_basic_info()函數,兩個函數功能相同,都可以根據輸入的證券代碼、名稱或者關鍵字查找證券的資訊,支持通配符或者模糊查找;如果同一個代碼對應不同的qt_code,例如股票000001代表平安銀行,對應qt_code: 000001.SZ,而指數000001代表上證指數,qt_code: 000001.SZqteasy會羅列出所有的證券資訊:

# 通过完整的qt_code获取信息
>>> qt.get_basic_info('000001.SZ')

輸出如下:

found 1 matches, matched codes are {'E': {'000001.SZ': '平安银行'}, 'count': 1}
More information for asset type E:
------------------------------------------
ts_code       000001.SZ
name               平安银行
area                 深圳
industry             银行
fullname     平安银行股份有限公司
list_status           L
list_date    1991-04-03
-------------------------------------------

更多的輸出可以查看下圖:

在這裏插入圖片描述

在上面的例子中,系統只找到了類型爲股票和指數的證券,如果還需要查找基金、期貨等更多的證券資訊,用同樣的方法下載更多的基礎數據表即可:

  • fund_basic: 基金基礎數據

  • future_basic: 期貨基礎數據

除了查找股票或證券的基本資訊以外,我們還能用qt.filter_stock()函數來篩選股票:

>>> qt.filter_stocks(date='20240212', industry='银行', area='上海')

輸出如下:

           name area industry market  list_date exchange
qt_code                                                 
600000.SH  浦发银行   上海       银行     主板 1999-11-10      SSE
601229.SH  上海银行   上海       银行     主板 2016-11-16      SSE
601328.SH  交通银行   上海       银行     主板 2007-05-15      SSE
601825.SH  沪农商行   上海       银行     主板 2021-08-19      SSE

下載滬市股票數據

金融數據中最重要的數據類型非量價數據莫屬。接下來,我們就來下載歷史價格數據。

qteasy的歷史數據全都是以K線數據的形式存儲在數據表中的,目前支持的K線數據包括:

  • 分鐘K線 - 1分鐘/5分鐘/15分鐘/30分鐘/60分鐘K線

  • 日K線

  • 周K線

  • 月K線

我們同樣使用qt.refill_data_source()函數下載股票數據。最常用的股票日K線數據保存在stock_daily表中。不過由於數據量較大,我們最好在下載數據時限定數據的範圍,通過start_date/end_date參數,指定下載數據的起始日期,分批下載歷史數據,否則,下載的過程將會非常漫長:

>>> qt.refill_data_source(tables='stock_daily', start_date='20230101', end_date='20231231')

上面的代碼下載了2023年全年所有已上市股票的日K線數據,同樣,下面的代碼可以用來下載常用指數(上證指數和滬深300指數)的日K線數據:

>>> qt.refill_data_source(tables='index_daily', symbols='000001, 000300', start_date='20231231', end_date='20240208')

從本地獲取股價數據

當股價數據保存在本地之後,就可以隨時提取出來使用了。

我們可以使用qt.get_history_data()函數來獲取股票的量價數據。這個函數是qteasy的一個通用接口,可以用來獲取各種類型的數據。在函數的參數中指定數據的類型(通過數據類型ID)、股票的代碼以及其他參數,就可以獲取相應的數據了。如果要獲取剛剛下載的K線價格,需要設置數據類型爲"open, high, low, close, vol"以獲取開盤價、最高價、最低價、收盤價和交易量:

>>> qt.get_history_data(
...         'open, high, low, close, vol',  # 数据类型,分别为开盘价、最高价、最低价、收盘价、成交量
...         shares='000001.SZ',   # 股票代码:平安银行
...         start='20230101',   # 数据开始日期
...         end='20230301',  # 数据结束日期
... )

得到結果如下:

{'000001.SZ':
              open   high    low  close         vol
 2023-01-04  13.71  14.42  13.63  14.32  2189682.53
 2023-01-05  14.40  14.74  14.37  14.48  1665425.18
 2023-01-06  14.50  14.72  14.48  14.62  1195744.71
 2023-01-09  14.75  14.88  14.52  14.80  1057659.11
 2023-01-10  14.76  14.89  14.39  14.44  1269423.39
 2023-01-11  14.45  14.78  14.39  14.67   830566.12
 2023-01-12  14.77  14.77  14.53  14.67   625694.84
 2023-01-13  14.67  14.95  14.55  14.95   949085.83
 2023-01-16  14.95  15.28  14.85  15.08  1560039.89
 2023-01-17  15.13  15.18  14.77  14.97   935834.54
 2023-01-18  14.95  15.18  14.91  15.11   718434.03
 2023-01-19  15.13  15.25  14.87  15.09   641875.20
 2023-01-20  15.16  15.24  15.00  15.13   608590.08
 2023-01-30  15.60  15.74  14.89  15.15  1374317.50
 2023-01-31  15.24  15.51  14.96  14.99  1030497.84
 2023-02-01  15.03  15.08  14.51  14.70  1653421.48}

上面函數的輸出是一個字典,字典的鍵爲shares參數指定的所有股票的代碼,而值爲一個DataFrame,包含該股票在指定期間的歷史數據,這裏我們指定了數據類型爲K線量價數據。當然,我們也可以指定其他的數據類型,只要這些數據已經下載到了本地,就可以直接讀取。

例如,指定數據類型htypes='pe, pb, total_mv'可以獲取股票的市盈率、市淨率和總市值等三項財務指標。如果某些指標存在缺失值的時候,可以定義填充方式填充缺失值,還可以對數據進行重新採樣,將每日的數據變爲每週或每小時數據。

關於get_history_data函數參數的詳細解釋,請參見qteasy文檔

生成K線圖

使用量價數據,更加方便易讀的方法是將數據顯示爲K線圖。

qteasy提供了qt.candle()函數,用於顯示專業K線圖,只要數據下載到本地後,就可以立即顯示K線圖:

>>> qt.candle('600004.SH', start='20230101', end='20230301')

在這裏插入圖片描述

下載復權因子數據到本地後,就可以顯示覆權價格了:

>>> qt.refill_data_source(tables='adj', start_date='20230101', end_date='20230601')
>>> qt.candle('600004.SH', start='20230101', end='20230301', adj='b')

在這裏插入圖片描述

qt.candle()函數支持傳入K線圖的開始日期、結束日期、K線頻率、復權方式以顯示不同區間和頻率的K線圖,也支持傳入移動均線的時長和macd的不同參數顯示不同的均線,qt.candle()函數還支持通過股票名稱顯示K線圖,如果輸入是股票名稱,會自動模糊查找,並且支持通配符。

下面是更多的K線圖例子,展示了股票、基金、指數等不同的資產類別,不同的數據頻率,不同的均線設定、不同的圖表類型等,爲了顯示下面示例中的K線圖,您需要下載相應的數據。

>>> import qteasy as qt
>>> df = qt.candle('159601', start='20210420', freq='d')
>>> df = qt.candle('000001.SH', start = '20211221', asset_type='IDX', plot_type='c')
>>> df = qt.candle('000300.SH', start = '20220331', asset_type='IDX', mav=[], plot_type='c')
>>> df = qt.candle('000300.SH', start = '20221021', asset_type='IDX', mav=[], plot_type='c', 
>>>                freq='30min')
>>> df = qt.candle('601728', freq='30min', adj='b', plot_type='c')
>>> df = qt.candle('沪镍主力', start = '20211130', mav=[5, 12, 36])
>>> df = qt.candle('510300', start='20200101', asset_type='FD', adj='b', mav=[])
>>> df = qt.candle('格力电器', start='20220101', asset_type='E', adj='f', mav=[5, 10, 20, 30])
>>> df = qt.candle('513100', asset_type='FD', adj='f', mav=[])
>>> df = qt.candle('110025', asset_type='FD', adj='f', mav=[9, 28])
>>> df = qt.candle('001104', asset_type='FD', adj='f', mav=[12, 26])

png

png

png

png

png

png

png

png

png

png

png

2.3. 數據類型DataType的查找

前面提到過,qteasy中的所有數據類型均被封裝爲DataType對象,代表一種可以被直接使用的歷史數據,每個DataType均有一個唯一的ID,通過這個ID,可以提取數據,在交易策略中引用該數據類型,完成qteasy中所需的工作。

爲了更加了解qteasy中的數據類型,我們可以用qt.find_history_data()函數來查詢所需的數據類型。qteasy中定義的數據類型是與數據頻率、資產類型掛鉤的,也就是說,不同資產的收盤價是不同的數據類型,不同頻率的收盤價也是不同的。

qt.find_history_data()函數可以根據輸入查找相關的數據類型,並且顯示它們的ID,數據表、說明等相關資訊,例如,搜索‘close’(收盤價)可以找到所有相關的數據類型:

>>> qt.find_history_data('close')

得到下面輸出:

matched following history data, 
use "qt.get_history_data()" to load these historical data by its data_id:
------------------------------------------------------------------------
          freq asset           table            desc
data_id                                             
close        d     E     stock_daily     股票日K线 - 收盘价
close        w     E    stock_weekly     股票周K线 - 收盘价
close        m     E   stock_monthly     股票月K线 - 收盘价
close     1min     E      stock_1min   股票60秒K线 - 收盘价
  ...      ...   ...           ...             ...
close        h    FD     fund_hourly    基金小时K线 - 收盘价
close        d   Any        top_list  融资融券交易明细 - 收盘价
========================================================================

再例如,搜索市盈率pe,可以得到:

>>> qt.find_history_data('pe')

得到下面輸出:

matched following history data, 
use "qt.get_history_data()" to load these historical data by its data_id:
------------------------------------------------------------------------
           freq asset             table                            desc
data_id                                                                
initial_pe    d     E         new_share                  新股上市信息 - 发行市盈率
pe            d   IDX   index_indicator                    指数技术指标 - 市盈率
pe            d     E   stock_indicator  股票技术指标 - 市盈率(总市值/净利润, 亏损的PE为空)
pe_2          d     E  stock_indicator2                  股票技术指标 - 动态市盈率
========================================================================

查找到相應的數據之後,只需要查看該數據所屬的數據表,將該數據表下載到本地數據源中(refill_data_source(tables, ...)),即可使用這些數據(qt.get_history_data(htype, shares, ...))了。

簡單介紹DataType對象

如上文所示,qteasy中的數據類型是以DataType對象的形式存在的,每個數據類型都有一個唯一的ID,通過這個ID可以提取數據,在交易策略中引用該數據類型,完成qteasy中所需的工作。

DataType代表了可以從數據源中提取出來的一種歷史數據,例如,股票日K線的收盤價就是一種歷史數據,股票周K線的收盤價又是另一種歷史數據,股票月K線的收盤價又是另一種歷史數據,雖然它們都是收盤價,但由於頻率不同,所以被封裝爲不同的數據類型。

DataType類封裝了統一的數據獲取API和屬性,大大方便了歷史數據在qteasy中的使用。當我們需要使用某種歷史數據時,只需要通過該ID使用get_history_data直接獲取即可。

而需要在交易策略中使用某種數據,只要在交易策略定義過程中註冊該數據的ID,就可以直接在策略中直接使用了,而不需要關心該數據是如何存儲的,如何下載的,如何清洗的等等細節問題。

2.4. 定期下載數據到本地

爲了保持本地數據源的數據更新,我們可以使用qt.refill_data_source()函數定期下載數據到本地。創建一個文件refill_data.py,並在其中寫入以下代碼:

import qteasy as qt

if __name__ == '__main__':
    # 解析命令行参数,--tabls参数表示数据表类型,--start_date和--end_date表示下载数据的起始日期和结束日期
    import argparse
    parser = argparse.ArgumentParser(description='refill data source')
    parser.add_argument('--tables', type=str, default='stock_daily', help='data table type')
    parser.add_argument('--start_date', type=str, default='20230101', help='start date')
    parser.add_argument('--end_date', type=str, default='20231231', help='end date')
    parser.add_argument('--parallel', type=bool, default=True, help='parallel download')
    parser.add_argument('--merge_type', type=str, default='update', help='merge type')
    args = parser.parse_args()
    tables = args.tables
    start_date = args.start_date
    end_date = args.end_date
    parallel = args.parallel
    merge_type = args.merge_type
    
    if tables == 'events':
        # 下载低频data和event数据,下载周期较长以cover所有的季度月度周度数据 (每周下载或每月下载)
        tables = 'stock_weekly, stock_monthly, index_weekly, index_monthly, '
        tables += 'income, balance, cashflow, financial, forecast, express, comp, report, events'
    elif tables == 'basics':
        # 下载基础数据,下载周期较长以cover所有的季度月度周度数据 (每周下载或每月下载)
        tables = 'basics'
    elif tables == 'daily':
        # 下载日频数据,下载周期较短以减少下载负载 (每天或每周下载)
        tables = 'adj, stock_daily, fund_daily, future_daily, options_daily, stock_indicator, stock_indicator2, index_indicator, shibor, libor, hibor, index_daily'
    elif tables == 'stock_mins':
        tables = 'adj, stock_1min, stock_5min, stock_15min, stock_30min, stock_hourly'
    elif tables == 'index_mins':
        tables = 'adj, index_1min, index_5min, index_15min, index_30min, index_hourly'
    elif tables == 'fund_mins':
        tables = 'adj, fund_1min, fund_5min, fund_15min, fund_30min, fund_hourly'
    else:
        tables == tables
    
    qt.refill_data_source(tables=tables, 
                          start_date=start_date, 
                          end_date=end_date, 
                          parallel= parallel, 
                          merge_type=merge_type)

上面的腳本文件提供了最基本的數據下載功能,可以根據需要修改tablesstart_dateend_date參數,以及parallelmerge_type參數,來下載不同的數據類型和不同的數據範圍。 您可以自行改進腳本文件以實現更多的功能

要下載2023年全年的stock_daily數據,只需要在命令行中運行以下命令:

(bash): python -m refill_data --tables stock_daily --start_date 20230101 --end_date 20231231

2.5. 回顧總結

至此,我們已經初步瞭解了qteasy中對數據的管理方式,瞭解了數據下載的方法。下載了基本數據以及一些量價數據。我們學會了如何提取數據、如何顯示K線圖。最後,我們還學會了查詢數據的方法,如果需要某種數據,知道如何查詢,如何下載和調用這些數據。

在下一篇教程中,我們將進一步加深對qteasy的瞭解,我們將學會如何創建交易策略,如何運行並回測交易策略。

關於qteasy的更多介紹,請參見qteasy文檔