3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在聚宽(JoinQuant)平台上进行因子拥挤度择时策略的长周期回测时,由于涉及大量标的的历史行情、财务指标及因子计算,策略极易触发平台的内存限制(3G)或因高频调用API导致运行缓慢。以下是针对内存和API调用的深度优化方案:
聚宽默认开启了数据缓存以加速运行,但在长周期、大股票池回测中,缓存会不断累积导致内存溢出。
initialize 中调用 disable_cache()。虽然这会略微降低单次查询速度,但能显著降低内存占用,防止进程被系统强制杀死。def initialize(context):
# 关闭缓存机制,防止长周期回测内存超限
disable_cache()
set_option('use_real_price', True)
get_current_data 的高频调用get_current_data() 是一个高耗时且在盘中按需获取数据的API。在 handle_data 或分钟回测中,切忌在循环中对每只股票单独调用。
get_bars / attribute_history 批量获取。# 错误示范:在循环中对每只股票调用
# for stock in g.stocks:
# current_data = get_current_data()[stock]
# 正确示范:在循环外一次性获取,利用 dict 机制按需加载
def handle_data(context, data):
current_data = get_current_data()
for stock in g.stocks:
if current_data[stock].paused:
continue
# 执行择时逻辑
get_fundamentals:从“每日查询”到“按季/按月批量获取”因子拥挤度计算通常需要市值(valuation)和财务报表数据。每天在盘中调用 get_fundamentals 会产生极大的API开销。
get_fundamentals_continuously:一次性获取多日的财务数据,减少I/O次数。before_market_open 中批量获取一次,并存入全局变量 g 中复用。def before_market_open(context):
# 仅在需要调仓或计算拥挤度时批量获取财务数据
q = query(valuation.code, valuation.market_cap, valuation.pe_ratio).filter(valuation.code.in_(g.stocks))
# 获取当前时间前一天的最新财务数据
g.fundamental_df = get_fundamentals(q, date=context.previous_date)
在计算因子拥挤度(如因子收益率标准差、行业集中度、因子自相关性)时,避免使用 Python 的 for 循环,应充分利用 pandas 和 numpy 的向量化操作,并结合 jqfactor 的内置函数。
from jqfactor import winsorize_med, standardlize, neutralize
def calculate_crowding_factor(context):
# 假设已获取因子值 DataFrame: df_factors (index为日期,columns为股票)
# 1. 中位数去极值 (向量化处理)
clean_factors = winsorize_med(g.factor_df, scale=3, axis=1)
# 2. 标准化
std_factors = standardlize(clean_factors, axis=1)
# 3. 行业与市值中性化
neutral_factors = neutralize(std_factors, how=['jq_l1', 'market_cap'], date=context.previous_date, axis=1)
return neutral_factors
在长周期模拟盘中,g 对象的大小不能超过 30M。不要将不可序列化的对象(如数据库连接 query、打开的文件等)存入 g。对于这些对象,应在 process_initialize 中以双下划线开头命名进行初始化:
def process_initialize(context):
# 每次进程重启时初始化,系统序列化 g 时会自动忽略双下划线开头的变量
g.__q = query(valuation.code, valuation.market_cap)