基于tushare的股票数据构建<一>

tushare中提供了很多非常优秀的数据结构,但是并不是所有的数据都对自己有用,这里需要进行构建自己的数据库以方便后续进行数据建模

tushare数据

tushare是完全免费的一个数据源,不只是有股票数据,还有很多期货数据,有着和谐的社区,为了防止有人恶意的申请接口,造成数据拥堵,tushare采用的是注册账号的方式,注册完账号后生成自己的token,之后接口申请的时候带上token就能获取数据。

注册地址:https://tushare.pro/register?reg=261052

积分制度:为了促进维护tushare社区,采用的是积分制度,积分越高具有的权限越大,不过通常注册后送的积分就能够获取到足够的信息了,积分永不消失

数据分类

本次只处理两种类型的数据,一种是基于季度更新数据,另外一种是公司的基本信息数据,进行数据整合与归类

按照季度进行更新的数据主要是关于很多季度报的信息数据,公司的基本信息数据大多都是不怎么变更的信息,比如上市公司所属行业,公司董事等信息。

主要逻辑

数据都是基于tushare上的接口,比如利润表,资产负债表等

前期准备工作:设计好mysql数据库

1从tushare上获取到需要的数据信息

2对数据进行清洗,变换成需要的数据类型等

3将信息整合起来进行存储

需要注意的是单纯的存储信息是比较容易的,但是自己的数据库需要保证信息的准确性与即时性,所以需要对信息进行更新

存储并非一次促成的,可能存储断点续存的需求,所以需要对重复数据进行识别与判定

数据规范表

字段非常多,数据量很大,需要进行数据归类,具有相似结构的数据进行归类存储,这里需要自己事先设计好数据规范表,方便以后进行查询与更改

一下给出我自己的数据规范表,这也是mysql数据的设计方式

按报表数据整合表:这个表是根据数据更新周期为季度的的整合数据,我认为这些数据对我的模型有用
通用字段

  1. 股票代码(ts_code)
    ts_code
  2. 报告日期(end_date)
    report_date
  3. 交易所(jys)
    jys
    财务数据
    主营业务构成
  4. 主营业务来源(bz_item)
    bz_item
  5. 主营业务收入(bz_sales)
    bz_sales
  6. 主营业务利润(bz_profit)
    bz_profit
  7. 主营业务成本(bz_cost)
    bz_cost
  8. 主营业务构成是否有数据(if_have_zyywgc)
    if_have_zyywgc,1表示有,0表示无
    利润表
  9. 基本每股收益(basic_eps)
    basic_eps
  10. 稀释每股收益(diluted_eps)
diluted_eps
  1. 营业总收入(total_revenue)
total_revenue
  1. 营业收入(revenue)
revenue
  1. 营业总成本(total_cogs)
total_cogs
  1. 营业支出(oper_exp)
oper_exp
  1. 营业利润(operate_profit)
operate_profit
  1. 利润总额(total_profit)
total_profit
  1. 所得税费用(income_tax)
income_tax
  1. 净利润-含少数股东损益(n_income)
n_income
  1. 净利润-不含少数股东损益(n_income_attr_p)
n_income_attr_p
  1. 年初未分配利润(undist_profit)
undist_profit
  1. 可分配利润(distable_profit)
distable_profit
  1. 利润表是否有数据(if_have_lrb)
if_have_lrb,1表示有,0表示无
资产负债表
  1. 末期总股本(total_share)
total_share
  1. 为未分配利润(undistr_porfit)
undistr_porfit
  1. 货币资金(money_cap)
money_cap
  1. 应收账款(accounts_receiv)
accounts_receiv
  1. 固定资产(fix_assets)
fix_assets
  1. 无形资产(intan_assets)
intan_assets
  1. 研发支出(r_and_d)
r_and_d
  1. 商誉(goodwill)
goodwill
  1. 资产总计(total_assets)
total_assets
  1. 应付账款(acct_payable)
acct_payable
  1. 应交税费(taxes_payable)
taxes_payable
  1. 资产负债表是否有数据(if_have_zcfzb)
if_have_zcfzb,1表示有,0表示无
现金流量表
  1. 净利润(net_profit)
net_profit
  1. 支付的各项税费(c_paid_for_taxes)
c_paid_for_taxes
  1. 处置固定资产、无形资产、其他长期资产收回的现金净额(n_recp_disp_fiolta)
n_recp_disp_fiolta
  1. 处置子公司及其他营业单位收到的现金净额(n_recp_disp_sobu)
n_recp_disp_sobu
  1. 投资支付现金(c_paid_invest)
c_paid_invest
  1. 取得子公司、及其他营业单位支付的现金净额(n_disp_subs_oth_biz)
n_disp_subs_oth_biz
  1. 汇率变动对现金的影响(eff_fx_flu_cash)
eff_fx_flu_cash
  1. 债务转为资本(conv_debt_into_cap)
conv_debt_into_cap
  1. 现金末期余额(end_bal_cash)
end_bal_cash
  1. 减现金初期余额(beg_bal_cash)
beg_bal_cash
  1. 现金流量表是否有数据(if_have_xjllb)
if_have_xjllb,1表示有,0表示无
市场参考数据
前十大股东
  1. 前十股东名(holder_name)
holder_name
  1. 前十持有数量(hold_amount)
hold_amount
  1. 持有比例(hold_ratio)
hold_ratio
  1. 前十大股东是否有数据(if_have_qsdgd)
