当前位置:网站首页>【量化交易行情不够快?】一文搞定通过Win10 wsl2 +Ubuntu+redis+pickle实现股票行情极速读写

【量化交易行情不够快?】一文搞定通过Win10 wsl2 +Ubuntu+redis+pickle实现股票行情极速读写

2022-08-10 12:42:00 IT里的交易员


前言

量化交易,行情先行!

对于量化交易,行情数据很重要,可以说很关键。个人做量化,因为网络时延、本地IO开销、电脑速度等原因,获取行情和处理交易的速度和机构托管在机房里的集群交易服务器自然没法比。但,个人量化也可以飞起来,至少比大多数散户可以快很多很多!!

量化交易,行情不快、不准,那可要了命的! 明明量化策划都没问题,可该触发的没触发,不该触发的时候又乱触发,究其原因,都是行情推送惹得祸!

那么,如何实现对行情数据的极速、稳定的访问呢?

笔者之前一直使用Mysql,后来也试过MongoDB,还曾甩开数据库,直接用csv文件读写,但速度都还不够快!直到后来学习到可以将数据缓存到内存里,那速度可真的快得不要不要滴!redis内存数据库的访问速度比mysql快了不止一个等量级,速度胜过各种数据库(没有了IO的开销,直接在内存里读写)。

做量化,行情很重要,自从搭建了这套系统,建立了自己又快有稳的行情库,再也不纠结各种行情获取和速度的问题了!

废话不多说,上方案:

基于个人电脑,我的解决方案是:先给Win10装wsl2,再在wsl2上装Ubuntu,再在Ubuntu上装redis,再让redis自动启动,最后用python 代码开机自动更新redis键值。每日开盘前将日K等行情数据载入redis,完成键值更新。开盘后加上实时行情即可生成当日实时日K,既节约流量消耗,又能提高速度。

提示:以下是本篇文章正文内容,有些细节需要点操作系统功底,我尽可能往简单点说。不会的也没关系,照着步骤操作就是。

一、准备环境分四步

1.1 给Win10装wsl2

硬件开启虚拟化

WSL(Windows Subsystem for Linux)是Windows推出的可让开发人员不需要安装虚拟机(vmware,virtbox)或者设置双系统启动就可以原生支持运行GNU/Linux的系统环境,简称WSL子系统。目前最新的版本是WSL2,在原先的基础上提高了文件系统的性能并添加了完全的的系统调用支持。WSL2使用全新体系架构使其能真正的运行一个Linux内核。

WSL2 是基于Hyper-V(Hyper-V是微软的一款虚拟化产品)的,所以Windows 机器必须支持虚拟化。打开任务管理器查看CPU选项“虚拟化”有没有启用。未开启的,开启虚拟化需要首先在BIOS里进行设置(各品牌主板进入BIOS的方式及设置方法可百度搜索,找到Intel Virtual Technology的选项点enable即可,现在的电脑一般都支持)
在这里插入图片描述

软件开启虚拟化及安装适用于Linux系统的Windows 子系统

安装虚拟机功能:
在Win10 的“程序与功能”里找到“启用或关闭Windows功能”,在Hyper-V和适用于Linux系统的Windows 子系统前打钩,安装以上两项后重启。
在这里插入图片描述
注意:这里的Win10的版本不能太低,最好在2004以上。通过【Win+R】的快捷键可以快速打开Windows系统的“运行”窗口,然后在这里输入winver,运行后即可看到Windows版本号。

启用虚拟机功能,并将WSL 2 设置为默认版本:
之前的安装完成了WSL。要使用WSL 2 必须先启用“虚拟机平台”可选功能。 计算机需要虚拟化功能才能使用此功能。
以管理员身份打开PowerShell并运行:

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

重启电脑后完成启用WSL 2。

将 WSL 2 设置为默认版本
打开 PowerShell,将 WSL 2 设置为默认版本:

PS C:\Windows\system32> wsl --set-default-version 2
有关与 WSL 2 的主要区别的信息,请访问 https://aka.ms/wsl2
操作成功完成。
PS C:\Windows\system32>

1.2 在wsl2基础上安装Ubuntu

Ubuntu是一个以桌面应用为主的Linux操作系统。前面的如果已经安装完毕,后面就可以进入微软商店Microsoft Store ,搜索Ubuntu,笔者经过比较,最后安装了Ubuntu 20.04.4 LTS。LTS 是 long-term support 的缩写,意为长期支持。有LTS字样一般这个版本比较稳定。

