12. 使用數據獲取渠道自動填充數據
前面介紹過DataSource對象的基本操作方法,但是在實際使用中,我們需要往DataSource對象中填充大量數據,如果使用前面章節介紹的DataSource.update_table_data()方法手動填充數據,這樣的工作量是非常大的。
這裏我們介紹如何使用數據獲取渠道自動填充數據。
12.1. QTEASY數據拉取功能
QTEASY數據管理模塊: 
如上圖所示,qteasy的數據功能分爲三層,第一層包括多種數據下載接口,用於從網絡數據提供商獲取數據,這個過程稱爲DataFetching。
12.2. 數據拉取接口refill_data_source()
qteasy提供了一個自動化數據下載接口qteasy.refill_data_source(),可以從多個不同的網絡數據提供商拉取多種金融數據,滿足不同用戶的使用習慣。qteasy提供的數據拉取API具備強大的多線程並行下載、數據分塊下載、下載流量控制和錯誤延時重試功能,以適應不同數據供應商各種變態的流量限制,同時數據拉取API可以方便地定期自動運行完成數據批量下載任務,不用擔心錯過高頻數據。
下面先用一個例子解釋如何使用qteasy.refill_data_source()接口自動填充數據。我們先創建一個不含數據的DataSource對象,並向其中填充最基本的數據。
>>> import qteasy as qt
>>> ds = qt.DataSource()
# 检查数据源中是否有数据
>>> ds.overview()
Analyzing local data source tables... depending on size of tables, it may take a few minutes
[########################################]104/104-100.0% A...zing completed!
Finished analyzing datasource:
file://csv@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.8MB 70K CFFEX SZSE
stock_basic True 852KB 5K None None
stock_daily True 98.8MB 1.3M 20211112 20241231
我們可以看到,DataSource對象中已經有了一些數據表,爲了進行下面的測試,我們將首先刪除trade_calendar以及stock_daily兩張數據表中的數據,然後再使用數據拉取接口自動填充它們。
首先刪除兩張數據表,爲了刪除數據表,首先將數據源的allow_drop_table屬性設置爲True,然後再刪除數據表。
>>> ds.allow_drop_table = True
>>> ds.drop_table_data('trade_calendar')
>>> ds.drop_table_data('stock_daily')
>>> ds.allow_drop_table = False
>>> overview = ds.overview()
Analyzing local data source tables... depending on size of tables, it may take a few minutes
[########################################]104/104-100.0% A...zing completed!
Finished analyzing datasource:
file://csv@qt_root/data/
1 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
stock_basic True 852KB 5K None None
可以看到,trade_calendar和stock_daily兩張數據表中的數據已經被刪除。
接下來,我們使用qteasy.refill_data_source()接口自動填充數據,代碼很簡單,只有一行,剩下的工作qteasy會自動完成。
>>> qt.refill_data_source(
tables='stock_daily', # 指定要填充的数据表:股票日K线数据
channel='tushare', # 指定数据下载渠道
data_source=ds, # 指定需要填充的数据源对象
start_date='20210101', # 指定数据下载的起始日期
end_date='20211231', # 指定数据下载的结束日期
)
Filling data source file://csv@qt_root/data/ ...
into 2 table(s) (parallely): {'stock_daily', 'trade_calendar'}
[########################################]243/243-100.0% <stock_daily> 2398764 wrtn in about 16 sec
[########################################]7/7-100.0% <trade_calendar> 70054 wrtn in about 1 sec
Data refill completed! 2468818 rows written into 2/2 table(s)!
拉取並填充數據後,可以檢查數據已經下載成功了:
>>> ds.read_table_data('stock_daily', shares='000001.SZ, 000002.SZ', start='20211111', end='20211131')
open high low close pre_close change pct_chg \
ts_code trade_date
000001.SZ 2021-11-11 17.35 18.43 17.32 18.35 17.40 0.95 5.4598
2021-11-12 18.31 18.63 18.11 18.27 18.35 -0.08 -0.4360
2021-11-15 18.35 18.63 18.20 18.43 18.27 0.16 0.8758
2021-11-16 18.36 18.54 18.17 18.22 18.43 -0.21 -1.1394
2021-11-17 18.15 18.30 17.98 18.11 18.22 -0.11 -0.6037
2021-11-18 18.09 18.12 17.73 17.80 18.11 -0.31 -1.7118
2021-11-19 17.80 18.24 17.70 18.15 17.80 0.35 1.9663
2021-11-22 18.03 18.25 17.90 18.12 18.15 -0.03 -0.1653
2021-11-23 18.11 18.35 17.68 17.88 18.12 -0.24 -1.3245
2021-11-24 17.77 17.95 17.66 17.87 17.88 -0.01 -0.0559
2021-11-25 17.74 17.79 17.63 17.68 17.87 -0.19 -1.0632
2021-11-26 17.62 17.67 17.52 17.58 17.68 -0.10 -0.5656
2021-11-29 17.41 17.57 17.36 17.51 17.58 -0.07 -0.3982
2021-11-30 17.54 17.68 17.35 17.44 17.51 -0.07 -0.3998
000002.SZ 2021-11-11 18.95 20.84 18.89 20.79 18.98 1.81 9.5364
2021-11-12 20.50 20.50 19.41 19.76 20.79 -1.03 -4.9543
2021-11-15 19.56 19.59 19.12 19.40 19.76 -0.36 -1.8219
2021-11-16 19.29 19.57 19.21 19.24 19.40 -0.16 -0.8247
2021-11-17 19.23 19.53 19.09 19.46 19.24 0.22 1.1435
2021-11-18 19.35 19.40 18.98 19.09 19.46 -0.37 -1.9013
2021-11-19 19.01 20.28 18.92 19.90 19.09 0.81 4.2431
2021-11-22 19.90 19.95 19.19 19.22 19.90 -0.68 -3.4171
2021-11-23 19.19 19.44 19.10 19.24 19.22 0.02 0.1041
2021-11-24 19.12 19.38 19.00 19.30 19.24 0.06 0.3119
2021-11-25 19.22 19.35 19.07 19.22 19.30 -0.08 -0.4145
2021-11-26 19.15 19.15 18.95 18.99 19.22 -0.23 -1.1967
2021-11-29 18.75 18.87 18.35 18.46 18.99 -0.53 -2.7909
2021-11-30 18.44 18.66 18.16 18.26 18.46 -0.20 -1.0834
vol amount
ts_code trade_date
000001.SZ 2021-11-11 2084729.00 3752413.858
2021-11-12 957546.46 1753072.716
2021-11-15 655089.99 1203764.095
2021-11-16 601110.48 1099113.409
2021-11-17 664640.38 1203859.180
2021-11-18 799843.77 1430058.311
2021-11-19 786371.56 1414506.380
2021-11-22 738617.80 1337768.172
2021-11-23 1235977.96 2213817.590
2021-11-24 741310.84 1316774.397
2021-11-25 603532.70 1068221.304
2021-11-26 694499.88 1219937.312
2021-11-29 512594.71 895105.981
2021-11-30 733616.06 1280384.552
000002.SZ 2021-11-11 3151015.76 6352746.112
2021-11-12 2065924.12 4100076.111
2021-11-15 959331.52 1852352.374
2021-11-16 593989.40 1149085.955
2021-11-17 623749.71 1205064.294
2021-11-18 609995.75 1168010.581
2021-11-19 1308293.09 2570652.947
2021-11-22 877584.30 1697701.639
2021-11-23 563435.65 1083646.252
2021-11-24 827366.98 1587246.249
2021-11-25 518123.06 995473.890
2021-11-26 504023.33 959331.064
2021-11-29 718595.81 1334479.867
2021-11-30 713092.22 1305310.857
12.3. 數據拉取API的功能特性
分析數據拉取的過程,我們可以看到,qteasy自動完成了下面的工作:
自動查找依賴表 —— 雖然我們只指定了
stock_daily數據表,但是qteasy自動檢測到trade_calendar數據表也是空的,且stock_daily表依賴交易日曆表,所以也自動填充了trade_calendar數據表。下載進度可視化 ——
qteasy提供了下載進度可視化,可以看到每個數據分塊的下載進度,以及總體下載進度,過程中可以顯示剩餘時間,方便用戶查看數據下載的情況。大數據量自動分塊 —— 上面的代碼下載了2021年全年所有股票的日K線數據,這些數據量共有239萬行,不管從任何數據渠道,這麼大量的數據都不可能一次性下載下來,因此,
qteasy自動將數據分塊,每一塊只有一天的數據,可以看到整年的數據被分成了243塊,數據分塊下載顯著降低了每次網絡申請的數據量,提高成功率且降低了被阻斷的風險。多線程並行下載 —— 實行數據分塊下載後,
qteasy自動使用多線程並行下載,加快數據下載速度,243個數據分塊並行下載總共耗時僅16秒。
有了上面這些特性,qteasy的數據拉取功能可以滿足幾乎所有用戶的數據獲取需求,不管是下載大量數據,還是下載高頻數據,qteasy都能提供高效的數據下載服務。
當然,除了上面提到的這些特性之外,qteasy還提供了更多的功能特性,以針對下載過程中出現的各種狀況,這些功能特性我們在後面會逐步介紹:
多渠道下載 ——
qteasy提供了多種數據下載渠道,很多數據表可以從多個不同的渠道下載,而且隨着版本更新,數據拉取渠道也在不斷增加。流量控制 —— 有些數據渠道對數據下載有流量限制,
qteasy提供了流量控制功能,可以限制數據下載的速度,即下載一定分塊數量的數據後,可以暫停一段時間,例如每下載300個分塊的數據,就暫停一分鐘,避免被數據渠道封禁。錯誤重試 —— 有些數據渠道下載數據時,可能會出現網絡錯誤,
qteasy提供了錯誤重試功能,可以在下載失敗後,自動重試下載,如果重試不成功,會延長重試等待時間再試,直到下載成功或超過重試次數並報錯。日誌記錄 ——
qteasy提供了數據下載日誌記錄功能,可以記錄每次數據下載的詳細資訊,包括下載的數據量、下載的時間、下載的速度等,方便用戶查看數據下載的情況。
多渠道拉取數據
qteasy提供了多種數據下載渠道,很多數據表可以從多個不同的渠道下載,而且隨着版本更新,數據拉取渠道也在不斷增加。
refill_data_source()接口的channel参数可以指定数据下载渠道,如果不指定,qteasy会使用默认渠道tushare(见qteasy/core.py中refill_data_source的默认逻辑)。用户也可以手动指定数据下载渠道。
当前内置四通道为:tushare、akshare、eastmoney(别名 emoney)、sina。
四通道能力对照(常用表)
下表概括常用数据表在各通道下的支持情况(「支持」表示当前版本已实现映射并可走 refill 链路;「不支持」表示该通道无映射,refill 会跳过并提示)。AKShare 完整 108 表状态见仓库内维护清单 tests/akshare_data_test_checklist.md。
数据表 |
tushare |
akshare |
eastmoney |
sina |
|---|---|---|---|---|
trade_calendar |
支持(需 token/积分) |
支持 |
暂不支持 |
暂不支持 |
stock_basic |
支持(行业/上市日等完整) |
支持(代码+简称索引;行业/地域等常为空) |
部分场景不支持 |
暂不支持 |
index_basic / fund_basic |
支持 |
支持(字段少于 Tushare 的项可能为空) |
部分 |
暂不支持 |
stock_daily / weekly / monthly |
支持 |
支持 |
支持(日/部分分) |
支持(日/分) |
stock_5/15/30min、hourly |
支持 |
支持 |
支持 |
支持 |
stock_adj_factor |
支持 |
支持(新浪因子源) |
暂不支持 |
暂不支持 |
index_daily / weekly / monthly |
支持 |
支持 |
支持(日) |
暂不支持 |
fund_daily / weekly / monthly / 1min |
支持 |
支持 |
部分 |
暂不支持 |
stock_suspend / money_flow / dividend |
支持 |
支持 |
暂不支持 |
暂不支持 |
new_share / stock_company |
支持 |
支持(字段可能少于 Tushare) |
暂不支持 |
暂不支持 |
realtime_bars / realtime_quotes |
支持 |
支持 |
支持 |
支持 |
index_1min 等指数分钟 |
支持 |
暂不支持(待 spike) |
支持 |
暂不支持 |
说明:
basics 表与
merge_type='update':对table_usage=='basics'的表(如stock_basic、index_basic、fund_basic等),主键冲突时仅用下载侧非空字段覆盖对应列,下载值为空字符串或NULL时保留本地已有值。因此可用 AKShare 补全代码列表拉分钟线依赖表,而不会冲掉此前用 Tushare 写入的industry、list_date等。按行业/地域筛选股票(filter_stocks/filter_stock_codes)仍建议以 Tushare 的stock_basic为准或先确认本地行业列非空。tushare:覆盖最全,多数表需配置
tushare_token及相应积分/权限。akshare:无需 token;当前 25 张历史/基础/事件表已实现(见
tests/akshare_data_test_checklist.md),其余表仍为blocked或not_supported。stock_basic等 basics 表仅保证 代码与名称索引,不替代 Tushare 完整基本面。eastmoney:无需 token;分钟线覆盖较全,部分基础表(如
stock_basic)可能无法从此通道拉取。sina:无需 token;以股票日线与分钟线为主,无周/月线等。
下面的代碼嘗試從eastmoney數據渠道下載stock_daily數據表從2025年最初兩個月的日K線數據:
>>> qt.refill_data_source(
tables='stock_daily',
channel='eastmoney', # 指定数据下载渠道为东方财经
data_source=ds,
start_date='20250101',
end_date='20250301',
)
Filling data source file://csv@qt_root/data/ ...
into 2 table(s) (parallely): {'stock_daily', 'stock_basic'}
[########################################]11078/11078-100.0% <stock_daily> 131264304 wrtn in about 17 min
[----------------------------------------]0/1-0.0% <stock_basic> can't be fetched from channel:eastmoney!
Data refill completed! 131264304 rows written into 1/2 table(s)!
驗證一下數據是否下載成功:
>>> ds.read_table_data('stock_daily', shares='000001.SZ, 000002.SZ', start='20250101', end='20250103')
open high low close pre_close change pct_chg \
ts_code trade_date
000001.SZ 2025-01-13 11.25 11.26 11.08 11.20 11.30 -0.10 -0.8850
2025-01-14 11.20 11.40 11.19 11.38 11.20 0.18 1.6071
2025-01-15 11.38 11.58 11.36 11.48 11.38 0.10 0.8787
2025-01-16 11.55 11.59 11.47 11.57 11.48 0.09 0.7840
2025-01-17 11.53 11.55 11.42 11.45 11.57 -0.12 -1.0372
2025-01-20 11.50 11.52 11.40 11.42 11.45 -0.03 -0.2620
2025-01-21 11.45 11.45 11.32 11.33 11.42 -0.09 -0.7881
2025-01-22 11.32 11.33 11.08 11.09 11.33 -0.24 -2.1183
2025-01-23 11.17 11.40 11.17 11.32 11.09 0.23 2.0739
2025-01-24 11.32 11.39 11.22 11.34 11.32 0.02 0.1767
2025-01-27 11.38 11.55 11.38 11.47 11.34 0.13 1.1464
000002.SZ 2025-01-13 6.60 6.77 6.55 6.76 6.69 0.07 1.0463
2025-01-14 6.76 6.93 6.75 6.91 6.76 0.15 2.2189
2025-01-15 6.88 6.96 6.79 6.86 6.91 -0.05 -0.7236
2025-01-16 6.90 7.07 6.84 6.88 6.86 0.02 0.2915
2025-01-17 6.58 6.65 6.45 6.63 6.88 -0.25 -3.6337
2025-01-20 6.60 6.94 6.48 6.85 6.63 0.22 3.3183
2025-01-21 6.84 7.54 6.82 7.36 6.85 0.51 7.4453
2025-01-22 7.27 7.36 6.98 7.02 7.36 -0.34 -4.6196
2025-01-23 7.15 7.70 7.08 7.36 7.02 0.34 4.8433
2025-01-24 7.33 7.54 7.21 7.39 7.36 0.03 0.4076
2025-01-27 7.38 7.56 7.22 7.27 7.39 -0.12 -1.6238
vol amount
ts_code trade_date
000001.SZ 2025-01-13 934966.0 1044904.416
2025-01-14 824629.0 934467.766
2025-01-15 1031631.0 1185403.653
2025-01-16 872964.0 1007689.274
2025-01-17 689765.0 791230.419
2025-01-20 832029.0 953092.179
2025-01-21 902069.0 1024879.174
2025-01-22 1347129.0 1504818.607
2025-01-23 1514920.0 1715172.472
2025-01-24 944944.0 1069899.088
2025-01-27 1151935.0 1324270.607
000002.SZ 2025-01-13 911147.0 611005.036
2025-01-14 1116454.0 765177.082
2025-01-15 887294.0 608363.557
2025-01-16 1110545.0 771648.218
2025-01-17 3620283.0 2369977.993
2025-01-20 2988167.0 2009728.944
2025-01-21 5849397.0 4290640.172
2025-01-22 3448728.0 2457396.391
2025-01-23 4416581.0 3245710.622
2025-01-24 2555024.0 1885566.128
2025-01-27 2151753.0 1580357.769
數據下載顯然也是成功的。分析上面的下載過程,可以發現幾個特點:
不同渠道下載的數據格式是相同的,這是
qteasy的設計原則,不同的數據下載渠道下載的數據會經歷相同的清洗過程,這樣用戶可以方便地切換不同的數據下載渠道,而不用擔心數據格式不同導致的數據處理問題。不同的渠道下載分塊方式不同,導致下載速度不同,
eastmoney數據渠道下載速度較慢,需要約17分鐘才能下載完成。這是由於不同下載渠道的特殊限制決定的。不同渠道的下載可以下載的數據表也不同,有些數據表無法通過某些渠道下載,可能是因爲權限限制或者其他因素導致的,如果某個數據表無法下載,
qteasy會自動跳過這個數據表,不會影響其他數據表的下載。
因此,用戶需要根據自身的情況選擇不同的渠道拉取數據。
通道切换与配置
一次性下载(脚本 / 交互):在 refill_data_source(..., channel='...') 中显式传入通道名即可,例如 Tushare 与 AKShare 对比如下:
>>> qt.refill_data_source(tables='stock_daily', channel='tushare', start_date='20240101', end_date='20240131')
>>> qt.refill_data_source(tables='stock_daily', channel='akshare', start_date='20240101', end_date='20240131')
实盘默认渠道(写入 qteasy.cfg 或通过 qt.configure() 修改):
配置键 |
含义 |
默认值 |
|---|---|---|
|
Trader 日更自动 refill 使用的通道 |
|
|
实盘获取实时价格的通道 |
|
示例:
>>> qt.configure(live_trade_data_refill_channel='akshare')
>>> qt.configure(live_price_acquire_channel='akshare')
修改后,实盘任务会使用新通道执行 refill / 取价;历史脚本仍可在每次 refill_data_source 调用中单独指定 channel,与全局配置无关。
實現下載流量控制
qteasy的refill_data_source提供了流量控制功能,可以限制數據下載的速度,即下載一定分塊數量的數據後,可以暫停一段時間,例如每下載300個分塊的數據,就暫停一分鐘,避免被數據渠道封禁。
這個功能通過refill_data_source()接口的download_batch_size和download_batch_interval兩個參數實現:
download_batch_size參數指定每次下載的數據分塊數量,如果設置爲300,則在下載300個數據分塊後,會暫停一段時間。download_batch_interval參數指定每次下載數據分塊後的暫停時間,默認爲0,即不暫停。
下面的代碼演示瞭如何使用download_batch_size和download_batch_interval參數實現下載流量控制:
>>> qt.refill_data_source(
tables='stock_daily',
channel='tushare',
data_source=ds,
start_date='20250101',
end_date='20250301',
download_batch_size=300, # 每次下载300个数据分块
download_batch_interval=60, # 每次下载300个数据分块后暂停60秒
)
如果是用流量控制,當然下載時間會變長,但是對於某些數據渠道,這是必須的,否則可能會被封禁或報錯導致下載失敗。
實現錯誤重試
需要注意的是,數據下載過程中出錯,qteasy會自動重試下載,重試機制如下:
第一次下載失敗後重試之前會等待一段時間,默認等待時間爲1.0秒
每次重試失敗後,等待時間都會增加,默認等待時間增加爲2倍,即第一次等待1.0秒,第二次等待2.0秒,第三次等待4.0秒,以此類推。
重試超過最大限額後停止重試並報錯,默認情況下最多重複7次。
以上三個錯誤重試參數都是通過qteasy的配置文件在設定的,用戶可以通過qt.config()接口查看或修改這些參數,也可以在qteasy的初始配置文件中修改這些參數。
hist_dnld_retry_cnt- 最大重試次數,默認爲7次hist_dnld_retry_wait- 第一次重試等待時間,默認爲1.0秒hist_dnld_backoff- 重試等待時間增加倍數,默認爲2.0
關於如何修改配置文件,或者使用qteasy的初始配置文件,請參考qteasy的配置文件章節。
日誌記錄
qteasy提供了數據下載日誌記錄功能,可以記錄每次數據下載的詳細資訊,包括下載的數據量、下載的時間、下載的速度等,方便用戶查看數據下載的情況。
其他功能
qteasy的refill_data_source()接口還提供了其他一些功能,例如:
限制下載數據的範圍,可以通過
start_date和end_date參數限制下載數據的時間範圍,通過shares參數限制下載數據的股票範圍。未传
start_date/end_date时的默认行为:内部将start_date视为该表映射中的最早可用日(如new_share为19700101),end_date视为当天。因此tables='basics'会包含需按日期分块下载的new_share(IPO 新股);若不传日期,会从 1970-01-01 分块拉至今日,耗时较长。若只需代码/行业类 basics、不要 IPO 表,请显式指定表名或传入较窄的日期窗。設置是否並行下載,可以通過
parallel參數設置是否並行下載,如果設置爲False,則會串行下載,否則會並行下載。設置是否下載依賴表,可以通過
download_dependent參數設置是否下載依賴表,如果設置爲False,則不會下載依賴表,否則會下載依賴表。設置是否強制更新交易日曆表。
其他更多關於該接口的解釋,請參見qteasy的API文檔。