打造自己的金融数据库(python+tushare)

简要介绍

获取金融数据量化交易必不可少的步骤,目前有许多在线的金融数据库,但是每次使用时都要到云端获取数据效率太低,因此本文将结合tushare的api与python手把手教你搭建本地金融数据库。
tushare是一个金融大数据开放社区 ,免费提供各类金融数据和区块链数据。python也是各类领域中数据处理的常用语言。

前期准备

首先需要安装python,安装了的同学可以跳过。
由于python2不再维护,这里我们需要安装python3。可以直接下载Anaconda来安装python,它会帮你装上各种常用的库,免去很多麻烦。

tushare提供了许多数据接口,但是需要注册后获取token才能调用接口。
可以通过以下链接注册,帮我赚个积分:https://tushare.pro/register?reg=311239
接口需要在python中安装tushare模块,在Anaconda prompt中输入“pip install tushare”后等待安装完成即可。
为了把数据存在本地的数据库,我们选用轻量化的sqlite3作为我们使用的数据库,Anaconda已经帮我们集成好了,可以直接调用。sqlite3不用提前安装,它会以一个“*.db”的格式保存在指定的目录下,方便迁移。

开始

来到最关键的地方了,话不多说,我们直接开始讲代码。

导入库

首先导入需要用到的库,库的说明写在注释中了。

import tushare as ts # tushare
import pandas as pd # 数据分析库,集成了许多常用的操作,比如时间序列分析
import matplotlib.pyplot as plt # 绘图
import sqlite3 # 轻量化的sql数据库

初始化token并获取所有股票代码

为了下载数据,首先需要获得所有股票的代码,tushare的.stock_basic会返回所有的股票代码与上市时间。token需要注册才可以获得>>>性感TOKEN点击就送

pro = ts.pro_api('0441c1c59f7ff1c2ad640c8b345a69ad34e1aeea864004a10046b2ae') # 初始化token
df_hsConst = pro.stock_basic(exchange='', list_status='L') # 获取所有股票的代码
df_hsConst.index = df_hsConst.ts_code # 把股票的代码作为dataframe的index
df_hsConst = df_hsConst.sort_index(ascending=True) # 按顺序重排一下,以上两步不是必须的

建立数据库

通过python提供的sqlite的api接口与数据库建立连接,它会保存在你当前python脚本的工作目录下面。
如果在执行sqlite3.connect时没有数据库,则代码会自动创建一个数据库文件。

adj = 'hfq'
sqlName = "stockData" +adj+".db"
conn=sqlite3.connect(sqlName) # 如果路径里面没有这个数据库,会自动创建
c=conn.cursor()

循环读取数据

tushare提供了pro_bar方法来获取股票数据,使用方法如下:

df_tmpStock = ts.pro_bar(ts_code=ts_code, adj=adj, start_date=start_date, end_date=end_date)

其中ts_code指定了股票代码,adj可以设置是前复权、后复权还是不复权数据,start_date和end_date指定了起始和结束时间。

由于tushare的数据在基础积分下每分钟内最多调取200次,每次4000条数据,因此在数据获取过程中需要一些额外的处理。这里将简单讲解思路,具体代码最后会直接在文末给出。

首先读取df_hsConst中股票的上市时间,如果距离当前时间超过4000,则分批读取。如果数据库中已经有这个股票以前的数据了,则我们只要下未下载的数据即可。通过这样的操作,每天收盘后,只要再运行这个脚本就可以把新的数据加入到数据库中了(但是得注意复权的选项,前复权就不能这么做了)。

我们这里先用轮询的方式一个个查询数据,这样效率最低但是直观。如果想提高效率可以用并行的方式来查询和储存。

运行效果

代码运行时,会把每次获取数据的收盘价画出来。
每次都会将最新获得的数据画出来

最终代码看这里

话不多说,最后的代码看这里。

"""
Created on Sun Oct 13 21:26:39 2019

@author: DJ666
# 数据下载脚本
"""
import tushare as ts
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import sqlite3

