国泰安12月份推出了基于Stata16编程软件的接口命令,命令包括getData、getDataCount、getDbs、getFields、getRecord、getTables、preview、login和setLanguage。接口命令对数据处理自动化有很大的推动作用,克服了手动下载数据导致的费时费力的弊端。本文将以自动下载股票收益率为例,带大家深入了解接口命令的使用。


CsmarStata接口文件www.gtarsc.com

CsmarStata文件来自国泰安官网,里面存放了接口命令的文件,包含一个run.bat文件和一个csmar文件夹,csmar文件夹又包含九个ado文件和一个jar文件。点击run.bat文件可以自动实现把ado文件放入指定的文件夹中。下面是关于如何使用run.bat文件的具体流程。(但是笔者不建议使用run.bat文件,因为它经常容易失败,所以更建议大家采取手动把ado文件放入指定文件夹的方式,后续有介绍)。




为什么stata运行时显示未下载Java stata命令下载不下来_查询数据库前十条数据


run.bat安装命令过程

另一种方式是手动把ado文件放入指定的文件夹中。我们只需要找到指定文件夹的位置,并根据每个ado文件的首字母创建对应的文件夹,把ado文件放入对应的文件夹即可,过程很简单。

首先,在stata的命令窗口输入sysdir,找到personal文件夹的位置。


为什么stata运行时显示未下载Java stata命令下载不下来_数据集_02


由九个ado文件的首字母,我们可以确定需要五个分别以c、g、l、p和s开头的文件夹(l是L的小写)。确保personal文件夹下有以下五个文件夹。


为什么stata运行时显示未下载Java stata命令下载不下来_sed_03


将九个ado文件根据文件首字母放入对应的文件夹中即可。以getData.ado文件等g开头的文件为例,将它们放入personal文件下的g文件夹中。


为什么stata运行时显示未下载Java stata命令下载不下来_数据集_04


为什么stata运行时显示未下载Java stata命令下载不下来_数据集_05


特别地,csmar-stata.jar文件要放在personal文件夹下面。


为什么stata运行时显示未下载Java stata命令下载不下来_查询数据库前十条数据_06


否则会因为找不到java文件,报告如下错误。


为什么stata运行时显示未下载Java stata命令下载不下来_数据_07


到这里,我们的接口命令就已经安装完成了。接下来让我们正式开始使用命令下载数据吧!

首先,让我们对十一个命令有个了解。

接口命令

介绍

getData

将符合条件的数据导入stata

getDataCount

统计符合提交条件的数据个数

getDbs

查询已购买的数据库,比如“股票交易市场”

getTables

查询数据库下面包含的表单,比如数据库“股票交易市场”下面的”日个股交易数据“

getFields

查询表单具体变量名称,比如”日个股交易数据“下面的”收盘价“

pack

发送打包数据的申请,会得到一个密钥

getRecord

利用pack得到的密钥,获取数据的下载地址

copy

拷贝下载地址,把文件保存到本地

preview

预览数据概貌

login

输入账号和密码,登录国泰安

setLanguage

设置语言,默认中文

笔者认为,十一个命令中真正重要的其实只有getData,后文会讲解原因,接下来将详细介绍如何用getData从国泰安下载数据。

国泰安官网关于getData给出的介绍如下


getData "Cuntrycd,Stkcd,Stknme,Conme" "Stkcd like'3%' limit 0,200000"" "trd_co" "2018-01-01" "2019-12-31"


其中,"Cuntrycd,Stkcd,Stknme,Conme"表示字段名称,Stkcd like'3%' 表示以3开头的股票代码,limit 0,200000意思是从第0条数据开始向后查询20万条数据,这两个是SQL语句。"trd_co"是表单名称,"2018-01-01" "2019-12-31"分别表示查询的起始时间和结束时间。

注意:limit 200000,200000表示从第20万条数据开始向后查询,这里并不包括第20万条数据。

getData可以直接把国泰安的数据导入stata中,这样比较,使用pack、getRecord和copy命令取获取数据显得很繁琐,这三个命令也可以被getData所取代。

