You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建带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)

关键优化点

  1. 合并指标计算函数:将sfm()和sroic()合并为calculateIndicators(),在同一个函数内完成所有财务数据请求和指标计算
  2. 减少security调用次数:每个标的只调用一次request.security,一次性获取SFM和SROIC结果,避免重复请求
  3. 修复SROIC颜色逻辑:原代码中颜色判断存在逻辑问题(>= sroic_lower会覆盖后续的>= sroic_lower2判断),优化后按区间分层判断

额外建议

  • 如果后续需要增加更多标的,尽量保持每个标的只发起一次request.security调用
  • 对于非必要的request.financial请求,可考虑移除或合并,进一步减少请求总数
  • 注意request.financial的频率参数(如FQ/FY),避免重复获取相同周期的数据

内容的提问来源于stack exchange,提问作者outofstep58

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:35:32