def try_get_data(ts_code,start_date,end_date,adj='None',tryCount=0):    
    try:
        #df_tmpStock = pro.daily(ts_code=ts_code, start_date=start_date, end_date=end_date)
        df_tmpStock = ts.pro_bar(ts_code=ts_code, adj=adj, start_date=start_date, end_date=end_date)
    except Exception as e:
        print(e)
        tryCount = tryCount +1
        if tryCount>100:
            return TooManyTry
        df_tmpStock = try_get_data(ts_code,start_date,end_date,tryCount)
    return df_tmpStock
    
# --------TOKEN设置--------
pro = ts.pro_api('你的TOKEN') # 注册下就能拿到token,https://tushare.pro/register?reg=311239

# --------获取所有的股票列表与上市时间--------
df_hsConst = pro.stock_basic(exchange='', list_status='L')
df_hsConst.index = df_hsConst.ts_code
df_hsConst = df_hsConst.sort_index(ascending=True) # 重新排列方便查看

# --------创建数据库--------
adj = 'hfq'
sqlName = "stockData" +adj+".db"
conn=sqlite3.connect(sqlName)#如果路径里面没有这个数据库,会自动创建
c=conn.cursor()

# --------自动下载--------
count = 0
for ii in df_hsConst.index:
    count = count + 1
    print('%s, remain: %2.3f%%' % (ii, 100*count/len(df_hsConst.index)))
    # 判断数据库中当前的股票数据表是否存在,如果存在则更新数据库中最后日期到当前日期的数据,否则添加整个股票数据表
    c.execute("select * from sqlite_master where type = 'table' and name = '" + ii + "'")
    if len(c.fetchall()):
        isTable = True
        c.execute("SELECT MAX(trade_date) FROM '" + ii + "'")
        tmp = c.fetchall()
        startDate = pd.to_datetime(tmp[0][0])+pd.Timedelta(days=1)
        nowDate = pd.to_datetime(pd.datetime.now())
    else:
        isTable = False
        startDate = df_hsConst.loc[ii].list_date
        startDate = pd.to_datetime(startDate)
        nowDate = pd.to_datetime(pd.datetime.now())
        
    tmpDf = nowDate-startDate
    quitFlag = False
    endDate = nowDate
    # 循环读取
    if tmpDf.days>=0:
        newLog = False
        while (True):
            
            if tmpDf.days>3500: # 一次获取4000条的限制
                print('Too many data, need loop, loopping...')
                endDate = startDate+pd.Timedelta(days=3500) # 一次获取4000条的限制
                if endDate >= nowDate:
                    endDate = nowDate
                    quitFlag = True
            else:
                quitFlag = True
            startDateStr = pd.to_datetime(startDate).strftime('%Y%m%d')
            endDateStr = pd.to_datetime(endDate).strftime('%Y%m%d')
            df_tmpStock = try_get_data(ts_code=ii, start_date=startDateStr,
                                       end_date=endDateStr,adj=adj)
            if newLog == False:
                df_Stock = df_tmpStock
                newLog = True # 第一次读取数据则创建该变量
            else: # 否则append到dataframe里
                df_Stock = df_Stock.append(df_tmpStock,ignore_index=True)
            if quitFlag == True:
                break
            startDate = endDate+pd.Timedelta(days=1)
            endDate = nowDate
            tmpDf = nowDate-startDate
            
        df_Stock.index = pd.to_datetime(df_Stock['trade_date']) 
        df_Stock.index = df_Stock.index.strftime('%Y-%m-%d')
        df_Stock = df_Stock.sort_index(ascending=True)
        print('Data Length: '+str(df_Stock.shape[0]))
        
        if isTable == True and not df_Stock.empty:
            pd.io.sql.to_sql(df_Stock,name=ii,
                         con=conn,if_exists='append')
            df_Stock.plot(y="close");
        elif not df_Stock.empty:
            pd.io.sql.to_sql(df_Stock,name=ii,
                         con=conn,if_exists='replace')
            df_Stock.plot(y="close");
        else:
            print('Suspension. Skipped.')   
    else:
         print(ii + ' Newest Data.')
    plt.pause(0.000001)

# --------完成后关闭数据库--------
conn.close()

后续

后续会探讨关于指数的数据分析。

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值