PineScript内存超限求助:仅用30个request.security()仍报错
问题
我了解PineScript允许最多40个request.security()函数,而我仅使用了30个,但运行代码时却触发“内存超限”错误。代码加载正常,但在回放模式下(尤其低周期如NIFTY/5M)会提示Memory Limits exceeded. Study allocates 1.2 times more than allowed,请求分析原因并提供优化方案。
原因分析
- 隐式重复计算:
func_roc()依赖全局变量n10/n20(来自NIFTY的request.security()结果),每个后续标的的request.security()调用执行func_roc()时,都会重复计算NIFTY的ROC值,而非复用已有结果,额外消耗内存与计算资源。 - 低周期数据过载:5分钟周期需要加载更多历史K线,30个
request.security()会同时拉取对应标的的全量数据,叠加后内存占用远超预期。 - 零散变量内存开销:用独立变量(
fc_roca2到fc_roca30)存储每个标的结果,大量零散变量会增加内存管理的额外负担。
优化方案
1. 复用基准计算结果
修改func_roc()为接收外部参数的形式,避免每个请求重复计算NIFTY的ROC值:
func_roc(n10, n20) => res = (ta.roc(close, 10) - n10) + (ta.roc(close, 20) - n20) math.round(res,1)
2. 数组批量存储结果
用数组替代独立变量,减少内存碎片化:
// 初始化数组存储结果 var float[] roc_results = array.new_float() // 标的列表统一管理 symbols = ['ADANIENT', 'ADANIPORTS', 'APOLLOHOSP', 'ASIANPAINT', 'AXISBANK', 'BAJAJ_AUTO', 'BAJFINANCE', 'BAJAJFINSV', 'BHARTIARTL', 'BRITANNIA', 'CIPLA', 'COALINDIA', 'DIVISLAB', 'DRREDDY', 'EICHERMOT', 'GRASIM', 'HCLTECH', 'HDFCBANK', 'HDFCLIFE', 'HEROMOTOCO', 'HINDALCO', 'HINDUNILVR', 'ICICIBANK', 'ITC', 'INDUSINDBK', 'INFY', 'JSWSTEEL', 'KOTAKBANK', 'LTIM']
3. 限制计算时机与数据加载
通过barstate.islast仅在最后一根K线执行计算,同时关闭超前引用减少内存占用:
roc_val = request.security(sym, '', func_roc(n10, n20), lookahead=barmerge.lookahead_off)
4. 循环优化表格渲染
用循环批量填充表格,替代重复的table.cell()调用:
if barstate.islast table.clear(tb1) row = 0 col = 0 for i = 0 to array.size(roc_results)-1 table.cell(tb1, col, row, str.tostring(array.get(roc_results, i))) col += 1 if col >= 5 // 每5个数据换行 col := 0 row += 1
完整优化代码
//@version=5 indicator("Optimized - Instruments", overlay = true) // 计算NIFTY基准ROC值 func_rocn() => r1=ta.roc(close, 10) r2=ta.roc(close, 20) [r1, r2] [n10, n20] = request.security('NIFTY', '', func_rocn(), lookahead=barmerge.lookahead_off) // 传入基准值计算单个标的ROC差值 func_roc(n10, n20) => res = (ta.roc(close, 10) - n10) + (ta.roc(close, 20) - n20) math.round(res,1) // 标的列表 symbols = ['ADANIENT', 'ADANIPORTS', 'APOLLOHOSP', 'ASIANPAINT', 'AXISBANK', 'BAJAJ_AUTO', 'BAJFINANCE', 'BAJAJFINSV', 'BHARTIARTL', 'BRITANNIA', 'CIPLA', 'COALINDIA', 'DIVISLAB', 'DRREDDY', 'EICHERMOT', 'GRASIM', 'HCLTECH', 'HDFCBANK', 'HDFCLIFE', 'HEROMOTOCO', 'HINDALCO', 'HINDUNILVR', 'ICICIBANK', 'ITC', 'INDUSINDBK', 'INFY', 'JSWSTEEL', 'KOTAKBANK', 'LTIM'] // 数组存储结果与表格初始化 var float[] roc_results = array.new_float() var tb1 = table.new(position.top_right, 5, 8, color.white, color.aqua, 1, color.aqua, 1) if barstate.islast array.clear(roc_results) // 批量获取所有标的结果 for sym in symbols roc_val = request.security(sym, '', func_roc(n10, n20), lookahead=barmerge.lookahead_off) array.push(roc_results, roc_val) // 批量填充表格 table.clear(tb1) row = 0 col = 0 for i = 0 to array.size(roc_results)-1 table.cell(tb1, col, row, str.tostring(array.get(roc_results, i))) col += 1 if col >= 5 col := 0 row += 1
内容的提问来源于stack exchange,提问作者Surendra Yannam
相关产品推荐
相关产品推荐

