从2020年初开始接触量化,马上就要满一年了。在这一年里,想过去做量化,想过去做机器学习,想过去做少儿编程教育。就这样大概折腾了小半年时间,最后在CSDN上看到这样一句话:“你把时间投在专业上,两三年,你就能在圈子里小有名气。四五年,你就能靠这个专业赚钱。过了10年以上,你就能成为这个领域的专家。”觉得自己可以按这句话努力一把,于是便坚定了探索量化的决心。

python、backtrader、量化、机器学习基本上都是从零学起,对近一年来的学习进度总体还算满意。CSDN的粉丝量280+,博客升级为5级,访问量9万+,总排名5万+,微信群成员260+,QQ群也建立起来。本来想在QQ群里以任务方式同步自己的学习进度,无奈踩的坑实在太多,学习时间也不固定,所以还是等我理清思路,再做系统化的分享。

这里也特别感谢各位群友的支持与帮助。这篇文章就是基于群友阿猪和阳光分享的内容进行的整理。

通达信数据获取优势

快!就是快!
在使用baostock获取或者更新股票数据时,4000多只股票基本要耗时1个多小时。

在使用通达信获取数据时,除了首次通过通达信软件把数据下载到本地需要十几分钟时间外,后面每日更新数据在1分钟内就能下载完毕,在加上脚本解析数据存入csv文件也是在1分钟内即可完成。

因此,有必要掌握通过通达信来获取股票数据的方法。

通达信软件下载日线数据

首先,下载通达信软件,安装后打开,在菜单栏点击“系统”->“盘后数据下载”,弹出下面的面板:

勾选日线和实时行情数据,选择需要下载的日线时间范围,点击开始下载,日线数据就会被保存在本地。其中上证A股的日线数据保存在“通达信安装路径\vipdoc\sh\lday”目录下,文件名为“市场代码.day”,例如“sh600000.day”,深证A股的日线数据保存在“通达信安装路径\vipdoc\sz\lday”目录下,文件名格式与上证A股相同,例如“sz000001.day”。

解析数据

通过通达信下载的day文件是二进制文件,这里对day文件进行解析,保存为csv文件。

def transform_data():# 保存csv文件的目录target = proj_path + 'data/tdx/day'if not os.path.exists(target):os.makedirs(target)code_list = []source_list = ['C:/new_tdx/vipdoc/sz/lday', 'C:/new_tdx/vipdoc/sh/lday']for source in source_list:file_list = os.listdir(source)# 逐个文件进行解析for f in file_list:day2csv(source, f, target)# 获取所有股票/指数代码code_list.extend(list(map(lambda x: x[:x.rindex('.')], file_list)))# 保存所有代码列表pd.DataFrame(data=code_list, columns=['code']).to_csv(proj_path + 'data/tdx/all_codes.csv', index=False)

这里代码最后一行是把所有股票/指数代码保存在all_codes.csv文件中,便于后续更新日线数据时使用。

代码中的day2csv方法实现了日线数据由day文件向csv文件的转化。

# 将通达信的日线文件转换成CSV格式
def day2csv(source_dir, file_name, target_dir):# 以二进制方式打开源文件source_file = open(source_dir + os.sep + file_name, 'rb')buf = source_file.read()source_file.close()# 打开目标文件,后缀名为CSVtarget_file = open(target_dir + os.sep + file_name[: file_name.rindex('.')] + '.csv', 'w')buf_size = len(buf)rec_count = int(buf_size / 32)begin = 0end = 32header = str('date') + ',' + str('open') + ',' + str('high') + ',' + str('low') + ',' \+ str('close') + ',' + str('amount') + ',' + str('volume') + '\n'target_file.write(header)for i in range(rec_count):# 将字节流转换成Python数据格式# I: unsigned int# f: floata = unpack('IIIIIfII', buf[begin:end])# 处理date数据year = a[0] // 10000month = (a[0] % 10000) // 100day = (a[0] % 10000) % 100date = '{}-{:02d}-{:02d}'.format(year, month, day)line = date + ',' + str(a[1] / 100.0) + ',' + str(a[2] / 100.0) + ',' \+ str(a[3] / 100.0) + ',' + str(a[4] / 100.0) + ',' + str(a[5]) + ',' \+ str(a[6]) + '\n'target_file.write(line)begin += 32end += 32target_file.close()