在这里插入图片描述
安装完毕就可以打开,设置密码后(密码最好抄下来,有些人用着用着就忘了)进入如下界面即安装成功。因为我们不使用Ubuntu的图形界面,所以到这里就可以了。这样既高效又不占资源。
在这里插入图片描述

1.3 给Ubuntu安装redis

安装redis,可参考redis官方网站:
Install Redis on Windows | Redis
https://redis.io/docs/getting-started/installation/install-redis-on-windows/

进入Ubuntu的命令界面,执行以下官方指导命令(我只执行了后两步):

curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list

sudo apt-get update
sudo apt-get install redis

安装完毕,将redis作为服务启动

sudo service redis-server start

执行redis-cli,输入ping,回复PONG,即标识redis正常运行。

[email protected]:~$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>

redis的命令操作,各位可以百度搜索先熟悉一下简单操作。不想学也没关系,后面用Python代码进行程序操作。

1.4 设置Win10开机后自动启动wsl2的Ubuntu

键盘Win+r 启动运行,输入shell:startup,转到Windows“启动”目录,新建文件wsl2run_Ubuntu_redis.vbs(文件名自命名,扩展名是vbs就行),并保存以下内容。

rem Msgbox "Win10开机自动启动wsl的Ubuntu,并由其启动redis"
Set ws = CreateObject("Wscript.Shell")
ws.run "wsl -d Ubuntu-20.04 -u root /etc/init.wsl start", vbhide

Ubuntu启动后,会自动加载redis服务,所以redis也就自动启动了。

小结:至此,方案中先给Win10装wsl2,再在wsl2上装Ubuntu,再在Ubuntu上装redis,再让redis自动启动的步骤就算完成了。下面是Python的事儿了。


二、利用Python操作redis读写行情数据

2.1 环境准备(下载和安装第三方包)

文中数据格式都是pandas的dataframe,建议安装Anaconda,提前准备好环境。

下面代码使用到redis和pickle两个库,安装命令如下:

pip install redis
pip install pickle

另,本例子中采集行情数据用到Ashare,请提前下载Ashare.py放到一个目录(我们这里假设都放在D:\pythoncode\)下。

行情采集仅是举例,更多行情采集可参考我的另一篇文章(【数据知多少】一文学懂通过Tushare、AKshare、baostock、Ashare、Pytdx获取股票行情数据(含代码)https://blog.csdn.net/popboy29/article/details/125815775

2.2 爬取行情数据写入redis,并进行读出和删除

这里仅为演示,实操应用代码比较长,恕无法全部展示。但涉及的操作如写入、读出、删除的框架已全部展示,需要扩充应用的,请自行修改。

以下为Python操作redis代码,假设保存在python_run_redis.py里,也放在D:\pythoncode\目录下。

# -*- coding: utf-8 -*-

''' 作者:IT里的交易员_CSDN 用途:将股票行情dataframe数据写入redis,并进行读取和删除。 注意:本文仅为演示,实操应用代码比较长,恕无法全部展示。 '''

# 使用本文代码,需要提前安装以下两个包,并提前下载Ashare包
# pip install redis
# pip install pickle

import time
# time.sleep(5)# 滞后5秒,等待wsl启动Ubuntu 及 redis。仅做测试,可将此行注释。

import redis
import pickle
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=False)
rs = redis.Redis(connection_pool=pool)

# 下载Ashare.py放到和这个文件相同目录下
from Ashare import get_price

# 计时开始
time11 = time.time()

if 1:
    # 提取行情并写入redis
    df=get_price('sh000001',frequency='1d',count=1000)      #支持'1d'日, '1w'周, '1M'月 
    print('上证指数日线行情\n',df)
    print('r.set 将df写入redis')
    df_bytes = pickle.dumps(df)
    rs.set('df', df_bytes)
    
if 1:  
    # 遍历并redis数据库
    rs_keys=rs.scan_iter()
    for key in rs_keys:
        print('redis现有键',key)

        if 1:
            # 读取键值
            df_bytes_from_redis = rs.get(key)
            if not df_bytes_from_redis is None:
                df = pickle.loads(df_bytes_from_redis)
                print('提取redis现有键值到df',df)
        if 1:
            # 删除键值
            rs.delete(key)
            print('redis现有键',key,'已删除')    
    
# 计时结束 
time21 = time.time()
print("Python操作redis耗时:",time21-time11,'秒')

经测试,写入、读出及删除结果如下:
1.采集1000条上证指数日线行情并写入redis,结果如下:

