news 2026/7/6 13:22:22

python:backtrader 如何使用 tushare 股票数据?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python:backtrader 如何使用 tushare 股票数据?

我来详细介绍在Backtrader中使用Tushare数据的几种方法,从简单到复杂,包括示例代码。

方法1:使用PandasData(推荐,最灵活)

这是最常用的方法,将Tushare数据转换为Pandas DataFrame,然后用Backtrader的PandasData适配器加载。

基本示例

importbacktraderasbtimporttushareastsimportpandasaspdfromdatetimeimportdatetime# 1. 从Tushare获取数据defget_tushare_data(ts_code='000001.SZ',start_date='20200101',end_date='20231231'):""" 获取Tushare股票数据并转换为Backtrader需要的格式 """# 初始化tushare(需要token)ts.set_token('你的tushare_token')# 替换为你的tokenpro=ts.pro_api()# 获取日线数据df=pro.daily(ts_code=ts_code,start_date=start_date,end_date=end_date)# 数据清洗和格式化df=df.sort_values('trade_date')# 按日期排序df['trade_date']=pd.to_datetime(df['trade_date'])# 转换为datetimedf.set_index('trade_date',inplace=True)# 设置日期为索引# 重命名列以匹配Backtrader的PandasDatadf.rename(columns={'open':'Open','high':'High','low':'Low','close':'Close','vol':'Volume'},inplace=True)# 只保留需要的列df=df[['Open','High','Low','Close','Volume']]returndf# 2. 创建自定义的PandasData类(可选,处理Tushare特有字段)classTusharePandasData(bt.feeds.PandasData):""" 自定义PandasData以处理Tushare数据 可以添加更多字段如换手率、涨跌幅等 """params=(('datetime',None),# 使用索引作为datetime('open','Open'),('high','High'),('low','Low'),('close','Close'),('volume','Volume'),('openinterest',-1),# 无持仓量字段# 可以添加额外字段# ('pct_chg', 'pct_chg'), # 如果需要涨跌幅)# 3. 完整的回测示例classSmaCrossStrategy(bt.Strategy):params=(('fast',10),('slow',30),)def__init__(self):self.fast_sma=bt.indicators.SMA(self.data.close,period=self.params.fast)self.slow_sma=bt.indicators.SMA(self.data.close,period=self.params.slow)self.crossover=bt.indicators.CrossOver(self.fast_sma,self.slow_sma)defnext(self):ifnotself.position:ifself.crossover>0:# 金叉self.buy()elifself.crossover<0:# 死叉self.close()defrun_backtest():# 创建Cerebro引擎cerebro=bt.Cerebro()# 获取数据print("正在获取数据...")df=get_tushare_data('000001.SZ','20200101','20231231')ifdf.empty:print("数据获取失败,请检查网络或token")returnprint(f"数据量:{len(df)}条")print(f"日期范围:{df.index[0]}{df.index[-1]}")# 创建数据源data=TusharePandasData(dataname=df)# 添加到引擎cerebro.adddata(data)# 添加策略cerebro.addstrategy(SmaCrossStrategy)# 设置初始资金cerebro.broker.setcash(100000.0)# 设置佣金cerebro.broker.setcommission(commission=0.001)# 0.1%佣金# 添加分析器cerebro.addanalyzer(bt.analyzers.Returns,_name='returns')cerebro.addanalyzer(bt.analyzers.SharpeRatio,_name='sharpe')cerebro.addanalyzer(bt.analyzers.DrawDown,_name='drawdown')cerebro.addanalyzer(bt.analyzers.TradeAnalyzer,_name='trades')# 运行回测print('初始资金: %.2f'%cerebro.broker.getvalue())results=cerebro.run()print('最终资金: %.2f'%cerebro.broker.getvalue())# 打印分析结果strat=results[0]print("\n=== 策略绩效 ===")print(f"总收益率:{strat.analyzers.returns.get_analysis()['rtot']:.2%}")sharpe_ratio=strat.analyzers.sharpe.get_analysis()print(f"夏普比率:{sharpe_ratio['sharperatio']:.3f}")drawdown=strat.analyzers.drawdown.get_analysis()print(f"最大回撤:{drawdown['max']['drawdown']:.2%}")print(f"最长回撤周期:{drawdown['max']['len']}天")trades=strat.analyzers.trades.get_analysis()if'total'intrades:print(f"总交易次数:{trades['total']['total']}")print(f"盈利交易:{trades['won']['total']}")print(f"亏损交易:{trades['lost']['total']}")iftrades['won']['total']>0:print(f"胜率:{trades['won']['total']/trades['total']['total']:.2%}")# 绘制图表cerebro.plot(style='candlestick',volume=True)if__name__=='__main__':run_backtest()