if_have_qsdgd,1表示有,0表示无
前十大流通股东
  1. 流通股东名称(holder_name)
lt_holder_name
  1. 持有数量(hold_amount)
lt_hold_amount
  1. 持有比例(lt_hold_ratio)
lt_hold_ratio,数据源网页无法获取,后续计算处理
  1. 前十大流通股东是否有数据(if_have_ltqsdgd)
if_have_ltqsdgd,1表示有,0表示无
概念明细
  1. 股票名称(name)
name
  1. 概念id(id)
gn_id
  1. 概念名称(concept_name)
concept_name
  1. 概念股明细列表是否有数据(if_have_gngmxlb)
if_have_gngmxlb,1表示有,0表示无

以上是基于季度的数据整合,我通过多个接口获取我想要的信息

股票的基本信息也是需要的,比如某股票是属于哪个版块,哪个行业,哪些概念,董事,董秘等,这些都关系到选股的时候需要参考的信息

股票基本数据整合表
股票列表信息

  1. 股票代码(ts_code)
    ts_code
  2. 代码(symbol)
    symbol
  3. 名称(name)
    stock_name
  4. 所在地区(area)
    area
  5. 所属行业(industry)
    Industry
  6. 市场类型(market)
    market
  7. 上市时间(list_date)
    list_date
  8. 是否沪深港通标的(is_hs)
    is_hs,N表示否,H表示沪股通,S表示深沪通
    沪深股通成分股
  9. 沪深港通类型(hs_type)
    hs_type,SH上海,SZ深圳
  10. 纳入沪深港通时间(in_date)
    in_date
  11. 剔除沪深港通时间(out_date)
    out_date
  12. 是否沪深港通最新数据(is_new)
    is_new,1是,0否
  13. 沪深港通数据是否存在(if_have_hsgtcf)
    if_have_hsgtcf,1存在,0不存在
    上市公司基本信息
  14. 法人代表(chairman)
    chairman
  15. 总经理(manager)
    manager
  16. 董秘(secretary)
    secretary
  17. 注册资本(reg_capital)
    reg_capital
  18. 所在省份(province)
    province
  19. 所在城市(city)
    city
  20. 公司简介(introduction)
    introduction
  21. 员工人数(employees)
    employees
  22. 主要业务及产品(main_business)
    main_business
  23. 经营范围(business_scope)
    business_scope
  24. 是否存在上市公司基本信息(if_have_base_info)
    if_have_base_info
  25. 更新日期(up_date)
    up_date

数据获取前的mysql表格创建

mysql表格是基于自己设计的数据规范表而言的,这种一个mysql表57个字段,加上主键id共58个字段,至少我是记不清每个字段的含义以及字段名的,所以需要事先自己定好,并写好注释,方便以后自己查询与维护