day文件中,每32个字节存储了一根日线数据,各字节存储数据如下:

  • 00 ~ 03 字节:年月日, 整型
  • 04 ~ 07 字节:开盘价*100,整型
  • 08 ~ 11 字节:最高价*100,整型
  • 12 ~ 15 字节:最低价*100,整型
  • 16 ~ 19 字节:收盘价*100,整型
  • 20 ~ 23 字节:成交额(元),float型
  • 24 ~ 27 字节:成交量(股),整型
  • 28 ~ 31 字节:(保留)

更新数据(非全部下载)

假设在每日收盘后,我们都要更新csv文件中的股票当日的K线数据,显然没有必要把所有的day文件从头解析一遍,而只需要从day文件的文件末,解析出我们需要更新的日线数据即可。当然,这也需要先从通达信软件先下载盘后数据,下载方法参考本文开头的“通达信软件下载日线数据”章节。更新数据代码如下:

def update_data():# 读入所有股票/指数代码codes = pd.read_csv(proj_path + 'data/tdx/all_codes.csv')['code']for code in codes:data_path = proj_path + 'data/tdx/day/' + code + '.csv'# 读取当前已存在的数据exist_df = pd.read_csv(data_path)# 获取需要更新的日线开始时间from_date = pd.read_csv(proj_path + 'data/tdx/day/' + code + '.csv')['date'].iloc[-1]# 提取新数据data = extract_data(from_date, 'C:/new_tdx/vipdoc/' + code[0:2] + '/lday/' + code + '.day')if not len(data):continuedf = pd.DataFrame(data).rename(columns={0: 'date', 1: 'open', 2: 'high', 3: 'low', 4: 'close', 5: 'amount', 6: 'volume'})# 合并数据df = exist_df.append(df)# 保存文件df.to_csv(data_path, index=False)

其中,extract_data用于提取日期from_date后的数据:

def extract_data(from_date, file_name):# 以二进制方式打开源文件source_file = open(file_name, 'rb')buf = source_file.read()source_file.close()buf_size = len(buf)rec_count = int(buf_size / 32)# 从文件末开始访问数据begin = buf_size - 32end = buf_sizedata = []for i in range(rec_count):# 将字节流转换成Python数据格式# I: unsigned int# f: floata = unpack('IIIIIfII', buf[begin:end])# 处理date数据year = a[0] // 10000month = (a[0] % 10000) // 100day = (a[0] % 10000) % 100date = '{}-{:02d}-{:02d}'.format(year, month, day)if from_date == date:breakdata.append([date, str(a[1] / 100.0), str(a[2] / 100.0), str(a[3] / 100.0), \str(a[4] / 100.0), str(a[5]), str(a[6])])begin -= 32end -= 32# 反转数据data.reverse()return data

小结

  • 通过解析通信达软件下载的日线数据,可以实现股票数据的快速获取。
  • 解析2000年以来的所有股票日线数据,在我的机器上大概耗时50s。
  • 更新当日K线数据,在我的机器上花费耗时大概为30s。

通信达日线数据解析全部代码如下:

