1. matlab 从 tushare 获取历史数据
1. matlab 从 tushare 获取历史数据
1.1. 引言
1.2. 准备工作
1.2.1. 注册 tushare 账号
1.2.2. 获取 token
1.2.3. 下载 tusharematlabsdk
1.2.4. 特别提示
1.3. 获取数据实例
1.3.1. 获取股票日线行情数据
1.3.2. 通用行情调用股票行情数据
1.3.3. 获取每日基本指标数据
1.3.4. kmv 模型获取财务数据
1.3.5. 总结
1.1. 引言
做量化研究,数据是必不可少的,然而市面主流数据提供商的终端产品(wind之类),价格高昂,不是一般人(穷学生)能承受得起的。而自己写爬虫去搜集数据,一来是比较有技术含量,初学者一般难以做到这一点,二来也费时费力。
就目前而言,免费的数据源方面 tushare 无疑是最强的。非常感谢 tushare 的开发者们,为穷苦大众造了件神器 :smile:。
目前,可以通过 http,python,matlab,r等四种语言调用 tushare 数据。然而 tushare 官网对 matlab 调用 tushare 数据介绍过于简单(tusharematlabsdk 文档中的 readme.txt 介绍会详细一下)。初学者恐怕难以运用,于是我特此写这篇文章来分享 matlab 调用 tushare 数据的心得 :grimacing:。
1.2. 准备工作
1.2.1. 注册 tushare 账号
点击这个连接,进入 tushare 官网注册一个账号(顺便帮博主涨涨积分,权当写这个教程的奖励吧:smile:)。
1.2.2. 获取 token
注册完账号后,进入 tushare 网站的个人主页,找到接口TOKEN这一页面,复制你自己的 token 以便后续使用。
1.2.3. 下载 tusharematlabsdk
官网页面有提供下载方式,也可以到我的csdn资源页面下载。
将下载好的资源解压,将文件所在的目录设为matlab搜索路径。具体做法为,打开 matlab 打开设置路径选项,然后添加你刚才解压的位置,如下:
或者等使用时,将其加载到matlab的工作目录中。总之要使 matlab 在调用该函数包内的函数时能搜索得到函数(我一般是选择后一种做法,后文讲解)。
1.2.4. 特别提示
虽然 tushare 是免费的,但是却是积分制,许多数据得有一定积分才能获取,并且每分钟内调取数据次数也是有限制的。每种数据限制不一,具体限制如何,得到官网查看。
要成功使用 matlab 从 tushare 中读取数据,必须使用 2016b 或者更新的版本。
1.3. 获取数据实例
1.3.1. 获取股票日线行情数据
这是第一个例子,我将详细讲解。学会了第一个,调取其他数据是照葫芦画瓢。首先,看官网对股票日线行情数据的描述:
官网这边给的示例是 python 的,但是对于 matlab 而言参数方面其实是一样的,不同之处在于函数的写法。
假设当前的工作目录是 example(之前没有将函数包加入搜索路径) ,那么首先得将 matlabtusharesdk 解压到该目录下。
具体编写的函数如下:
close all
clear
clc
% 加载tushare包
addpath(genpath(pwd));
% 替换成你自己的 token
token = '**************c7a25d89f63c0537ac*************************';
api = pro_api(token);
% 读取数据参数设定
start_time = '20180101';
end_time = '20181231';
% 股票代码
stockcode = '000001.SZ';
% 读取数据
df = api.query('daily', 'ts_code',stockcode, 'start_date',start_time, 'end_date',end_time);
其中 addpath(genpath(pwd));
这句的作用就是把当前目录下,所有的函数都临时加载至搜索路径中,这样我们就可以调用 tusharematlabsdk 了。所谓临时加载,就是说,你如果退出重启了 matlab 这次添加的路径就无效了,这个技巧可以记下,可以避免很多冲突。
运行代码,就可以看到,我们已经成功读取数据:
可以继续拓展一下,如何批量读取呢?这个目前来看,只能循环读取(如果有好办法,请不吝赐教)。如下:
close all
clear
clc
%% load data
f = '股票名单.xlsx';
[~,stocklist] = xlsread(f);
% 加载tushare包
addpath(genpath(pwd));
% 替换成你自己的 token
token = '********************13c7a25d89f63******************';
api = pro_api(token);
% 读取数据参数设定
start_time = '20180101';
end_time = '20181231';
% 循环读取股票数据
nstock = length(stocklist);
% data = cell(1,nstock);
for i = 1:nstock
df = api.query('daily', 'ts_code',stocklist{i}, 'start_date',start_time, 'end_date',end_time);
data = flipud(df);
writetable(data,['2018年 ',stocklist{i},' 数据.xls']);
end
这里读取的股票名包含十个股票代码:
这里随便提一下,因为 tushare 读出来的数据是,从离现在近的日期到远的日期,这与我平时使用的习惯不符,所以用了 flipud
翻转数据。然后 table 格式的数据,使用 writetable
保存非常方便。
特别注意,上图,中 api.daily
形式调用数据在 matlab 中是行不通的。另外图片中还提到了 api.query
形式调用的数据是不复权的。如果需要指定数据,前复权或者后复权则需要使用==通用行情接口==
1.3.2. 通用行情调用股票行情数据
通用行情接口的语法形式如下: data = pro_bar(ts_code, pro_api, start_date, end_date, freq, asset, market, adj, ma, factors, retry_count);
输入参数如下:
输入参数: 不能少于4个
ts_code:证券代码,支持股票,ETF/LOF,期货/期权,港股,数字货币,如'000001.SZ','000905.SH'
start_date:开始日期 YYYYMMDD, 如'20181001'
end_date:结束日期 YYYYMMDD,''表示当前日期
freq:支持1/5/15/30/60分钟,周/月/季/年, 如'D'
asset:证券类型 E:股票和交易所基金,I:沪深指数,C:数字货币,F:期权/港股/中概美国/中证指数/国际指数,如'E'
market:市场代码,默认''
adj:复权类型,''不复权,'qfq':前复权,'hfq':后复权
ma:均线,支持自定义均线频度,如:ma5/ma10/ma20/ma60/maN,如[],5,10],[5,10,20],有n个MA值,输出就会相应追加列,不足N天的均线值用填充
factors因子数据,目前支持以下两种:
vr:量比,默认不返回,返回需指定:factor=['vr']
tor:换手率,默认不返回,返回需指定:factor=['tor']
以上两种都需要:factor=['vr', 'tor']
retry_count:网络重试次数,默认3
使用通用行情接口调用上文数据:
close all
clear
clc
% 加载tushare包
addpath(genpath(pwd));
token = '***************************f63c0537ac35**********************';
api = pro_api(token);
% 读取数据参数设定
start_time = '20180101';
end_time = '20181231';
% 股票代码
stockcode = '000001.SZ';
% 读取数据
df1 = api.query('daily', 'ts_code',stockcode, 'start_date',start_time, 'end_date',end_time);
% data = pro_bar(ts_code, pro_api, start_date, end_date, freq, asset, market, adj, ma, factors, retry_count);
df2 = pro_bar(stockcode, api,start_time,end_time);
isequal(df1.close,df2.close)
通过 isequal
函数比较发现这两种方式调用数据的结果是完全一致的。
通用行情借口调用数据更具备灵活性。比如,上面代码中需要指定为前复权需要一指定数据频率和证券类型: df2 = pro_bar(stockcode, api,start_time,end_time,'D','E','','qfq');
这样才能正确运行,如果没有指定将会返回空值。
这边需要特别注意,如果 end_date
为空,那么表示获取到现在为止的最新数据,如果 start_date
为空那么表示的是从上市到 end_date
为止的数据。
1.3.3. 获取每日基本指标数据
每日指标数据说明页面。
编写如下代码即可读取数据:
close all
clear
clc
% 加载tushare包
addpath(genpath(pwd));
token = '9349af0c4c826464413c7a25d89f63c0537ac35f4237da3ffa432c25';
api = pro_api(token);
% 读取数据参数设定
start_time = '20180101';
end_time = '20181231';
% 股票代码
stockcode = '000001.SZ';
% 读取数据
df1 = api.query('daily_basic', 'ts_code', stockcode, 'start_date',start_time,'end_date',end_time,...
'fields','ts_code,trade_date,turnover_rate,volume_ratio,pe,pb');
1.3.4. kmv 模型获取财务数据
获取资产负债表和财务指标数据,这些只要依照 tushare 说明页面上的例子,把 matlab 的参数写对就行了,参考 api.query
形式读取数据的例子即可:
close all
clear
clc
% 加载tushare包
addpath(genpath(pwd));
token = '9349af0c4c826464413c7a25d89f63c0537ac35f4237da3ffa432c25';
api = pro_api(token);
% 读取数据参数设定
start_time = '20180101';
end_time = '20181231';
% 股票代码
stockcode = '000001.SZ';
% 读取数据
% 资产负债表
df2 = api.query('balancesheet', 'ts_code',stockcode,'start_date',start_time,'end_date',end_time,...
'fields','ts_code,ann_date,f_ann_date,end_date,report_type,comp_type,cap_rese');
% 财务指标数据 获取每股净资产数据
df3 = api.query('fina_indicator', 'ts_code',stockcode, 'start_date',start_time,'end_date',end_time);
上面学了这么多,现在这里就写一个用 tushare 读取财务数据的真实例子(用来做 kmv 模型的),这是读取数据的函数:
function [ve,vd,deltaE,N] = getStockData(stockcode,start_time,end_time,api,nn)
% 该函数从tushare读取每只股票数据并进行计算
% nn 为长期负债乘数
%% 获取财务数据
df2 = api.query('balancesheet', 'ts_code',stockcode,'start_date',start_time,'end_date',end_time,...
'fields','ts_code,ann_date,f_ann_date,end_date,report_type,comp_type,cap_rese');
% 取计算期内最新的一次报表作为计算依据
% 债务账面价值=短期流动负债 + 0.5*长期负债
try
% 为避免触发读取权限限制,限速
pause(0.4);
vd = df2.total_cur_liab(1) + nn*df2.total_ncl(1);
catch
if isempty(df2.total_ncl{1})
df2.total_ncl{1} = 0;
end
vd = df2.total_cur_liab(1) + nn*df2.total_ncl{1};
end
% 获取每股净资产数据
df3 = api.query('fina_indicator', 'ts_code',stockcode, 'start_date',start_time,'end_date',end_time);
%% 时间
% 读取交易日历
df4 = api.query('trade_cal','start_date',start_time, 'end_date',end_time);
ind = df4.is_open == 1;
df4 = df4(ind,:);
trade_date = size(df4,1);
%% 获取每日指标数据
df1 = api.query('daily_basic', 'ts_code', stockcode, 'start_date',start_time,'end_date',end_time,'fields','ts_code,trade_date,turnover_rate,volume_ratio,pe,pb');
% 计算 每日股权价值=流通股股数*股票日收盘价+非流通股股数*每股净资产
% 注意读取出来的数据中的股本单位是万股,因此要乘以10000
% 计算股权价值
ve = df1.close .* df1.float_share + (df1.total_share-df1.float_share) .* df3.bps(1);
ve = ve * 10000;
% 计算股权价值收益率
% 计算收益率时注意将股票日期翻转成matlab中的顺序
% ret = price2ret(flipud(df1.close));
ret = price2ret(flipud(df1.close));
% 求平均每日股权价值
% ve = mean(ve);
% 取最后一天的股权价值
ve = ve(1);
% N 为股票实际交易天数
N = size(df1,1);
% md = garch(1,1);
% estMd = md.estimate(ret,'Display','off');
% % 无条件方差即波动率计算
% sigma = estMd.Constant/(1-estMd.GARCH{1}-estMd.ARCH{1});
% deltaE = sqrt(sigma*trade_date);
% 计算股权价值波动率
delta_day = std(ret);
% 年化股权价值波动率
deltaE = delta_day*sqrt(trade_date);
end
而这个是调用这个函数获取数据的脚本:
close all
clear
clc
%% 从excel文件中读取要计算的股票名单
f = '股票选择.xls';
[~,sheet] = xlsfinfo(f);
sheet = sheet{4};
[~,~,stocktable] = xlsread(f,sheet);
% 因为数据中不同轮数的股票数量不同
temp = stocktable(3:end,3);
temp = double(string((temp)));
% nn = find(isnan(temp));
nn = length(temp);
% nn = nn -1 + 2;
nn = nn + 2;
list = [stocktable(3:nn,2:3);stocktable(3:nn,4:5);stocktable(3:nn,6:7)];
% 将股票代码加上.SZ或者.SH
temp = list(:,2);
num = double(string(temp));
nstock = length(list);
for i=1:nstock
if num(i) < 100000
list{i,2} = [list{i,2},'.SZ'];
else
list{i,2} = [list{i,2},'.SH'];
end
end
%% 从tushare中读取数据
% 加载tushare包
addpath(genpath(pwd));
% 自己的 token
token = '******************f63c0537ac35f4237d**************';
api = pro_api(token);
% 设定数据时间
start_time = '20180101';
end_time = '20181231';
% 预定义数据矩阵,[ve,vd,deltaE]
ve = nan(nstock,1);
vd = nan(nstock,1);
deltaE = nan(nstock,1);
N = nan(nstock,1);
nn = 0.5;
% 循环读取
for i=1:nstock
stockcode = list{i,2};
[ve(i),vd(i),deltaE(i),N(i)] = getStockData(stockcode,start_time,end_time,api,nn);
disp(['第',num2str(i),'只股票',stockcode,' 读取成功']);
end
data = table(ve,vd,deltaE,N);
save('stockdata.mat','data','list','stocktable','start_time','sheet')
disp([start_time(1:4),' ',sheet,' 数据读取成功']);
这里股票选择文件数据如下,为了方便大家学习复现结果已经将文件上传,点击下载:
1.3.5. 总结
目前就暂时写这么多吧,万变不离其宗,调用数据时把格式写对就行。另外确实有时候 tushare 自己或出错,看这里。但是这种情况非常少见(我只碰到过一次),而且一般也会很快得到修复。如果有任何疑问,欢迎留言交流 :grin:。