本文包括程序为作者原创。
通达信具有强大的板块处理能力,并且一些板块数据是动态更新的,做股票量化设计的时候,借助通达信的板块动态文件,取到事半功倍的效果,本文用实例说明如何利用通达信板块数据动态更新到自己的板块库。
一、 通达信的板块板块文件及其数据格式;
通达信针对股票的常用板块有风格板块、概念板块、指数板块,分别对应的文件为block_fg.dat;block_gn.dat;block_zs.dat
存储路径为 \T0002\hq_cache
三个板块的数据格式均为二进制文件,并且格式相同:
文件存储格式:
文件头:384字节
板块个数:2字节
各板块数据存储结构(紧跟板块数目依次存放),
每个板块占据的存储空间为2813个字节,可最多包含400只个股
板块名称:9字节
该板块包含的个股个数:2字节
板块类别:2字节
该板块下个股代码列表(连续存放,直到代码为空)
个股代码:7字节
二、 通达信板块数据更新频率;
通达信对不同的板块更新的频率不同,具体可以参考通达信的红宝书文件。为简单期间,本地数据库建议每天更新,更新时间设在上午9:00之后。
三、 Matlab对板块数据的储存格式
用table格式,table包括四个字段,分别为Date,fg,gn,zs;对应更新时间,风格板块,概念板块和指数板块三个板块类别。存储格式为N*2的元胞数组,N为该类别的板块数。
四、 自动更新设置
根据上交所交易日戳,如果table中的最后更新时间小于上交所日戳的最后时间,则自动更新。并且将自动更新的判断单独设立函数。在其他需要更新的地方也可正常调用。比如个股日线数据更新。
程序代码附后,剪贴板可能会有少数字符不能直接执行,需要修改。
网友如有更好优化,欢迎留言。
functionreadblock();
%%
批量读入通达信板块数据到表格
%
读入的板块文件分别为:block_fg.dat(风格板块);block_gn.dat(概念板块);block_zs.dat(指数板块)
%
文件位于
‘C:\new_jyqyb\T0002\hq_cache’目录下;
%
存储格式为表,表的域名分别为:日期,风格板块,概念板块,指数板块
%
后面的数据域为元胞数组,{nCount,nLevel,nIndexOffset,blName,blstocks},
%
分别对应的说明为:{板块数,版块分类,板块指针,板块名称,成分代码};
%
根据通达信的定义,有些板块成分股有固定的调整周期,所以为确保数据完整性,
%
板块数据也需要每天更新。
blockFile =
['block_fg.dat';'block_gn.dat';'block_zs.dat'];
blockNmae =
['风格板块';'概念板块';'指数板块'];
blockPathin
= 'C:\new_jyqyb\T0002\hq_cache'
;
blockPathout
= 'D:\Stock\Data';
blockFileout
= 'block.mat';
fo = [
blockPathout,'\',blockFileout];
if
~exist(fo,'file')
%判断板块数据表是否存在,
block =
table;
needUp
= 1;
else
load(fo)
%打开存在的板块数据表;
if
~isempty(block)
bd=block.Date(end);
if
~(strcmp(class(bd),'char'))
blockoldDate =
char(bd);
else
blockoldDate =
bd;
end
needUp
= Needupdata(blockoldDate);
else
needUp
= 1;
end
end
while
needUp
== 1
%如果需要更新
bnum =
length(blockFile(:,1));
for
bln =
1:bnum
bf =
[blockPathin,'\',blockFile(bln,:)];
blocktemp(bln,:) ={
readoneblock(bf)};
end
D1 =
datestr(now,'yyyy-mm-dd
HH:MM:SS');
blocktabletemp =
cell2table({D1,blocktemp(1,1),blocktemp(2,1),blocktemp(3,1)},...
'VariableNames',{'Date','fg','gn','zs'});
block =
[block;blocktabletemp];
save
(fo,'block');
needUp
= 0;
end;
function[nnblodk]
= readoneblock(blockfilename)
%%
取通达信板块数据
%
概念板块
%{
数据结构
文件存储路径:tdx\T0002\hq_cache\block.dat
文件存储格式:
文件头:384字节
板块个数:2字节
各板块数据存储结构(紧跟板块数目依次存放),
每个板块占据的存储空间为2812个字节,可最多包含399个个股
板块名称:9字节
该板块包含的个股个数:2字节
板块类别:2字节
该板块下个股代码列表(连续存放,直到代码为空)
个股代码:7字节
%}
fngn =
blockfilename;
fid =
fopen(fngn,'r','n','gb-2312');
szVersion =
char(fread(fid,64,'char'))';
%文件版本信息
szVersion(abs(szVersion)==0)=[];
%切除后面的无效字符
fseek
(fid,384,'bof');
nIndexOffset =
fread(fid,1,'uint16');
%板块个数
for
i =
1:nIndexOffset
fseek
(fid,386+(i-1)*2813,'bof');
ju =
1;
cc =
char(fread(fid,1,'char'));
for
k =
1:8
while
ju
cc1 =
char(fread(fid,1,'char'));
if
abs(cc1) >
0
cc =
[cc,cc1];
else
ju =
0;
end
end
end
szName(i,:) ={ cc
};
fseek
(fid,395+(i-1)*2813,'bof');
nCount(i) =
fread(fid,1,'uint16');
%fseek
(fid,397+(i-1)*2813,'bof');
nLevel(i) =
fread(fid,1,'uint16');
sztemp
= [char(fread(fid,[7,400],'char'))];
sztemp
= sztemp';
sztemp(int16(nCount(i)+1):end,:)=[];
sztemp(:,7)=[];
sz(i,1) =
{sztemp};
end;
nnblodk
= [szName,sz];
fclose(fid);
clear
nCount
nLevel
nIndexOffset
blName
blstocks
cc*
i
ju
k
sz*
ans
fngh;
function
[
Needs_updating] = Needupdata( endDate,cStock )
%%
根据给定的日期,确定数据是否需要更新,这里约定的输入参数格式为
‘yyyy-mm-dd
HH:MM:SS’
%
输出值为
逻辑型,1表示需要更新;0表示不需要;
%
原理: 1、取交易所交易日戳数据
%
2、得到最后一个交易日期,约定的更新日期为每天收盘后2小时;
%
3、如果最后更新时间小于最后一个交易日的;
%
4、默认为大盘或板块类,如果指定cStock,则取对应的股票交易日戳;
load
My %
My储存登陆信息’
ret =
gm.InitMD(My_username,
My_password,1);
if nargin<2
cStock = 'SHSE';
else
if
length(cStock)>6
cStock = str2symbol(cStock(end-5:end)) ;
end
end
start_time =
datestr(datenum(today)-300,'yyyy-mm-dd');
end_time =
datestr(today,'yyyy-mm-dd');
tradedate =
gm.GetCalendar( cStock, start_time, end_time );
td1 =
char(tradedate.strtime(end));
td =
[td1(1:10),'
09:01:00'];
if length(endDate)==10
endDate = [endDate,'
00:00:00'];
else
if
datenum(endDate,'yyyy-mm-dd
HH:MM:SS')'yyyy-mm-dd
HH:MM:SS')
Needs_updating = 1;
else
Needs_updating = 0;
end;
end;
function
[symb_11]
= str2symbol(str6)
%%
股票代码转化为掘金量化代码’
if
strcmp(str6(1),'6')
symb_11 = ['SHSE.',str6];
else
symb_11 = ['SZSE.',str6];
end