import os
import sys
import time
import pandas as pd
from struct import unpack# 获取当前目录
proj_path = os.path.dirname(os.path.abspath(sys.argv[0])) + '/../'# 将通达信的日线文件转换成CSV格式
def day2csv(source_dir, file_name, target_dir):# 以二进制方式打开源文件source_file = open(source_dir + os.sep + file_name, 'rb')buf = source_file.read()source_file.close()# 打开目标文件,后缀名为CSVtarget_file = open(target_dir + os.sep + file_name[: file_name.rindex('.')] + '.csv', 'w')buf_size = len(buf)rec_count = int(buf_size / 32)begin = 0end = 32header = str('date') + ',' + str('open') + ',' + str('high') + ',' + str('low') + ',' \+ str('close') + ',' + str('amount') + ',' + str('volume') + '\n'target_file.write(header)for i in range(rec_count):# 将字节流转换成Python数据格式# I: unsigned int# f: floata = unpack('IIIIIfII', buf[begin:end])# 处理date数据year = a[0] // 10000month = (a[0] % 10000) // 100day = (a[0] % 10000) % 100date = '{}-{:02d}-{:02d}'.format(year, month, day)line = date + ',' + str(a[1] / 100.0) + ',' + str(a[2] / 100.0) + ',' \+ str(a[3] / 100.0) + ',' + str(a[4] / 100.0) + ',' + str(a[5]) + ',' \+ str(a[6]) + '\n'target_file.write(line)begin += 32end += 32target_file.close()def transform_data():# 保存csv文件的目录target = proj_path + 'data/tdx/day'if not os.path.exists(target):os.makedirs(target)code_list = []source_list = ['C:/new_tdx/vipdoc/sz/lday', 'C:/new_tdx/vipdoc/sh/lday']for source in source_list:file_list = os.listdir(source)# 逐个文件进行解析for f in file_list:day2csv(source, f, target)# 获取所有股票/指数代码code_list.extend(list(map(lambda x: x[:x.rindex('.')], file_list)))# 保存所有代码列表pd.DataFrame(data=code_list, columns=['code']).to_csv(proj_path + 'data/tdx/all_codes.csv', index=False)def extract_data(from_date, file_name):# 以二进制方式打开源文件source_file = open(file_name, 'rb')buf = source_file.read()source_file.close()buf_size = len(buf)rec_count = int(buf_size / 32)# 从文件末开始访问数据begin = buf_size - 32end = buf_sizedata = []for i in range(rec_count):# 将字节流转换成Python数据格式# I: unsigned int# f: floata = unpack('IIIIIfII', buf[begin:end])# 处理date数据year = a[0] // 10000month = (a[0] % 10000) // 100day = (a[0] % 10000) % 100date = '{}-{:02d}-{:02d}'.format(year, month, day)if from_date == date:breakdata.append([date, str(a[1] / 100.0), str(a[2] / 100.0), str(a[3] / 100.0), \str(a[4] / 100.0), str(a[5]), str(a[6])])begin -= 32end -= 32# 反转数据data.reverse()return datadef update_data():# 读入所有股票/指数代码codes = pd.read_csv(proj_path + 'data/tdx/all_codes.csv')['code']for code in codes:data_path = proj_path + 'data/tdx/day/' + code + '.csv'# 读取当前已存在的数据exist_df = pd.read_csv(data_path)# 获取需要更新的日线开始时间from_date = pd.read_csv(proj_path + 'data/tdx/day/' + code + '.csv')['date'].iloc[-1]# 提取新数据data = extract_data(from_date, 'C:/new_tdx/vipdoc/' + code[0:2] + '/lday/' + code + '.day')if not len(data):continuedf = pd.DataFrame(data).rename(columns={0: 'date', 1: 'open', 2: 'high', 3: 'low', 4: 'close', 5: 'amount', 6: 'volume'})# 合并数据df = exist_df.append(df)# 保存文件df.to_csv(data_path, index=False)def get_all_stock_codes():all_codes_file = proj_path + 'data/tdx/all_codes.csv'if not os.path.exists(all_codes_file):print('请先更新数据!')returndf = pd.read_csv(all_codes_file)df = df[((df['code'] >= 'sh600000') & (df['code'] <= 'sh605999')) | \((df['code'] >= 'sz000001') & (df['code'] <= 'sz003999')) | \((df['code'] >= 'sz300000') & (df['code'] <= 'sz300999'))]df.to_csv(proj_path + 'data/tdx/all_stock_codes.csv', index=False)if __name__ == '__main__':# 程序开始时的时间time_start = time.time()# 获取所有股票代码# get_all_stock_codes()# 转换所有数据transform_data()# 更新数据# update_data()# 程序结束时系统时间time_end = time.time()print('程序所耗时间:', time_end - time_start)

欢迎大家关注、点赞、转发、留言,感谢支持!
微信群用于学习交流,感兴趣的读者请扫码加微信!
QQ群(676186743)用于资料共享,欢迎加入!


