提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
量化交易,数据先行。
可你是不是也经常遇到:行情没下载读取不到,下载了读取不够快,直接订阅行情数量又不够,或者速度不够快。
那么你可以尝试一下下面这个方法。
一、DiskCache是什么,它有什么优势?
DiskCache是一个用Python编写的高效轻量级磁盘和文件缓存库,旨在提供比内存缓存更持久的存储解决方案,同时保持接近内存缓存的访问速度。它特别适用于需要大量临时存储且对性能敏感的应用。
比如我们量化交易需要用到的行情数据,就刚好符合其应用场景。
它是一个纯 Python 的缓存包,可有效利用上 G 空间用于缓存,通过数据库和内存映射文件,缓存性能可以匹配并超越行业标准解决方案。
根据官方(https://github.com/grantjenks/python-diskcache)展示的读写删除时间,可以看到diskcache在读写删除方便均耗时较小。
Project | diskcache | dbm | shelve | sqlitedict | pickleDB |
---|---|---|---|---|---|
get | 25 µs | 36 µs | 41 µs | 513 µs | 92 µs |
set | 198 µs | 900 µs | 928 µs | 697 µs | 1,020 µs |
delete | 248 µs | 740 µs | 702 µs | 1,717 µs | 1,020 µs |
二、DiskCache基本操作示例
1. 安装DiskCache
通过pip即可安装DiskCache,使用镜像库可加速安装过程。
pip install diskcache -i https://pypi.tuna.tsinghua.edu.cn/simple
2. DiskCache常用操作
# 导入库文件
from diskcache import Cache
# 实例化缓存对象,指定缓存目录
cache = Cache('/cachedb/cachedb_01')
# 设置缓存项
cache.set('300750', '宁德时代')
cache.set('300250', '初灵信息')
cache.set('300450', '先导智能')
print(list(cache)) # 输出不排序的键名list
print(list(cache.iterkeys())) # 输出排序的键名list
print(cache.peekitem()) # 输出最后一个键值
print(cache.peekitem(last=False)) # 输出第一个键值
# DiskCache支持设置带有过期时间的缓存项,使得数据可以在指定时间后自动失效。
# 设置缓存项,其中expire参数指定过期时间(单位:秒)
cache.set('300750', '宁德时代', expire=5)
# 尝试等待超时后再获取
import time
time.sleep(5)
value = cache.get('300750')
print('Cached value after expiration:', value) # 输出: Cached value after expiration: None
# 获取缓存项
value = cache.get('300750')
print('Cached value:', value) # 输出: Cached value: '宁德时代'
# 添加新的缓存
cache.add('300750', '宁德时代', expire=10)
# 删除指定的缓存项
cache.delete('300750')
# 验证缓存项是否已被删除,已删除的返回None
value = cache.get('300750')
print('Cached value:', value) # 输出: Cached value: None
# 另一种删除方法,返回值为删除的键值
value = cache.pop('300750')
# 检查键是否存在
if '300750' in cache:
print("'300750' exists in cache")
else:
print("'300750' does not exist in cache")
# 更新缓存时间
cache.touch('300750', expire=10)
# 手动清理过期缓存
cache.expire()
# 输出键值数量
print('cache.count:',cache.count)
# 输出磁盘容量占用情况
print('cache.volume():',cache.volume())
# 关闭缓存对象
cache.close()
# 删除缓存文件。缓存不会自动删除keys和值。缓存旨在持久化,因此需要手动删除。
import shutil
try:
shutil.rmtree(cache.directory)
except OSError: # Windows wonkiness
pass
三、用DiskCache写入和读取行情信息
我们通常使用DataFrame来存取行情信息。这里我们引用我们的老朋友Ashare库来爬取行情信息,但将行情df写入DiskCache前,我们需要使用pickle先转化一下,当然读取出来也需要再反向转化一下。具体示例如下:
# 导入库文件
from diskcache import Cache
# 实例化缓存对象,指定缓存目录
cache = Cache('/cachedb/cachedb_01')
import pickle
from Ashare import *
code = '300750.sz'
df = get_price(code,frequency='1m',count=250) #支持'1m','5m','15m','30m','60m'
print('上证指数分钟线\n',df)
# 将df写入cache
df_bytes = pickle.dumps(df)
cache.set(code, df_bytes)
print(cache.get(code))
# 从cache读取为df
df_bytes_from_cache = cache.get(code)
if not df_bytes_from_cache is None:
df = pickle.loads(df_bytes_from_cache)
print(df)
四、DiskCache的高级操作
1. 指定缓存空间
# 实例化缓存,指定大小限制为300MB
cache = Cache('/cachedb/cachedb_01', size_limit=300*1024*1024)
2. FanoutCache 分片
diskcache可使用diskcache.FanoutCache 自动分片基础数据库。分片是对数据进行水平分区。可用于减少阻塞写入。尽管读和写不会互相阻碍,但写入会阻碍其他写入。分片默认值为8。
from diskcache import FanoutCache
cache=FanoutCache(r"/cachedb/cachedb_01",shards=4,timeout=1)
cache.set('300750', '宁德时代')
print(cache.get('300750'))
cachedb_01文件夹中创建一个具有四个分片和一秒超时的缓存。如果操作花费的时间超过一秒,它们将尝试中止操作。每一个分片大小平均分配,占总空间的四分之一。diskcache的默认大小为1GB。
3. 缓存信息统计
# 获取并打印缓存统计信息
stats = cache.stats(enable=True) # 需要先启用统计
print("Cache hits:", stats['hits'])
print("Cache misses:", stats['misses'])
总结
我们这里只是简单的介绍了DiskCache的一下主要操作和用法,并对量化需要用到的行情信息读写进行了展示,作为基本应用已经足够用了,基本操作也就这些了。在使用了mysql,sqlite,txt,redis,综合速度和持久化,个人更倾向于DiskCache。
量化交易,数据先行。稳定高效的行情是首要的,将日K行情缓存到DiskCache,再获取当日日K并concat成完整日K,这个是我尝试多种方案后,目前最高效的方法。
更多官方API介绍,请移步官方网站进一步学学。
https://grantjenks.com/docs/diskcache/api.html