利用Tushare进行股票因子计算

开发背景

笔者tushare ID:414988

一、获取沪深300成分股

基本思路:

  1. 先获取全部股票
  2. 获取沪深300股票代码
  3. 根据沪深300股票代码,提取对应的ts代码
  4. 根据ts代码获取沪深300股票列表

1. 获取全部股票代码

stock_list = pro.stock_basic(exchange='',list_status='L', fields='ts_code,symbol,name,area,industry,market,exchange')
stock_list

ts_code	symbol	name	area	industry	market	exchange
0	000001.SZ	000001	平安银行	深圳	银行	主板	SZSE
1	000002.SZ	000002	万科A	深圳	全国地产	主板	SZSE
2	000004.SZ	000004	国华网安	深圳	软件服务	主板	SZSE
3	000005.SZ	000005	世纪星源	深圳	环境保护	主板	SZSE
4	000006.SZ	000006	深振业A	深圳	区域地产	主板	SZSE
...	...	...	...	...	...	...	...
4231	688777.SH	688777	中控技术	浙江	软件服务	科创板	SSE
4232	688788.SH	688788	科思科技	深圳	通信设备	科创板	SSE
4233	688819.SH	688819	天能股份	浙江	电气设备	科创板	SSE
4234	688981.SH	688981	中芯国际	上海	半导体	科创板	SSE
4235	689009.SH	689009	九号公司-UWD	北京	专用机械	CDR	SSE
4236 rows × 7 columns

2. 获取沪深300成分股代码

hs300s = ts.get_hs300s() 
hs300s
	date	code	name	weight
0	2021-03-31	600000	浦发银行	0.68
1	2021-03-31	600004	白云机场	0.08
2	2021-03-31	600009	上海机场	0.29
3	2021-03-31	600010	包钢股份	0.19
4	2021-03-31	600011	华能国际	0.10
...	...	...	...	...
295	2021-03-31	300498	温氏股份	0.40
296	2021-03-31	300529	健帆生物	0.16
297	2021-03-31	300601	康泰生物	0.25
298	2021-03-31	300628	亿联网络	0.10
299	2021-03-31	300676	华大基因	0.13
300 rows × 4 columns
hs300_symbols = hs300s.loc[:]['code']
hs300_symbols
0      600000
1      600004
2      600009
3      600010
4      600011
        ...  
295    300498
296    300529
297    300601
298    300628
299    300676
Name: code, Length: 300, dtype: object

3. 根据沪深300股票代码,提取对应的ts代码

# 获取沪深300的所有股票的ts代码
hs300_code_list = []

for i in range(stock_list.shape[0]):
    if stock_list.loc[i]['symbol'] in hs300_symbols.values:
        hs300_code_list.append(stock_list.loc[i]['ts_code'])

4. 根据ts代码获取沪深300股票列表

注意:tushare平台的pro.stock_basic一分钟只能访问200次,因此300只股票数据可以分为两次读取,中间间隔一分钟。

n_flag = 0
hs300_stock_list = pd.DataFrame()
for code in hs300_code_list:
    hs300_stock_list = pd.concat([hs300_stock_list, pro.stock_basic(ts_code=code)], axis=0)
    if n_flag == 99:
        n_flag = 0
        time.sleep(60)

# 重建索引
hs300_stock_list = hs300_stock_list.reset_index(drop=True)
hs300_stock_list
# 将300只股票的权重合并到对应的hs300_stock_list中
hs300_weights = np.zeros(hs300s.shape[0])
for i in range(hs300s.shape[0]):
    index = hs300_stock_list[hs300_stock_list.symbol==hs300s.loc[i]['code']].index.tolist()[0]
    hs300_weights[index] = (hs300s.loc[i]['weight'])
    
hs300_weights = pd.DataFrame(hs300_weights)
hs300_weights.columns = ['weight']
hs300_stock_list = pd.concat([hs300_stock_list, hs300_weights['weight']], axis=1)
hs300_stock_list
	ts_code	symbol	name	area	industry	market	list_date	weight
0	000001.SZ	000001	平安银行	深圳	银行	主板	19910403	1.12
1	000002.SZ	000002	万科A	深圳	全国地产	主板	19910129	1.07
2	000063.SZ	000063	中兴通讯	深圳	通信设备	主板	19971118	0.42
3	000066.SZ	000066	中国长城	深圳	IT设备	主板	19970626	0.14
4	000069.SZ	000069	华侨城A	深圳	旅游景点	主板	19970910	0.22
...	...	...	...	...	...	...	...	...
295	603993.SH	603993	洛阳钼业	河南	小金属	主板	20121009	0.2
296	688008.SH	688008	澜起科技	上海	半导体	科创板	20190722	0.15
297	688009.SH	688009	中国通号	北京	运输设备	科创板	20190722	0.08
298	688012.SH	688012	中微公司	上海	专用机械	科创板	20190722	0.12
299	688036.SH	688036	传音控股	深圳	通信设备	科创板	20190930	0.18
300 rows × 8 columns

二、计算市值对数

pro.daily_basic接口同样一分钟只允许访问200次。
采用一样的方法,在循环中sleep一分钟。
其中total_mv为总市值,circ_mv为流通市值

