Zipline自定义分钟级数据bundle无日历偏移问题求助
我之前也碰到过完全一样的问题!当时自己做了加密货币的Zipline bundle,只导入了分钟级数据,回测时就触发了这个KeyError: Equity(0 [ETHBTC]),根源确实是Zipline底层的日历偏移逻辑依赖日线数据的索引——哪怕你用分钟级回测,它也不会自动帮你重采样生成日线数据,文档里说的“非强制”其实是指你可以不用单独导入日线,但前提是你的bundle能让Zipline从分钟数据自动生成,而默认逻辑里并没有做这件事。
下面是我亲测有效的解决步骤:
1. 在Bundle构建时主动生成日线数据
这是最根本的解决方法,你需要在bundle的ingest函数里,处理完分钟数据后,手动用pandas重采样生成日线数据,并存入bundle的日线存储路径里。
举个代码示例(假设你已经有了分钟级的DataFrame minute_pricing_df):
# 从分钟数据重采样生成日线数据 daily_pricing_df = minute_pricing_df.resample('D').agg({ 'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last', 'volume': 'sum' }).dropna() # 然后把daily_pricing_df写入到bundle对应的daily pricing存储位置 # 比如用zipline的BcolzDailyBarWriter来写入 from zipline.data.bcolz_daily_bars import BcolzDailyBarWriter writer = BcolzDailyBarWriter(daily_pricing_df.index, your_asset_sid_map) writer.write(daily_pricing_df, your_output_path)
这样Zipline在启动回测时就能找到日线数据的日历偏移,不会触发KeyError了。
2. 在回测初始化时提前触发日线数据加载
如果暂时不想修改bundle的构建逻辑,你可以在算法的initialize函数里提前加载一次日线数据,强制Zipline初始化日历偏移:
def initialize(context): # 设置回测的发射频率为分钟 context.sim_params.emission_rate = 'minute' # 获取目标资产 context.ethbtc = symbol('ETHBTC') # 提前加载1天的日线数据,触发Zipline初始化日历偏移 data.history(context.ethbtc, 'price', 1, '1d') def handle_data(context, data): order(context.ethbtc, 10) record(ETHBTC=data.current(context.ethbtc, 'price'))
这一步相当于“提前触发”Zipline加载日线数据的索引,这样后续handle_data里调用data.current时就不会找不到偏移量了。
3. 检查Zipline版本兼容性
你用的是Python3.5对应的Zipline版本,这个版本比较老,对加密货币这类非美股资产的多时间维度数据处理有bug,不会自动从分钟数据重采样生成日线。如果条件允许,建议升级到Zipline的最新兼容版本(注意匹配Python版本,比如Python3.8+对应的Zipline版本),新版本对非传统资产的支持更完善,可能不需要手动处理日线数据。
内容的提问来源于stack exchange,提问作者kiecodes

