问题描述
写的实盘代码,对方在模拟端里测试的时候,无论在回测,还是实盘,数据均为空。
比如运行下面的代码,回测里面:
import datetime
def initialize(context):
g.start = True
def handle_data(context, data):
if g.start:
log.info("公众号:可转债量化分析")
g.start = False
execution(context)
def execution(context):
code_list = ['600119.SS']
new_df = get_price(code_list, start_date=None, end_date=None, frequency='1m', fields=[
'close'], fq='pre', count=30)
print(new_df)
输出的数据是空的。
解决方案
在 Ptrade 量化平台中,遇到 get_price 返回空数据是一个非常常见的问题。根据 Ptrade 官方 API 文档的底层逻辑,导致你代码中数据为空的核心原因主要有以下两点:
为什么 get_price 会返回空数据?
-
get_price不包含当天数据(核心原因)
Ptrade 官方文档明确指出:“数据返回内容不包括当天数据”。get_price主要用于获取历史指定时间段的数据。如果你在盘中(或回测的当天)调用它来获取1m(分钟级别)的数据,且没有指定end_date,系统默认截止到昨天,这会导致在某些券商的模拟端或实盘环境中直接返回空值。 -
end_date参数未明确指定
在回测环境中,get_price的end_date如果不传,系统有时无法正确推断当前的回测时间边界。文档建议:“回测中输入请小于回测日期,交易、研究中输入请小于当前日期”。
解决方案:使用 get_history 替代
在 handle_data、run_daily 或 run_interval 等盘中运行的函数里,获取最近 N 根 K 线(尤其是分钟线)的标准做法是使用 get_history,而不是 get_price。
get_history 专为盘中实时获取行情设计,且可以通过 include=True/False 参数控制是否包含当前未走完的 K 线。
修正后的代码示例:
def initialize(context):
g.start = True
# 建议在初始化时设置股票池,这样 get_history 可以更高效地获取数据
set_universe(['600119.SS'])
def handle_data(context, data):
if g.start:
log.info("开始获取数据")
g.start = False
execution(context)
def execution(context):
code_list = ['600119.SS']
# 使用 get_history 替代 get_price
# count=30: 获取30根K线
# frequency='1m': 1分钟线
# include=False: 不包含当前正在生成的这一分钟(避免未来函数)
new_df = get_history(count=30, frequency='1m', field=['close'], security_list=code_list, fq='pre', include=False)
print(new_df)
补充避坑指南
- 多线程调用冲突:文档中特别警告,
get_history与get_price不支持多线程同时调用。千万不要在run_interval和handle_data同一时刻同时调用这两个接口,否则会偶发性返回空数据。 - 多股票返回格式差异:当你传入
code_list(即使里面只有1只股票)时,Ptrade 会将其视为多股票查询。在 Python 3.11 环境下,返回的 DataFrame 会包含code列;在 Python 3.5 环境下,返回的可能是 Panel 对象或以股票代码为列名的 DataFrame。建议打印出type(new_df)确认数据结构,以便后续正确解析。