Python量化交易学习笔记(46)——通达信日线数据获取相关推荐

  1. Python量化交易学习笔记(1)

    Python量化交易学习笔记(1) http://zwpython.com/ http://www.topquant.vip/?p=2275 [更多参见] <zwPython,目前最好的py开发 ...

  2. Python量化交易学习笔记(18)——放量突破布林线中轨买入策略

    本文将探索新的策略回测程序,主要是为了尝试不同的技术指标在backtrader平台上的应用,为后续复杂策略的实现做准备. 本文将实现的策略是,当股票放量突破布林线中轨时进行买入,当股票收盘价低于短期均 ...

  3. Python量化交易学习笔记(33)——backtrader仓位管理

    本文将对backtrader的仓位管理进行介绍,具体以同时回测交易3只股票为例,查看每日仓位情况. 策略 买入条件:5日线金叉60日线 卖出条件:5日线死叉60日线 示例 仓位信息输出的核心代码位于策 ...

  4. Python量化交易学习笔记(2)——A股数据下载

    由于笔者只接触过A股交易,因此本系列笔记仅针对A股交易展开.笔者的计算机为Windows 10 64位操作系统. TOP极宽量化总群(124134140)群文件中提供了大量的学习资料,一眼看去有点懵圈 ...

  5. Python量化交易学习笔记(21)——A股股票列表更新

    在zwPython2020中,股票数据下载更新时,所读取的股票列表文件的目录位置为"zwPython\TQDat\TQDown2020v1\data\tq_wrk_code.csv" ...

  6. Python量化交易学习笔记(19)——连续下跌买入止盈止损卖出策略

    好友提出要验证连续下跌买入止盈止损卖出策略,本文对该策略回测和实现做分析记录. 买入条件中,连续下跌定义为收盘价连续4日低于前1日的收盘价.卖出条件中,止盈率设置为10%,止损率设置为5%.回测初始资 ...

  7. Python量化交易学习笔记(20)——保护点卖出策略

    本文主要记录保护点卖出策略,给买入的股票设立保护点,随着股票收盘价的提升,保护点不断提高,股价一旦跌破保护点,即卖出股票. 示例的买入条件为,5日线金叉60日线,且股价进行小幅回踩(较金叉日收盘价下跌 ...

  8. Python量化交易学习笔记(36)——backtrader多股回测避坑3

    本文继续记录多股回测时可能遇到的异常情况. 坑描述 多股回测时,当日期达到所有股票的技术指标都能够计算出有效值后,backtrader才开始进行回测.由于这种逻辑的存在,如果某些股票在回测周期的最后几 ...

  9. Python量化交易学习笔记(25)——Data Feeds扩展

    背景:需要扩展data feeds的场景 在backtrader中,data feeds中包含了被普遍认为是业界标准的几个字段: datetime open high low close volume ...

最新文章

  1. centos7安装JDK1.7
  2. mysql安装的根目录_MySql安装及基础配置(一)
  3. BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]
  4. 一个还算简单的微信消息SDK(基于.Net Standard 2.0)
  5. 模拟航班查询及预定系统 编写示例
  6. 用计算机听音乐和看电影教学反思,与计算机交朋友
  7. 一个php请求的执行过程,PHP程序执行的过程原理
  8. Oculus关于Internal Error:OVR53225466报错解决方法
  9. mysql文件扩展名查询_如何通过MySQL查询获取文件的文件扩展名?
  10. Java分层架构的使用规则
  11. Spss典型相关分析的常见问题
  12. 工业级嵌入式串口转wifi模块
  13. MySQL学习第三弹——约束与多表查询详解
  14. java 获取本年月份、本月/本周所有日期
  15. Android:自定义View实现绚丽的圆形进度条
  16. Cesium测量工具,距离测量、面积测量、高度测量
  17. 50个Java多线程面试题
  18. Windows中快速获取文件目录的方法
  19. Idea 2021新建项目没有spring选项
  20. NCQ TCQ 什么是NCQ 什么是TCQ 区别

热门文章

  1. 基于新代数控系统PLC基础语法汇总
  2. python基础学习十四:面向对象三大特性之继承
  3. 互联网时代,政府如何应对网络舆情监测危机
  4. 毕业设计- Android图书借阅管理系统
  5. 数据采集协同架构,集成马扎克、西门子、海德汉、广数、凯恩帝、三菱、海德汉、兄弟、哈斯、宝元、新代、发那科、华中各类数控以及各类PLC数据采集软件
  6. CSS透明度[简述]
  7. 微软2014校园招聘笔试题
  8. 如何快速删除空行……
  9. 信号完整性分析心得体会_电子线路cad心得体会.doc
  10. Knowledge-based Collaborative Deep Learning for Benign-Malignant Lung Nodule Classification论文阅读