n_flag = 0
indi_dic = pd.DataFrame()
for code in hs300_code_list:
    indi = pro.daily_basic(ts_code=code, start_date='20060101', end_date='20210401', fields='ts_code,trade_date,turnover_rate,total_mv,circ_mv')
    indi_dic = pd.concat([indi_dic, indi], axis=0)
    if n_flag == 150:
        n_flag = 0
        time.sleep(60)
# 统计一下是否完整收集300只股票
len(indi_dic['ts_code'].unique())
3

使用apply和lambda计算市值对数

import math
indi_dic['totalmv_size_factor'] = indi_dic['total_mv'].apply(lambda x: math.log(x))
indi_dic['circmv_size_factor'] = indi_dic['circ_mv'].apply(lambda x: math.log(x))
# 改个名字
indi_dic = indi_dic.rename(columns={'totalmv_size_factor':'ln_total_capital', 'circmv_size_factor':'ln_circ_capital'})
indi_dic
	ts_code	trade_date	turnover_rate	total_mv	circ_mv	ln_total_capital	ln_circ_capital
0	000001.SZ	20210401	0.2806	4.226609e+07	4.226573e+07	17.559496	17.559487
1	000001.SZ	20210331	0.4004	4.271243e+07	4.271207e+07	17.570000	17.569992
2	000001.SZ	20210330	0.3806	4.255718e+07	4.255682e+07	17.566359	17.566351
3	000001.SZ	20210329	0.4049	4.170332e+07	4.170297e+07	17.546091	17.546083
4	000001.SZ	20210326	0.4236	4.102411e+07	4.102376e+07	17.529671	17.529662
...	...	...	...	...	...	...	...
359	688036.SH	20191011	19.1273	3.805600e+06	3.404245e+05	15.151984	12.737949
360	688036.SH	20191010	18.9791	3.980000e+06	3.560252e+05	15.196792	12.782757
361	688036.SH	20191009	21.2596	3.842400e+06	3.437164e+05	15.161608	12.747572
362	688036.SH	20191008	32.4079	4.019200e+06	3.595318e+05	15.206593	12.792558
363	688036.SH	20190930	67.9496	4.624000e+06	4.136333e+05	15.346771	12.932735
787958 rows × 7 columns

三、计算收益率

获取月线数据,每分钟最多访问该接口120次,中间sleep

n_flag = 0
monthly_line = pd.DataFrame()
for code in hs300_code_list:
    mon = pro.monthly(ts_code=code, start_date='20060101', end_date='20210331', fields='ts_code,trade_date,open,close')
    monthly_line = pd.concat([monthly_line, mon], axis=0)
    if n_flag == 99:
        n_flag = 0
        time.sleep(60)
monthly_line
	ts_code	trade_date	close	open
0	000001.SZ	20210331	22.01	21.54
1	000001.SZ	20210226	21.38	23.00
2	000001.SZ	20210129	23.09	19.10
3	000001.SZ	20201231	19.34	19.70
4	000001.SZ	20201130	19.74	17.65
...	...	...	...	...
8	300015.SZ	20200731	45.30	43.90
9	300015.SZ	20200630	43.45	39.20
10	300015.SZ	20200529	39.16	44.31
11	300015.SZ	20200430	44.39	39.25
12	300015.SZ	20200331	39.38	40.55
1300 rows × 4 columns

设置索引为日期

monthly_line0 = monthly_line
monthly_line0 = monthly_line0.set_index('trade_date')
monthly_line0.index = pd.to_datetime(monthly_line0.index,format='%Y%m%d').to_period('M')
monthly_line0
	ts_code	close	open
trade_date			
2021-03	000001.SZ	22.01	21.54
2021-02	000001.SZ	21.38	23.00
2021-01	000001.SZ	23.09	19.10
2020-12	000001.SZ	19.34	19.70
2020-11	000001.SZ	19.74	17.65
...	...	...	...
2020-07	688036.SH	100.10	70.00
2020-06	688036.SH	71.00	50.66
2020-05	688036.SH	50.00	53.50
2020-04	688036.SH	54.50	42.38
2020-03	688036.SH	42.81	58.60
3893 rows × 3 columns

用groupby分组操作

price_month = (monthly_line0.groupby(['trade_date', 'ts_code']).sum())
price_month
		close	open
trade_date	ts_code		
2020-03	000001.SZ	12.80	14.55
000002.SZ	25.65	29.90
000063.SZ	42.80	52.00
000066.SZ	11.94	14.13
000069.SZ	6.39	6.59
...	...	...	...
2021-03	603993.SH	5.28	6.72
688008.SH	61.20	75.00
688009.SH	5.67	5.93
688012.SH	107.51	126.07
688036.SH	209.38	200.57
3893 rows × 2 columns

计算收益率

price_month['return'] = (price_month['close'] - price_month['open']) / price_month['open']
price_month
		close	open	return
trade_date	ts_code			
2020-03	000001.SZ	12.80	14.55	-0.120275
000002.SZ	25.65	29.90	-0.142140
000063.SZ	42.80	52.00	-0.176923
000066.SZ	11.94	14.13	-0.154989
000069.SZ	6.39	6.59	-0.030349
...	...	...	...	...
2021-03	603993.SH	5.28	6.72	-0.214286
688008.SH	61.20	75.00	-0.184000
688009.SH	5.67	5.93	-0.043845
688012.SH	107.51	126.07	-0.147220
688036.SH	209.38	200.57	0.043925
3893 rows × 3 columns
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值