问题描述
/
解决方案
问题背景:ptrade与Tushare的代码后缀差异
在量化交易开发中,很多开发者习惯使用 Tushare 获取本地数据进行研究,然后将策略迁移到 ptrade 平台进行回测和实盘。然而,这两个平台在**上海证券交易所(上交所)**的股票代码后缀定义上存在差异,导致直接混用代码会引发一系列报错。
- ptrade 平台:上交所股票后缀为
.SS(如600570.SS),深交所为.SZ(如000001.SZ)。 - Tushare 接口:上交所股票后缀为
.SH(如600570.SH),深交所为.SZ(如000001.SZ)。
深交所的代码后缀(.SZ)在两边是兼容的,核心冲突在于上交所的 .SS 与 .SH。
常见问题表现
如果不进行代码转换,直接混用会导致以下典型问题:
- 下单失败:在 ptrade 中调用
order('600570.SH', 100),系统会提示找不到该标的或标的不存在,导致委托失败。 - 行情获取报错:使用
get_history()或get_price()时传入.SH后缀,返回的数据为空或直接抛出异常。 - 持仓查询错位:从 ptrade 的
context.portfolio.positions获取的持仓代码(带.SS),直接传给 Tushare 接口查询基本面或财务数据时,Tushare 会返回空 DataFrame。
解决方案:编写Python转换函数
为了在策略中无缝衔接 ptrade 和 Tushare 的数据,最稳妥的方法是编写两个简单的字符串转换函数,在数据交互的边界进行清洗。
1. Tushare 代码转 ptrade 代码
当您从 Tushare 获取了股票池列表,准备传入 ptrade 的 set_universe() 或 order() 时使用:
def ts_to_ptrade(ts_code):
"""
将 Tushare 代码 (如 600570.SH) 转换为 ptrade 代码 (如 600570.SS)
"""
if not isinstance(ts_code, str):
return ts_code
if ts_code.endswith('.SH'):
return ts_code.replace('.SH', '.SS')
return ts_code
# 批量转换列表
def ts_to_ptrade_list(ts_code_list):
return [ts_to_ptrade(code) for code in ts_code_list]
2. ptrade 代码转 Tushare 代码
当您获取了 ptrade 的持仓代码,需要调用 Tushare 接口获取额外数据时使用:
def ptrade_to_ts(pt_code):
"""
将 ptrade 代码 (如 600570.SS) 转换为 Tushare 代码 (如 600570.SH)
"""
if not isinstance(pt_code, str):
return pt_code
if pt_code.endswith('.SS'):
return pt_code.replace('.SS', '.SH')
return pt_code
# 批量转换列表
def ptrade_to_ts_list(pt_code_list):
return [ptrade_to_ts(code) for code in pt_code_list]
ptrade 策略中的实战应用示例
以下是一个在 ptrade 策略中结合 Tushare 数据(假设通过某种方式引入)并处理代码后缀的完整示例:
import pandas as pd
# 转换函数定义
def ts_to_ptrade(ts_code):
return ts_code.replace('.SH', '.SS') if ts_code.endswith('.SH') else ts_code
def initialize(context):
# 假设这是从 Tushare 获取的选股列表
tushare_pool = ['600570.SH', '000001.SZ', '600000.SH']
# 转换为 ptrade 兼容格式
g.security = [ts_to_ptrade(code) for code in tushare_pool]
# 设置 ptrade 股票池
set_universe(g.security)
log.info(f"转换后的股票池: {g.security}")
def handle_data(context, data):
for stock in g.security:
# 获取 ptrade 行情数据
hist = get_history(5, '1d', 'close', security_list=stock)
if not hist.empty:
current_price = data[stock]['close']
# 简单的买入逻辑
if current_price > hist['close'].mean() and get_position(stock).amount == 0:
order(stock, 100)
log.info(f"买入 {stock}")
总结
处理 ptrade 与 Tushare 的代码后缀不兼容问题,核心在于明确数据流向。在将外部数据喂给 ptrade API 之前,务必将 .SH 替换为 .SS;在将 ptrade 产生的代码用于外部查询时,反向替换即可。养成在策略初始化阶段统一清洗代码格式的习惯,可以有效避免实盘中因代码不匹配导致的交易遗漏。