外观
其他时间周期与数据
约 15630 字大约 52 分钟
简介
Mine Script® 允许用户从图表使用范围之外的数据源和上下文请求数据。本页介绍的函数可从多种替代数据源获取数据:
- request.security() 从其他交易品种、时间周期或其他上下文获取数据。
- request.security_lower_tf() 获取日内数据(即低于图表时间周期的数据)。
注意
在本页面以及我们文档中讨论 request.*() 函数的其他部分,我们经常使用"上下文"(context)这一术语来描述适用于图表或脚本获取数据的交易品种、时间周期以及任何修改(价格调整、交易时段设置、非标准图表类型等)。
以下是 request.* 命名空间下各函数的签名:
request.security(symbol, timeframe, expression, gaps, lookahead, ignore_invalid_symbol, currency, calc_bars_count) → series <type>
request.security_lower_tf(symbol, timeframe, expression, ignore_invalid_symbol, currency, ignore_invalid_timeframe, calc_bars_count) → array<type>request.*() 系列函数具有众多潜在应用场景。本页面将详细讨论这些函数及其典型用例。
共同特性
request.*() 命名空间中的许多函数都具有一些共同的属性和参数。在深入探讨每个函数之前,我们先熟悉这些共同特性。
运行机制
所有request.*()函数都具有相似的内部行为,尽管它们并非都共享相同的必需参数。脚本中每个唯一的request.*()调用都会从定义的上下文(即交易品种ID和时间周期)请求数据集,并在检索到的数据上评估表达式。
request.security()和request.security_lower_tf()函数允许程序员通过symbol、timeframe和expression参数直接指定请求的上下文和表达式,使其适用于广泛的数据请求场景。
例如,这个简单脚本中的request.security()调用请求"FXCM:XAUUSD"的日线数据,并使用检索到的hl2价格计算20根K线线性回归线的斜率。前两个参数指定请求的上下文,第三个参数指定要在请求数据上评估的表达式:

Mine Script®
已复制
脚本最多可通过任意组合的request.*()函数调用执行40个唯一请求。只有唯一的request.*()调用会计入此限制,因为只有这些调用会获取新数据。对具有相同参数的同一request.*()函数的冗余调用不会检索新数据,而是复用首次执行调用时的数据。
gaps
当使用request.*()函数从其他上下文获取数据时,数据可能不会像当前图表那样在每个新K线到来时都更新。request.*()函数的gaps参数控制着该函数如何处理请求序列中的空值情况。
注意
当使用 indicator() 函数的 timeframe 参数在另一个时间周期评估整个脚本时,timeframe_gaps 参数决定了脚本如何处理不存在的数值。该参数与 request.*() 函数的 gaps 参数功能类似。
假设我们在1分钟图表上运行的脚本,使用request.security()请求该交易品种的小时数据。该函数调用仅在覆盖小时K线开盘和收盘时间的1分钟K线上返回新值。在其他图表K线上,我们可以通过gaps参数决定函数返回na值还是最后可用值。
当gaps参数设置为barmerge.gaps_on时,函数在所有尚未从请求上下文确认新数据的图表K线上返回na结果。反之,当参数设置为barmerge.gaps_off时,函数会用历史K线上最后确认的值和实时K线上最新发展的值来填充请求数据中的空缺。
以下脚本通过绘制两个request.security()调用的结果来演示行为差异,这两个调用在1分钟图表上获取当前交易品种的小时时间周期收盘价。第一个调用使用gaps = barmerge.gaps_off,第二个使用gaps = barmerge.gaps_on:

Mine Script®
已复制
请注意:
- barmerge.gaps_off是所有适用的
request.*()函数中gaps参数的默认值。 - 脚本使用带断点的线型(plot.style_linebr)绘制请求序列,该样式不会像默认线型(plot.style_line)那样跨越na值。
- 当使用barmerge.gaps_off时,request.security()函数在所有历史K线上返回小时时间周期最后确认的收盘价。在实时K线上运行(本例中背景色为color.aqua的K线),它会返回当前最新收盘价,无论是否确认。更多信息请参阅本页面的历史与实时行为部分。
ignore_invalid_symbol
request.*() 函数中的 ignore_invalid_symbol 参数决定了函数如何处理无效数据请求,例如:
- 使用
request.*()函数时,将不存在的股票代码作为symbol/ticker参数传入。
当 ignore_invalid_symbol 参数为 false 时,request.*() 函数调用在发出错误请求时会产生运行时错误并停止脚本执行。当该参数值为 true 时,函数在这种情况下会返回 na 值而不是引发错误。
currency
目前仅支持 USD 货币。
lookahead
request.security() 中的 lookahead 参数用于指定函数调用的前视行为,其默认值为 barmerge.gaps_off。
当从更高时间周期(HTF)上下文请求数据时,lookahead 值决定了 request.*() 函数是否可以返回超出其所执行历史K线时间范围的数据。换句话说,该参数决定了请求数据在历史K线上是否可能包含前视偏差。
当从更低时间周期(LTF)上下文请求数据时,lookahead 参数决定了函数是从每个图表时间周期K线的第一根内部K线(LTF K线)还是最后一根内部K线获取数值。
程序员在使用前视功能时应格外谨慎,特别是在从更高时间周期请求数据时。当使用 barmerge.lookahead_on 作为 lookahead 值时,必须确保不会因未来数据泄漏到历史K线中而损害脚本逻辑的完整性。
以下情况可以在 request.*() 调用中启用 lookahead 参数:
- 当 request.security() 中的表达式引用了带有历史偏移量的序列(例如
close[1]),这会阻止函数请求它在实时状态下无法访问的未来值。 - 调用中指定的时间周期与脚本执行的图表时间周期相同,即 timeframe.period。
- 函数调用请求的是内部K线时间周期的数据,即比 timeframe.period 更小的时间周期。更多信息请参阅相关章节。
注意
使用 request.security() 将未来数据泄露到过去具有误导性,在脚本发布中是不被允许的。虽然您的脚本在历史K线上可能因看似"“神奇”地获取了预知能力(这在实时K线上无法复现)而表现优异,但这会误导您自己和脚本使用者。如果您发布脚本与他人共享,请确保不会通过从历史K线数据集访问未来信息来误导用户。
这个示例展示了 lookahead 参数如何影响更高时间周期数据请求的行为,以及为什么在 request.security() 中启用 lookahead 而不偏移表达式是具有误导性的。该脚本以三种不同方式调用 request.security() 来获取当前图表标的物的更高时间周期最高价,并将结果序列绘制在图表上进行比较。
第一个调用使用 barmerge.gaps_off(默认值),其他调用使用 barmerge.lookahead_on。然而,第三个 request.security() 调用还使用历史引用运算符 [] 来偏移其表达式,以避免将未来数据泄露到过去。
正如我们在图表上看到的,使用未偏移的 barmerge.lookahead_on(紫红色线)请求的序列在历史K线上显示了最终更高时间周期最高价,而这些价格在实际可用之前就已出现,而其他两个调用则没有这种情况:

