创建带Faustmann比率与Spitznaegel ROIC的表格时请求超限问题
解决TradingView脚本请求证券数量超限问题
问题根源
当前代码的核心问题是重复且嵌套的请求调用:
- 每个标的调用了2次
request.security(一次计算SFM,一次计算SROIC) - 每次
request.security内部又包含多个request.financial调用,每个request.financial都会被算作一次独立的证券请求 - 3个标的的情况下,总请求数远超过TradingView的40次限制
优化方案
核心思路是合并请求:把SFM和SROIC的计算逻辑放在同一个request.security调用中,每个标的只发起一次跨证券请求,一次性获取所有需要的财务数据并计算两个指标。
优化后的完整代码
//@version=5 indicator('test screener', overlay=true) //////////// // INPUTS // col_width = input.float(6, title = "Column Width (%)") scr_numb = input.int(3, title = "Screen #", tooltip = '1 - rightmost screener', minval = 1) ///////////// // SYMBOLS // u01 = input.bool(true, title = "", group = 'Symbols', inline = 's01') u02 = input.bool(true, title = "", group = 'Symbols', inline = 's02') u03 = input.bool(true, title = "", group = 'Symbols', inline = 's03') s01 = input.symbol('CF', group = 'Symbols', inline = 's01') s02 = input.symbol('CLF', group = 'Symbols', inline = 's02') s03 = input.symbol('DFS', group = 'Symbols', inline = 's03') ////////////////// // COMBINED CALCULATIONS // // 合并SFM和SROIC的计算,每个标的只调用一次security calculateIndicators(s) => // --- SFM计算 --- cur_assets = request.financial(s, "TOTAL_CURRENT_ASSETS", "FQ") net_ppe = request.financial(s, "PPE_TOTAL_NET", "FQ") cap_leases = request.financial(s, "CAPITAL_OPERATING_LEASE_OBLIGATIONS", "FQ") long_term_investments = request.financial(s, "LONG_TERM_INVESTMENTS", "FQ") cur_liabilities = request.financial(s, "TOTAL_CURRENT_LIABILITIES", "FQ") cash = request.financial(s, "CASH_N_EQUIVALENTS", "FQ") invested_capital = cur_assets[0] + net_ppe[0] + cap_leases[0] + long_term_investments[0] - cur_liabilities[0] - cash[0] shares_outstanding = request.financial(s, "TOTAL_SHARES_OUTSTANDING", "FQ") common_market_cap = shares_outstanding[0] * close long_term_debt = request.financial(s, "LONG_TERM_DEBT", "FQ") preferred_stock = request.financial(s, "PREFERRED_STOCK_CARRYING_VALUE", "FQ") net_worth = invested_capital + cash[0] - long_term_debt[0] - cap_leases[0] - preferred_stock[0] fm = common_market_cap / net_worth // --- SROIC计算 --- var ebit_ttm = float(na) var ebit_q1 = 0.0 var ebit_q2 = 0.0 var ebit_q3 = 0.0 var ebit_q4 = 0.0 ebit_series_filled = request.financial(s, "EBIT", "FQ", ignore_invalid_symbol = false) ebit_series_fq = request.financial(s, "EBIT", "FQ", ignore_invalid_symbol = true) ebit_series_fy = request.financial(s, "EBIT", "FY", ignore_invalid_symbol = false) if not na(ebit_series_fq[0]) ebit_q4 := ebit_q3 ebit_q3 := ebit_q2 ebit_q2 := ebit_q1 ebit_q1 := ebit_series_fq[0] ebit_ttm := ebit_q1 + ebit_q2 + ebit_q3 + ebit_q4 else if na(ebit_series_filled[0]) and not na(ebit_series_fy[0]) ebit_ttm := ebit_series_fy[0] roic = ebit_ttm / invested_capital // 返回两个指标结果 [fm, roic] // 只调用一次security获取每个标的的两个指标 [sfm01, sroic01] = request.security(s01, timeframe.period, calculateIndicators(s01)) [sfm02, sroic02] = request.security(s02, timeframe.period, calculateIndicators(s02)) [sfm03, sroic03] = request.security(s03, timeframe.period, calculateIndicators(s03)) // Get only symbol only_symbol(s) => array.get(str.split(s, ":"), 1) //////////// // ARRAYS // s_arr = array.new_string(0) u_arr = array.new_bool(0) sfm_arr = array.new_float(0) sroic_arr = array.new_float(0) // Add Symbols array.push(s_arr, only_symbol(s01)) array.push(s_arr, only_symbol(s02)) array.push(s_arr, only_symbol(s03)) // FLAGS array.push(u_arr, u01) array.push(u_arr, u02) array.push(u_arr, u03) // SFM array.push(sfm_arr, sfm01) array.push(sfm_arr, sfm02) array.push(sfm_arr, sfm03) // SROIC array.push(sroic_arr, sroic01) array.push(sroic_arr, sroic02) array.push(sroic_arr, sroic03) /////////// // PLOTS // n_symbols = 3 indicator_1 = 'SFM-HOMIES' indicator_2 = 'SROIC-HOMIES' sfm_os = input.float(0, title = "SFM Overbought", group = "Indicators") sfm_ob = input.float(1, title = "SFM Oversold", group = "Indicators") sroic_lower = input.float(0.2, title = "SROIC Lower Limit", group = "Indicators") sroic_lower2 = input.float(0.5, title = "SROIC Lower Limit2", group = "Indicators") var tbl = table.new(position.top_right, 3, n_symbols+1, frame_color=#151715, frame_width=1, border_width=2, border_color=color.new(color.white, 100)) if barstate.islast table.cell(tbl, 0, 0, 'Symbol', width = col_width, text_halign = text.align_center, bgcolor = color.gray, text_color = color.white, text_size = size.small) table.cell(tbl, 1, 0, indicator_1, width = col_width, text_halign = text.align_center, bgcolor = color.gray, text_color = color.white, text_size = size.small) table.cell(tbl, 2, 0, indicator_2, width = col_width, text_halign = text.align_center, bgcolor = color.gray, text_color = color.white, text_size = size.small) for i = 0 to n_symbols-1 if array.get(u_arr, i) table.cell(tbl, 0, i + 1, array.get(s_arr, i), text_halign = text.align_center, bgcolor = color.gray, text_color = color.white, text_size = size.small) sfm_col = array.get(sfm_arr, i) > sfm_ob ? color.red : array.get(sfm_arr, i) < sfm_os ? color.red : array.get(sfm_arr, i) < sfm_ob and array.get(sfm_arr, i) > sfm_os ? color.green : #aaaaaa table.cell(tbl, 1, i + 1, str.tostring(array.get(sfm_arr, i), "#.##"), text_halign = text.align_center, bgcolor = sfm_col, text_color = color.white, text_size = size.small) sroic_col = array.get(sroic_arr, i) < sroic_lower ? color.red : array.get(sroic_arr, i) >= sroic_lower and array.get(sroic_arr, i) < sroic_lower2 ? color.yellow : array.get(sroic_arr, i) >= sroic_lower2 ? color.green : #aaaaaa table.cell(tbl, 2, i + 1, str.tostring(array.get(sroic_arr, i), "#.##"), text_halign = text.align_center, bgcolor = sroic_col, text_color = color.white, text_size = size.small)
关键优化点
- 合并指标计算函数:将
sfm()和sroic()合并为calculateIndicators(),在同一个函数内完成所有财务数据请求和指标计算 - 减少security调用次数:每个标的只调用一次
request.security,一次性获取SFM和SROIC结果,避免重复请求 - 修复SROIC颜色逻辑:原代码中颜色判断存在逻辑问题(
>= sroic_lower会覆盖后续的>= sroic_lower2判断),优化后按区间分层判断
额外建议
- 如果后续需要增加更多标的,尽量保持每个标的只发起一次
request.security调用 - 对于非必要的
request.financial请求,可考虑移除或合并,进一步减少请求总数 - 注意
request.financial的频率参数(如FQ/FY),避免重复获取相同周期的数据
内容的提问来源于stack exchange,提问作者outofstep58
相关产品推荐
相关产品推荐

