tick数据什么方式保存?写入csv还是hdf5或是数据库?
csv写入最高效,最大的问题是大文件的读取,就算用上一些提高效率的方式,也远远不如hdf5和数据库。
hdf5如果是整块写入速度很快,但是记录实时行情需要不断追加,要想像csv那样按行写入,就只能每次获取到数据转换成DataFrame,效率非常低下。
代码1是 csv和hdf5的对比
代码2是 csv和SQLite数据库
import numpy as np
import pandas as pd
import csv
df=pd.read_csv('a.csv')
%%time
csvheader = ['date','open','high','low','close']
csvfile = open('t1.csv', 'w', newline='')
csvfile_w = csv.writer(csvfile)
csvfile_w.writerow(csvheader)
i=0
for date,o,h,l,c in zip(df['date'],df['open'],df['high'],df['low'],df['close']):
i+=1
if i>100:
break
mdlist=[date,o,h,l,c]
csvfile_w.writerow(mdlist)
csvfile.close()
# Wall time: 34.9 ms
%%time
store=pd.HDFStore('t1','w')
i=0
for date,o,h,l,c in zip(df['date'],df['open'],df['high'],df['low'],df['close']):
i+=1
if i>100:
break
mdlist=[date,o,h,l,c]
df1=pd.DataFrame([mdlist],columns=['date','open','high','low','close'])
store.append('df1',df1)
store.close()
# Wall time: 464 ms
为了尽量还原场景,我把3个合约的tick合并后按时间排序
import csv, sqlite3
from line_profiler import LineProfiler
subID = ['rb2310', 'au2310', 'sc2309']
with open('../data/rb2310_tick.csv', newline='') as f:
reader = csv.reader(f)
next(reader)
a = list(reader)
with open('../data/au2310_tick.csv', newline='') as f:
reader = csv.reader(f)
next(reader)
b = list(reader)
with open('../data/sc2309_tick.csv', newline='') as f:
reader = csv.reader(f)
next(reader)
c = list(reader)
res = a + b + c
res.sort(key=lambda x: x[18]) # 根据tick时间排序
def test_csv_write(res):
csvfiles = {}
submap = {}
csvheader = ['symbol', 'updateTime', 'lastPrice']
for id in subID:
csvname = f"./csv/{id}_tick.csv"
csvfile = open(csvname, 'w', newline='')
csvfile_w = csv.writer(csvfile)
csvfile_w.writerow(csvheader)
csvfiles[id] = csvfile
submap[id] = csvfile_w
for tick in res:
submap[tick[1]].writerow([tick[1], tick[18], tick[2]])
csvfiles[tick[1]].flush()
def test_db_write(res):
dbfiles = {}
for id in subID:
fname = f"./db/{id}_tick.db"
conn = sqlite3.connect(fname)
conn.execute('''CREATE TABLE IF NOT EXISTS tick
(id INTEGER PRIMARY KEY AUTOINCREMENT,
symbol varchar(10),
updateTime varchar(10),
lastPrice varchar(10));''')
dbfiles[id] = conn
for tick in res:
dbfiles[tick[1]].execute(f"insert into tick (symbol,updateTime,lastPrice) values ('{tick[1]}','{tick[18]}','{tick[2]}')")
dbfiles[tick[1]].commit()
def main():
test_csv_write(res)
test_db_write(res)
lp = LineProfiler()
test_func = lp(main)
test_func()
lp.print_stats()
下面是打印结果
Line # Hits Time Per Hit % Time Line Contents
==============================================================
54 def main():
55 1 302705.0 302705.0 0.2 test_csv_write(res)
56 1 179921444.0 179921444.0 99.8 test_db_write(res)
总结:
实时数据的记录用csv是最高效的,可以在每天收盘后把csv转换成hdf5或数据库。
数据库管理起来方便,但空间占用跟csv文件差不多。hdf5就算不使用压缩参数也比csv小很多,虽然也可以追加写入,不如数据库方便。
我自己的方案是对csv文件进行管理,比如K线文件,我实盘需要的K线数量300根已经足够,所以只要csv文件超过300行,就可以处理掉多余的数据。
比如每次开盘前程序启动,先检查各个合约的csv文件的行数,如果超过5000行就打包成rar,以合约id+当前日期 命名,并自动上传到百度网盘。然后读取该文件后,取最后300行重新写入到该文件。
为了提高效率,不一定要检查csv文件的行数,可以用 os.path.getsize(file_name) 读取文件字节,估算下超过多少字节可以清理。
或者干脆每次开盘前一律取300行数据重写csv文件。最简单的代码:
pd.read_csv(fname).tail(300).to_csv(fname,index=False)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具