但是国泰安官网关于getData的介绍还不足够,仍存在三个问题没解决。

第一个是这里只介绍了利用SQL指定股票代码,那么如何才能导入自己用表格存放的股票代码呢?

第二个是国泰安的数据下载有二十万条的上限,如果自己下载的数据量很大,如何才能突破这个限制呢?

第三个是国泰安对某些数据的下载有时间范围要求,比如下载日个股股票收益率的时间范围要在五年之内,如何才能下载超过五年的数据呢?

接下来笔者将逐一回答以上三个问题。

第一个问题,我们可以用levelsof解决。将我们需要指定的股票代码放入命为stock的dta文件中,股票代码的列变量名命名为stockid,利用destring命令确保stockid变量是数值型,用levelsof将stockid中的股票代码存放入命为r(levels)的暂元中,Stkcd in (`r(levels)') 表示筛选我们指定的股票代码。


use stock.dta,clear
destring stockid,replace
levelsof stockid
clear
getData "Cuntrycd,Stkcd,Stknme,Conme" "Stkcd in (`r(levels)') limit 0,200000"" "trd_co" "2018-01-01" "2019-12-31"


注意:1、必须将stockid变量设置为数值型,否则命令会报错
2、执行前getData前务必执行clear,清空当前数据集。

第二个问题,我们可以巧妙利用capture和while解决20万数据量上限的问题。第一行首先用capture执行无数据量限制的申请。while (_rc != 0) | (_N != 0)表示只要满足这两个条件,这花括号内的程序就会执行。执行capture以后能获得_rc,_rc等于0表示程序正常执行,_rc不等于0表示申请数据被驳回。_N表示当前数据集里样本个数。该whie的条件表示当申请数据被驳回运行花括号内的程序,或者成功申请但是数据集内的样本个数为零时停止执行花括号内的程序。limit `start',200000中`start'是从0开始的步长为20万的暂元,getData的命令会一直向国泰安申请数据,直到while不满足为止。tempfile security_returns`num'表示临时文件,申请到的文件可以存放到临时文件中,最后合并成一个完整的文件(合并的命令可以用append)。

注意:getData申请的数据如果小于limit的范围,能够成功申请,但是样本个数为零。比如getData "Cuntrycd,Stkcd,Stknme,Conme" "Stkcd in (`r(levels)') limit 200000,200000"" "trd_co" "2018-01-01" "2019-12-31"
假设该命令返回的只有一万条数据,但是limit要求从第二十万行数据开始读取,程序虽然能够正常运行,但是返回的样本个数为零。


capture getData "Cuntrycd,Stkcd,Stknme,Conme" "Stkcd in (`r(levels)') " "trd_co" "2018-01-01" "2019-12-31"
local start 0
local num   1
while (_rc != 0) | (_N != 0){
    clear
    capture getData "Cuntrycd,Stkcd,Stknme,Conme" "Stkcd in (`r(levels)') limit `start',200000"" "trd_co" "2018-01-01" "2019-12-31"
    local start = `start' + 200000
    tempfile security_returns`num'
    save "`security_returns`num''",replace
    local num = `num' + 1
}


第三个问题,我们可以利用levelsof产生时间上下限的暂元,来替换getData中的起始时间和结束时间。mdy(1,5,2020)表示生成日期为2020年5月1日的变量。year_up表示其实时间,year_low表示截止时间。format %tdCCYY-NN-DD设置year_up和year_low的显示为"YYYY-MM-DD"比如2020-01-05。tostring把日期型变量year_up和year_low变成字符型变量year_up_s和year_low_s,选项usedisplayformat确保字符变量的格式为"YYYY-MM-DD"。levelsof可以把year_up_s和year_low_s的字符型日期保存为暂元。这样我们就可以在getData中调用时间暂元了。


gen year_up = mdy(1,5,2020)
gen year_low = mdy(1,5,2021)
format %tdCCYY-NN-DD year_up year_low
tostring year_up,gen(year_up_s) force usedisplayformat
tostring year_low,gen(year_low_s) force usedisplayformat
levelsof year_up_s,local(year_up_m)
levelsof year_low_s,local(year_low_m)
capture getData "Cuntrycd,Stkcd,Stknme,Conme" "Stkcd in (`r(levels)') limit `start',200000"" "trd_co" `year_up_m' `year_low_m'


注意,不能使用local year_up_m=year_up_s[1]来定义暂元。

继续第三个问题,我们已经知道如何替换getData中的起始和截止时间,接下来只要获取到分段时间并保存到两列变量,再利用上面的levelsof获取时间暂元,问题就解决了。while的判断条件表示起始时间如果加4年比截止时间小,就执行花括号的程序。year_up1和year_low1用来存放几组分段时间。如果满足花括号内容,就把该组时间按行依次存放到year_up1和year_low1。但是因为最后一组起始时间和截止时间间隔不足五年,while的条件没有把最后一组考虑进去,所以需要单独用replace存放最后一组时间。


local muplti = 1
gen year_up1 = .
gen year_low1 = .
while mdy(month(year_up),day(year_up),year(year_up) + 4*`muplti') < year_low{
    capture replace year_up1 = mdy(month(year_up),day(year_up),year(year_up) + 4*(`muplti'-1)) in `muplti'
    capture replace year_low1 = mdy(month(year_up),day(year_up),year(year_up) + 4*`muplti') in `muplti'
    local muplti = `muplti' + 1
}
replace year_up1 = mdy(month(year_up),day(year_up),year(year_up) + 4*(`muplti'-1)) in `muplti'
replace year_low1 = mdy(month(year_low),day(year_low),year(year_low))  in `muplti'


接下来我们依次读取year_up1和year_low1各组时间。sum统计year_up1,year_up1的组数存放在`r(N)'中。将year_up1和year_low1转变成"YYYY-MM-DD"格式的字符型日期。用两列字符型变量year_upt和year_lowt存放每组日期,给levelsof读取。因为getData需要使用clear,为了避免当前数据集缺失,使用preserve和restore保存记录和恢复当前数据。


qui sum year_up1
local row_num = `r(N)'
format %tdCCYY-NN-DD year_up1 year_low1
tostring year_up1,replace force usedisplayformat
tostring year_low1,replace force usedisplayformat
gen year_upt = "."
gen year_lowt = "."
local row = 1 
while `row' <= `row_num'{
    replace year_upt = year_up1[`row']
    replace year_lowt = year_low1[`row']
    levelsof year_upt,local(year_up)
    levelsof year_lowt,local(year_low)
    preserve 
    clear
    getData "Stkcd,Dretwd,Trddt" "Stkcd in (`r(levels)') limit 0,200000" "TRD_Dalyr" `year_up' `year_low'
    tempfile security_returns`num'
    save "`security_returns`num''",replace  
    restore  
    local row = 1 + `row'
}


为了令代码不让人望而生畏,这里limit没有用循环解除下载量上限的问题。后文有完整可运行的demo。

到这里,getData的介绍就结束了。接下来本文先介绍剩下的九个接口命令,最后给出一个可运行的example。

  • login

login输入账号和密码,即可登录国泰安数据。语法如下。


login "账号" "密码"


  • setLanguage

setLanguage设置使用的语言,默认是中文。

  • getDataCount

getDataCount可以统计申请的数据个数,语法如下。


getDataCount "Cuntrycd,Stkcd,Stknme,Conme" "Stkcd like'3%'"" "trd_co" "2018-01-01" "2019-12-31"


  • getDbs

getDbs可以显示已购买的数据库,语法如下。


clear
getDbs


  • getTables

getTables可以显示某个数据库下的表单,以数据库"股票市场交易"为例。


clear
getTables "股票市场交易"


  • getFields

getFields可以显示某个表单下的具体变量名称,以TRD_Dalyr(日个股交易数据)为例。


clear
getFields TRD_Dalyr


  • pack

pack可以向国泰安提交申请,获得下载数据的密钥,以下载个股收益率为例。


pack "Stkcd,Dretwd,Trddt" "Stkcd like'300001'" "TRD_Dalyr" "2018-01-01" "2019-01-01"


  • getRecord

getRecord命令后面附带pack返回的密钥,可以得到数据压缩包的下载地址。以上面pack得到的密钥为例。


clear
getRecord 796085229362122752


  • copy

copy命令后面附带getRecord返回的压缩包下载链接,可以把数据下载到本地。以上面getRecord得到的下载地址为例。


copy "http://file.csmar.com/group1/M00/5A/AD/CuIKV1_0QaaAOZ18AAAIWsEo0hA966.zip" "D:Drivers桌面GTADailyReturn.zip",replace


  • unzipfile

unzipfile可以把压缩包解压。以DailyReturn.zip为例(上文copy自定义的文件名)。解压命令如下。最后利用insheet命令就可以读取数据了。


unzipfile DailyReturn,replace
insheet using TRD_Dalyr.csv


由于getDataCount和pack返回的结果只能显示在结果窗口中,无法调用,所以如果以pack的方式下载数据,就不得不沿用手工下载数据的方法。所以笔者本文的重点是getData的使用。
注意,getDbs、getTables、getFields和getRecord得到的结果可以打开数据集查看,这也为什么使用前需要清空数据集。

到这里,所有命令都已经介绍完了。接下来给出四个完整下载数据的Demo。具体使用视频见B站:阿JIN是个读书郎。(视频还在录制)

  • Demo 1 : 利用pack下载数据
***** 登录国泰安 *****
	login "账号" "密码"
	
	***** 查看数据(可选) *****
	clear
	getDbs
	clear
	getTables 股票市场交易
	clear
	getFields TRD_Dalyr
	***** 下载数据 *****	
	pack "Stkcd,Dretwd,Trddt" "Stkcd like'300001'" "TRD_Dalyr" "2018-01-01" "2019-01-01"
	clear
	getRecord 796085229362122752
	copy "http://file.csmar.com/group1/M00/5A/AD/CuIKV1_0QaaAOZ18AAAIWsEo0hA966.zip" "D:Drivers桌面GTADailyReturn.zip",replace
	unzipfile DailyReturn,replace
	erase "TRD_Dalyr[DES][csv].txt"
	clear
	insheet using TRD_Dalyr.csv
	edit


  • Demo 2 : 无时间限制下载数据
***** 登录国泰安 *****
	login "账号" "密码"
	
	***** 导入需要下载的股票代码(可选) *****
	clear
	set obs 100
	gen stockid = "300001" 
	gen year_up = mdy(1,1,2014) 
	gen year_low = mdy(1,5,2020) 
	
	***** 下载个股收益率数据 *****
	local muplti = 1
	gen year_up1 = .
	gen year_low1 = .
	while mdy(month(year_up),day(year_up),year(year_up) + 4*`muplti') < year_low{
		capture replace year_up1 = mdy(month(year_up),day(year_up),year(year_up) + 4*(`muplti'-1)) in `muplti'
		capture replace year_low1 = mdy(month(year_up),day(year_up),year(year_up) + 4*`muplti') in `muplti'
		local muplti = `muplti' + 1
	}
	replace year_up1 = mdy(month(year_up),day(year_up),year(year_up) + 4*(`muplti'-1)) in `muplti'
	replace year_low1 = mdy(month(year_low),day(year_low),year(year_low))  in `muplti'
	qui sum year_up1
	local row_num = `r(N)'
	format %tdCCYY-NN-DD year_up1 year_low1
	tostring year_up1,replace force usedisplayformat
	tostring year_low1,replace force usedisplayformat
	gen year_upt = "."
	gen year_lowt = "."
	local row = 1 
	local num = 1
	while `row' <= `row_num'{
		replace year_upt = year_up1[`row']
		replace year_lowt = year_low1[`row']
		levelsof year_upt,local(year_up)
		levelsof year_lowt,local(year_low)
		preserve 
		clear
		getData "Stkcd,Dretwd,Trddt" "Stkcd = '300001' limit 0,200000" "TRD_Dalyr" `year_up' `year_low'
		tempfile security_returns`num'
		save "`security_returns`num''",replace  
		restore  
		local row = 1 + `row'
		local num = 1 + `num'
	}
	local num = `num' - 1
	use `security_returns1',clear
	forvalues i = 2/`num'{
		append using "`security_returns`i''"
	}
	save security_returns.dta,replace


  • Demo 3 : 无数据量限制下载数据
***** 登录国泰安 *****
	login "账号" "密码"
	
	***** 导入需要下载的股票代码(可选) *****
	clear
	capture getData "Stkcd,Dretwd,Trddt" "Stkcd like '3%'" "TRD_Dalyr" "2016-01-01" "2019-12-31"
	local start 0
	local num   1
	while (_rc != 0) | (_N != 0){
		clear
		capture getData "Stkcd,Dretwd,Trddt" "Stkcd like '3%' limit `start',200000" "TRD_Dalyr" "2018-01-01" "2019-12-31"
		local start = `start' + 200000
		tempfile security_returns`num'
		save "`security_returns`num''",replace
		local num = `num' + 1
	}	
	local num = `num' - 1
	use `security_returns1',clear
	forvalues i = 2/`num'{
		append using "`security_returns`i''"
	}
	save security_returns.dta,replace


  • Demo 4 : 无数据量和时间限制下载数据
***** 登录国泰安 *****
	login "账号" "密码"

	***** 导入需要下载的股票代码(可选) *****
	clear
	set obs 10
	gen year_up = mdy(1,1,2014)
	gen year_low = mdy(1,5,2020)
	
	***** 下载个股收益率数据 *****
	local muplti = 1
	gen year_up1 = .
	gen year_low1 = .
	while mdy(month(year_up),day(year_up),year(year_up) + 4*`muplti') < year_low{
		capture replace year_up1 = mdy(month(year_up),day(year_up),year(year_up) + 4*(`muplti'-1)) in `muplti'
		capture replace year_low1 = mdy(month(year_up),day(year_up),year(year_up) + 4*`muplti') in `muplti'
		local muplti = `muplti' + 1
	}
	replace year_up1 = mdy(month(year_up),day(year_up),year(year_up) + 4*(`muplti'-1)) in `muplti'
	replace year_low1 = mdy(month(year_low),day(year_low),year(year_low))  in `muplti'
	qui sum year_up1
	local row_num = `r(N)'
	format %tdCCYY-NN-DD year_up1 year_low1
	tostring year_up1,replace force usedisplayformat
	tostring year_low1,replace force usedisplayformat
	gen year_upt = "."
	gen year_lowt = "."
	local row = 1 
	local num = 1	
	
	***** 下载股票收益率 *****
	noisily: display "  下载股票收益率 ..."
	
	local j = 1
	
	while `row' <= `row_num'{

		replace year_upt = year_up1[`row']

		replace year_lowt = year_low1[`row']

		levelsof year_upt,local(year_up)

		levelsof year_lowt,local(year_low)

		preserve 

		clear

		capture getData "Stkcd,Dretwd,Trddt" "Stkcd like '3%'" "TRD_Dalyr" `year_up' `year_low'

		local start 0

		while (_rc != 0) | (_N != 0){
			clear

			capture getData "Stkcd,Dretwd,Trddt" "Stkcd like '3%' limit `start',200000" "TRD_Dalyr" `year_up' `year_low'

			local start = `start' + 200000
			
			tempfile security_returns`num'

			save "`security_returns`num''",replace
			
			noisily: display "  第 " `j' " 个股票收益率数据集成功下载..."
			
			local num = `num' + 1
			
			local j = `j' + 1

		}
		restore

		local row = 1 + `row'
	}
	
	use "`security_returns1'",clear

	local num = `num' - 1

	local  j = 1
	
	forvalues i = 2/`num'{
		
		append using "`security_returns`i''"
		
		noisily: display "  第 " `j' " 个股票收益率数据集已成功合并..."
		
		local j = `j' + 1

	}

	tempfile security_returns
	
	save "`security_returns'",replace
	
	rename Stkcd stockid
	
	rename Trddt Date
	
	rename Dretwd sreturn
	
	anythingtodate Date
	
	destring stockid,replace
	
	save security_returns.dta,replace

	noisily: display "  ...succeeded"