基于Tushare的数据搜集与沪市选股
目录
一、 引言
二、 数据搜集
三、数据预处理
四、 XGBoost算法实现
一、 引言
为了回馈tushare平台免费对高校学生开放使用,本人(tushare ID : 421217)与大家分享一下基于tushare数据的量化交易。
本文主要分为数据搜集与算法实现两个部分,在数据搜集部分本文主要利用tushare平台搜集了沪市A股在2013-1~2021-9的行情类、每股类、情绪类、动量类、统计类与常见的技术指标及部分特征滞后项共87个特征(具体指标可见代码),总计88163条数据;而后进行数据预处理与基于XGBoost算法的选股。具体流程见下文。
二、 数据搜集
本文把时间序列分为3个时间段,以2013-1~2020-11的数据作为训练集数据,2020-12的数据作为验证集,2021-1的数据作为测试集,并不断滚动训练直至2021-8。本文的87个特征均以真实月度数据或利用talib库结合23日日度数据计算得出,2021-1数据搜集代码示例如下:
import pandas as pd
import numpy as np
import tushare as ts
import talib as ta
import matplotlib.pyplot as plt
pro = ts.pro_api('your token')
ts.set_token('your token')#设置token
api = ts.pro_api()
import warnings
warnings.filterwarnings('ignore')
pd.options.display.max_columns=Nonedef Changestr(datetime1): #用于统一时间格式str1 = datetime1.strftime('%Y-%m-%d')return str1
def Changemonth(datetime1):#用于统一时间格式str1 = datetime1.strftime('%Y%m%d')return str1data=pd.read_excel(r'D:\xxx.xlsx')#待搜集的股票池
stock=pd.DataFrame()
for pp,qq in data.iterrows():if data.iloc[pp,0]<=pd.to_datetime('2020-07-15'): stock_y=pd.DataFrame()######stock_y=ts.pro_bar(ts_code=qq['ts_code'], start_date='2020-08-01', end_date='20210131',freq='M',adj='qfq') #获取月度数据######if pd.DataFrame(stock_y).empty:continuestock_y.sort_values('trade_date',inplace=True)stock_y.reset_index(inplace=True)stock_y.drop('index',inplace=True,axis=1)stock_y['cum_returns']=(stock_y['pct_chg']/100+1).cumprod()-1stock_y.drop('change',axis=1,inplace=True)lsttt=[]for i in stock_y['trade_date']:lsttt.append(i[0:6])stock_y['tt']=lsttt######ss=pro.query('daily_basic', ts_code=qq['ts_code'],start_date='2020-08-01', end_date='20210131',fields='ts_code,trade_date,turnover_rate,volume_ratio,pe,pb,ps,dv_ratio,total_share,float_share,total_mv,circ_mv')######if pd.DataFrame(ss).empty:continuess.sort_values('trade_date',inplace=True)ss.reset_index(inplace=True)ss.drop('index',inplace=True,axis=1)ss.set_index('trade_date',inplace=True)ss.index=pd.to_datetime(ss.index)kk=ss.resample('m').mean()kk.reset_index(inplace=True)lsttt0=[]for i in kk['trade_date']:lsttt0.append(Changemonth(i)[0:6])kk['tt']=lsttt0stock_y=pd.merge(stock_y,kk,on='tt')stock_y.drop(['tt','trade_date_y'],axis=1,inplace=True)stock_y.set_index('trade_date_x',inplace=True)stock_y.index=pd.to_datetime(stock_y.index)######stock1=ts.pro_bar(ts_code=qq['ts_code'],start_date='2020-08-01', end_date='20210131',freq='D',adj='qfq') #获取日度数据######if pd.DataFrame(stock1).empty:continuestock1.sort_values('trade_date',inplace=True)stock1.reset_index(inplace=True)stock1.drop('index',inplace=True,axis=1)stock1.set_index('trade_date',inplace=True)stock1.index=pd.to_datetime(stock1.index)#行情指标'''high,open,low,close,pct_chg,vol,amount,pre_close'''#每股类指标'''turnover_rate,volumn_ratio,dv_ratio,float_share,circ_mv,pe,pb,ps'''#情绪类指标stock1['PSY']=pd.DataFrame((stock1['pct_chg']>0).rolling(23).mean()*100).valuesstock1["rsi"] = ta.RSI(stock1['close'],timeperiod=23)stock1['willr'] = ta.WILLR(stock1['high'], stock1['low'], stock1['close'], timeperiod=23)stock1['turnover_rate_std']=ss.turnover_rate.rolling(23).std()stock1['ATR'] = ta.ATR(stock1.high, stock1.low, stock1.close, timeperiod=23)stock_y['obv'] = ta.OBV(stock_y['close'],stock_y['vol'])stock1['AR_high']=(stock1['open']/stock1['high']).rolling(23).mean()stock1['AR_low']=(stock1['open']/stock1['low']).rolling(23).mean()stock1['BR_high']=(stock1['pre_close']/stock1['high']).rolling(23).mean()stock1['BR_low']=(stock1['pre_close']/stock1['low']).rolling(23).mean()# #动量指标'''cum_returns'''stock1['BIAS']=(stock1['close']-stock1['close'].rolling(23).mean())/stock1['close']stock1['cci'] = ta.CCI(stock1['high'], stock1['low'], stock1['close'], timeperiod=23)stock1['MINUS_DI'] = ta.MINUS_DI(stock1.high, stock1.low, stock1.close, timeperiod=23)stock1['MINUS_DM']= ta.MINUS_DM(stock1.high, stock1.low, timeperiod=23)stock1['MOM']= ta.MOM(stock1.close, timeperiod=23)stock_y['AD'] = ta.AD(stock_y.high, stock_y.low, stock_y.close, stock_y.vol)stock_y['HT_TRENDMODE'] = ta.HT_TRENDMODE(stock_y.close)#统计类指标stock1['pct_chg_std']=stock1.pct_chg.rolling(23).std()stock1['close_std'] = np.sqrt(ta.VAR(stock1.close,timeperiod=23))stock1['vol_std']=stock1['vol'].rolling(23).std()stock1['amount_std']=stock1['amount'].rolling(23).std()stock_y['typeprice'] = ta.TYPPRICE(stock_y.high,stock_y.low, stock_y.close)stock_y['AVGPRICE'] = ta.AVGPRICE(stock_y.open,stock_y.high, stock_y.low, stock_y.close)stock_y['WCLPRICE'] = ta.WCLPRICE(stock_y.high, stock_y.low, stock_y.close)stock1['midprice'] = ta.MIDPRICE(stock1.high,stock1.low,timeperiod=23)# 技术指标stock1['midpoint'] = ta.MIDPOINT(stock1.close, timeperiod=23)stock1['EMA'] = ta.EMA(stock1.close, timeperiod=23)stock1['MFI'] = ta.MFI(stock1.high, stock1.low, stock1.close, stock1.vol, timeperiod=23)stock1['macd'], stock1['macdsignal'], stock1['macdhist'] = ta.MACD(stock1['close'], fastperiod=12, slowperiod=23, signalperiod=9)stock1['upperband'], stock1['middleband'], stock1['lowerband'] = ta.BBANDS(stock1['close'], timeperiod=23, nbdevup=2, nbdevdn=2, matype=0)stock1['TEMA'] = ta.TEMA(stock1.close, timeperiod=23)stock_y['RVI']=(stock_y['close']-stock_y['open'])/(stock_y['high']-stock_y['low'])stock1['trix']=ta.TRIX(stock1.close,23)stock_y.reset_index(inplace=True)lsttt0=[]for i in stock_y['trade_date_x']:lsttt0.append(Changemonth(i)[0:6])stock_y['tt']=lsttt0kk=stock1.resample('m').last().iloc[:,10:]kk.reset_index(inplace=True)lsttt0=[]for i in kk['trade_date']:lsttt0.append(Changemonth(i)[0:6])kk['tt']=lsttt0stock_y=pd.merge(stock_y,kk,on='tt')stock_y.drop(['tt','trade_date_x'],axis=1,inplace=True)stock_y.set_index('trade_date',inplace=True)stock_y.index=pd.to_datetime(stock_y.index)lst=['PSY','rsi','willr','turnover_rate_std','ATR','obv','AR_high','AR_low','BR_high','BR_low','cum_returns','BIAS','cci','MINUS_DI','MINUS_DM','MOM','AD','HT_TRENDMODE']for m in lst:for i in [1,2]:stock_y[m+'_L%d'%i]=stock_y[m].shift(i)stock_y.drop(['total_share','total_mv'],axis=1,inplace=True)######stock=stock.append(stock_y.loc['2021-01-01':])
三、数据预处理
在数据搜集完成后,本文仅发现dv_ratio特征存在缺失值,以0填补;对所有特征进行z-score标准化处理,运用LOF算法去除异常值,把VIF系数大于10的特征剔除后,仍剩余28个特征。
考虑到特征众多,后续解释较为困难,继续运用因子分析的方式对28个特征降维,在保留80.1614%的方差下,选出了12个重要特征,其因子载荷矩阵如下图所示:
后续本文将用这12个特征与XGBoost算法建模选股。
四、 XGBoost算法实现
本文交易策略为:经参数调优后,在验证集上预测准确率大于50%,且做多上涨概率最大的前5只股票收益率为正,那么在测试集将开仓,否则本月什么也不做,并每月重新估计模型参数,不断滚动预测下去,XGBoost示例代码如下:
import xgboost as xgb
lst=[]
a=np.random.randint(100000000)
for i in range(1):#查看每月收益情况: dt=xgb.DMatrix(xt.values,zzyt)dc=xgb.DMatrix(xc.values,yc)params ={'objective' : 'binary:logistic', #目标函数,逻辑回归(二分类问题)'booster' : 'gbtree', #基学习器'eta' : 0.1, #学习率'gamma' : 0, #惩罚力度'max_depth' :4 ,'eval_metric' : ['error'], #评估指标'min_child_weight':1,'subsample':1,'scale_pos_weight':1,'colsample_bytree':1,'seed':a}watch_list=[(dt,'train')] model = xgb.train(params,dt,1000,evals = watch_list,early_stopping_rounds =10,verbose_eval=False)print((model.predict(dc).round()==yc).mean())#计算准确率
回测结果如下:
可以看到,本文最终获取了45.66%的收益,并实现了0回撤,远远超越了上证综指的表现。 这8个月的选股列表如下表所示:
2021-1 | 2021-2 | 2021-3 | 2021-4 | 2021-5 | 2021-6 | 2021-7 | 2021-8 |
未开仓 | 600543.SH | 600549.SH | 600521.SH | 688208.SH | 未开仓 | 601038.SH | 未开仓 |
---|---|---|---|---|---|---|---|
600707.SH | 600511.SH | 603733.SH | 600892.SH | 601865.SH | |||
601127.SH | 600847.SH | 603960.SH | 600328.SH | 603208.SH | |||
603919.SH | 603225.SH | 600699.SH | 603966.SH | 600526.SH | |||
601579.SH | 600569.SH | 600884.SH | 603530.SH | 603008.SH |
基于Tushare的数据搜集与沪市选股相关推荐
- 基于tushare的股票数据构建1
基于tushare的股票数据构建<一> tushare中提供了很多非常优秀的数据结构,但是并不是所有的数据都对自己有用,这里需要进行构建自己的数据库以方便后续进行数据建模 tushare数 ...
- 基于Tushare一键生成股票基本面数据
tushare ID:488821 开发这个项目完全是出于好奇,就在想自己是否也可以弄出一个类似"芝士财富"这样的一键获取基本面信息的效果. 基于Tushare的api文档和str ...
- python tus股票数据分析_python 股票量化分析(一)---基于Tushare平台的个股历史行情获取...
在浩瀚如烟的股票中,如何将好股选择出来?长线.中线.短线个股如何筛选?国内外政治.经济.地缘博弈基本面对股市的影响有多大,怎样将其纳入股票选择买卖的决策因子?公司财报.未来规划.公司所处行业发展前景怎 ...
- SAP License:SAP顾问该不该参与数据搜集
SAP系统上线时要导入数据,这是众所周知的.一般来说,顾问会提供数据搜集的模板(一般是EXCEL模板),然后客户在这个模板上进行填写.很多人认为,数据搜集是客户的事情,顾问主要是提供模板,将搜集上来的 ...
- 如何使用DolphinDB处理Tushare金融数据
DolphinDB是新一代的时序数据库,不仅可以作为分布式数据仓库或者内存数据库来使用,而且自带丰富的计算工具,可以作为研究工具或研究平台来使用,非常适用于量化金融.物联网等领域的海量数据分析.量化金 ...
- Hadoop精华问答 | 基于Hadoop的数据中心有什么好处?
戳蓝字"CSDN云计算"关注我们哦! 2006年项目成立的一开始,"Hadoop"这个单词只代表了两个组件--HDFS和MapReduce.到现在的13个年头, ...
- 【前沿进展】基于手机信令数据的交通出行特征研究
文章目录 0 概述 1 手机信令数据预处理 2 手机信令数据分析应用 2.1 停留点识别 2.2 职住地分析 2.3 出行方式识别 2.4 交通小区划分 2.5 公交特征分析 2.6 人车轨迹关联 3 ...
- LEAP能源供应转换、能源需求及碳排放预测中的基础数据搜集及处理、能源平衡表核算、模型框架构建、模型操作、情景设计、结果分析、优化、预测结果不确定性分析
采用部门分析法建立的LEAP(Long Range Energy Alternatives Planning System/ Low emission analysis platform,长期能源可替 ...
- Python 应用: 使用Tushare的数据,计算多只股票收益率之间的相关系数与协方差
Python 应用: 使用Tushare的数据,计算多只股票收益率之间的相关系数与协方差 我的Tushare ID:393587 引入模块 导出数据 数据处理 计算相关系数与协方差 引入模块 第一步, ...
最新文章
- 车小米O2O保养平台搭建完毕
- 12-Qt6 列表类QList
- 域名的购买,备案,解析以及绑定云服务器上的项目
- Java中的ThreadLocal的使用--学习笔记
- [推举]网络工程师必懂的专业术语
- java 阻塞 直到完成_完成所有提交的任务后关闭Java执行程序而不会阻塞
- Node.js 模块化开发
- 教你使用faceBook的chisel来提高调试效率
- VC++界面美化---模仿MS Office 选项对话框
- 《她身之欲》(珠三角阅流动人口社群特殊职业研究)阅读感想
- 工信部发布《2018中国区块链产业白皮书》:量子计算机将给密码体系带来重大安全威胁
- html页面打印a4尺寸,html网页打印A4样式
- 开发移动应用的7个致命错误
- 新媒体运营:内容运营的核心与技巧
- 如何查找APP漏洞并渗透测试 解决网站被黑客攻击
- 如何上传自己的项目到Maven中央仓库
- linux bmc管理(工作笔记,随时更新)
- Python(x,y)
- 如何利用能源收获来缓解智能家居的安装挑战?
- kali官方ios下载今天刚刚下载的