用Tushare Pro接口:金融數(shù)據(jù)獲取與量化分析實(shí)戰(zhàn)指南)
簡(jiǎn)介面向MATLAB金融數(shù)據(jù)分析人員tushare_matlab_sdk.zip是一份用于獲取中國(guó)股票市場(chǎng)數(shù)據(jù)的輕量級(jí)SDK資源包解決了在MATLAB中直接調(diào)用tushare接口獲取日K線、分時(shí)、財(cái)務(wù)等數(shù)據(jù)并做后續(xù)處理的問(wèn)題適合具備基礎(chǔ)MATLAB能力、希望開(kāi)展量化分析或金融建模的初、中級(jí)使用者。包內(nèi)共8個(gè)文件包含6個(gè).m腳本網(wǎng)絡(luò)請(qǐng)求封裝urlread2、核心API pro_api、K線數(shù)據(jù)獲取pro_bar、請(qǐng)求頭構(gòu)造http_createHeader等與2個(gè)txt說(shuō)明文檔使用說(shuō)明及積分獲取指南整體僅15KB部署便捷。目前已有396人學(xué)習(xí)通過(guò)內(nèi)含的tushare_pro_test測(cè)試腳本可完整演示token配置、HTTP請(qǐng)求構(gòu)造與數(shù)據(jù)返回解析過(guò)程配合參數(shù)編碼、請(qǐng)求頭等輔助函數(shù)能快速掌握SDK調(diào)用與數(shù)據(jù)清洗思路。說(shuō)明文檔還專(zhuān)門(mén)介紹了tushare積分獲取方法與注意事項(xiàng)幫助用戶(hù)合理管理API請(qǐng)求配額整體上它為MATLAB用戶(hù)搭建起連接tushare數(shù)據(jù)服務(wù)的現(xiàn)成橋梁可顯著提升金融數(shù)據(jù)獲取效率為后續(xù)建模與可視化提供穩(wěn)定數(shù)據(jù)源。 拿到tushare_matlab_sdk.zip這個(gè)壓縮包的人多半是和我一樣在 MATLAB 里折騰了好幾天金融數(shù)據(jù)接口最后決定找個(gè)現(xiàn)成 SDK 來(lái)省點(diǎn)事的人。Tushare Pro 在 Python 圈子幾乎是標(biāo)配但到了 MATLAB 這邊資料少得可憐能搜到的帖子不是年代久遠(yuǎn)就是只給個(gè)思路不給完整代碼。這個(gè) ZIP 包就是干這個(gè)的把 Tushare Pro 的數(shù)據(jù)接口封裝成 MATLAB 可以直接調(diào)用的函數(shù)解壓、設(shè)好路徑、填上 token就能在 MATLAB 里拉股票行情、財(cái)務(wù)數(shù)據(jù)、宏觀經(jīng)濟(jì)指標(biāo)。適合誰(shuí)用量化研究入門(mén)者、做課程設(shè)計(jì)的學(xué)生、需要在 MATLAB 里做金融建模但又不想碰 Python 的人。這篇東西不打算講太多大道理就按我實(shí)際使用的順序把從解壓到跑通、再到踩坑排錯(cuò)的過(guò)程完整寫(xiě)一遍。1. 為什么 MATLAB 用戶(hù)需要這個(gè)壓縮包1.1 Python 生態(tài)和 MATLAB 生態(tài)的數(shù)據(jù)鴻溝Tushare 官方主推的是 Python SDK文檔、示例、社區(qū)討論幾乎全都在 Python 一側(cè)。但金融建模、信號(hào)處理、策略回測(cè)這些活兒很多老用戶(hù)就是在 MATLAB 里干的拉數(shù)據(jù)卻要切出去用 Python導(dǎo)成 CSV再讀回 MATLAB。這套流程第一二次還能忍次數(shù)多了就非常痛苦中間環(huán)節(jié)容易出錯(cuò)字段類(lèi)型亂掉更新頻率也跟不上。MATLAB 本身不是不能直接請(qǐng)求 HTTP 接口webwrite、webread都能用但 Tushare Pro 的接口返回的是嵌套 JSON帶fields和items兩個(gè)數(shù)組需要自己寫(xiě)一堆解析代碼。這個(gè) SDK ZIP 包的核心價(jià)值就是把這些重復(fù)勞動(dòng)封裝好了設(shè)置 token、拼請(qǐng)求、解析 JSON、拼成表格幾條命令搞定。你不用理解 HTTP 協(xié)議細(xì)節(jié)不需要手動(dòng)處理 JSON 結(jié)構(gòu)像調(diào)用普通 MATLAB 函數(shù)一樣就能拿到數(shù)據(jù)。1.2 打開(kāi) ZIP 包后你實(shí)際會(huì)看到什么正常解壓后這個(gè)包一般會(huì)包含這幾個(gè)部分核心函數(shù)文件一個(gè)負(fù)責(zé)調(diào) Tushare API 的入口函數(shù)名字通常叫tushare或pro_bar接受 api_name、params、fields 等參數(shù)。輔助工具函數(shù)處理返回?cái)?shù)據(jù)格式轉(zhuǎn)換、日期格式化、字段重命名之類(lèi)的工作。示例腳本demo.m或類(lèi)似命名演示了拉日線行情、財(cái)務(wù)指標(biāo)的基本用法。說(shuō)明文檔通常是 README 或 PDF寫(xiě)了 token 設(shè)置方式和支持的接口列表。這里提醒一下不同來(lái)源的包結(jié)構(gòu)略有差異但核心邏輯大同小異。如果解壓后發(fā)現(xiàn)入口函數(shù)名字不一樣不用慌先看 README找到那個(gè)唯一的入口函數(shù)后面的用法基本一致。2. 安裝配置三步走從 ZIP 解壓到第一個(gè)請(qǐng)求2.1 申請(qǐng) Token 時(shí)容易被忽略的積分門(mén)檻拿到包之后第一件事不是解壓是去 Tushare 官網(wǎng)注冊(cè)賬號(hào)、申請(qǐng) token。這里有個(gè)很現(xiàn)實(shí)的坑Tushare Pro 的接口是有積分門(mén)檻的不同積分能調(diào)的接口不一樣。以我自己的經(jīng)驗(yàn)為例剛注冊(cè)時(shí)是 120 積分能調(diào)daily日線行情這類(lèi)基礎(chǔ)接口但要調(diào)moneyflow資金流向、main_bill主力資金這類(lèi)稍高級(jí)的接口需要 2000 積分以上。積分的獲取方式包括完善資料、貢獻(xiàn)數(shù)據(jù)、參與社區(qū)任務(wù)等剛開(kāi)始不用太焦慮先用基礎(chǔ)接口跑通流程后續(xù)再考慮提權(quán)。在 MATLAB 里設(shè)置 token 的方式SDK 一般都提供了函數(shù)比如% 設(shè)置你的 token只需執(zhí)行一次 tushare.set_token(你的Token字符串);這個(gè)設(shè)置函數(shù)會(huì)把 token 保存到 MATLAB 的預(yù)設(shè)目錄或當(dāng)前工作區(qū)之后調(diào)用數(shù)據(jù)接口時(shí) SDK 會(huì)自動(dòng)帶上。如果你用的是我自己封裝的版本我習(xí)慣直接把 token 寫(xiě)在一個(gè)config.m里用的時(shí)候讀取function tk get_tushare_token() tk 你的Token字符串; % 這里填你在官網(wǎng)獲取的 token end2.2 解壓和路徑設(shè)置MATLAB 的坑從這里開(kāi)始這個(gè)環(huán)節(jié)看起來(lái)簡(jiǎn)單但踩的人很多。解壓 ZIP 包時(shí)有幾個(gè)注意事項(xiàng)第一路徑不要帶中文盡量不要有空格。MATLAB 對(duì)中文路徑的支持這些年好了一些但 SDK 里如果有跨平臺(tái)文件操作、路徑拼接遇到中文目錄時(shí)偶爾會(huì)出詭異問(wèn)題。最好解壓到D:\Tools\tushare_matlab_sdk這種純英文路徑。第二解壓后要addpath把目錄加進(jìn) MATLAB 搜索路徑??梢允謩?dòng)操作主頁(yè) → 設(shè)置路徑 → 添加文件夾。也可以用命令addpath(genpath(D:\Tools\tushare_matlab_sdk)); savepath;genpath是為了把子目錄也加進(jìn)去因?yàn)?SDK 通常有多個(gè)子文件夾。第三有些 SDK 依賴(lài) MATLAB 的 JSON 解析能力也就是需要 R2016b 及以上版本jsondecode函數(shù)。如果你還在用老版本功能會(huì)受限建議至少用 R2019b 之后兼容性好很多。2.3 最小驗(yàn)證先跑通一遍最簡(jiǎn)單的行情請(qǐng)求配置完成后用最簡(jiǎn)單的方式驗(yàn)證環(huán)境是否就緒。以拉取平安銀行最近一天行情為例% 設(shè)置 token tushare.set_token(你的Token字符串); % 調(diào)日線行情接口 data tushare(daily, ts_code000001.SZ, trade_date20240115, , );這里需要注意的是不同 SDK 封裝對(duì)參數(shù)的處理方式不同。有些版本接受params結(jié)構(gòu)體有些接受字符串拼接。如果是結(jié)構(gòu)體版本這樣寫(xiě)params struct(ts_code, 000001.SZ, trade_date, 20240115); data tushare(daily, params);如果這一步能返回一個(gè) table里面有開(kāi)高低收、成交量這些字段說(shuō)明整個(gè)鏈路已經(jīng)打通。如果報(bào)錯(cuò)直接看第 4 章的排查記錄。3. 核心接口拆解一次完整的行情拉取是怎么跑通的3.1 API 請(qǐng)求的本質(zhì)一個(gè) POST 請(qǐng)求加一串 JSONTushare Pro 的接口本質(zhì)是一個(gè) HTTP POST 請(qǐng)求請(qǐng)求體是 JSON 格式包含四個(gè)部分api_name要調(diào)的接口名比如daily、stock_basic、income。token你的訪問(wèn)憑證。params查詢(xún)參數(shù)比如股票代碼、日期范圍。fields要返回的字段逗號(hào)分隔的字符串。以日線行情為例請(qǐng)求體就長(zhǎng)這樣{ api_name: daily, token: your_token_here, params: {ts_code: 000001.SZ, start_date: 20240101, end_date: 20240115}, fields: ts_code,trade_date,open,high,low,close,vol,amount }MATLAB 里用webwrite發(fā)這個(gè)請(qǐng)求代碼大致是api_url http://api.tushare.pro; body struct(api_name, daily, token, token, params, params, fields, fields); options weboptions(MediaType, application/json, Timeout, 30); response webwrite(api_url, body, options);但這里有個(gè)關(guān)鍵點(diǎn)webwrite在發(fā)送結(jié)構(gòu)體時(shí)默認(rèn)編碼方式可能不是標(biāo)準(zhǔn)的 JSON有些版本會(huì)把數(shù)組轉(zhuǎn)成 cell導(dǎo)致服務(wù)端解析失敗。這就是 SDK 存在的意義之一——它內(nèi)部處理好了序列化和解析邏輯。你不需要自己寫(xiě)這段代碼。3.2 怎么把返回的 fields/items 變成可分析的表格Tushare Pro 的返回?cái)?shù)據(jù)格式比較特別不是直接給 JSON 對(duì)象數(shù)組而是給了兩個(gè)平行數(shù)組{ code: 0, msg: null, data: { fields: [ts_code, trade_date, open, high, low, close, vol, amount], items: [ [000001.SZ, 20240115, 9.5, 9.8, 9.4, 9.7, 500000.0, 4800000.0] ] } }fields是字段名列表items是數(shù)據(jù)行列表每一行和fields對(duì)應(yīng)。SDK 的核心工作之一就是把這兩部分合并成 MATLAB table% SDK 內(nèi)部大致邏輯 fields_cell response.data.fields; % 字段名 items_cell response.data.items; % 數(shù)據(jù)行 % 轉(zhuǎn)成 cell2table data_table cell2table(items_cell, VariableNames, matlab.lang.makeValidName(fields_cell));matlab.lang.makeValidName這一步很重要因?yàn)?Tushare 某些字段名帶點(diǎn)號(hào)或下劃線開(kāi)頭直接作為VariableNames會(huì)報(bào)錯(cuò)SDK 內(nèi)部做了規(guī)范化處理。3.3 參數(shù)與字段的正確打開(kāi)方式實(shí)際使用中最容易搞混的是三個(gè)概念api_name、params和fields。api_name是接口名決定了你訪問(wèn)哪類(lèi)數(shù)據(jù)。我用得最多的是這幾個(gè)接口名數(shù)據(jù)內(nèi)容常見(jiàn)參數(shù)典型場(chǎng)景daily日線行情ts_code, trade_date, start_date, end_dateK線圖、價(jià)格分析stock_basic股票基礎(chǔ)信息list_status, exchange股票池篩選income利潤(rùn)表ts_code, period, report_type財(cái)務(wù)分析daily_basic每日指標(biāo)ts_code, trade_date估值指標(biāo)PE、PBtrade_cal交易日歷exchange, start_date, end_date交易日判斷params是查詢(xún)條件。這里有個(gè)小經(jīng)驗(yàn)Tushare 的日期參數(shù)統(tǒng)一是YYYYMMDD格式的字符串不是 MATLAB 的 datetime 類(lèi)型。如果你手里是 datetime要先轉(zhuǎn)換date_str datestr(datetime(today), yyyymmdd);不建議直接傳datetime某些版本的 SDK 會(huì)做隱式轉(zhuǎn)換但格式容易錯(cuò)統(tǒng)一用字符串最省心。fields是返回字段列表逗號(hào)分隔的字符串。不傳的話Tushare 會(huì)返回該接口的全部字段。但建議明確指定一是減少傳輸量、提升速度二是避免返回一堆你用不到的列干擾后續(xù)處理。4. 高頻報(bào)錯(cuò)的一線排查記錄4.1 積分不足報(bào)錯(cuò)不是你的代碼問(wèn)題剛接觸 Tushare 的人看到抱歉您沒(méi)有訪問(wèn)該接口的權(quán)限或者積分不夠這類(lèi)提示第一反應(yīng)是自己代碼寫(xiě)錯(cuò)了但其實(shí)不是。這是賬號(hào)積分權(quán)限的問(wèn)題。排查鏈路是這樣的確認(rèn)報(bào)錯(cuò)發(fā)生在請(qǐng)求發(fā)送之后、數(shù)據(jù)解析之前——說(shuō)明 HTTP 鏈路沒(méi)問(wèn)題請(qǐng)求到達(dá)了服務(wù)器是服務(wù)器拒絕的。登錄 Tushare 官網(wǎng)在個(gè)人主頁(yè)查看當(dāng)前積分。對(duì)照接口文檔里的積分要求看當(dāng)前賬號(hào)是否滿足。如果確實(shí)不足兩個(gè)辦法一是換用低門(mén)檻接口比如daily只需要 120 積分二是提升積分。我用過(guò)最省事的辦法是先跑通daily和stock_basic這兩個(gè)基礎(chǔ)接口足夠覆蓋大部分學(xué)習(xí)和課程設(shè)計(jì)場(chǎng)景了。做策略回測(cè)用日線數(shù)據(jù)完全夠不一定要碰那些高積分接口。4.2 返回空數(shù)據(jù)trade_date 的三個(gè)常見(jiàn)坑辛辛苦苦把代碼跑通結(jié)果返回的表格是 0 行這種挫敗感我太熟了。排查方向按頻率排列第一個(gè)坑是日期格式錯(cuò)誤。Tushare 的trade_date必須是YYYYMMDD8 位字符串。寫(xiě)成2024-01-15或2024/01/15都查不到數(shù)據(jù)但服務(wù)端不會(huì)報(bào)錯(cuò)只是返回空結(jié)果。第二個(gè)坑是日期是非交易日。比如拉 2024 年 1 月 14 日周日的日線自然是沒(méi)有數(shù)據(jù)的。這時(shí)候要先用trade_cal接口確認(rèn)交易日cal tushare(trade_cal, exchangeSSE,start_date20240101,end_date20240131);第三個(gè)坑是復(fù)權(quán)問(wèn)題。Tushare 的daily接口返回的是不復(fù)權(quán)價(jià)格。如果你拉長(zhǎng)時(shí)間段做回測(cè)遇到股票中間有除權(quán)除息價(jià)格會(huì)出現(xiàn)跳變看起來(lái)像數(shù)據(jù)錯(cuò)了。這時(shí)候需要改用復(fù)權(quán)接口或者用adj_factor復(fù)權(quán)因子自己計(jì)算后復(fù)權(quán)價(jià)格。4.3 webwrite 超時(shí)和 invalid zip archive 這類(lèi)環(huán)境問(wèn)題先說(shuō)webwrite超時(shí)。在 MATLAB 里直接調(diào)webwrite請(qǐng)求 Tushare數(shù)據(jù)量稍大比如一次拉 3000 行以上很容易觸發(fā)默認(rèn)的超時(shí)設(shè)置。報(bào)錯(cuò)信息通常是The connection timed outSDK 一般會(huì)把Timeout設(shè)置得比較長(zhǎng)比如 60 秒。如果你自己封裝記得這樣設(shè)置options weboptions(MediaType, application/json, Timeout, 60);再說(shuō)熱搜詞里出現(xiàn)的invalid zip archive: could not find eocd。這個(gè)錯(cuò)誤和 Tushare SDK 本身關(guān)系不大它出現(xiàn)在解壓階段意思是 ZIP 文件不完整或損壞。常見(jiàn)原因是下載中斷、文件被安全軟件攔截、或者解壓軟件版本過(guò)舊。解決辦法重新下載 ZIP 包下載時(shí)留意文件大小是否和網(wǎng)頁(yè)標(biāo)注一致。換解壓工具Windows 自帶解壓不行的話用 7-Zip。如果是從網(wǎng)盤(pán)下載的確認(rèn)文件沒(méi)有被壓縮軟件二次壓縮。我在使用中還遇到過(guò) MATLAB 的addpath路徑問(wèn)題導(dǎo)致函數(shù)找不到報(bào)錯(cuò)是Undefined function or variable tushare。這多半是路徑?jīng)]加對(duì)或者 MATLAB 當(dāng)前工作目錄不對(duì)。用which tushare看能否定位到函數(shù)文件如果顯示not found就重新執(zhí)行一次addpath(genpath(...))。5. 讓數(shù)據(jù)真正可用的三個(gè)擴(kuò)展寫(xiě)法5.1 批量拉取多只股票的行情拿到單只股票的日線之后下一步很自然是批量處理。這里有個(gè)請(qǐng)求頻率的常識(shí)Tushare Pro 有訪問(wèn)頻率限制基礎(chǔ)接口通常是每分鐘數(shù)十次到數(shù)百次具體看積分。盲目用 for 循環(huán)猛拉幾十只股票容易觸發(fā)限流。我的做法是加一個(gè)延時(shí)同時(shí)把每次請(qǐng)求的數(shù)據(jù)緩存到本地% 批量拉取多只股票日線數(shù)據(jù) stock_list {000001.SZ, 000002.SZ, 600000.SH, 600036.SH}; all_data cell(length(stock_list), 1); for i 1:length(stock_list) params struct(ts_code, stock_list{i}, start_date, 20240101, end_date, 20240201); all_data{i} tushare(daily, params); pause(0.5); % 控制請(qǐng)求頻率避免觸發(fā)限流 end % 合并所有股票的數(shù)據(jù) full_data vertcat(all_data{:});注意vertcat合并的前提是每張表的字段一致Tushare 返回的字段順序一般穩(wěn)定但保險(xiǎn)起見(jiàn)可以先用full_data.Properties.VariableNames檢查。5.2 轉(zhuǎn)成 timetable 做時(shí)間序列分析MATLAB 做金融時(shí)間序列分析最順手的容器是timetable不是普通 table。timetable支持按時(shí)間索引切片、重采樣、滯后運(yùn)算比 table 方便太多。把 Tushare 返回的 table 轉(zhuǎn)成 timetable 的代碼% 假設(shè) data 是 tushare(daily, ...) 返回的 table % 把 trade_date 字符串列轉(zhuǎn)成 datetime data.trade_date datetime(data.trade_date, InputFormat, yyyyMMdd); % 按時(shí)間排序Tushare 返回順序可能不穩(wěn)定 data sortrows(data, trade_date); % 轉(zhuǎn)成 timetable以 trade_date 為行時(shí)間 fin_tt table2timetable(data, RowTimes, data.trade_date); % 之后就能用 timetable 的各種高級(jí)功能了 % 比如計(jì)算 5 日均線 fin_tt.close_ma5 movmean(fin_tt.close, 5);轉(zhuǎn)成 timetable 之后movmean、lag、retime這些函數(shù)直接上手畫(huà)圖也更方便plot(fin_tt.trade_date, fin_tt.close);5.3 緩存機(jī)制避免重復(fù)請(qǐng)求消耗積分和等待時(shí)間Tushare 接口是按訪問(wèn)次數(shù)計(jì)量的雖然基礎(chǔ)接口額度相對(duì)寬裕但反復(fù)拉同一批數(shù)據(jù)既浪費(fèi)時(shí)間也容易碰到頻率限制。更合理的做法是加一層本地緩存數(shù)據(jù)拉下來(lái)后存成.mat文件下次運(yùn)行直接讀取。我常用的緩存邏輯function data get_daily_cached(ts_code, start_date, end_date) % 生成緩存文件名確保同一參數(shù)走同一份緩存 cache_file fullfile(tempdir, sprintf(%s_%s_%s.mat, ts_code, start_date, end_date)); if isfile(cache_file) loaded load(cache_file); data loaded.data; return; end % 緩存不存在請(qǐng)求接口 params struct(ts_code, ts_code, start_date, start_date, end_date, end_date); data tushare(daily, params); % 保存緩存 save(cache_file, data); end這個(gè)函數(shù)加了判斷邏輯參數(shù)相同就直接讀.mat參數(shù)變則重新請(qǐng)求。tempdir是系統(tǒng)臨時(shí)目錄也可以換成你自己的數(shù)據(jù)目錄比如./data_cache。緩存機(jī)制的最大好處是你在調(diào)試下游代碼時(shí)不會(huì)因?yàn)榉磸?fù)跑同一段數(shù)據(jù)拉取邏輯白白消耗 API 調(diào)用次數(shù)。實(shí)測(cè)下來(lái)一次拉 20 只股票一年數(shù)據(jù)有緩存和沒(méi)緩存的運(yùn)行時(shí)間差異是很明顯的——后者完全取決于網(wǎng)絡(luò)和接口速度前者幾乎秒開(kāi)。我個(gè)人在實(shí)際操作中還有一個(gè)體會(huì)這類(lèi) SDK 包用順手之后完全可以自己改源碼擴(kuò)展。比如我就在原版基礎(chǔ)上加了一個(gè)get_kline函數(shù)內(nèi)部封裝了daily和adj_factor兩個(gè)接口直接返回前復(fù)權(quán) K 線?;ㄒ粋€(gè)下午改一改后面所有策略腳本都跟著省事。如果你也拿到一個(gè)開(kāi)源或者半開(kāi)源的 MATLAB SDK別只當(dāng)黑盒用讀一遍入口函數(shù)的代碼看懂它怎么拼請(qǐng)求、怎么解析響應(yīng)后面所有擴(kuò)展需求都會(huì)變得很清晰。本文還有配套的精品資源點(diǎn)擊獲取