问题描述
/
解决方案
get_trade_days 的 count 参数最大限制
在 ptrade 量化交易平台中,使用 get_trade_days 接口获取交易日历时,官方文档明确建议 count 参数的值不应大于 3000。
为什么不能设置过大(如 10000)?
- 历史数据极限:A股市场成立于1990年底。一年大约有250个交易日,3000个交易日已经可以回溯约12年的时间,甚至更早(API底层限制返回数据的开始日期不早于1990年)。设置
count=10000意味着要获取40年前的交易日,这超出了底层数据的有效范围。 - 内存与性能消耗:请求超大范围的无效数据会导致底层引擎进行无意义的循环计算和内存分配,极易引发策略运行缓慢,甚至导致内存溢出(OOM)使策略崩溃。
如何优化大数据量获取与策略性能?
如果您在策略中需要频繁处理大量的交易日历数据,建议采用以下优化方案:
1. 限制合理的 count 范围
绝大多数策略(如计算均线、动量等)通常只需要回溯几十到几百个交易日。请根据实际业务逻辑传入最小够用的 count 值(例如一年传入 250)。
2. 使用 start_date 和 end_date 替代 count
如果您明确知道需要获取的时间段,使用 start_date 和 end_date 进行区间查询,比使用 count 盲目回溯更加高效且安全。
# 推荐做法:明确指定日期范围
trade_days = get_trade_days(start_date='2020-01-01', end_date='2023-01-01')
3. 避免在 handle_data 中高频调用
handle_data(日线/分钟线)或 tick_data(Tick级)会被高频触发。如果在这些函数中反复调用 get_trade_days,会极大地拖慢策略运行速度。
优化方案:在 initialize 或 before_trading_start 中一次性获取并缓存到全局变量 g 中。
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
# 在初始化时获取一次,避免盘中重复获取
g.recent_trade_days = get_trade_days(count=250)
def before_trading_start(context, data):
# 每天盘前更新一次即可
g.recent_trade_days = get_trade_days(count=250)
def handle_data(context, data):
# 直接使用缓存的数据,速度极快
days = g.recent_trade_days
pass
4. 使用 get_all_trades_days() 替代
如果您确实需要极长周期的交易日历,可以直接调用 get_all_trades_days() 获取当前日期之前的所有交易日(返回一个 numpy.ndarray),然后在本地使用 Python 的切片功能进行处理,这样比反复调用 get_trade_days 性能更好。
def initialize(context):
# 一次性获取历史所有交易日
all_days = get_all_trades_days()
# 使用 numpy 切片获取最近 1000 个交易日
g.my_days = all_days[-1000:]
总结
遇到策略运行缓慢或内存溢出时,首先检查是否在循环或高频事件(如 handle_data)中传入了不合理的超大参数(如 count=10000)。遵循 “按需获取、盘前缓存、合理切片” 的原则,可以显著提升 ptrade 策略的运行效率。