Mine Script®
已复制
需要注意:
- 使用 barmerge.gaps_off 请求的序列在每个更高时间周期结束时才会出现新的历史值,而使用 barmerge.lookahead_on 请求的两个序列都在每个周期开始时就有新的历史数据。
- 在实时K线上,没有使用
lookahead的序列(蓝色)和使用lookahead但没有历史偏移的序列(紫红色)显示相同的值(即该更高时间周期未确认的最高价),因为这些点之后不存在可以泄露到过去的数据。这两个图表在脚本重新执行后都会重绘其结果,因为实时K线会变成历史K线。 - 使用
lookahead并加上历史偏移的序列(青色)不会重绘其值,因为它始终引用更高时间周期最后确认的值。更多信息请参阅本页的避免重绘部分。
数据源
TradingVue的数据提供商提供不同的数据源,脚本可通过这些数据源获取标的物的相关信息,包括:
- 日内历史数据(适用于时间周期 < 1D)
- 日终(EOD)历史数据(适用于时间周期 >= 1D)
- 实时数据(可能存在延迟,具体取决于账户类型和额外数据服务)
- 盘后交易数据
并非所有标的物都具备全部数据源类型。
对于同时具备日内和日终历史数据的标的物,成交量数据可能存在差异,因为部分交易(大宗交易、场外交易等)可能仅在交易日结束时才纳入统计。因此,日终数据源会包含这部分成交量,而日内数据源则不会。加密货币等标的物的日终与日内成交量差异几乎不存在,但股票市场这类差异很常见。
价格数据也可能出现细微差异。例如,某日的日终K线最高价可能与数据提供商当日提供的任何日内最高价都不一致。
另一关键区别在于:日终数据源不包含盘后交易时段的信息。
通过request.*()函数获取实时K线数据时需注意,标的物的历史数据和实时数据往往来自不同数据源。经纪商/交易所可能对实时K线数据进行追溯调整,这些变更仅在刷新图表或重启脚本后才会反映。
此外,图表数据源与脚本从提供商请求的数据源由独立并发进程管理。在极少数情况下,可能出现请求结果与实时K线图表短暂不同步的竞态条件,脚本会在重新执行后自动修正。
这些因素可能导致request.*()函数在跨上下文请求数据时出现数值波动,也会造成实时K线与历史K线数据的差异。不同数据源间的具体差异并无统一规律可循。
注意
作为准则,TradingVue本身不生成数据;其图表展示及脚本访问的所有信息均依赖于合作的数据提供商。
当使用从其他上下文请求的数据源时,还需特别注意脚本执行图表与被请求数据源之间的时间轴差异,因为 request.*() 函数会将返回的序列适配到当前图表的时间轴上。例如:在“SPY”图表上通过 request.security() 请求“BTCUSD”数据时,只有当“SPY”图表有新数据时才会显示“BTCUSD”的新数值。由于“SPY”并非“24-hour symbol”,返回的“BTCUSD”数据会出现断点,而这些断点在直接查看“BTCUSD”图表时并不存在。
request.security()
request.security() 函数允许脚本从脚本执行图表之外的其他上下文请求数据,例如:
- 其他标的物,包括价差标的物
- 其他时间周期(请参阅我们用户手册中关于时间周期的页面,了解 Mine Script 中的时间周期规范)
该函数的声明如下:
request.security(symbol, timeframe, expression, gaps, lookahead, ignore_invalid_symbol, currency, calc_bars_count) → series <type>symbol 参数值代表要获取数据的标的物标识符。该参数接受以下任意格式的值:
- 表示标的物的“字符串”(如“EURUSD”)或“交易所:标的物”组合(如“OANDA:EURUSD”)。当值不包含交易所前缀时,函数会自动选择交易所。建议尽可能指定交易所前缀以确保结果一致。用户也可以传递空字符串给该参数,这将使函数使用当前图表的标的物。
- 内置变量 syminfo.ticker 或 syminfo.tickerid,它们返回当前图表引用的标的物或“交易所:标的物”组合。除非交易所信息在数据请求中无关紧要,否则建议使用 syminfo.tickerid 以避免歧义。有关
syminfo.*变量的更多信息,请参阅我们图表信息页面的相关章节。
timeframe 参数用于指定请求数据的时间周期。该参数接受采用我们时间周期规范格式的“字符串”值(例如“1D”代表日线周期)。若要请求与脚本执行图表相同时间周期的数据,可使用 timeframe.period 变量或空字符串。
request.security() 函数的 expression 参数决定了从指定上下文获取的数据内容。这个多功能参数接受 int、float、bool、color、string 和 chart.point 类型的“series”值,同时也可接受元组、集合、用户自定义类型以及函数和方法调用的输出结果。有关可获取数据类型的更多细节,请参阅下文可请求数据章节。
注意
当在 expression 参数中使用 input.source() 调用的值,且该输入引用自另一个指标的序列时,request.*() 函数将使用当前图表的标的物来计算该值的结果(无论提供的 symbol 参数为何),因为它们无法评估外部序列所需的作用域。因此,我们不建议尝试从其他上下文请求外部源输入数据。
时间周期
request.security() 函数可以请求任何可用时间周期的数据,不受脚本执行图表时间周期的限制。获取数据的时间周期取决于函数调用中的 timeframe 参数,该参数可以表示:
更高时间周期(例如在日内图表上运行脚本时使用“1D”作为 timeframe 值) 或与图表相同的时间周期(即使用 timeframe.period 或空字符串作为 timeframe 参数) 脚本也可以通过 request.security() 请求有限制的更低时间周期数据(例如在60分钟图表上运行时使用“1”作为 timeframe 参数)。但通常不建议将此函数用于低时间周期数据请求,这种情况下使用 request.security_lower_tf() 函数是更优选择。
更高时间周期
request.security() 的大多数使用场景涉及请求比图表时间周期更高或相同时间周期的数据。例如,以下脚本从请求的 higherTimeframe 获取 hl2 价格,并将结果序列与当前图表的 hl2 一并绘制在图表上以供比较:

Mine Script®
已复制
需要注意:
- 我们已在
expression参数中添加了偏移量,并在 request.security() 中使用 barmerge.lookahead_on,以确保返回的序列在历史K线和实时K线上行为一致。更多信息请参阅避免重绘部分。
请注意,在上面的示例中,有可能选择实际上比图表时间周期更低的 higherTimeframe 值,因为代码并未对此进行限制。当设计专门用于处理更高时间周期的脚本时,我们建议添加条件来防止访问更低时间周期,特别是如果您打算发布该脚本。
在下面的示例中,我们在之前的代码中添加了一个 if 条件结构,当 higherTimeframe 输入表示的时间周期小于图表时间周期时,会引发运行时错误,从而有效防止脚本请求 LTF 数据:

Mine Script®
已复制
更低时间周期
虽然request.security()函数设计用于处理大于或等于图表时间周期的请求,但它也可以有限制地请求更低时间周期(LTF)数据。当调用此函数访问更低时间周期时,它会在LTF上下文中评估表达式,但每个图表K线只能返回单个内部K线(LTF K线)的结果。
函数在每个历史图表K线上返回哪个内部K线的数据取决于调用中的lookahead参数值:当使用barmerge.lookahead_on时返回图表周期内首个可用内部K线值;当使用barmerge.lookahead_off(默认值)时返回图表周期内最后内部K线值。在实时K线上,无论lookahead值如何设置,函数都返回该时间周期内表达式的最新值,因为函数获取的实时内部K线信息尚未完成排序。
此脚本从最接近图表周期1/4大小的有效时间周期获取收盘价数据,并进行两个不同lookahead值的request.security()调用:第一个调用使用barmerge.lookahead_on访问每个图表K线中首个内部K线值;第二个调用使用默认lookahead值(barmerge.lookahead_off)请求分配给每个图表K线的最后内部K线值。脚本将两个调用的输出绘制在图表上进行比较差异。

Mine Script®
已复制
需要注意:
- 脚本通过timeframe.in_seconds()计算图表时间周期秒数,除以4后通过timeframe.from_seconds()转换为有效时间周期字符串,从而确定
lowerTimeframe值。 - 未使用前视的序列(紫色线)与图表时间周期的收盘价对齐,因为这是图表K线中最后一个内部K线值。
- 在橙色背景的K线上可见:两个request.security()调用在每个实时K线上均返回相同值(当前收盘价)。
- 具有可用内部K线数据的图表K线数量取决于请求的低时间周期、
calc_bars_count值及用户订阅计划。
注意
虽然脚本可使用request.security()获取每个图表K线中单个内部K线的值(这在某些特殊场景可能有用),但我们建议尽可能使用request.security_lower_tf()函数进行内部K线分析,因为它返回包含图表K线内所有可用内部K线数据的数组。更多信息请参阅相关章节。
可请求数据
request.security()函数功能多样,可获取任何基本类型(int、float、bool、color 或 string)的值,也能请求引用基本类型的数据结构和内置/用户定义类型的ID。该函数请求的数据取决于其expression参数,该参数接受以下任意参数:
注意
request.security()函数会复制表达式所需的上下文和作用域,以便在其他时间周期或品种上计算请求值,这会增加运行时内存消耗。此外,每次调用request.security()产生的额外作用域都会计入脚本的编译限制。
内置变量和函数
request.security() 的一个常见使用场景是从其他品种或时间周期请求内置变量或函数/方法调用的输出结果。
例如,假设我们需要在日内图表上计算某品种日线级别的20周期 ohlc4 均线,只需一行代码即可实现:
Mine Script®
已复制
上面这行代码计算的是当前品种在日线时间周期上的 ta.sma(ohlc4, 20) 值。
需要注意的是,Mine 新手有时可能会混淆上面这行代码,认为它等同于以下写法:
Mine Script®
已复制
然而,这行代码将返回完全不同的结果。它不是从日线时间周期请求20周期SMA,而是从日线时间周期请求ohlc4价格,然后在当前图表上计算20个K线的ta.sma()。
本质上,当需要从其他上下文请求表达式结果时,应该直接将表达式传递给request.security()调用的expression参数,如初始示例所示。
让我们扩展这个概念。下面的脚本计算一个多时间周期(MTF)均线带,其中带状中的每个均线都在各自时间周期上计算相同数量的K线。每个request.security()调用都使用ta.sma(close, length)作为expression参数,从指定时间周期返回length周期的SMA:

Mine Script®
已复制
需要注意:
- 脚本通过将图表timeframe.in_seconds()值乘以2、3和4来计算带状更高时间周期,然后使用timeframe.from_seconds()将每个结果转换为有效时间周期字符串。
- 无需在每个request.security()调用中调用ta.sma(),可以使用
chartAvg变量作为每个调用中的expression参数来达到相同效果。更多信息请参阅下一章节。 - 在实时K线上,此脚本还会跟踪每个更高时间周期未确认的
SMA值。更多详情请参阅历史和实时行为章节。
计算变量
request.security() 的 expression 参数接受在全局作用域中声明的变量,这使得脚本能够从其他上下文评估其变量的计算结果,而无需在每个函数调用中重复列出这些操作。
例如,可以声明以下变量:
Mine Script®
已复制
并通过 request.security() 在另一个上下文中执行该变量的计算:
Mine Script®
已复制
上面这行函数调用将返回 priceReturn 在另一个品种数据上的计算结果,该结果会被适配为当前图表的序列。脚本可以直接在图表上显示这个结果,或者用于其他运算。
以下示例比较了当前图表品种和另一个指定品种的价格回报率。脚本先在图表上下文中声明 priceReturn 变量,然后在 request.security() 中使用该变量来计算其在另一个品种上的值。接着计算 priceReturn 和 requestedReturn 之间的相关性,并将结果绘制在图表上:

Mine Script®
已复制
需要注意:
- request.security() 调用执行了与
priceReturn声明相同的计算,只是使用了从输入品种获取的close值。 - 脚本根据相关值使用渐变色绘制图表。要了解 Mine 中颜色渐变的更多信息,请参阅用户手册颜色章节的相关部分。
元组
在Mine脚本中,元组是用方括号括起来的逗号分隔表达式集合,可以包含任何可用类型的多个值。当创建需要返回多个值的函数或其他局部代码块时,我们会使用元组。
request.security()函数可以接受元组作为其expression参数,允许脚本通过单次函数调用请求多个不同类型的序列。被请求元组中的表达式可以是本页可请求数据章节中列出的任何类型(不包括其他元组)。
元组在脚本需要从特定上下文获取多个值时特别实用。
例如,此脚本计算收盘价在length周期内的百分比排名,并将表达式赋值给rank变量。然后调用request.security()请求包含rank、ta.crossover(rank, 50)和ta.crossunder(rank, 50)值的元组(来自指定时间周期)。脚本绘制requestedRank,并使用crossOver和crossUnder的布尔值通过bgcolor()有条件地高亮图表背景:

Mine Script®
已复制
需要注意:
- 我们使用历史引用运算符[]将
rank变量表达式偏移1根K线,并在request.security()调用中包含barmerge.lookahead_on,以确保实时K线转为历史K线后数值不会重绘。详见避免重绘章节。 - 由于request.security()调用返回的是元组,因此我们使用元组声明来定义
requestedRank、crossOver和crossUnder变量。要了解更多关于元组的使用,请参阅用户手册类型系统章节的相关部分。
用户定义函数
用户自定义函数和方法是由用户编写的自定义功能模块。它们允许用户定义与特定标识符关联的操作序列,脚本可以在执行过程中方便地调用这些功能(例如 myUDF())。
request.security() 函数可以请求用户自定义函数和方法的结果,这些函数的作用域可以包含本页可请求数据章节中列出的任何类型。
例如,以下脚本包含一个用户自定义的 weightedBB() 函数,该函数计算由指定权重序列加权的布林带。函数返回一个包含自定义带值的元组。脚本在 request.security() 中将 weightedBB() 作为 expression 参数调用,以获取在指定时间周期上计算的带值元组,并将结果绘制在图表上:

Mine Script®
已复制
需要注意:
- 在作为 request.security() 表达式的
weightedBB()调用中,我们对source和weight参数进行了偏移,并使用 barmerge.lookahead_on 以确保请求的结果反映实时 K 线上该时间周期最后确认的值。更多信息请参阅相关章节。
图表点
图表点(chart.point)是表示图表坐标的引用类型。线条、方框、折线和标签都使用 chart.point 对象来设置其显示位置。
request.security() 函数可以在其 expression 参数中使用 chart.point 实例的 id,从而允许脚本从其他上下文获取图表坐标。
以下示例从更高时间周期请求历史图表点的元组,并用它们在图表上绘制方框。脚本声明了引用最后确认 K 线的 chart.point id 的 topLeft 和 bottomRight 变量,然后使用 request.security() 请求包含来自 higherTimeframe 的表示 topLeft 和 bottomRight 的图表点 id 的元组。
当 higherTimeframe 上开始新 K 线时,脚本使用从 requestedTopLeft 和 requestedBottomRight 图表点获取的时间和价格坐标绘制新方框:

Mine Script®
已复制
需要注意:
- 由于此示例专为更高时间周期设计,当
higherTimeframe的 timeframe.in_seconds() 小于图表时间周期时,脚本会触发自定义运行时错误。
集合
Mine脚本集合(数组、矩阵和映射)是包含指定类型任意数量元素的数据结构。request.security()函数可以检索以下元素类型集合的ID:
本示例计算指定品种和时间周期上,确认K线的高低范围与10根K线内最高最低值范围的比率。它使用映射来存储计算所需的数值。
脚本创建了一个键为“string”类型、值为“float”类型的数据映射(map),用于存储每根K线的高、低价以及10根K线内的最高、最低价。该映射作为request.security()的expression参数,用于计算表示指定上下文数据的otherData映射。脚本使用otherData映射中“High”、“Low”、“Highest” 和 “Lowest”键关联的值来计算比率,并将结果绘制在图表面板中:

Mine Script®
已复制
需要注意:
- 当指定上下文无可用数据时,本脚本中的request.security()调用可能返回
na。由于无法在map变量为na值时调用其方法,我们添加了if条件结构,仅当otherData引用有效map ID时才计算新的比率值。
用户定义类型
用户自定义类型(UDT)是包含任意数量字段的复合类型,这些字段可以是任何可用类型,包括其他用户自定义类型。
当UDT的字段满足以下条件时,request.security()函数可以从其他上下文检索UDT生成的对象ID:
以下示例通过指定品种请求对象ID,并将其字段值显示在图表面板中。
脚本包含一个TickerInfo UDT,其中包含:
- 用于存储
syminfo.*值的“string”类型字段 - 存储近期“float”价格数据的数组字段
- 保存请求品种bar_index值的“int”类型字段
脚本在每根K线上将新的TickerInfo ID赋值给info变量,并将该变量作为request.security()的expression参数,以获取表示来自指定品种的计算info的对象ID。
脚本在标签中显示requestedInfo对象的description、tickerType、currency和barIndex值,并使用plotcandle()显示其prices数组中的值:

Mine Script®
已复制
需要注意:
- 本脚本中使用的
syminfo.*变量均返回“simple string”限定类型。但Mine中的对象始终被限定为“series”类型,因此赋值给info对象字段的所有值都会自动采用“series”限定符。 - 由于请求品种数据与主图表存在差异,request.security()调用可能返回
na。在此情况下,脚本会为requestedInfo分配新的TickerInfo对象以防止运行时错误。
request.security_lower_tf()
request.security_lower_tf() 是专为从更低时间周期(LTF)上下文可靠请求数据而设计的函数,可作为 request.security() 的替代方案。
与 request.security() 只能获取每个图表 K 线中单个内部 K 线(LTF K 线)数据不同,request.security_lower_tf() 会获取每个图表 K 线内所有可用内部 K 线的数据,脚本可访问并用于额外计算。
注意
使用 request.security_lower_tf() 需要频繁操作数组,因为该函数始终返回数组结果。因此我们建议您充分熟悉数组操作,以便在脚本中充分发挥此函数的功能。
以下是该函数的声明格式,与 request.security() 类似:
request.security_lower_tf(symbol, timeframe, expression, ignore_invalid_symbol, currency, ignore_invalid_timeframe, calc_bars_count) → array<type>该函数仅请求小于或等于图表时间周期的数据。若请求的时间周期高于图表时间周期,函数将根据调用中的ignore_invalid_timeframe参数决定抛出运行时错误或返回na值。该参数默认值为false,意味着尝试请求更高时间周期(HTF)数据时将抛出错误并中止脚本执行。
请求内部K线数据
内部K线数据可为脚本提供额外信息,这些信息在仅分析图表时间周期采样数据时可能不明显或无法获取。request.security_lower_tf()函数可从内部K线上下文中检索多种数据类型。
在深入本节内容前,建议先阅读上文request.security()章节中的可请求数据部分,该部分提供了关于可请求数据类型的基础知识。request.security_lower_tf()的expression参数接受该章节讨论的大部分相同参数(不包括对集合和脚本主作用域中声明的可变变量的直接引用)。虽然接受的参数类型相似,但本函数返回数组结果,其解释和处理方式存在以下差异:
注意
与 request.security() 相同,request.security_lower_tf() 会复制计算表达式所需的上下文和作用域。这些额外作用域将增加运行时内存消耗,并计入脚本的编译限制。
内部K线数据数组
更低时间周期包含比更高时间周期更多的数据点,因为新数值以更高频率出现。例如,将1分钟图表与小时图表相比较时,每分钟图表每小时最多可包含60倍的K线数量(具体取决于可用数据)。
为处理图表单根K线内存在多根内部K线的特性,request.security_lower_tf()始终以数组形式返回结果。返回数组中的元素代表从更低时间周期获取的表达式值,并按各内部K线时间戳“升序”排列。
返回数组的类型模板与调用中传递的值类型对应:
- 表达式为“int”时返回
array<int>实例 - 表达式为“bool”时返回
array<bool>实例 - 其他类型依此类推
以下脚本使用内部K线信息将图表收盘价变动分解为正向和负向部分。它在每根图表K线上调用request.security_lower_tf()从lowerTimeframe获取ta.change(close)的“float”数组,然后通过for…in循环访问数组所有元素来累计positiveChange和negativeChange总和。脚本将累计值相加计算出netChange,最终在图表上绘制结果并与priceChange进行对比:

Mine Script®
已复制
需要注意:
- 基于内部K线数据的绘图可能不会出现在所有可用图表K线上,因为request.security_lower_tf()最多只能访问请求上下文中最近的100,000根内部K线。当在无法获取内部K线数据的图表K线上执行此函数时,将返回空数组。
- 每根图表K线包含的内部K线数量可能因数据源和脚本运行的图表而异。例如,由于某些1分钟间隔内缺乏交易活动,供应商的1分钟数据流可能不包含60分钟时间周期内每分钟的数据。要检查获取的内部K线数量,可对结果数组使用array.size()。
- 若
lowerTimeframe值大于图表时间周期,由于未在request.security_lower_tf()调用中提供ignore_invalid_timeframe参数,脚本将抛出运行时错误。
内部K线数据元组
当将元组或返回元组的函数调用作为request.security_lower_tf()的expression参数传递时,结果是一个由数组组成的元组,其类型模板与参数中的类型相对应。例如,使用[float, string, color]元组作为表达式将导致函数返回[array<float>, array<string>, array<color>]数据。使用元组表达式允许脚本通过单个request.security_lower_tf()函数调用获取多个内部K线数据数组。
以下示例从更低时间周期请求OHLC数据,并使用线条和方框在图表上可视化当前K线的内部K线。脚本调用request.security_lower_tf(),以[open, high, low, close]元组作为expression参数,获取表示来自计算得出的lowerTimeframe的OHLC信息的数组元组。随后使用for循环根据获取的数据和当前K线索引设置线条坐标,在当前图表K线旁显示结果,提供最新蜡烛内部价格波动的“放大视图”。同时绘制方框环绕线条,标示内部K线绘图所占的图表区域:

Mine Script®
已复制
需要注意:
- 脚本使用两条线绘制每根蜡烛:一条代表影线,另一条代表实体。由于图表最多可显示500条线,我们已将
maxIntrabars输入参数限制为250。 lowerTimeframe值是通过计算timeframe.in_seconds()除以maxIntrabars的math.ceil()结果,并使用timeframe.from_seconds()转换为有效时间周期字符串得出的。- 脚本使用请求的
hData数组的array.max()设置方框顶部,使用请求的lData数组的array.min()设置方框底部。如图表所示,这些值对应图表K线的最高价和最低价。
请求集合数据
在某些情况下,脚本可能需要从内部K线上下文请求集合的ID。然而,与request.security()不同,由于数组不能直接引用其他集合,因此不能将集合或返回集合的函数调用作为request.security_lower_tf()的expression参数传递。
尽管存在这些限制,但如有需要,可以通过包装类型的帮助从更低时间周期请求集合数据。
注意
以下所述为高级应用场景,不建议初学者使用。在探索此方法前,建议先充分理解Mine脚本中用户自定义类型和集合的工作原理。如非必要,建议优先使用更简单的方法处理低时间周期数据请求,仅在其他方法均不适用时采用此方案。
要通过request.security_lower_tf()请求集合数据,必须创建包含集合ID引用字段的用户自定义类型(UDT)。这一步骤是必要的,因为数组不能直接引用其他集合,但可以引用包含集合字段的UDT:
Mine Script®
已复制
定义好Wrapper UDT后,我们现在可以将该UDT对象的ID传递给request.security_lower_tf()的expression参数。
一个直接的方法是调用内置的*.new()函数作为expression参数。例如,以下代码行在request.security_lower_tf()中调用Wrapper.new(),并以array.from(close)作为其collection参数:
Mine Script®
已复制
或者,我们可以创建一个返回UDT对象的用户自定义函数或方法,并在request.security_lower_tf()中调用该函数。例如,以下代码调用自定义的newWrapper()函数作为expression参数,该函数返回一个Wrapper ID:
Mine Script®
已复制
无论采用上述哪种方法,结果都是一个包含图表K线中所有可用内部K线的Wrapper ID数组。脚本可通过这些ID引用特定内部K线的Wrapper实例,并在后续操作中使用其集合字段。
以下脚本运用此方法从lowerTimeframe收集内部K线数据数组,并用于显示特定内部K线的数据。其自定义的Prices类型包含一个data字段,用于引用存储价格数据的array<float>实例,用户定义的newPrices()函数则返回Prices对象的ID。
脚本以newPrices()调用作为expression参数调用request.security_lower_tf(),从图表K线的每个内部K线获取Prices ID数组,然后使用array.get()获取指定可用内部K线的ID(如果存在)。最后,对该实例的data数组使用array.get(),并调用plotcandle()在图表上显示其值:

Mine Script®
已复制
需要注意:
- 仅当
requestedPrices数组的大小大于intrabarIndex时,intrabarPrices变量才会引用PricesID,因为尝试使用array.get()获取不存在的元素将导致越界错误。 - 仅当存在有效的
PricesID时,intrabarData变量才会引用intrabarPrices的data字段,因为脚本无法引用na值的字段。 - 本示例中的处理流程对于实现预期结果并非必需。如前一节所述,我们可以改用
[open, high, low, close]元组作为expression参数来获取数组元组进行后续操作,从而避免使用UDT。
历史与实时行为
request.*()命名空间中的函数在历史K线和实时K线上可能表现不同。此行为与Mine的执行模型密切相关。
考虑脚本在主上下文中的行为。在图表历史数据中,脚本计算所需值一次并提交至该K线,后续执行可访问这些状态。但在未确认的实时K线上,脚本会随数据更新重新计算值以反映实时变化。每次重新计算前,会将值回滚至最后提交状态(称为rollback),仅当K线闭合时才提交最终值。
现在考虑通过request.security()从其他上下文请求数据的行为。与主上下文评估历史K线时类似,request.security()仅在指定上下文的K线确认时返回新历史值。在实时K线上执行时,它会在每根图表K线上返回重新计算的值,类似于脚本在主上下文对未闭合K线重新计算值的方式。
但该函数仅在上下文K线闭合时确认请求值。当脚本重启时,原实时K线转为历史K线,此时request.security()仅返回这些K线上已确认的值。本质上,此行为意味着当实时K线上的值波动但未获上下文确认时,请求数据可能会重绘。
注意
在使用request.*()函数时,区分历史K线和实时K线通常很有帮助。脚本可以通过barstate.ishistory和barstate.isrealtime变量来判断K线处于历史状态还是实时状态。
在大多数从更广上下文请求数据的场景中,通常需要获取已确认且稳定的数值,这些数值在实时K线上不会波动。下文将说明如何实现这一结果并避免数据请求的重绘问题。
避免重绘
更高时间周期数据
当从更高时间周期请求值时,这些值可能会重绘,因为实时K线可能包含来自发展中HTF K线的未确认信息,并且脚本可能会调整历史K线上新值出现的时间。为避免HTF数据重绘,必须确保函数在所有K线上仅返回具有一致时间性的已确认值,无论K线状态如何。
获得非重绘结果最可靠的方法是使用仅引用过去K线(例如close[1])的expression参数,同时使用barmerge.lookahead_on作为lookahead值。
不建议将barmerge.lookahead_on用于未偏移的HTF数据请求,因为它会促使request.security()“向前查看”HTF K线的最终值,在脚本历史中实际可用之前检索已确认值。但是,如果表达式中使用的值至少偏移1根K线,函数检索的“未来”数据就不再是真正的未来数据,而是代表来自已确立可用HTF K线的确认值。换句话说,对表达式应用偏移可有效防止脚本重启执行时请求数据重绘,并消除历史序列中的前视偏差。
以下示例展示了一个会重绘的HTF数据请求。该脚本使用未经偏移修改或附加参数的request.security()从更高时间周期获取ta.wma()调用的结果。它还通过高亮背景来指示哪些K线在计算期间处于实时状态。
如下图所示,所请求WMA的绘图仅在HTF K线闭合时改变历史K线上的值,而在所有实时K线上都会波动,因为数据包含来自更高时间周期的未确认值:

Mine Script®
已复制
为避免此脚本出现重绘,可在request.security()调用中添加lookahead = barmerge.lookahead_on,并通过历史引用运算符[]将ta.wma()的调用历史偏移1根K线,从而确保请求始终在每个新时间周期开始时获取最后确认的HTF K线的WMA值。与前一脚本不同,此版本在历史K线和实时K线上表现一致,如下图所示:

Mine Script®
已复制
较低时间周期数据
request.security()和request.security_lower_tf()函数可以从更低时间周期上下文获取数据。request.security()函数每根图表K线只能获取单个内部K线的数据,而request.security_lower_tf()可以获取所有可用内部K线的数据。
当使用这些函数获取内部K线数据时,需要注意此类请求并不能避免重绘行为。历史序列和实时序列通常依赖于不同的数据源。如本页数据源章节所述,数据提供商可能会追溯修改实时数据,并且实时数据流中可能出现竞争条件。这两种情况都可能导致在实时K线上获取的内部K线数据在脚本重启执行后发生重绘。
此外,一个会导致LTF请求重绘的特殊情况是:使用带有barmerge.lookahead_on的request.security()来获取每根图表K线的第一个内部K线数据。虽然在历史K线上通常能按预期工作,但在实时K线上它只会追踪最新的内部K线,因为request.security()不会保留所有内部K线信息,并且函数在实时K线上获取的内部K线在脚本重启前是未排序的:

Mine Script®
已复制
可以通过使用request.security_lower_tf()来改善此行为并追踪每根图表K线中第一个内部K线(或任意可用内部K线)的值,因为该函数会维护一个按时间顺序排列的内部K线值数组。在此示例中,我们对请求的内部K线数据数组调用array.first(),以获取每根图表K线中第一个可用内部K线的收盘价:

Mine Script®
已复制
需要注意:
- 尽管request.security_lower_tf()在处理历史和实时内部K线方面更优化,但在某些情况下仍可能因数据提供商的数据差异(如前文所述)出现轻微重绘。
- 此代码可能不会在所有可用图表K线上显示内部K线数据,具体取决于每根图表K线包含的内部K线数量,因为
request.*()函数从LTF上下文最多可获取100,000根内部K线。