上证指数日线行情
                 open      high       low     close        volume

2018-06-27  2842.396  2854.258  2798.800  2813.178  1.294208e+10
2018-06-28  2799.904  2825.987  2782.446  2786.897  1.183579e+10
2018-06-29  2789.811  2848.372  2782.381  2847.418  1.256717e+10
2018-07-02  2841.580  2845.680  2756.815  2775.557  1.370350e+10
2018-07-03  2774.570  2786.888  2722.449  2786.888  1.424985e+10
...              ...       ...       ...       ...           ...
2022-08-01  3246.616  3264.304  3225.553  3259.959  2.922048e+10
2022-08-02  3231.262  3231.262  3155.187  3186.266  3.941762e+10
2022-08-03  3188.891  3217.550  3159.457  3163.674  3.248857e+10
2022-08-04  3179.428  3190.999  3155.704  3189.039  2.608989e+10
2022-08-05  3195.227  3228.886  3184.455  3227.027  2.746837e+10

[1000 rows x 5 columns]
r.set 将df写入redis
Python操作redis耗时: 0.259993314743042

2.从redis读出刚才写入的dataframe数据,结果如下:

redis现有键 b'df'
提取redis现有键值到df                 open      high       low     close        volume

2018-06-27  2842.396  2854.258  2798.800  2813.178  1.294208e+10
2018-06-28  2799.904  2825.987  2782.446  2786.897  1.183579e+10
2018-06-29  2789.811  2848.372  2782.381  2847.418  1.256717e+10
2018-07-02  2841.580  2845.680  2756.815  2775.557  1.370350e+10
2018-07-03  2774.570  2786.888  2722.449  2786.888  1.424985e+10
...              ...       ...       ...       ...           ...
2022-08-01  3246.616  3264.304  3225.553  3259.959  2.922048e+10
2022-08-02  3231.262  3231.262  3155.187  3186.266  3.941762e+10
2022-08-03  3188.891  3217.550  3159.457  3163.674  3.248857e+10
2022-08-04  3179.428  3190.999  3155.704  3189.039  2.608989e+10
2022-08-05  3195.227  3228.886  3184.455  3227.027  2.746837e+10

[1000 rows x 5 columns]
Python操作redis耗时: 0.027001142501831055

3.删除刚才的数据,结果如下:

redis现有键 b'df'
redis现有键 b'df' 已删除
Python操作redis耗时: 0.01200413703918457

2.3 开机启动Python脚本

键盘Win+r 启动运行,输入shell:startup,转到Windows“启动”目录,新建文件python_run_redis.bat(文件名自命名,扩展名是bat,此为Windows的批处理文件。和之前的vbs不同,请注意!),并保存以下内容。

python D:\pythoncode\python_run_redis.py

注意:要开机自运行,为了保证效果,在python_run_redis.py里将这行注释去掉,如下:
time.sleep(5)# 滞后5秒,等待wsl启动Ubuntu 及 redis。仅做测试,可将此行注释。

小结:至此,方案中电脑开机运行Python 写入日K数据到redis也完成了。


至于一次性将所有品种的各种周期的行情加载到redis,数据量太大,代码也贼复杂。另外,开盘后将历史行情加上实时行情即可生成当日实时日K的方法,也比较复杂。

不过这些都是实现了。篇幅有限,今天先说到这里。各位先跑起来再说!

总结

经测试,将所有股票日K写入redis耗时: 451.9708275794983 秒(这个有采集时长,如果每日盘后下载,通过本地加载应给更快。)不过无所谓,盘前9分钟而已,只要每日定时开机时间,比如9点,完全可以搞定以上操作。

另测试,将redis历史行情结合当日行情,合成生成全量股票代码当日实时日K数据并计算指标耗时: 0.3719971179962158 秒(这个神了,速度杠杠滴!)。

有人怀疑这个速度?哈哈,因为我用的行情不是文中举例的那个,其它几个也不是。又有人说了,量化软件都提供tick行情了,谁还用这个方案?那只能说谁用谁知道。每个tick都在线获取数据,那网络开销,CPU开销,估计跑上几个策略就把电脑累趴了。所以提前缓存到本地才是王道!而本地,只有内存数据库速度才是No1!

这版个人版的极速解决方案,我也是探索了很长时间。希望对大家有帮助!

原网站

版权声明
本文为[IT里的交易员]所创,转载请带上原文链接,感谢
https://blog.csdn.net/popboy29/article/details/126189105