方法2:使用通用CSVData(保存为CSV再读取)

如果不想每次都从Tushare API获取,可以先保存到本地CSV。

importbacktraderasbtimporttushareastsimportpandasaspdimportosclassTushareCSVData(bt.feeds.GenericCSVData):""" 自定义CSV数据加载器 """params=(('datetime',0),# 日期列索引('open',1),# 开盘价列索引('high',2),# 最高价列索引('low',3),# 最低价列索引('close',4),# 收盘价列索引('volume',5),# 成交量列索引('openinterest',-1),# 无持仓量('dtformat','%Y-%m-%d'),# 日期格式('nullvalue',0.0),)defdownload_and_save_tushare_data(ts_code='000001.SZ',start_date='20200101',end_date='20231231',save_path='data.csv'):"""下载Tushare数据并保存为CSV"""ts.set_token('你的tushare_token')pro=ts.pro_api()df=pro.daily(ts_code=ts_code,start_date=start_date,end_date=end_date)# 格式化df=df.sort_values('trade_date')df['trade_date']=pd.to_datetime(df['trade_date'])# 保存为CSVdf.to_csv(save_path,index=False)print(f"数据已保存到:{save_path}")returnsave_path# 使用示例csv_file=download_and_save_tushare_data('000001.SZ')data=TushareCSVData(dataname=csv_file)

方法3:使用自定义Data Feed(最灵活,但复杂)

对于需要特殊处理的场景,可以创建完全自定义的Data Feed。

classTushareDirectData(bt.feeds.DataBase):""" 直接连接Tushare的Data Feed(示例) 注意:这需要处理实时数据连接,实际使用较少 """params=(('ts_code','000001.SZ'),('start_date','20200101'),('end_date','20231231'),)def__init__(self):super().__init__()# 初始化tushare连接ts.set_token('你的tushare_token')self.pro=ts.pro_api()self.data_df=Noneself.idx=0defstart(self):"""开始加载数据"""self.data_df=self.pro.daily(ts_code=self.p.ts_code,start_date=self.p.start_date,end_date=self.p.end_date)self.data_df=self.data_df.sort_values('trade_date')self.idx=0def_load(self):"""加载下一行数据"""ifself.idx>=len(self.data_df):returnFalserow=self.data_df.iloc[self.idx]# 设置当前bar的数据self.lines.datetime[0]=bt.date2num(pd.to_datetime(row['trade_date']))self.lines.open[0]=row['open']self.lines.high[0]=row['high']self.lines.low[0]=row['low']self.lines.close[0]=row['close']self.lines.volume[0]=row['vol']self.lines.openinterest[0]=0self.idx+=1returnTrue

完整的多股票回测示例

defmulti_stock_backtest():"""多股票回测示例"""cerebro=bt.Cerebro()# 股票列表stocks=['000001.SZ','000002.SZ','000858.SZ']forstock_codeinstocks:try:# 获取数据df=get_tushare_data(stock_code,'20200101','20231231')ifnotdf.empty:# 创建数据源data=TusharePandasData(dataname=df,name=stock_code)cerebro.adddata(data)print(f"已添加:{stock_code}")else:print(f"跳过{stock_code},无数据")exceptExceptionase:print(f"获取{stock_code}数据失败:{e}")iflen(cerebro.datas)==0:print("没有可用的数据")return# 添加策略cerebro.addstrategy(SmaCrossStrategy)# 设置初始资金和佣金cerebro.broker.setcash(100000.0)cerebro.broker.setcommission(commission=0.001)# 运行回测print(f"初始资金:{cerebro.broker.getvalue():.2f}")cerebro.run()print(f"最终资金:{cerebro.broker.getvalue():.2f}")# 绘图cerebro.plot()

Tushare数据字段映射表

Tushare字段Backtrader字段说明
trade_datedatetime交易日期
openopen开盘价
highhigh最高价
lowlow最低价
closeclose收盘价
volvolume成交量
amount-成交额(需特殊处理)
pct_chg-涨跌幅(可添加为额外字段)

实用技巧和注意事项

1.数据预处理

defpreprocess_tushare_data(df):"""数据预处理"""# 1. 处理缺失值df=df.fillna(method='ffill')# 2. 处理异常值df=df[(df['High']>=df['Low'])&(df['Volume']>0)]# 3. 添加额外指标df['Returns']=df['Close'].pct_change()# 4. 确保索引是datetimedf.index=pd.to_datetime(df.index)returndf

2.使用缓存提高效率

importpickleimporthashlibfromfunctoolsimportlru_cache@lru_cache(maxsize=10)defget_cached_tushare_data(ts_code,start_date,end_date):"""带缓存的数据获取"""cache_key=f"{ts_code}_{start_date}_{end_date}"cache_file=f"cache/{hashlib.md5(cache_key.encode()).hexdigest()}.pkl"ifos.path.exists(cache_file):withopen(cache_file,'rb')asf:returnpickle.load(f)else:df=get_tushare_data(ts_code,start_date,end_date)os.makedirs('cache',exist_ok=True)withopen(cache_file,'wb')asf:pickle.dump(df,f)returndf

3.处理复权数据

defget_adj_data(ts_code,start_date,end_date):"""获取复权数据"""ts.set_token('你的token')pro=ts.pro_api()# 获取复权因子df_adj=pro.adj_factor(ts_code=ts_code,trade_date='')# 获取前复权数据df=pro.pro_bar(ts_code=ts_code,adj='qfq',# qfq:前复权, hfq:后复权start_date=start_date,end_date=end_date)# ... 后续处理returndf

4.常见问题解决

问题1:数据时间范围不正确

# 确保数据包含回测所需的时间范围start_date='20190101'# 比回测开始时间早,用于计算指标end_date='20231231'

问题2:成交量单位不一致

# Tushare的成交量单位是"手",需要转换为"股"df['Volume']=df['Volume']*100# 1手 = 100股

问题3:非交易日数据缺失

# 填充非交易日df=df.asfreq('D')# 设置为每日频率df=df.fillna(method='ffill')# 向前填充

5.优化建议

  1. 使用Tushare Pro:免费版有频率限制,Pro版更稳定
  2. 批量下载数据:避免在循环中频繁调用API
  3. 本地缓存:减少API调用次数
  4. 错误处理:添加重试机制
  5. 数据验证:检查数据完整性和准确性

总结

使用Tushare数据配合Backtrader的最佳实践

  1. 使用PandasData方法(方法1),灵活且高效
  2. 做好数据预处理缓存
  3. 注意数据字段映射单位转换
  4. 添加适当的错误处理日志记录

这样就能充分利用 Tushare 丰富的数据和 Backtrader 强大的回测功能了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 0:36:57

Netcode for GameObjects Boss Room 多人RPG战斗(19)

ActionPlayers ActionPlayers是Boss Room项目中负责管理和执行动作(Action)的核心组件,分为客户端和服务器端两个版本,分别处理动作的视觉表现和逻辑执行。 1. 系统架构 1.1 核心组件 组件 职责 位置 ClientActionPlayer 客户端动作可视化与生命周期管理 Assets/Scripts/G…

作者头像 李华
网站建设 2026/7/5 6:13:28

深度学习优化器算法巧思速览

1. 为什么要研究优化器算法&#xff1f;它的关联问题&#xff1a;训练为什么要调参&#xff0c;调的是什么参&#xff1f;如果就这个问题去问各种大语言模型&#xff0c;它们能给出一堆的理由。但就博主而言&#xff0c;答案只有一个&#xff1a;干掉调参&#xff0c;解放生产力…

作者头像 李华
网站建设 2026/7/6 11:38:37

macOS上优雅运行Docker容器

什么是colimacolima主页Colima&#xff08;Container on Lima&#xff09;是一个轻量级的容器运行时管理工具&#xff0c;专为macOS&#xff08;同时也支持Linux&#xff09;设计&#xff0c;提供了一种简单优雅的方式来运行容器。它基于Lima项目&#xff0c;后者为macOS提供了…

作者头像 李华
网站建设 2026/7/6 0:50:46

XXL-JOB分布式任务调度

1.什么是任务调度 简单说&#xff1a;按照指定的规则&#xff08;时间、频率、条件&#xff09;自动执行某个任务&#xff0c;不需要人工手动触发。比如&#xff1a; 每天凌晨 2 点执行数据备份&#xff1b;每 5 分钟检查一次接口可用性&#xff1b;订单支付超时&#xff08;30…

作者头像 李华
网站建设 2026/7/6 8:42:41

MYSQL与B+树与索引相关面试题

第一题&#xff08;基础&#xff09;&#xff1a;请简述 MySQL 中索引底层为什么选择 B 树&#xff0c;而不是 B 树、红黑树等其他数据结构&#xff1f;第二题&#xff08;基础进阶&#xff09;&#xff1a;MySQL 中聚簇索引和非聚簇索引的区别是什么&#xff1f;它们的叶子节…

作者头像 李华
网站建设 2026/7/6 9:27:00

PostgreSQL pgvector扩展Windows环境完整安装指南

PostgreSQL pgvector扩展Windows环境完整安装指南 【免费下载链接】pgvector Open-source vector similarity search for Postgres 项目地址: https://gitcode.com/GitHub_Trending/pg/pgvector 在人工智能应用日益普及的今天&#xff0c;向量相似性搜索已成为现代数据库…

作者头像 李华