百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

【手把手教你】搭建自己的量化分析数据库

toyiye 2024-06-21 12:20 8 浏览 0 评论

引 言

量化交易的分析基础是数据,包括股票历史交易数据、上市公司基本面数据、宏观和行业数据等。随着信息流量的日益膨胀,学会获取、查询和加工数据信息变得越来越重要。对于鼓捣量化交易的人来说,怎么能说不会玩数据库呢?目前常用的开源(免费)数据库有MySQL、Postgresql 、Mongodb 和 SQLite (Python自带),在2018-2019年DB-Engines 排行榜上位居前十(见下图),可见其使用量和受欢迎程度较高。这几个数据库各有自己的特点和适用环境,关于该学习哪一个或如何学习网上有很多相关资料。本文主要为大家简单介绍如何使用 Python 操作 Postgresql 数据库(其他数据库类似),利用 psycopg2 和 sqlalchemy 实现 postgresql 与 pandas 的 dataframe 进行交互,一步步搭建自己的量化分析数据库。

PostgreSQL的安装与使用

安装 PostgreSQL。到其官网选择适合自己电脑配置的版本下载安装即可(下载地址),安装过程除了设置密码,其他可选择全部默认,如实在不会可参考CSDN上的文章:PostgreSQL安装详细步骤(windows)。安装完之后在安装目录里还可以看到pgAdmin4,这个是自带的数据库图形化工具,最新版是Web 应用程序,有点类似 Python 的 Jupyter Notebook,可用来查看和操作postgresql 数据库。

Python上安装psycopg2 和 sqlalchemy 库。psycopg2 是 Python 连接PostgreSQL数据库的接口,sqlalchemy 应用更广泛,可连接数据库(MySQL, SQLite, PostgreSQL),尤其是对于 pandas 的dataframe型数据,操作起来十分方便。关于这两个 python 库的介绍网上有很多,这里不详细展开,在cmd上使用pip install xxx 进行安装即可。

1实例应用

首先,使用 tushare 获取3000多只股票行情数据到本地,使用psycopg2 和 sqlalchemy 为接口,将数据存入本地PostgreSQL数据库中,方便进一步查询和操作。

#先引入后面分析、可视化等可能用到的库
import tushare as ts
import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
#正常显示画图时出现的中文和负号
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
#设置token
token='输入你的token'
pro = ts.pro_api(token)
数据获取函数,默认时间可以随时改动
#如果报错,把tushare升级到最新
def get_data(code,start='20190101',end='20190425'):
 df=ts.pro_bar(ts_code=code, adj='qfq', start_date=start, end_date=end)
 return df
交易代码获取函数,获取最新交易日的代码
#获取当前交易日最新的股票代码和简称
def get_code():
 codes = pro.stock_basic(list_status='L').ts_code.values
 return codes

插入PostgreSQL 数据库操作,函数里使用了try...except...pass是为了避免某些数据出错导致程序崩溃。

from sqlalchemy import create_engine
import psycopg2
engine = create_engine('postgresql+psycopg2://postgres:123456@localhost:5432/postgres')
def insert_sql(data,db_name,if_exists='append'):
 #使用try...except..continue避免出现错误,运行崩溃
 try:
 data.to_sql(db_name,engine,index=False,if_exists=if_exists)
 #print(code+'写入数据库成功')
 except:
 pass

由于行情数据量庞大,下载比较慢,先下载20190101至20190425期间日交易数据,后续再不断更新。

#下载20190101-20190425数据并插入数据库stock_data
#此步骤比较耗费时间,大致25-35分钟左右
for code in get_code():
 data=get_data(code)
 insert_sql(data,'stock_data')
#读取整张表数据
df=pd.read_sql('stock_data',engine)
print(len(df))
#输出结果:270998
#选取ts_code=000001.SZ的股票数据
df=pd.read_sql("select * from stock_data where ts_code='000001.SZ'",engine)
print(len(df))
构建一个数据更新函数,可以下载和插入其他时间周期的数据。2018年1月1日至2019年4月25日,数据就已达到108万条。
#更新数据或下载其他期间数据
def update_sql(start,end,db_name):
 from datetime import datetime,timedelta
 for code in get_code():
 data=get_data(code,start,end)
 insert_sql(data,db_name)
 print(f'{start}:{end}期间数据已成功更新')
#下载20180101-20181231期间数据
#只需运行一次,不再运行后可以注释掉
#下载数据比较慢,需要20-35分钟左右
start='20180101'
end='20181231'
db_name='stock_data'
#数据下载和存入数据库
update_sql(start,end,db_name)
#使用pandas的read_sql读取数据
df_all_data=pd.read_sql('stock_data',engine)
print(len(df_all_data))
#输出结果:1087050
#查看交易代码和交易日期个数
print(len(df_all_data.ts_code.unique()))
print(len(df_all_data.trade_date.unique()))
#输出结果:3604;319
d=df_all_data.trade_date.unique()
print(d.max())
print(d.min())
2019-04-25T00:00:00.000000000
2018-01-02T00:00:00.000000000
#获取交易日2019年4月25日数据
pd.read_sql("select * from stock_data where trade_date='2019-04-25' ",engine).head() 

