量化交易,我们需要经常性的处理行情数据,每次都在线提取数据,量大就容易造成时延大,影响效率。而且行情数据逻辑比较简单,其实使用csv也是可以的,因为其一次写入即可,几乎不会更新,虽然量大,但没有复杂的表关联,所以关系数据库,如MySQL在这种场景下反而会造成存储空间占用多、读写慢,影响效率。而ClickHouse主要用于在线分析处理查询(OLAP),具有高效的数据压缩、向量引擎、列式存储特性,非常适合金融行情数据存储。
下面我们就来说说怎们使用ClickHouse。
提示:以下是本篇文章正文内容,下面案例可供参考
ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的用于在线分析处理查询(OLAP :Online Analytical Processing)MPP架构的列式存储数据库(DBMS:Database Management System),能够使用 SQL 查询实时生成分析数据报告。ClickHouse的全称是Click Stream,Data WareHouse。
官网如下:Fast Open-Source OLAP DBMS - ClickHouse https://clickhouse.com/
如何装Ubuntu?如何在Win10操作系统装Ubuntu?
【量化交易行情不够快?】一文搞定通过Win10 wsl2 +Ubuntu+redis+pickle实现股票行情极速读写_IT里的交易员的博客-CSDN博客_redis 量化
https://blog.csdn.net/popboy29/article/details/126189105
假定我们已安装了Ubuntu,进入命令行模式,依次输入如下命令(看完再安装,以免踩坑):
sudo apt-get install apt-transport-https ca-certificates dirmngr
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 8919F6BD2B48D754
echo "deb https://packages.clickhouse.com/deb stable main" | sudo tee /etc/apt/sources.list.d/clickhouse.list
sudo apt-get update
sudo apt-get install -y clickhouse-server clickhouse-client
sudo service clickhouse-server start
clickhouse-client # or "clickhouse-client --password" if you set up a password.
浏览器输入127.0.0.1:8123,显示“Ok.” 如下,则表示服务启动成功。
如安装sudo apt-get install -y clickhouse-server clickhouse-client过程中出现如下错误:
Connection failed [IP: 91.189.91.38 80] E: Failed to fetch…
解决办法:修改DNS为8.8.8.8即可
方法如下:sudo vi /etc/resolv.conf
修改后保存,再运行安装命令即可。
直接打开使用会提示:
认证失败:密码不正确或没有这个用户名
Code:516. Authentication failed: password is incorrect or there is no user with such name.
我们需要编辑检查以下步骤。
输入以下命令编辑users.xml
sudo vim /etc/clickhouse-server/users.xml
按键盘insert键,进入编辑状态,将如下代码粘贴在标签里,添加ckuser用户,如下图:
<ckuser>
<password>house123password>
<networks incl="networks" replace="replace">
<ip>::/0ip>
networks>
<profile>defaultprofile>
<quota>defaultquota>
ckuser>
在按键盘Esc键,输入":",看到左下角出现冒号后输入wq!,回车后保存退出。
输入以下命令,重启clickhouse
sudo service clickhouse-server restart
在官网下载安装客户端,并选择菜单“数据库” - >“新建数据库连接”,如下图,输入用户名和密码。
https://dbeaver.io/download/
使用
注意到可以使用两个端口,8123 和 9000 分别接收 http 协议和tcp协议。
如果用 jdbc 连接,端口为 8123
如果用 driver 连接,端口为 9000
使用前记着先安装python包clickhouse_driver
pip install clickhouse_driver
from clickhouse_driver import Client
client = Client(host='127.0.0.1', port=9000, database='HQ', user='ckuser' ,password='house123')
sql = 'DROP DATABASE HQ'
res = client.execute(sql)
print('DROP DATABASE',res)
sql = 'CREATE DATABASE IF NOT EXISTS HQ'
res = client.execute(sql)
print('CREATE DATABASE',res)
sql = '''
CREATE TABLE IF NOT EXISTS HQ.600000SH
(
code String,
trade_time DateTime('Asia/Shanghai'),
open Nullable(Float32),
close Nullable(Float32),
high Nullable(Float32),
low Nullable(Float32),
last Nullable(Float32),
volume Nullable(Float64),
amount Nullable(Float64)
)
ENGINE = ReplacingMergeTree()
ORDER BY (trade_time, code)
'''
res = client.execute(sql)
print('CREATE TABLE',res)
sql = 'SHOW TABLES'
res = client.execute(sql)
print('SHOW TABLES',res)
显示结果如下,说明代码正常
DROP DATABASE []
CREATE DATABASE []
CREATE TABLE []
SHOW TABLES [(‘600000SH’,)]
from clickhouse_driver import Client
client = Client(host='127.0.0.1', port=9000, database='HQ', user='ckuser' ,password='house123')
if 0:
# 删除名为HQ的数据库
sql = 'DROP DATABASE HQ'
res = client.execute(sql)
print('DROP DATABASE',res)
if 0:
# 建立名为HQ的数据库
sql = 'CREATE DATABASE IF NOT EXISTS HQ'
res = client.execute(sql)
print('CREATE DATABASE',res)
def creat_hq_table(code):
# 在HQ数据库下建立code的数据表
sql = 'CREATE TABLE IF NOT EXISTS HQ.'+code
sql = sql+'''
(
code String,
trade_time DateTime('Asia/Shanghai'),
open Nullable(Float32),
close Nullable(Float32),
high Nullable(Float32),
low Nullable(Float32),
volume Nullable(Float64),
)
ENGINE = ReplacingMergeTree()
ORDER BY (trade_time, code)
'''
res = client.execute(sql)
print('CREATE TABLE',res)
def drop_hq_table(code):
# 删除HQ数据库下code的数据表
sql = 'DROP TABLE HQ.'+code
res = client.execute(sql)
print('DROP TABLE',res)
if 0:
# 显示所有数据表
sql = 'SHOW TABLES'
res = client.execute(sql)
print('SHOW TABLES',res)
# ==============以下为读写操作=================
from Ashare import *
import pandas as pd
import re,time
def read_sql(sql):
data, columns = client.execute(sql, columnar=True, with_column_types=True)
df = pd.DataFrame({re.sub(r'\W', '_', col[0]): d for d, col in zip(data, columns)})
return df.round(2)
def get_type_dict(tb_name):
# 从数据表提取数据到dataframe
sql = f"select name, type from system.columns where table='{tb_name}';"
df = read_sql(sql)
df = df.set_index('name')
type_dict = df.to_dict('dict')['type']
return type_dict
def to_sql(df, tb_name):
# 将dataframe写入数据表
type_dict = get_type_dict(tb_name)
columns = list(type_dict.keys())
# 类型处理
for i in range(len(columns)):
col_name = columns[i]
col_type = type_dict[col_name]
if 'Date' in col_type:
df[col_name] = pd.to_datetime(df[col_name])
elif 'Int' in col_type:
df[col_name] = df[col_name].astype('int')
elif 'Float' in col_type:
df[col_name] = df[col_name].astype('float')
elif col_type == 'String':
df[col_name] = df[col_name].astype('str').fillna('')
# df数据存入clickhouse
cols = ','.join(columns)
data = df.to_dict('records')
client.execute(f"INSERT INTO {tb_name} ({cols}) VALUES", data, types_check=True)
# ===============表格美化输出===============
def df_table(df,index):
import prettytable as pt
#利用prettytable对输出结果进行美化,index为索引列名:df_table(df,'market')
tb = pt.PrettyTable()
df = df.reset_index(drop = True)
tb.add_column(index,df.index)
for col in df.columns.values:#df.columns.values的意思是获取列的名称
tb.add_column(col, df[col])
print(tb)
if __name__ == "__main__":
# 1.过Ashare获取数据
print('开始提取K线数据')
from Ashare import *
code = '600000SH'
df_data=get_price('SH600000',frequency='1d',count=10000) #frequency='1d' 表是获取日K,count=1000,表示获取1000根K线
# print('Ashare行情获取\n',df_data)
# 由于提取数据列里没有这个,手动补充下,否则数据库写入报错
df_data['code'] = code
df_data['trade_time'] = df_data.index
df_table(df_data,'df_data')
# 2. 测试计时开始,测试哪个就把if 后面的0改为1即可,其它改成0。
time1 = time.time()
print('建表、写、读操作开始...')
if 0:
drop_hq_table(code)
creat_hq_table(code)
if 0:
to_sql(df_data, code)
if 1:
sql = 'select * from '+code
df = read_sql(sql)
time2 = time.time()
print("读耗时:",time2-time1,'秒')
# 建表、写、读耗时: 1.5301368236541748 秒(5148条行情记录)
df_table(df.tail(20),code)
建表、写、读耗时: 1.5301368236541748 秒(5418条行情记录)
单纯读取5418行记录,读耗时: 0.23186087608337402 秒。
通常我们都希望可以直接开机启动,所以我们这里补充开机启动操作方法。
1、修改启动文件,需要使用超级管理员权限,如下:
sudo vim /etc/init.wsl
2、进入界面后按键盘Insert,插入如下内容:
sudo service clickhouse-server start
3、然后按键盘Esc键,输入:,左下角出现冒号,输入wq!后回车即可返回到命令符界面,下次开机就可以自动启动clickhouse服务。
MySQL VS ClickHouse
Clickhouse优缺点及性能情况_dongcheng_2015的博客-CSDN博客_clickhouse优点缺点
https://blog.csdn.net/dongcheng_2015/article/details/119898798