import pandas as pd
import tushare as ts
import pymysql
import os
import docx
import time
import datetime
import warnings
from urllib import parse
from sqlalchemy import create_engine
from docx.shared import Cm, Inches
from docx.shared import RGBColor,Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH
warnings.filterwarnings('ignore')
pd.set_option('expand_frame_repr', False)
pd.set_option('display.max_columns', None)
pd.set_option('colheader_justify', 'centre')
pro = ts.pro_api('77675d1dcec7fa0f2e893dca61d3acd7910cdd4672318f62b0354487')
def tushare_to_mysql(st_date, ed_date):
engine = create_engine('mysql://root:%[email protected]:3306/tushare?charset=utf8' % parse.unquote_plus('123456.'))
print('数据库连接成功')
trade_d = pro.trade_cal(exchange='SSE', is_open='1',start_date=st_date,end_date=ed_date,fields='cal_date')
for date in trade_d['cal_date'].values:
df_basic = pro.stock_basic(exchange='', list_status='L')
df_daily = pro.daily(trade_date=date)
df_daily_basic = pro.daily_basic(ts_code='', trade_date=date,fields='ts_code, turnover_rate, turnover_rate_f,'
' volume_ratio, pe, pe_ttm, pb, ps, ps_ttm,'
' dv_ratio, dv_ttm, total_share, float_share,'
' free_share, total_mv, circ_mv ')
df_first = pd.merge(left=df_basic, right=df_daily, on='ts_code', how='outer')
df_all = pd.merge(left=df_first, right=df_daily_basic, on='ts_code', how='outer')
df_all = df_all.drop('symbol', axis=1)
for w in ['name', 'area', 'industry', 'market']:
df_all[w].fillna('问题股', inplace=True)
df_all['ts_code'] = df_all['ts_code'].astype(str)
df_all['list_date'] = pd.to_datetime(df_all['list_date'])
df_all['trade_date'] = pd.to_datetime(df_all['trade_date'])
df_all = df_all.rename(columns={
'ts_code': '股票代码', 'name': '股票名称', 'area': '所在地域', 'industry': '行业'
, 'market': '市场类型', 'list_date': '上市日期', 'trade_date': '交易日期', 'change': '涨跌额'
, 'pct_chg': '涨跌幅', 'vol': '成交量(手)', 'amount': '成交额(千元)', 'turnover_rate': '换手率(%)'
, 'turnover_rate_f': '流通换手率', 'volume_ratio': '量比', 'pe': '市盈率', 'pe_ttm': '滚动市盈率'
, 'pb': '市净率', 'ps': '市销率', 'ps_ttm': '滚动市销率', 'dv_ratio': '股息率'
, 'dv_ttm': '滚动股息率', 'total_share': '总股本(万股)', 'float_share': '流通股本(万股)'
, 'free_share': '自由流通股本(万股)', 'total_mv': '总市值(万元)', 'circ_mv': '流通市值(万元)'})
engine.execute('drop table if exists {}_ts;'.format(date))
print('%s is downloading....' % (str(date)))
df_all.to_sql('{}_ts'.format(date),engine,index=False)
print('{}成功导入数据库'.format(date))
def get_mysql_data_analysis(st_date, ed_date):
trade_d = pro.trade_cal(exchange='SSE', is_open='1', start_date=st_date, end_date=ed_date, fields='cal_date')
conn = pymysql.connect(host='localhost', user='root', password='123456.', db='tushare', charset='utf8')
for date_now in trade_d['cal_date'].values:
cursor = conn.cursor()
sql = 'select * from {}_ts;'.format(date_now)
cursor.execute(sql)
col_result = cursor.description
result = cursor.fetchall()
columns = []
for i in range(len(col_result)):
columns.append(col_result[i][0])
df = pd.DataFrame(list(result),columns=columns)
df = df.set_index('股票代码', drop=False)
df['成交额(千元)'] = df['成交额(千元)']/100000
df['流通市值(万元)'] = df['流通市值(万元)']/10000
df['总市值(万元)'] = df['总市值(万元)']/10000
df.loc[df['股票代码'].str.startswith('3'), 'exchange'] = 'CY'
df.loc[df['股票代码'].str.startswith('6'), 'exchange'] = 'SH'
df.loc[df['股票代码'].str.startswith('0'), 'exchange'] = 'SZ'
df_up = df[df['涨跌额'] > 0.00]
df_even = df[df['涨跌额'] == 0.00]
df_down = df[df['涨跌额'] < 0.00]
limit_up = df[df['涨跌额']/df['pre_close'] >= 0.097]
limit_down = df[df['涨跌额']/df['pre_close'] <= -0.0970]
limit_up_new = limit_up[pd.to_datetime(date_now) - limit_up['上市日期'] <= pd.Timedelta(days=15)]
limit_up_fresh = limit_up[pd.to_datetime(date_now) - limit_up['上市日期'] <= pd.Timedelta(days=365)]
limit_down_new = limit_down[pd.to_datetime(date_now) - limit_down['上市日期'] <= pd.Timedelta(days=15)]
limit_down_fresh = limit_down[pd.to_datetime(date_now) - limit_down['上市日期'] <= pd.Timedelta(days=365)]
print('A股上涨个数: %d, A股下跌个数: %d, A股走平个数: %d。' % (df_up.shape[0], df_down.shape[0], df_even.shape[0]))
print('A股总成交额:%d 亿, 总成交量:%d 手' % (df['成交额(千元)'].sum(), df['成交量(手)'].sum()))
print('A股平均市盈率:%.2f, 平均流通市值 %.2f 亿, 平均总市值 %.2f 亿' % (df['市盈率'].mean(), df['流通市值(万元)'].mean(), df['总市值(万元)'].mean()))
print('涨停数量:%d 个, 涨停中上市日期小于15天的:%d, 涨停中上市日期小于1年的:%d' % (limit_up.shape[0], limit_up_new.shape[0], limit_up_fresh.shape[0]))
print('跌停数量:%d 个, 涨停中上市日期小于15天的:%d, 涨停中上市日期小于1年的:%d' % (limit_down.shape[0], limit_down_new.shape[0], limit_down_fresh.shape[0]))
file = docx.Document()
headb = file.add_heading('%s中国股市今日收盘分析报告' % (date_now), level=0).alignment = WD_ALIGN_PARAGRAPH.CENTER
head1 = file.add_heading('股市基本概况:',level=1)
text1 = file.add_paragraph()
text1.add_run('A股上涨个数:').bold = True
text1.add_run('{} '.format(str(df_up.shape[0]))).font.color.rgb = RGBColor(255, 0, 0)
text1.add_run('A股下跌个数:').bold = True
text1.add_run('{} '.format(str(df_down.shape[0]))).font.color.rgb = RGBColor(0, 255, 0)
text1.add_run('A股走平个数:').bold = True
text1.add_run('{} '.format(str(df_even.shape[0]))).font.color.rgb = RGBColor(0, 0, 255)
text1.line_spacing = Pt(25)
text1.style = 'List Bullet'
text2 = file.add_paragraph()
text2.add_run('A股总成交额:').bold = True
text2.add_run('{}'.format(str(round(df['成交额(千元)'].sum(),2)))).font.color.rgb = RGBColor(128, 0, 128)
text2.add_run('亿 ')
text2.add_run('总成交量:').bold = True
text2.add_run('{}'.format(str(round(df['成交量(手)'].sum(),2)))).font.color.rgb = RGBColor(128, 0, 128)
text2.add_run('手 ')
text2.line_spacing = Pt(25)
text2.style = 'List Bullet'
text3 = file.add_paragraph()
text3.add_run('A股平均市盈率:').bold = True
text3.add_run('{} '.format(str(round(df['市盈率'].mean())))).font.color.rgb = RGBColor(128, 0, 128)
text3.add_run('平均流通市值:').bold = True
text3.add_run('{}'.format(str(round(df['流通市值(万元)'].mean(),2)))).font.color.rgb = RGBColor(128, 0, 128)
text3.add_run('亿')
text3.add_run('\n')
text3.add_run('平均总市值:').bold = True
text3.add_run('{}'.format(str(round(df['总市值(万元)'].mean(),2)))).font.color.rgb = RGBColor(128, 0, 128)
text3.add_run('亿 ')
text3.line_spacing = Pt(25)
text3.style = 'List Bullet'
text3.add_run('\n')
text4 = file.add_paragraph()
text4.add_run('涨停数量:').bold = True
text4.add_run('{}'.format(str(limit_up.shape[0]))).font.color.rgb = RGBColor(255, 0, 0)
text4.add_run('个 ')
text4.add_run('涨停中上市日期小于15天的:').bold = True
text4.add_run('{}'.format(str(limit_up_new.shape[0]))).font.color.rgb = RGBColor(255, 0, 0)
text4.add_run('个 ')
text4.add_run('\n')
text4.add_run('涨停中上市日期小于1年的:').bold = True
text4.add_run('{}'.format(str(limit_up_fresh.shape[0]))).font.color.rgb = RGBColor(255, 0, 0)
text4.add_run('个 ')
text4.line_spacing = Pt(25)
text4.style = 'List Bullet'
text5 = file.add_paragraph()
text5.add_run('跌停数量:').bold = True
text5.add_run('{}'.format(str(limit_down.shape[0]))).font.color.rgb = RGBColor(0, 255, 0)
text5.add_run('个 ')
text5.add_run('跌停中上市日期小于15天的:').bold = True
text5.add_run('{}'.format(str(limit_down_new.shape[0]))).font.color.rgb = RGBColor(0, 255, 0)
text5.add_run('个 ')
text5.add_run('\n')
text5.add_run('跌停中上市日期小于1年的:').bold = True
text5.add_run('{}'.format(str(limit_down_fresh.shape[0]))).font.color.rgb = RGBColor(0, 255, 0)
text5.add_run('个 ')
text5.line_spacing = Pt(25)
text5.style = 'List Bullet'
file.add_page_break()
def get_output(df, columns='_industry', name='_limit_up'):
df = df.copy()
output = pd.DataFrame()
output = pd.DataFrame(df.groupby(columns)['股票代码'].count())
output['平均市盈率'] = round(df.groupby(columns)['市盈率'].mean(),2)
output['平均流通市值(亿)'] = round(df.groupby(columns)['流通市值(万元)'].mean(),2)
output['平均总市值(亿)'] = round(df.groupby(columns)['总市值(万元)'].mean(),2)
output['平均成交量(手)'] = round(df.groupby(columns)['成交量(手)'].mean(),2)
output['平均成交额(亿)'] = round(df.groupby(columns)['成交额(千元)'].mean(),2)
output.sort_values('股票代码', ascending=False, inplace=True)
output.rename(columns={
'股票代码': name + '合计'}, inplace=True)
return output
for i in ['行业', '市场类型', '所在地域']:
output_limit_up = get_output(limit_up, columns=i, name='涨停').reset_index()
output_limit_down = get_output(limit_down, columns=i, name='跌停').reset_index()
output_total = get_output(df, columns=i, name='全部').reset_index()
tabletext = file.add_paragraph()
tabletext.add_run('类别:').bold = True
tabletext.add_run('{} '.format(str(i))).font.color.rgb = RGBColor(222, 125, 44)
for j in [output_limit_up, output_limit_down]:
tb = file.add_table(rows=len(j.index)+1, cols=len(j.columns),style='Medium Grid 3 Accent 1')
tb.autofit = True
for x in range(len(j.columns)):
tb.cell(0, x).text = j.columns[x]
tb.cell(0, x).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
for row in range(len(j.index)):
for col in range(len(j.columns)):
tb.cell(row+1, col).text = str(j.iloc[row, col])
tb.cell(row+1, col).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
file.add_paragraph('\n')
file.add_page_break()
file.save('E:\\James\\code\\quantitative_finance\\{}_分析报告.docx'.format(str(date_now)))
print('{}_分析报告分析完成'.format(str(date_now)))
if __name__=="__main__":
tushare_to_mysql('20200801', '20200902')
get_mysql_data_analysis('20200801', '20200902')