金融量化投资的人都知道,要获取完整有效的原始数据非常麻烦,很多都是需要钱的,因此免费的数据异常珍贵,但实际中免费的数据往往不是常见的格式,无法用普通的记事本打开。因此如何转换这些数据成为免费的数据获取者的首要问题。同时也是量化投资者练习软件的一个必要技能。
R语言能够转换通达信格式的数据。当然这是多此一举,因为可以直接根据上面的方法点击鼠标导出,但这里更主要的是展示R语言强大的数据处理功能,同时便于读者熟悉数据处理方法。此处以获取美丽生态上市公司数据为例,并利用R语言转换成常见文档格式(csv或txt)。
1.1下载通达信.day格式数据
这个非常简单,只提一下。其中利用通达信盘后数据下载后,得到的.day格式保存在“D://Program Files//new_tdx//vipdoc//sh//lday//”文件夹下(这个文件夹会随电脑通达信程序安装文件夹不同而略存在差异。)
这种格式无法用通常的word或者记事本打开,打开了也是常见的乱码。因此处理之前,还需要获知.day文件中究竟是哪种编码的数据才行,在此基础上才能利用编码转换命令,转换成常见的文档格式。此处借助二进制查看软件进行分析。
1.2利用Binary Viewer软件查看.day数据
毫无疑问,.day格式的数据不能用常见的软件打开。同时利用常见的命令读取文档也无法正常读取,如利用命令为:
>mlst<- read.table('F://sz000010.day')
Warning messages:
1: In read.table("F://sz000001.day"): line 1 appears to contain embedded nulls
2: Inread.table("F://sz000001.day") : line 2 appears to contain embedded nulls
3: Inread.table("F://sz000001.day") : incomplete final line found by readTableHeader on 'F://sz000001.day'
得到的结果为:
>mlst
V11 h-1\001<d6>\0062 \a
利用scan命令读取文档,得到相似的结果。可以看出,这种数据经分析发现是与二进制相关的文档,无法用正常的方法打开,需要借助其他方法。要正确读取文档,首先要了解文档具体内容,此时需要借助其他软件。一般显示乱码的文件可以用二进制查看工具。此处继续发扬免费的精神,用Binary Viewer软件进行分析。具体选择不同选项进行查看,然后对比其结果是否与通信达软件中显示的数据是否一致。此处具体以sh000010.day数据,初步分析应该是对应上交所上市的股票代码为000010的数据,即美丽生态股票数据,利用Binary Viewer打开后得到的结果如图所示。
图3.31 BinaryViewer软件查看.day格式数据
软件显示的内容大致分为三部分。第一是是左边有颜色的部分是可视化模式(Visualizer),说实话笔者也不懂是什么内容;第二是中间是不同编码条件下对应的数据结果(Data View),具体可以用点击鼠标左键切换不同的模式,如图中显示的是Unsigned Integer(单字节)和Text(ASCII)下的结果,不用说,这些不同编码的内容读者也不知所云。第三部分是右边那些数据监测(Data Inspector),可以选择Big Endian(大端存储格式)和LittleEndian(小端存储格式)形式察看数据,这是我们关注的重点。当鼠标点击DataView中的不同位置,当对应的数字不同,则右边数据监测部分的结果会发生变化,那大致可以通过右边的Data Inspector察看具体数据。则点击文档大致位于末尾处的位置,因为末尾处的价格和成交量就是当前的价格和成交量,当前查看时间为2017年3月8日,美丽生态的价格在7块钱左右,那就慢慢移动,找哪些地方可能对应7左右和差不多时间的数据。
具体找到倒数第二行,如图3.32所示,鼠标点击067数字,发现右边选择Little Endian时,在4 bytes处的Unsigned(Signed) Integer处显示为20170307(具体结果如图3.33),太兴奋了,这不是传说是中日期吗?进一步移动鼠标,选择后面的200,可以看出,相同的地方出现了712,与通达信股票价格对应,发现这就是当天的开盘价7.12,唯一遗憾的就是扩大了100倍。也就是说,数据对应的是Little Endian方式,且字节数为4。
1.3 利用R语言转换数据格式
上述BinaryViewer分析出.day格式的数据编码形式,即Little Endian的形式,且以4字节为基础的数据。基于此对数据进行转换。R语言中,肯定有相应的工具包和函数处理和转换数据,最先想到的是readBin函数。对应命令为:
>mlst<- readBin('F://sz000010.day',n=10,endian='little',what='int')其中what是指数据类型,就是上述的整数(integer),endian为上述显示的“little”,n为10,即读取前10个数据。得到的结果为:
>mlst[1] 20000104 738 751 716 747 1239925819
[7] 256500 735 20000105 747
可以看出,20000104即为日期,进一步为了确定738、751等数据的内容,上通达信软件中找出2000年1月4号的数据,进一步在前复权、不复权和后复权等选项对数据进行转换,发现前复权数据与上述数据恰好一致,但相差100倍。即738为开盘价,具体对应通达信的7.38,成交量256500对应2565。另一个需要注意的是,成交总额数据是错误的,其中通达信显示190万,而上述显示1239925819,相距甚远。因此进一步利用BinaryViews软件进行查看,发现选择big endian形式,size为real方式,即实数形式,在原来相同的地方看到结果变为1898631,这与190万相接近,正是我们想要的结果。但利用readBin函数处理发现,当endian为'big'时,转换的数据与真实数据存在差异,通过不断尝试,发现下列命令能够得到正确的结果,具体如下:
>readBin('F://sz000010.day',what='double',endian = 'little',size=4,n=10)
[1]3.254234e-38 1.034158e-42 1.052375e-42 1.003330e-42 1.046770e-42 1.898631e+06
[7]3.594331e-40 1.029954e-42 3.254235e-38 1.046770e-42
其中第6个数字1898631即对应的成交额。与通达信190万一致。但这种简单的方法能够得到正确的结果,读取数据比较麻烦,因为我们不知道n到底有多长,因此,应该有更好的其他工具包进行分析。
图3.34 通达信美丽生态2010年1月4号不复权K线数据
经研究发现可以利用hexView工具包。下面具体利用hexView包中的readRaw主函数对day格式文档进行处理,并转换成txt或csv等格式的行业板块等数据,保存至当地文件夹。具体思路为,首先循环读取保存为txt格式的通达信行业代码,然后利用readRaw主函数转换.day格式数据,以记事本(.txt)格式保存在相应文件夹下。此方法的难点在于利用readRaw函数分析数据。仍以sz000010.day为例。其中readRaw函数的参数如下:
>args(readRaw)function (file, width = NULL, offset = 0,nbytes = NULL, machine = "hex", human = "char", size = switch(human, char = 1, int = 4, real =8), endian = .Platform$endian, signed = TRUE)
NULL
其中machine=’hex’表示数据原编码模式是16进制,即机器识别方式, human表示输出读者可以识别的模式,具体为字符形式,size表示转换为读者可以识别的形式,这种用integer,即整数形式,size表示源数据的格式。经过BinaryViewer查看,这些数据内容应该为整数形式,即human为int形式,且4字节,endian为little。基于此,对应的命令为:
>mhst<-readRaw(file= "D://Program Files//new_tdx//vipdoc//sz//lday//sz000010.day",
machine='hex',human='int',size=switch('int',int=4),endian='little')
mhst里面到底保存了什么东西,查看非常麻烦,则可用blockValue函数查看区域块值,输入:
>mhst<-blockValue(hmst)
查看最后16个值,命令为:
>tail(mhst,16)得到的结果为:
[1] 20170306 693 707 668 707 1284871617
[7] 11187604 65536 20170307 712 714 701[13] 709 1283274734 9372800 0
略作核对一番,可知,分别对应的3月6日至7日的开盘、收盘、最高和最低等价格,只不过价格都增加了100倍。
>mhst<-readRaw(file= "D://Program Files//new_tdx//vipdoc//sz//lday//sz000010.day",
> human='real',size=switch('real',real=4),endian='little')
得到的结果与上述一致。进一步对数据进行相应的处理,即可以得到正确的数据。
上述处理数据的方法可以扩展到其他领域。如感兴趣,可进一步参考《量化投资基础、方法与策略——R语言实战指南》(电子工业出版社)。