CREATE TABLE `quarterly_list` (`id` int(11) NOT NULL AUTO_INCREMENT,`ts_code` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '股票代码',`report_date` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '报告日期',`jys` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '交易所',`bz_item` text CHARACTER SET utf8 COMMENT '主营业务来源',`bz_sales` text CHARACTER SET utf8 COMMENT '主营业务收入',`bz_profit` text CHARACTER SET utf8 COMMENT '主营业务利润',`bz_cost` text CHARACTER SET utf8 COMMENT '主营业务成本',`if_have_zyywgc` int(11) DEFAULT NULL COMMENT '主营业务构成是否有数据',`basic_eps` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '每股基本收益',`diluted_eps` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '稀释每股收益',`total_revenue` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '营业总收入',`revenue` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '营业收入',`total_cogs` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '营业总成本',`oper_exp` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '营业支出',`operate_profit` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '营业利润',`total_profit` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '利润总额',`income_tax` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '所得税费用',`n_income` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '净利润_含少数股东损益',`n_income_attr_p` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '净利润_不含少数股东损益',`undist_profit` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '年初未分配利润',`distable_profit` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '可分配利润',`if_have_lrb` int(11) DEFAULT NULL COMMENT '利润表是否有数据',`total_share` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '总股本',`undistr_porfit` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '未分配利润',`money_cap` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '货币资金',`accounts_receiv` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '应收账款',`fix_assets` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '固定资产',`intan_assets` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '无形资产',`r_and_d` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '研发支出',`goodwill` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '商誉',`total_assets` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '资产总计',`acct_payable` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '应付账款',`taxes_payable` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '应交税费',`if_have_zcfzb` int(11) DEFAULT NULL COMMENT '资产负债表是否有数据',`net_profit` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '净利润',`c_paid_for_taxes` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '支付的各项税费',`n_recp_disp_fiolta` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '处置固定资产、无形资产、其他长期资产收回的现金净额',`n_recp_disp_sobu` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '处置子公司及其他营业单位收到的现金净额',`c_paid_invest` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '投资支付金额',`n_disp_subs_oth_biz` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '取得子公司、及其他营业单位支付的现金净额',`eff_fx_flu_cash` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '汇率变动对现金的影响',`conv_debt_into_cap` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '债务转为资本',`end_bal_cash` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '现金末期余额',`beg_bal_cash` varchar(255) CHARACTER SET utf8 DEFAULT NULL COMMENT '减现金初期余额',`if_have_xjllb` int(11) DEFAULT NULL COMMENT '现金流量表是否有数据',`holder_name` text CHARACTER SET utf8 COMMENT '前十股东',`hold_amount` text CHARACTER SET utf8 COMMENT '前十持有量',`hold_ratio` text CHARACTER SET utf8 COMMENT '持有比例',`if_have_qsdgd` int(11) DEFAULT NULL COMMENT '前十大股东是否有数据',`lt_holder_name` text CHARACTER SET utf8 COMMENT '流通股东名称',`lt_hold_amount` text CHARACTER SET utf8 COMMENT '流通股东持有量',`lt_hold_ratio` text CHARACTER SET utf8 COMMENT '流通股东持有比例',`if_have_ltqsdgd` int(11) DEFAULT NULL,`name_stock` varchar(255) CHARACTER SET utf8 DEFAULT NULL,`gn_id` text CHARACTER SET utf8 COMMENT '概念id',`concept_name` text CHARACTER SET utf8 COMMENT '概念名称',`if_have_gngmxlb` int(11) DEFAULT NULL COMMENT '概念明细列表是否有数据',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

股票基本信息配置表

CREATE TABLE `stock_base_info` (`id` int(11) NOT NULL AUTO_INCREMENT,`ts_code` varchar(255) DEFAULT NULL COMMENT '股票标识',`symbol` varchar(255) DEFAULT NULL COMMENT '股票代码',`stock_name` varchar(255) DEFAULT NULL COMMENT '股票名称',`area` varchar(255) DEFAULT NULL COMMENT '所在地区',`industry` varchar(255) DEFAULT NULL COMMENT '所属行业',`market` varchar(255) DEFAULT NULL COMMENT '市场类型',`list_date` varchar(255) DEFAULT NULL COMMENT '上市时间',`is_hs` varchar(255) DEFAULT NULL COMMENT '是否沪深港通标的',`hs_type` varchar(255) DEFAULT NULL COMMENT '沪深港通类型',`in_date` varchar(255) DEFAULT NULL COMMENT '纳入沪深港通时间',`out_date` varchar(255) DEFAULT NULL COMMENT '剔除沪深港通时间',`is_new` varchar(255) DEFAULT NULL COMMENT '是否沪深港通最新数据',`if_have_hsgtcf` int(255) DEFAULT NULL COMMENT '沪深港通数据是否存在',`chairman` varchar(255) DEFAULT NULL COMMENT '法人代表',`manager` varchar(255) DEFAULT NULL COMMENT '总经理',`secretary` varchar(255) DEFAULT NULL COMMENT '董秘',`reg_capital` varchar(255) DEFAULT NULL COMMENT '注册资本',`province` varchar(255) DEFAULT NULL COMMENT '所在省份',`city` varchar(255) DEFAULT NULL COMMENT '所在城市',`introduction` text COMMENT '公司简介',`employees` varchar(255) DEFAULT NULL COMMENT '员工人数',`main_business` text COMMENT '主要业务及产品',`business_scope` text COMMENT '经营范围',`if_have_base_info` int(11) DEFAULT NULL COMMENT '是否存在上市公司基本信息',`up_date` date DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3617 DEFAULT CHARSET=utf8;

mysql表格设计完成

导包与配置

这里需要用到pndas进行数据处理,时间社会,tushare导入,下载配置,配置mysql的信息

import tushare as ts
import pandas as pd
from datetime import datetime
import pymysqlLINK_MYSQL = {'host': '127.0.0.1','port': 3306,'user': 'root','passwd': 'Python_123456','charset': 'utf8','db': 'stock',  # 自己的mysql库
}ts.set_token('填写你自己的token')
pro = ts.pro_api()

不知道怎么获取token的可以直接进入到tushare主页里面的说明,或者参考本人的前一篇文章

需要定义一个判定函数,不是每次从接口中都返回自己期望的数据,有时候因为网络延迟等原因造成数据丢失也是很正常的,有时候别人本来就没有更新数据,当然返回的是空所以需要对获取的数据进行判定

# 定义对获取数据进行判定的函数
def judge_data(data):# 判定数据是否为空 如果为空则返回falsereturn False if len(data) == 0 else True

用于判定返回的data数据数据是否存储

按季度更新的信息整合

主营业务构成

通过主营业务构成接口进行数据获取

# 定义获取 财务数据 主营业务构成
def get_finance_main_business(stocks_label, period):# 进行数据获取df = pro.fina_mainbz(ts_code=f'{stocks_label}', type='P', period=period,fields='bz_item,bz_sales,bz_profit,bz_cost,update_flag')  # 用于标识是否更新过# 进行数据判别if judge_data(df):# 表示有数据return {'bz_item': '||'.join(list(df.bz_item.values)),'bz_sales': '||'.join([str(i) for i in list(df.bz_sales.values)]),'bz_profit': '||'.join([str(i) for i in list(df.bz_profit.values)]),'bz_cost': '||'.join([str(i) for i in list(df.bz_profit.values)]),'if_have_zyywgc': 1}else:# 表示数据为空return {'bz_item': None, 'bz_sales': None, 'bz_profit': None, 'bz_cost': None,'if_have_zyywgc': 0}  # 最后一个用来标注该表没有获取到数据

当获取具体的某个股票信息的主营业务信息的时候,这里需要进行数据的拼接,一个公司的主营业务可以有多个,个数上并不是一定的,这里采用的是字符串拼接的方式,把字段bz_item等多条字段使用||进行拼接成新的字符串存储

利润表

获取利润表信息

# 获取 财务数据 利润表
def get_finance_profit_statement(stocks_label, period):# 进行数据获取df = pro.income(ts_code=f'{stocks_label}', period=period,fields='basic_eps,diluted_eps,total_revenue,revenue,total_cogs,oper_exp,operate_profit,total_profit,income_tax,n_income,n_income_attr_p,undist_profit,distable_profit,update_flag')  # 用于标识是否更新过if judge_data(df):if len(df) > 1:  # 一般而言修正信息只会有一次,但是如果存在多次这里可能执行会报错,暂时不考虑这个bugdf = df.loc[df.update_flag == '1']  # 只获取修正信息return {'basic_eps': str(df.loc[0, 'basic_eps']),'diluted_eps': str(df.loc[0, 'diluted_eps']),'total_revenue': str(df.loc[0, 'total_revenue']),'revenue': str(df.loc[0, 'revenue']),'total_cogs': str(df.loc[0, 'total_cogs']),'oper_exp': str(df.loc[0, 'oper_exp']),'operate_profit': str(df.loc[0, 'operate_profit']),'total_profit': str(df.loc[0, 'total_profit']),'income_tax': str(df.loc[0, 'income_tax']),'n_income': str(df.loc[0, 'n_income']),'n_income_attr_p': str(df.loc[0, 'n_income_attr_p']),'undist_profit': str(df.loc[0, 'undist_profit']),'distable_profit': str(df.loc[0, 'distable_profit']),'if_have_lrb': 1,}else:return {'basic_eps': None, 'diluted_eps': None, 'total_revenue': None, 'revenue': None, 'total_cogs': None,'oper_exp': None, 'total_profit': None, 'income_tax': None, 'n_income': None, 'n_income_attr_p': None,'undist_profit': None, 'distable_profit': None, 'if_have_lrb': 0}

对需要的字段进行字符串化的处理,这样方便mysql使用字符串进行存储,如果后续需要用到的时候直接可以对原数据进行类型的强转就行了

资产负债表

获取资产负债表信息

# 获取 财务数据 资产负债表
def get_finance_balance_sheet(stocks_label, period):# 获取数据 数据可能一次出来两条df = pro.balancesheet(ts_code=f'{stocks_label}', period=period,fields='total_share,undistr_porfit,money_cap,accounts_receiv,fix_assets,intan_assets,r_and_d,goodwill,total_assets,acct_payable,taxes_payable,update_flag')  # 用于标识是否更新if judge_data(df):if len(df) > 1:df = df.loc[df.update_flag == '1']return {'total_share': str(df.loc[1, 'total_share']),'undistr_porfit': str(df.loc[1, 'undistr_porfit']),'money_cap': str(df.loc[1, 'money_cap']),'accounts_receiv': str(df.loc[1, 'accounts_receiv']),'fix_assets': str(df.loc[1, 'fix_assets']),'intan_assets': str(df.loc[1, 'intan_assets']),'r_and_d': str(df.loc[1, 'r_and_d']),'goodwill': str(df.loc[1, 'goodwill']),'total_assets': str(df.loc[1, 'total_assets']),'acct_payable': str(df.loc[1, 'acct_payable']),'taxes_payable': str(df.loc[1, 'taxes_payable']),'if_have_zcfzb': 1}else:return {'total_share': None, 'undistr_porfit': None, 'money_cap': None, 'accounts_receiv': None,'fix_assets': None, 'intan_assets': None, 'r_and_d': None, 'goodwill': None, 'total_assets': None,'acct_payable': None, 'taxes_payable': None, 'if_have_zcfzb': 0}

获取资产负债表信息,更新思路雷同

现金流量表

获取现金流量表信息

# 获取 财务数据 现金流量表
def get_cash_flow_list(stocks_label, period):# 获取数据df = pro.cashflow(ts_code=f'{stocks_label}', period=period,fields='net_profit,c_paid_for_taxes,n_recp_disp_fiolta,n_recp_disp_sobu,c_paid_invest,n_disp_subs_oth_biz,eff_fx_flu_cash,conv_debt_into_cap,end_bal_cash,beg_bal_cash,update_flag')if judge_data(df):if len(df) > 1:  # 获取更新后的数据df = df = df.loc[df.update_flag == '1']return {'net_profit': str(df.loc[0, 'net_profit']),'c_paid_for_taxes': str(df.loc[0, 'c_paid_for_taxes']),'n_recp_disp_fiolta': str(df.loc[0, 'n_recp_disp_fiolta']),'n_recp_disp_sobu': str(df.loc[0, 'n_recp_disp_sobu']),'c_paid_invest': str(df.loc[0, 'c_paid_invest']),'n_disp_subs_oth_biz': str(df.loc[0, 'n_disp_subs_oth_biz']),'eff_fx_flu_cash': str(df.loc[0, 'eff_fx_flu_cash']),'conv_debt_into_cap': str(df.loc[0, 'conv_debt_into_cap']),'end_bal_cash': str(df.loc[0, 'end_bal_cash']),'beg_bal_cash': str(df.loc[0, 'beg_bal_cash']),'if_have_xjllb': 1}else:return {'net_profit': None, 'c_paid_for_taxes': None, 'n_recp_disp_fiolta': None, 'n_recp_disp_sobu': None,'c_paid_invest': None, 'n_disp_subs_oth_biz': None, 'eff_fx_flu_cash': None, 'conv_debt_into_cap': None,'end_bal_cash': None, 'beg_bal_cash': None, 'if_have_xjllb': 0}

前十大股东

前十大股东的持股比例与变动具有市场参考意义,并且也是按照季度进行更新的

# 获取 市场参考数据 前十大股东
def get_top_10_holder(stocks_label, period):# 或取数据 10个数据df = pro.top10_holders(ts_code=f'{stocks_label}', period=period, fields='holder_name,hold_amount,hold_ratio')# 进行判断if judge_data(df):return {'holder_name': '||'.join(list(df.holder_name.values)),'hold_amount': '||'.join([str(i) for i in list(df.hold_amount.values)]),'hold_ratio': '||'.join([str(i) + '%' for i in list(df.hold_ratio.values)]),'if_have_qsdgd': 1}else:return {'holder_name': None, 'hold_amount': None, 'hold_ratio': None, 'if_have_qsdgd': 0}

前十大流通股东

前十大流通股东这个更加具有选股参考意义

# 获取 市场参考数据 前十大流通股东
def get_lt_top_10_holder(stocks_label, period):# 获取数据 10条数据df = pro.top10_floatholders(ts_code=f'{stocks_label}', period=period, fields='holder_name,hold_amount')if judge_data(df):return {'lt_holder_name': '||'.join(list(df.holder_name.values)),'lt_hold_amount': '||'.join([str(i) for i in list(df.hold_amount.values)]),'if_have_ltqsdgd': 1}else:return {'lt_holder_name': None, 'lt_hold_amount': None, 'if_have_ltqsdgd': 0}

前十大股东与前十大流通股东都是10条数据的方式,这里都需要进行数据的整合

概念明细

概念明细信息也被归整到季度更新信息中

# 获取 市场参考数据 概念股明细列表
def get_concept_list(stocks_label, period):# 获取数据 可能有好几个概念df = pro.concept_detail(ts_code=f'{stocks_label}', fields='name,id,concept_name')if judge_data(df):return {'name_stock': set(list(df.name.values)).pop(),'gn_id': '||'.join(list(df.id.values)),'concept_name': '||'.join(list(df.concept_name.values)),'if_have_gngmxlb': 1}else:return {'name_stock': None, 'gn_id': None, 'concept_name': None, 'if_have_gngmxlb': 0}

按季度更新数据清洗

实际上在数据获取的时候已经对数据进行的清洗的部分工作,这里主要是进行数据的整合

# 构建按季度整合文档的主函数
def get_all_quarter(stocks_label: str, period):# 构建股票通用信息data = {'ts_code': stocks_label.split('.')[0], 'report_date': period, 'jys':stocks_label.split('.')[1]}  # 股票代码 报告日期# 获取 财务数据 主营业务构成data1 = get_finance_main_business(stocks_label, period)# 获取 财务数据 利润表data2 = get_finance_profit_statement(stocks_label, period)# 获取 财务数据 资产负债表data3 = get_finance_balance_sheet(stocks_label, period)# 获取 财务数据 现金流量表data4 = get_cash_flow_list(stocks_label, period)# 获取 市场参考数据 前十大股东data5 = get_top_10_holder(stocks_label, period)# 获取 市场参考数据 前十大流通股东data6 = get_lt_top_10_holder(stocks_label, period)# 获取 市场参考数据 概念股明细列表data7 = get_concept_list(stocks_label, period)# 进行数据整合source_data = dict(data, **data1, **data2, **data3, **data4, **data5, **data6, **data7)# 对数据中的字符串 None 进行处理for k, v in source_data.items():if v == 'None':source_data[k] = None# 对前十大流通股东的 持有比例 进行计算if source_data['total_share'] == None:source_data['lt_hold_ratio'] = Noneelse:source_data['lt_hold_ratio'] = '||'.join(['%.4f' % (float(i) / float(source_data['total_share'])) + '%' for i in source_data['lt_hold_amount'].split('||')])return source_data

这样就能将数据变化成可以进行存储的数据方式

按季度数据的存储

按照季度更新的数据最后一步就是需要进行存储到指定的mysql中,前面已经配置了LINK_MYSQL配置信息

# 定义写入函数
def quarterly_save_in_mysql(data):# 连接数据库link_mysql = pymysql.connect(**LINK_MYSQL)# 创建游标cursor = link_mysql.cursor(pymysql.cursors.DictCursor)# 进行查询,用于判断是更新还是写入search_sql = f'select * from quarterly_list where ts_code={data["ts_code"]}'cursor.execute(search_sql)res = cursor.fetchall()  # 获取查询结果if res:  # 表示该股票已经记录过了 接下来是进行针对固定的部分进行更新print(f'股票 {data["ts_code"]} 的季度数据已经存在 下面进行更新操作')else:  # 表示股票还没有被写入过 接下来是进行写入write_in_sql = 'insert into quarterly_list(ts_code, report_date, jys, bz_item, bz_sales, bz_profit, bz_cost, if_have_zyywgc, basic_eps, diluted_eps, total_revenue, revenue, total_cogs, oper_exp, operate_profit, total_profit, income_tax, n_income, n_income_attr_p, undist_profit, distable_profit, if_have_lrb, total_share, undistr_porfit, money_cap, accounts_receiv, fix_assets, intan_assets, r_and_d, goodwill, total_assets, acct_payable, taxes_payable, if_have_zcfzb, net_profit, c_paid_for_taxes, n_recp_disp_fiolta, n_recp_disp_sobu, c_paid_invest, n_disp_subs_oth_biz, eff_fx_flu_cash, conv_debt_into_cap, end_bal_cash, beg_bal_cash, if_have_xjllb, holder_name, hold_amount, hold_ratio, if_have_qsdgd, lt_holder_name, lt_hold_amount, lt_hold_ratio, if_have_ltqsdgd, name_stock, gn_id, concept_name, if_have_gngmxlb) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'data_list = [data['ts_code'],data['report_date'],data['jys'],data['bz_item'],data['bz_sales'],data['bz_profit'],data['bz_cost'],data['if_have_zyywgc'],data['basic_eps'],data['diluted_eps'],data['total_revenue'],data['revenue'],data['total_cogs'],data['oper_exp'],data['operate_profit'],data['total_profit'],data['income_tax'],data['n_income'],data['n_income_attr_p'],data['undist_profit'],data['distable_profit'],data['if_have_lrb'],data['total_share'],data['undistr_porfit'],data['money_cap'],data['accounts_receiv'],data['fix_assets'],data['intan_assets'],data['r_and_d'],data['goodwill'],data['total_assets'],data['acct_payable'],data['taxes_payable'],data['if_have_zcfzb'],data['net_profit'],data['c_paid_for_taxes'],data['n_recp_disp_fiolta'],data['n_recp_disp_sobu'],data['c_paid_invest'],data['n_disp_subs_oth_biz'],data['eff_fx_flu_cash'],data['conv_debt_into_cap'],data['end_bal_cash'],data['beg_bal_cash'],data['if_have_xjllb'],data['holder_name'],data['hold_amount'],data['hold_ratio'],data['if_have_qsdgd'],data['lt_holder_name'],data['lt_hold_amount'],data['lt_hold_ratio'],data['if_have_ltqsdgd'],data['name_stock'],data['gn_id'],data['concept_name'],data['if_have_gngmxlb'],]# 执行sqlcursor.execute(write_in_sql, data_list)link_mysql.commit()  # 提交link_mysql.close()print(f'{data["ts_code"]}的 季度数据 写入完成')

存储示例

一切都撸妥当之后进行数据写入,这里给出测试数据的写入方式

if __name__ == '__main__':res = get_all_quarter('002155.SZ', '20190331')# 进行存储quarterly_save_in_mysql(res)

存储结果


看起来还不错,一切都比较顺利

股票基本信息整合

股票基本信息属于是那种几乎不变的信息,具有长久的效益,因此这里需要虽然很少更新一次,但是还是需要进行检查更新的步骤

处于交易的股票信息

通过接口获取股票的基本信息

# 定义获取当前正在交易的所有股票基本信息
def get_all_stock_info():data = pro.stock_basic(exchange='', list_status='L',fields='ts_code,symbol,name,area,industry,list_date,market,is_hs')# 数据需要逐条存入对应的数据库if judge_data(data):return dataelse:print('股票列表获取失败!')return None

沪深股通成分股

# 定义获取沪深股通成分股信息
def get_hsgtcf_info():data_sh = pro.hs_const(hs_type='SH')  # 上交所data_sz = pro.hs_const(hs_type='SZ')  # 深交所# 拼接连个表格data = pd.concat([data_sh, data_sz])return data

股票基本信息

# 获取上市公司的基本信息
def get_all_company_base_info():data_SH = pro.stock_company(exchange='SZSE',fields='ts_code,chairman,manager,secretary,reg_capital,province,city,introduction,employees,main_business,business_scope')  # 深交所data_SZ = pro.stock_company(exchange='SSE',fields='ts_code,chairman,manager,secretary,reg_capital,province,city,introduction,employees,main_business,business_scope')  # 上交所# 拼接两个数据data = pd.concat([data_SH, data_SZ])return data

处理逻辑

因为正则交易的股票信息实际上将整个A股的所有股票都捞过来了,而基本信息属于是单个股票的信息,那么数据需要存储在一个表里面的时候就需要将数据进行一一对应的关系进行存储

先从处于交易的股票信息中获取股票代码,然后根据代码去查询沪深股同成分股是否有该股信息,有就将数据获取出来,根据股票代码进行获取该股票基本的信息,将信息获取回来后进行数据整合再拼接

数据处理函数

# 定义数据整合与处理函数
def data_integration_for_base_info():# 获取数据data_stock = get_all_stock_info()  # 获取股票列表data_hsgtcf = get_hsgtcf_info()  # 获取沪深股通data_base = get_all_company_base_info()  # 获取公司的基本信息# 对数据进行判断 是否已经拿到了数据if all([len(data_stock), len(data_hsgtcf), len(data_base)]):  # 三个接口同时返回数据才进行数据处理# 进行逐行处理data = data_stock.apply(by_row_deal_with_stock_base_info, axis=1, args=(data_hsgtcf, data_base))# 为了防止name作为mysql中的关键字影响这里对data中的name列进行更名data.rename(columns={'name': 'stock_name'}, inplace=True)# 进行数据的写入# data.apply(write_base_info_in_mysql, axis=1)return dataelse:print('股票列表数据为空,无法获取对应的信息')

需要注意的是pandas中的apply函数,具有逐行传入解析的功能

逐行处理函数

# 定义逐行处理数据的函数
def by_row_deal_with_stock_base_info(data, data_hsgtcf, data_base):# 获取股票ts_codets_code = data.ts_code# 根据ts_code查询出data_hsgtcf和data_base中的对应数据data_hsgtcf = data_hsgtcf.loc[data_hsgtcf.ts_code == ts_code]  # 获取出数据data_base = data_base.loc[data_base.ts_code == ts_code]  # 获取出数据# 对数据进行判定后处理 有可能数据不存在if len(data_hsgtcf) == 1:hsgtcf_index = data_hsgtcf.index.values[0]data['hs_type'] = data_hsgtcf.loc[hsgtcf_index, 'hs_type']data['in_date'] = data_hsgtcf.loc[hsgtcf_index, 'in_date']data['out_date'] = data_hsgtcf.loc[hsgtcf_index, 'out_date']data['is_new'] = data_hsgtcf.loc[hsgtcf_index, 'is_new']data['if_have_hsgtcf'] = 1else:data['hs_type'] = Nonedata['in_date'] = Nonedata['out_date'] = Nonedata['is_new'] = Nonedata['if_have_hsgtcf'] = 0if len(data_base) == 1:base_index = data_base.index.values[0]data['chairman'] = data_base.loc[base_index, 'chairman']data['manager'] = data_base.loc[base_index, 'manager']data['secretary'] = data_base.loc[base_index, 'secretary']data['reg_capital'] = data_base.loc[base_index, 'reg_capital']data['province'] = data_base.loc[base_index, 'province']data['city'] = data_base.loc[base_index, 'city']data['introduction'] = data_base.loc[base_index, 'introduction']data['employees'] = data_base.loc[base_index, 'employees']data['main_business'] = data_base.loc[base_index, 'main_business']data['business_scope'] = data_base.loc[base_index, 'business_scope']data['if_have_base_info'] = 1else:data['chairman'] = Nonedata['manager'] = Nonedata['secretary'] = Nonedata['reg_capital'] = Nonedata['province'] = Nonedata['city'] = Nonedata['introduction'] = Nonedata['employees'] = Nonedata['main_business'] = Nonedata['business_scope'] = Nonedata['if_have_base_info'] = 0data.ts_code = data.ts_code.split(".")[0]return data

注意其中的一些字段名的变化

股票基本数据存储

需要注意的是这里的逻辑,如果数据库中已经存在这个股票的数据记录,那就对数据进行更新,如果不存在,那就直接写入

# 定义数据写入函数 包含更新和去重功能
def write_base_info_in_mysql(data):# 链接mysqllink_mysql = pymysql.connect(**LINK_MYSQL)cursor = link_mysql.cursor(pymysql.cursors.DictCursor)# 先查询数据是否存在,存在则更新,不存在则添加find_sql = f'select * from stock_base_info where ts_code={data.ts_code}'cursor.execute(find_sql)res = cursor.fetchall()if len(res) == 1:  # 表示存在# 进行数据更新update_sql = 'update stock_base_info set symbol=%s,stock_name=%s,area=%s,industry=%s,market=%s,list_date=%s,is_hs=%s,hs_type=%s,in_date=%s,out_date=%s,is_new=%s,if_have_hsgtcf=%s,chairman=%s,manager=%s,secretary=%s,reg_capital=%s,province=%s,city=%s,introduction=%s,employees=%s,main_business=%s,business_scope=%s,if_have_base_info=%s,up_date=%s where ts_code=%s'data_list = [str(data.symbol), data.stock_name, data.area, data.industry, data.market, data.list_date, data.is_hs, data.hs_type, data.in_date, data.out_date, data.is_new, data.if_have_hsgtcf, data.chairman, data.manager, data.secretary, str(data.reg_capital), data.province, data.city, data.introduction, str(data.employees), data.main_business, data.business_scope, data.if_have_base_info, datetime.now(), data.ts_code]cursor.execute(update_sql, data_list)link_mysql.commit()print(f'股票 {data.ts_code} 名称 {data.stock_name} 更新完成')else:  # 表示不存在# 进行数据的写入write_sql = 'insert into stock_base_info(ts_code,symbol,stock_name,area,industry, market, list_date, is_hs, hs_type, in_date,out_date,is_new, if_have_hsgtcf, chairman, manager, secretary, reg_capital, province, city, introduction, employees, main_business, business_scope, if_have_base_info, up_date) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'data_list = [data.ts_code, str(data.symbol), data.stock_name, data.area, data.industry, data.market, data.list_date,data.is_hs, data.hs_type, data.in_date, data.out_date, data.is_new, data.if_have_hsgtcf, data.chairman, data.manager, data.secretary, str(data.reg_capital), data.province, data.city, data.introduction, str(data.employees), data.main_business, data.business_scope,data.if_have_base_info, datetime.now()]cursor.execute(write_sql, data_list)link_mysql.commit()print(f'股票 {data.ts_code} 名称 {data.stock_name} 写入完成')return data

存储示例

if __name__ == '__main__':res = data_integration_for_base_info()

存储结果

懒得截图了

总结

将数据整合后进行存储,存储为自己需求的方式,关系型数据库本身就是将关系性质作为优势进行存储的,数据间存在很强的耦合性质,然而实际的数据来看,关于股票的还有很多文字性质的信息和每日更新的股价信息,这些信息处于是每天更新的,一些龙虎榜信息也不是每个股票每天都入选的。

很多信息从多个维度构成了股票的整个肖像,基本面,资金面,消息面,宏观经济等等,都会构成选股的有效参数

为了后期建模方便,实际上还需要采用非关系型数据库进行存储,最终我会构建自己的知识图谱,构建自己的模型,现在上班比较忙,没有太多时间来撸这些东西,一切都慢慢来吧

基于tushare的股票数据构建1相关推荐

  1. 基于tushare实现股票实时价格变动的监控并用itchat实现微信消息提醒

    基于tushare实现股票实时价格变动的监控并用itchat实现微信消息提醒 1.实时检查股票价格的函数 2.定义开盘时间,收盘时间和当前时间 3.定义一个微信发送提醒消息的函数 4.主循环函数实现自 ...

  2. python tushare获取股票数据_Python 金融: TuShare API 获取股票数据 (1)

    多多教Python 金融 是我为金融同行,自由职业投资人 做的一个专栏.这里包含了我自己作为量化交易员,在做研究时所用到的Python技巧和实用案例.这个栏目专业性会比较强:本人29岁,量化工作5年的 ...

  3. 利用python进行股票分析(五)通过tushare读取股票数据

    文章目录 5. 通过tushare读取股票数据 5.1. 切换pip3的源 5.2. 获取股票数据 5.2.1. 前复权和后复权 5.2.2. 读取tushare数据,保存到csv文件 5.2.3. ...

  4. python tushare获取股票数据并可视化_荐Python获取股票数据及其可视化--基于tushare库...

    01 Tushare简介 Tushare是一个金融大数据开放社区,它免费提供各类金融数据和区块链数据 , 助力智能投资与创新型投资.在Tushare 旧版 运行了3年后,Tushare Pro终于要跟 ...

  5. python tushare获取股票数据并可视化_Python股票数据获取及其可视化——基于tushare库...

    01 Tushare简介 Tushare是一个金融大数据开放社区,它免费提供各类金融数据和区块链数据 , 助力智能投资与创新型投资.在Tushare 旧版 运行了3年后,Tushare Pro终于要跟 ...

  6. bootstrap-table真实交互数据_博思远略:基于AI交互场景数据构建用户画像的几点思考...

    什么是用户,就是那些藏在每台电脑.手机.pad.智能watch屏幕背后的使用产品或服务恰如你我--有血有肉.有情绪.有想法.有阅历.有逻辑.有思考.固守某种习惯且独一无二.形形色色的人. 用户画像本质 ...

  7. python tushare获取股票数据并可视化_使用Python获取股票数据Tushare

    最近不是在炒股吗,挣点儿零花钱,权当学习金融知识了,前几天了解到转债,T+0,这个东西有点儿刺激啊,哈哈,就是老去看手机,实在有点儿耽误事儿,就想着,用python把股票价格拉下来,如果有上下的变动, ...

  8. tushare获得股票数据后进行数据合并

    tushareID:511783 1.各种模块的导入 %matplotlib inline import matplotlib.pyplot as plt import seaborn plt.sty ...

  9. 树莓派上安装tushare获取股票数据

    建立虚拟环境 通过命令 python3 -m venv tushare 安装一个虚拟环境,然后通过命令 source bin/activate 来切换到tushare虚拟环境 首先安装lxml 因为t ...

最新文章

  1. 软件设计原则——合成复用原则
  2. 手写ORM入门篇(一)
  3. 程序员利用Python破解老婆撤回的消息,这样竟然还有老婆?
  4. python库快速安装_python的pip快速安装代码
  5. 简单html图片轮播_抖音图片轮播的视频怎么制作?小白1分钟就能学会,超简单...
  6. tomcat编码配置gbk_tomcat的编码设置 tomcat中文问题的解决
  7. ppt flash无法播放解决方法
  8. 组合体计算机绘图的实验原理,《机械制图及计算机绘图》实验教案.pdf
  9. 【开源】EasyDarwin编译全过程:Linux系统下编译运行最新版EasyDarwin的步骤介绍
  10. 安装Ubuntu系统时硬盘分区最合理的方法
  11. lisp方格网法计算土方量_CAD计算土方方量插件
  12. java的string的intern_java String的intern()方法
  13. 基于html5的城市公交查询系统,本科毕业论文 城市公交查询系统
  14. 程序员高手和程序员菜鸟的区别是什么?
  15. 后台接收前台传来的图片并保存在本地
  16. 塔顶分凝器全凝器区别_(单选)在相同的回流比和塔顶蒸汽组成下,采用分凝器+全凝器的二元连续精馏塔与仅采用全凝器的塔相比,()...
  17. OBS 相芯美颜 之 美颜SDK介绍
  18. mysql 8.0设置密码 (doc命令)
  19. Linuxprobe-28期-第二节课
  20. 【JavaWeb学习,快一起呀,干!】第二章 Servlet基础(3)—— 应用:数据处理

热门文章

  1. 用开源软件搭建企业内部协作平台, Kill QQ MSN
  2. java调用hp打印机驱动_Java Equip.getHp方法代码示例
  3. 关于矩阵求导的理解与计算方法
  4. 2022最后一天盘点
  5. Download the React DevTools for a better development experience
  6. 2021年全国研究生数学建模竞赛华为杯C题帕金森病的脑深部电刺激治疗建模研究求解全过程文档及程序
  7. JAVA+网络数据包的抓取与分析实验
  8. 云产品测试报告书写指南
  9. 记录一次爬取知识星球的word文档
  10. 关于H3C路由器web远程管理关闭的问题