问题描述
/
解决方案
问题分析
在ptrade量化交易平台中,如果您在早上8:10使用get_price函数尝试获取上一交易日的数据却获取不到(返回空数据或报错),通常是由以下几个原因造成的:
- 券商系统日切与维护:早上8:00至9:00通常是券商柜台系统和行情服务器进行“日切”(清算、结算、历史数据归档与新一日数据初始化)的时间段。在这个时间窗口内,历史行情数据库可能处于锁定、更新或重启状态,导致API无法正常读取数据。
- 默认日期判定偏差:
get_price函数如果不传入end_date,系统会默认使用“当前日期”。在日切未完全结束前,系统对“当前日期”的判定可能存在滞后,导致获取逻辑出错。 - 官方文档的限制说明:根据ptrade官方文档在
before_trading_start部分的说明:“当在9:10前开启交易时,受行情未更新原因在该函数内调用实时行情接口会导致数据有误。” 虽然get_price是历史数据接口,但同样受底层行情服务就绪状态的影响。
解决方案与最佳实践
为了稳定地获取上一交易日的数据,建议采取以下几种解决方案:
方案一:调整数据获取的执行时间(推荐)
避免在极早的时间段(如8:10)获取数据。您可以将获取数据的逻辑放在before_trading_start函数中(实盘默认在9:10执行),或者使用run_daily指定在9:15之后执行。
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
# 推荐:使用 run_daily 在 9:15 获取数据,此时系统已完全就绪
run_daily(context, get_yesterday_data, time='09:15')
def get_yesterday_data(context):
# 此时获取上一交易日数据非常稳定
df = get_price(g.security, count=1, frequency='1d', fields=['close'])
if df is not None and not df.empty:
log.info("成功获取上一交易日收盘价: %s" % df['close'].iloc[-1])
def handle_data(context, data):
pass
方案二:在 before_trading_start 中获取
实盘交易中,before_trading_start 默认在 9:10 执行,此时获取历史数据通常是安全的。
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
def before_trading_start(context, data):
# 9:10 执行,获取过去5天的历史数据
df = get_price(g.security, count=5, frequency='1d', fields=['close', 'open'])
log.info("盘前获取的历史数据:\n%s" % df)
def handle_data(context, data):
pass
方案三:明确指定 end_date 并增加异常重试
如果您必须在研究环境或极早的定时任务中运行,请务必明确传入上一交易日的具体日期作为 end_date,并加入 try-except 保护机制。
import time
def get_data_with_retry(security, target_date):
max_retries = 3
for i in range(max_retries):
try:
# 明确传入 end_date
df = get_price(security, end_date=target_date, count=1, frequency='1d')
if df is not None and not df.empty:
return df
except Exception as e:
log.warning("第 %d 次获取数据失败: %s" % (i+1, e))
time.sleep(5) # 等待5秒后重试
return None
总结:量化交易中,数据的稳定性至关重要。尽量顺应券商系统的运行规律,将盘前数据准备工作安排在 9:10 至 9:25 之间,可以最大程度避免因系统日切导致的数据获取失败问题。