构建数据查询和可视化函数:
def plot_data(condition,title):
 from pyecharts import Bar
 from sqlalchemy import create_engine
 engine = create_engine('postgresql+psycopg2://postgres:123456@localhost:5432/postgres')
 data=pd.read_sql("select * from stock_data where+"+ condition,engine)
 count_=data.groupby('trade_date')['ts_code'].count()
 attr=count_.index
 v1=count_.values
 bar=Bar(title,title_text_size=15)
 bar.add('',attr,v1,is_splitline_show=False,linewidth=2)
 return bar
查询股价低于2元个股数据分布
c1="close<2"
t1="股价低于2元个股时间分布"
plot_data(c1,t1)

查询股价日涨幅超过9.5%个股数据分布:

c2="pct_chg>9.5"
t2="股价涨幅超过9.5%个股时间分布"
plot_data(c2,t2)

查询股价日跌幅超过-9.5%个股数据分布:

c3="pct_chg<-9.5"
t3="股价跌幅超过-9.5%个股时间分布"
plot_data(c3,t3)

结合选股策略对数据库进行查询和提取数据:

#筛选代码
#获取当前交易的股票代码和名称
def get_new_code(date):
 #获取当前所有交易股票代码
 df0 = pro.stock_basic(exchange='', list_status='L')
 df1 =pro.daily_basic(trade_date=date)
 df=pd.merge(df0,df1,on='ts_code')
 #剔除2017年以后上市的新股次新股
 df=df[df['list_date'].apply(int).values<20170101]
 #剔除st股
 df=df[-df['name'].apply(lambda x:x.startswith('*ST'))]
 #剔除动态市盈率为负的
 df=df[df.pe_ttm>0]
 #剔除大市值股票
 df=df[df.circ_mv<10**5]
 #剔除价格高于20元股票
 #df=df[df.close<20]
 codes=df.ts_code.values
 return codes
len(get_new_code('20190425'))
#输出结果:46
import talib as ta
#20日均线交易策略
def find_stock(date):
 f_code=[]
 for code in get_new_code(date):
 try:
 data=df_all_data.loc[df_all_data.ts_code==code].copy()
 data.index=pd.to_datetime(data.trade_date)
 data=data.sort_index()
 data['ma_20']=ta.MA(data.close,timeperiod=20)
 if data.iloc[-1]['close']>data.iloc[-1]['ma_20']:
 f_code.append(code)
 except:
 pass
 return f_code
fs=find_stock('20190305')
print(f'筛选出的股票个数:{len(fs)}')
if fs:
 df_find_stocks=pd.DataFrame(fs,columns=['ts_code'])
 #将选出的股票存入数据库,如果表已存在,替换掉,相当于每次更新
 insert_sql(df_find_stocks,'find_stocks',if_exists='replace')
 print('筛选的股票已入库')
筛选出的股票个数:9
筛选的股票已入库
#查看数据库中筛选的股票池
codes=pd.read_sql('find_stocks',engine)
codes=codes.values.tolist()
codes=[c[0] for c in codes]
#print(codes)

对筛选的股票作进一步分析:

select_data=pd.DataFrame()
for code in codes:
 try:
 df_= df_all_data[df_all_data.ts_code.values==code]
 df_.index=pd.to_datetime(df_.trade_date)
 df_=df_.sort_index()
 select_data[code]=df_.close
 except:
 pass
select_data.fillna(method='ffill',inplace=True)
select_data.tail()
ret=select_data.apply(lambda x:x/x.shift(1)-1)
ret=ret.dropna()
ret.tail()
prod_ret=ret.apply(lambda x:(1+x).cumprod())
prod_ret.plot(figsize=(12,5))
plt.xlabel('',fontsize=15)
plt.title('股票池累计净值',size=15)
ax = plt.gca() 
ax.spines['right'].set_color('none') 
ax.spines['top'].set_color('none') 
plt.show()

#根据代码从数据库中获取数据
def get_data_from_sql(code):
 from sqlalchemy import create_engine
 engine = create_engine('postgresql+psycopg2://postgres:123456@localhost:5432/postgres')
 data=pd.read_sql(f"select * from stock_data where ts_code='{code}'",engine)
 data.index=pd.to_datetime(data.trade_date)
 data=data.sort_index()
 #计算20日均线
 data['ma20']=data.close.rolling(20).mean()
 return data

利用20日均线交易策略,搭建数据查询和可视化函数kline_plot(),完整代码将分享在知识星球上。对选出的股票日K线、20日均线、成交量、买入(buy)和卖出(sell)信号进行可视化。

kline_plot('002790.SZ')

kline_plot('300573.SZ')

结语

数据库操作其实要学的东西还很多,本文旨在抛砖引玉,简单介绍使用Python对PostgreSQL数据库与dataframe型数据进行交互,一步步搭建自己的量化分析数据库。由于文中用到的数据仅为百万条左右,实际上使用excel的csv来读写也很快,并且比较直观,但随着数据的不断增多,要建立自己完善的量化分析系统,数据库的学习就显得尤为重要了。注意,文中所提及选股方式和股票代码仅作为示例应用,不构成任何投资建议。

关于Python金融量化


专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取30多g的量化投资视频资料、公众号文章Python完整源码、量化投资前沿分析框架,与博主直接交流、结识圈内朋友等。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码