判断K线是否落在自定义交易时段内
我们时常需要让脚本知道,当前的K线是否发生在一个特定的交易时段内。利用这些信息,我们可以实现例如仅在特定时间段内进行交易,或将警报限制在某个交易时段内等功能。
但Pine Script是如何判断一根K线是否落在某个特定的时间窗口内的呢?让我们看看如何用代码实现这一点。
自定义函数
Pine Script的 time() 函数可以判断脚本是否正在一个自定义时段内的K线上进行计算。该函数会返回两种值:当K线处于时段内时,它返回该K线的时间;如果K线处于时段外,我们则会得到 na 值。
就我们的目的而言,我们感兴趣的是 time() 返回na以外的值。因为那意味着K线正发生在该时段内。
我们通过下面这个自定义函数来利用这一特性:
// 当当前K线发生在指定的时段内时,InSession() 函数返回 'true',
// 并为给定的时区进行校正(可选)。
// 当K线不发生在该时间段内,或当图表时间周期为1天或更高时,
// 返回 'false'。
InSession(sessionTime, sessionTimeZone=syminfo.timezone) =>
not na(time(timeframe.period, sessionTime, sessionTimeZone))
这个 InSession() 函数有两个参数。第一个参数 sessionTime 通过一个Pine Script的时段字符串来定义时段的开始和结束时间。例如 "0800-1500",代表从8:00到15:00的时段。
另一个参数 sessionTimeZone 通过一个Pine Script的时区字符串来设定时段的时区。这是一个可选参数,在未设置时,默认使用交易品种的时区(syminfo.timezone)。一个可能的值是 "GMT+1",代表GMT+1时区。
在函数内部,我们进行了一个比较,当当前K线处于指定的时段和时区内时,该比较返回 true;当K线在该范围之外时,我们则得到 false。
为了得到这个真/假结果,我们使用了几个代码元素。让我们从最内层的括号(( 和 ))开始,由内而外地进行分析。
我们使用了带有三个参数的 time() 函数。timeframe.period 使函数使用图表当前的时间周期。通过 sessionTime 和 sessionTimeZone,我们将传给 InSession() 函数的值传递给了 time()。
现在,time() 会返回K线的时间(当K线在时段内时)或者 na。虽然我们想知道K线是否发生在时段内,但我们对K线的时间本身不感兴趣,一个真/假的结果会更好用。
所以,我们将 time() 包装在 na() 函数内部。当 time() 返回 na 时(即K线在时段外),na() 会返回 true;当 time() 返回K线时间时(即K线在时段内),它返回 false。
这样好一些了,但也和我们想要的结果相反:我们不希望在K线处于时段内时得到 false 值。所以,我们在 na() 前面放上 not 运算符,它会返回相反的布尔值。现在,我们就能在K线处于时段内时得到 true,而在时段外时得到 false 了。
函数特性
使用 InSession() 函数时需要记住的一些事情:
- 它在日线和更高的时间周期上总是返回
false。因为这些K线没有具体的时段信息,所以它们不可能发生在某个时间段内。 - 图表上显示的K线时间可能与指定的时段不同,但该函数仍可能将它们识别为时段的一部分。这种情况发生在函数使用的时区与图表显示的时区不同时。
- 该函数可能在时段内找不到任何一根K线。当设置的时段发生在交易品种的隔夜期间时(例如由于时区差异),这种情况就会出现。
函数范例
把上述函数加入脚本后,有多种方式可以使用它。
一个方便的使用方式是用我们希望测试的时段来调用该函数。例如,要查看当前K线是否发生在9:30到16:00之间,我们可以这样做:
// 查看当前K线是否落在上午9:30到下午4点的时段内
isInSession = InSession("0930-1600")
当我们也为函数提供一个时区时,它会进行时差转换来找到在该时区内的K线。例如,要为纽约(GMT-5)时间9:30到16:00时段内的K线背景上色,我们可以这样做:
// 检查当前K线是否在纽约时间9:30到16:00的时段内
inUSSession = InSession("0930-1600", "GMT-5")
// 为该时段内的K线设置红色背景
bgcolor(inUSSession ? color.new(color.red, 80) : na)
该函数也可以使用隔夜时段。比方说,我们想在17:15到1:00的时段内显示一条指数移动平均线。为此,当 InSession() 返回 true 时,我们使用 plot() 函数绘制该平均线,否则使用 na 值来禁用绘图:
// 只在17:15到1:00的时段内绘制移动平均线
emaValue = ta.ema(close, 20)
plot(InSession("1715-0100") ? emaValue : na, color=color.orange)
有时我们想知道当前K线具体发生在哪个时段。要做到这一点,我们可以多次调用 InSession(),每次用一个不同的时段进行检查。
例如,下面的代码会基于三个可能的交易时段来更改K线的颜色:
// 将0:00-6:00时段的K线设为绿色,9:00-12:00之间的设为蓝色,
// 13:00-17:30时段内的设为紫色,其他(作为默认)则为黄色
priceBarColour = if InSession("0000-0600")
color.green
else if InSession("0900-1200")
color.blue
else if InSession("1300-1730")
color.purple
else
color.yellow
barcolor(priceBarColour)
脚本范例
让我们来看看 InSession() 函数在完整脚本中是如何运作的。下面的指标会创建两种颜色的背景。
发生在指定时段和时区内的K线会获得蓝色背景,而不在该时段内的K线则使用黄色的图表背景。
该指标的完整代码如下:
//@version=5
indicator(title="See if bar falls in session", overlay=true)
// 当当前K线发生在指定的时段内时,InSession() 函数返回 'true',
// 并为给定的时区进行校正(可选)。
// 当K线不发生在该时间段内,或当图表时间周期为1天或更高时,
// 返回 'false'。
InSession(sessionTime, sessionTimeZone=syminfo.timezone) =>
not na(time(timeframe.period, sessionTime, sessionTimeZone))
// 创建输入项
session = input.session("0900-1700", title="Session")
timeZone = input.string("GMT+1", title="Time Zone")
// 检查当前K线是否落在指定的时段内
bgcolor(InSession(session, timeZone) ? color.new(color.blue, 80) : na)
// 验证K线是否 *不* 发生在时段内
bgcolor(not InSession(session, timeZone) ? color.new(color.yellow, 70) : na)
我们以 indicator() 函数开始,用于命名该脚本并将其叠加显示在主图的交易品种上。
然后,我们引入了上面讨论过的自定义 InSession() 函数。
接下来,我们创建了两个输入项。第一个是时段输入(input.session()),我们用它来定义一个9:00到17:00的交易时段,并将其值存储在 session 变量中供后续使用。
另一个输入是字符串输入(input.string())。这个输入用于设定时段的时区,其默认值为 "GMT+1"。我们使用 timeZone 变量来追踪其当前值。
然后我们为时段内和时段外的K线背景上色:
// 检查当前K线是否落在指定的时段内
bgcolor(InSession(session, timeZone) ? color.new(color.blue, 80) : na)
// 验证K线是否 *不* 发生在时段内
bgcolor(not InSession(session, timeZone) ? color.new(color.yellow, 70) : na)
我们在这里两次调用了 bgcolor() 函数。每一次,条件运算符(?:)都会在 color.new() 函数创建的颜色和 na 值(用于关闭背景色)之间进行选择。
第一个背景色通过 InSession() 函数来判断当前K线是否落在我们用输入项设置的时段内。因此,我们使用 session 变量来获取‘Session’输入的当前值,并用 timeZone 变量获取‘Time Zone’输入的值。当K线处于该时间范围内时,条件运算符会返回一个透明的蓝色(color.blue),否则,传给 bgcolor() 的 na 值会关闭背景。
另一个背景色则用于那些不在时段内的K线。为了测试这一点,我们在 InSession() 前面放上 not 运算符。我们使用相同的参数调用该函数。当K线确实在时段之外时,背景会变为透明的黄色(color.yellow),否则,由于 na 的存在,背景色会被关闭。
图表示例
该指标在图表上看起来是这样的:
蓝色背景高亮了9:00-17:00 GMT+1时段内的K线。黄色背景则用于该范围之外的K线。
当我们将时段输入修改为一个从17:00到15:00的隔夜时段时,图表会变为:
现在只有两根K线处于时段之外(黄色背景),而几乎所有的K线都在时段之内(蓝色背景)。
需要记住的一件事是,图表和时段分别使用的是哪个时区。比方说,指标高亮的是9:00到17:00 (GMT+1) 时段内的K线,但图表的显示时区被设置为了UTC (GMT)。在这种情况下,脚本会高亮8:00到16:00(不含)这个时间范围内的K线:
虽然这乍一看似乎不正确,但它实际上是完全正确的:GMT时区中的8:00 K线,正好对应GMT+1时区的9:00点。
如果我们希望K线的时间戳与我们指定的时段相匹配,我们可以将图表的显示时区设置为与 InSession() 函数所使用的时区相同。
对于前面的例子,这意味着将图表切换到UTC+1时区,这样9:00的K线就会在我们告诉脚本要使用的9:00-17:00时段的开始时出现:
总结
time()函数可以判断当前K线是否落在某个特定的时段内。如果是,该函数会返回一个非na的值。- 自定义的
InSession()函数正是利用了这一特性。当K线处于给定的时段和指定的时区内时,InSession()返回true(否则返回false)。 - 当
InSession()和图表使用不同的时区时,K线的时间戳将与时段不匹配(但计算结果仍然是正确的)。 InSession()可能在图表上找不到任何处于该时段内的K线。当设置的时段发生在交易品种的隔夜时间范围内时(例如由于时区差异),这种情况就会出现。






