判断K线是否是时段的第一根
我们时常需要让脚本知道,当前的K线是否标志着该时段的开始。利用这些信息,我们可以实现例如仅在特定时间段内进行交易,或将警报限制在某个交易时段内等功能。
但要实现这些,Pine Script需要知道哪一根K线是时段的第一根。让我们看看如何用代码实现这一点。
自定义函数
要判断一根K线是否是某个时段的第一根,我们首先要弄清楚该时段在哪些K线上是活跃的。然后我们检查当前K线是否处于该时段内,而前一根K线则不在。只有在时段的第一根K线上,这种比较才会成立。
以下是如何在一个自定义的Pine Script函数中实现这个想法:
// 当当前K线是指定时段内的第一根时,IsSessionStart() 返回 'true',
// 并为给定的时区进行校正(可选)。
// 对于时段内的其他K线、时段外的K线,以及当时间周期为1天或更高时,
// 返回 'false'。
IsSessionStart(sessionTime, sessionTimeZone=syminfo.timezone) =>
inSess = not na(time(timeframe.period, sessionTime, sessionTimeZone))
inSess and not inSess[1]
这个 IsSessionStart() 函数有两个参数。sessionTime 是一个用于指定自定义交易时段的时段字符串。sessionTimeZone 是一个用于设定该时段时区的时区字符串。如果我们不设置后者,该函数会默认使用交易品种的时区(syminfo.timezone)。
我们在函数内部做了两件事。首先,我们判断当前K线是否发生在指定时段和给定时区内。这个方法与上一节中的方法相同。我们将这个真/假结果存入 inSess 变量中,当K线在时段内时,该变量为 true,在时段外则为 false。
另一项任务是判断当前K线是否是时段的第一根。为此,我们评估当前K线是否在时段内,同时前一根K线是否不在时段内。这意味着 inSess 应该为 true,同时,该变量在前一根K线上的值应为 false。实现该逻辑的代码是 inSess and not inSess[1]。这会在时段的第一根K线上返回 true(而在任何其他K线上返回 false)。
函数特性
该函数有几个值得了解的特性:
- 当自定义时段覆盖了图表上的所有K线时,代码无法分辨哪根K线是第一根(因为每根K线都在时段内)。
- 我们必须在每一根K线上都调用该函数。因为它比较当前和前一根K线,如果跳过K线,它将无法正确计算。
- 该函数可能找不到时段的第一根K线。当设置的时段发生在交易品种的隔夜时间段时(例如由于时区差异),这种情况就会出现。
- 该函数在日线和更高的时间周期上总是返回
false,因为这些时间周期的K线没有具体的时段信息。
函数范例
把上述函数加入脚本后,我们可以通过多种方式来使用它。
首先,我们可以调用该函数并将结果存储在一个变量中供后续使用。比方说,我们想知道当前K线是否是9:30到16:00时段的第一根。在这种情况下,我们可以这样做:
// 检查当前K线是否是9:30-16:00时段内的第一根
isFirstBarOfSession = IsSessionStart("0930-1600")
当然,我们也可以在任何允许使用布尔值(真/假)的地方直接使用这个自定义函数。让我们假设我们想为纽约(GMT-5)时区9:30到16:00时段的第一根K线背景上色。要实现这种情况,我们可以这样做:
// 为9:30-16:00时段的第一根K线的背景涂上蓝色
bgcolor(IsSessionStart("0930-1600", "GMT-5") ? color.new(color.blue, 80) : na)
而要使用 barcolor() 函数将隔夜17:00到4:00时段的第一根价格K线标记为黑色,我们可以这样做:
// 使17:00到4:00时段的第一根K线变为黑色
priceBarColour = if IsSessionStart("1700-0400")
color.black
barcolor(priceBarColour)
脚本范例
让我们让一个完整的脚本来使用这个自定义的 IsSessionStart() 函数。下面的指标会创建两个输入项:一个用于设置时段,另一个用于定义时区。
然后,脚本会寻找该时段的第一根K线。当找到时,它会在图表上放置一个时钟表情符号来高亮显示这第一根K线。
该指标的完整代码如下:
//@version=5
indicator(title="Start of session example", overlay=true)
// 当当前K线是指定时段内的第一根时,IsSessionStart() 返回 'true',
// 并为给定的时区进行校正(可选)。
// 对于时段内的其他K线、时段外的K线,以及当时间周期为1天或更高时,
// 返回 'false'。
IsSessionStart(sessionTime, sessionTimeZone=syminfo.timezone) =>
inSess = not na(time(timeframe.period, sessionTime, sessionTimeZone))
inSess and not inSess[1]
// 创建输入项
session = input.session("0800-2200", title="Session")
timeZone = input.string("GMT-8", title="Time Zone")
// 验证K线是否为指定时段内的第一根
isFirstOfSession = IsSessionStart(session, timeZone)
// 用一个字符高亮时段的第一根K线
plotchar(isFirstOfSession, char='⏰', size=size.small)
我们以 indicator() 函数开始,它用于命名该脚本并将其放置在主图的交易品种之上。
然后,我们引入了上面讨论过的自定义 IsSessionStart() 函数。
接下来,我们创建了两个输入项。一个是由 input.session() 函数创建的时段输入,它用于设置我们希望从中找到第一根K线的交易时段。另一个输入是使用 input.string() 函数创建的字符串输入,它用于定义该时段的时区。我们分别使用 session 和 timeZone 变量来追踪这两个输入的值。
之后,我们便可以找出当前K线是否是该时段的第一根:
// 验证K线是否为指定时段内的第一根
isFirstOfSession = IsSessionStart(session, timeZone)
这段代码用两个参数来调用 IsSessionStart() 函数。第一个参数 session 是‘Session’输入项的变量。另一个参数 timeZone 则持有着‘Time Zone’输入项的当前值。我们将 IsSessionStart() 返回的布尔值(真/假)存入 isFirstOfSession 变量中。
我们接下来在绘图时使用这个变量:
// 用一个字符高亮时段的第一根K线
plotchar(isFirstOfSession, char='⏰', size=size.small)
这里的 plotchar() 函数在图表上创建一个绘制的字符。绘图的条件是 isFirstOfSession 变量。至于绘制的字符,我们使用了一个经典的(模拟)闹钟表情符号。
在图表上,该范例指标的效果如下:
这里,脚本高亮了8:00的K线,在小时图上,这确实是8:00到22:00时段的第一根K线。
被高亮的K线的时间戳并不总是与时段的开始时间相匹配。当图表和时段使用不同的时区时,就会发生这种情况。
举个例子,假设时段使用的是GMT-3,而图表使用的是UTC-5。这会导致绘制的字符比K线的时间戳早出现2个小时。因此,对于8:00-22:00的时段,这个时区差异会使得时段从6:00的K线开始,而不是8:00的K线:
判断K线是否是时段的最后一根
当我们在Pine Script中编写一个自定义时段时,有时我们希望知道当前的K线是否是该时段的最后一根。这些信息在多种情况下都很有用。
例如,我们可以在时段结束前平掉持仓、收集时段的收盘价,或者仅仅是在图表上高亮显示时段的结束。
但要实现这些,Pine Script需要知道哪一根K线是时段的最后一根。让我们看看如何用代码实现这一点。
自定义函数
在寻找一个时段的最后一根K线时,有一个小小的障碍。在Pine Script中,我们无法从下一根K线获取数据。所以我们无法制定一个规则说,“如果时段在下一根K线上结束,那么当前K线就是时段的最后一根”。
但我们可以实现一个变通方案。那就是,等到图表上出现一个完整的交易时段。然后在图表上第一个交易时段结束后的那一根K线上,我们收集其前一根K线的时间戳。这会告诉我们该时段的最后一根K线所具有的时间。
然后,我们就可以在第二个及后续的时段中寻找最后一根K线了。当这些时段中的某一根K线与我们之前记录的时间戳相匹配时,它就是该时段的最后一根K线。
以下是如何在Pine Script中编写这种方法的代码:
// IsLastBarSession() 当当前K线是指定时段的最后一根时返回 'true',
// 并为给定的时区进行校正(可选)。
// 对于时段内的其他K线、时段后的K线,以及当时间周期为
// 天或更高时,返回 'false'。
IsLastBarSession(sessionTime, sessionTimeZone=syminfo.timezone) =>
var int lastBarHour = na
var int lastBarMinute = na
var int lastBarSecond = na
inSess = not na(time(timeframe.period, sessionTime, sessionTimeZone))
if not inSess and inSess[1]
lastBarHour := hour[1]
lastBarMinute := minute[1]
lastBarSecond := second[1]
hour == lastBarHour and minute == lastBarMinute and second == lastBarSecond
这个自定义的 IsLastBarSession() 函数有两个参数。第一个 sessionTime 是一个用于定义交易时段的时段字符串。另一个 sessionTimeZone 是一个用于指定该时段时区的时区字符串。如果我们不提供后者,该函数会默认使用交易品种的时区(syminfo.timezone)。
在函数内部,我们做了几件事。首先,我们创建了三个持久性变量(var)。它们将用于保存在历史上作为时段最后一根K线的时间戳。它们以空值 (na) 开始。(如果我们使用默认的0,我们可能会在图表开始时意外地捕获到0:00:00的K线。)
然后,我们判断当前K线是否发生在指定的时段和时区内。这使用了前面判断K线是否落在时段内的相同方法。我们将测试结果存储在 inSess 变量中,当K线在时段内时,该变量为 true,在时段外则为 false。
然而,我们并非对任何K线都感兴趣,我们想找到的是时段的最后一根K线。所以,一个 if 语句会判断当前K线是否不在时段内(not inSess),而前一根K线在时段内(inSess[1])。当这种情况发生时,我们就知道自定义时段刚刚结束了。
如果时段刚刚结束,我们需要获取前一根K线的时间,因为那根K线就是时段的最后一根。所以我们更新 lastBarHour、lastBarMinute 和 lastBarSecond 变量为那根前一根K线的时间。收集了这些时间后,在下一个时段中,脚本就可以寻找最后一根时段K线了。
这项任务由函数的最后一条语句完成。该代码会判断当前K线的小时、分钟和秒是否都与我们之前从早期时段的最后一根K线收集到的时间相匹配。当当前K线具有相同的时间时,我们就知道它是时段的最后一根,因此函数返回 true。对于时段内的其他K线,以及时段外的K线,IsLastBarSession() 函数都会返回 false。
函数特性
上面的自定义函数有以下这些值得注意的特性:
- 该函数依赖于前一个时段的K线时间来寻找当前时段的最后一根K线。这在基于时间的图表上有效,但在基于价格的图表(如Renko图和range图)上无效。(在这些图表类型上,目前没有可靠的方案来识别时段的最后一根K线。)
- 当自定义时段覆盖了图表上的所有K线时,代码无法分辨哪根K线是时段的最后一根。该识别需要至少一根在时段外的K线。
- 该函数假设交易品种的交易时间保持不变,因为它使用今天的时段结束时间来看第二天的时段何时结束。当交易时间改变时(例如,当有假日或由于数据问题或交易所中断而导致K线缺失时),这个假设便不再成立。
- 我们必须在每一根K线上都执行该函数。因为它比较当前和前一根K线,如果跳过K线,其结果将不可靠。
- 该函数可能在图表上的任何地方都找不到时段的最后一根K线。当设置的时段发生在交易品种的隔夜时间段时(例如由于时区差异),这种情况就会出现。
- 该函数在日线和更高的时间周期上总是返回
false,因为这些时间周期的K线没有具体的时段信息。
函数范例
把上述函数加入脚本后,我们可以通过多种方式来使用它。
- 首先,我们可以调用该函数并将其布尔值(真/假)结果存储在一个变量中供后续使用。比方说,我们想找出当前K线是否是9:00到17:30时段的最后一根。因此我们编码:
// 检查当前K线是否是9:00到17:30时段的最后一根 isSessionLast = IsLastBarSession("0900-1730") - 我们也可以在任何Pine Script能处理布尔值的地方直接使用该函数。让我们假设我们想为洛杉矶(GMT-8)时区9:00-17:30时段的最后一根K线背景上色。要实现这一点,我们可以这样做:
// 为9:00 - 17:30 GMT-8时段的最后一根K线设置红色背景 bgcolor(IsLastBarSession("0900-1730", "GMT-8") ? color.new(color.red, 80) : na) - 以同样的方式,我们也可以找到一个隔夜时段的最后一根K线。例如,要将18:00到8:00时段的最后一根K线标记为黄色,我们可以将
barcolor()函数与IsLastBarSession()结合使用,像这样:// 将18:00 - 8:00时段的最后一根K线涂成黄色 barcolor(IsLastBarSession("1800-0800", "GMT+2") ? color.yellow : na) - 我们可能还想在时段的最后一根K线上生成一个平仓订单。这样,当时段结束后的第一根K线开盘时,TradingView就会平掉策略的持仓。或者,如果我们使用
process_orders_on_close设置,我们就会在时段最后一根K线的确切收盘时刻平仓。 要在一个8:00到22:00时段的最后一根K线上生成一个平仓订单,我们可以这样做:// 如果这是8:00-22:00时段的最后一根K线,平掉所有持仓 if IsLastBarSession("0800-2200") strategy.close_all()
脚本范例
让我们看看一个完整的脚本如何使用 IsLastBarSession() 函数。下方的指标使用11:00到16:00的时段。我们通过这个自定义函数来寻找该时段的最后一根K线。当找到时,我们将其背景涂成紫红色。
该指标的完整代码如下:
//@version=5
indicator(title="Last bar in session", overlay=true)
// IsLastBarSession() 当当前K线是指定时段的最后一根时返回 'true',
// 并为给定的时区进行校正(可选)。
// 对于时段内的其他K线、时段后的K线,以及当时间周期为
// 天或更高时,返回 'false'。
IsLastBarSession(sessionTime, sessionTimeZone=syminfo.timezone) =>
var int lastBarHour = na
var int lastBarMinute = na
var int lastBarSecond = na
inSess = not na(time(timeframe.period, sessionTime, sessionTimeZone))
if not inSess and inSess[1]
lastBarHour := hour[1]
lastBarMinute := minute[1]
lastBarSecond := second[1]
hour == lastBarHour and minute == lastBarMinute and second == lastBarSecond
// 通过输入项来配置时段
session = input.session("1100-1600", title="Trading Session")
timeZone = input.string("GMT", title="Time Zone")
// 查看当前K线是否是时段的最后一根
lastSessionBar = IsLastBarSession(session, timeZone)
// 用紫红色背景高亮时段的最后一根K线
bgcolor(lastSessionBar ? color.new(color.fuchsia, 80) : na)
首先,我们调用 indicator() 函数,通过 title 命名脚本,并使用 overlay 使其显示在主图的交易品种之上。
然后我们引入了上面讨论过的自定义 IsLastBarSession() 函数。
接下来,我们创建了两个输入项。第一个是使用 input.session() 函数创建的时段输入,其默认值为11:00到16:00的时段。另一个是使用 input.string() 函数创建的字符串输入,它指定了时段的时区,并以 "GMT" 作为其初始值。session 和 timeZone 变量分别追踪这两个输入的当前值。
之后,我们寻找时段内的最后一根K线:
// 查看当前K线是否是时段的最后一根
lastSessionBar = IsLastBarSession(session, timeZone)
// 用紫红色背景高亮时段的最后一根K线
bgcolor(lastSessionBar ? color.new(color.fuchsia, 80) : na)
这段代码首先用两个参数调用 IsLastBarSession() 函数:第一个是时段输入项的变量 session,另一个是包含时区信息的字符串输入 timeZone。
当脚本在时段的最后一根K线上进行计算时,IsLastBarSession() 返回 true(而在任何其他K线上返回 false)。我们将这个结果存入 lastSessionBar 变量。
接下来,bgcolor() 函数为图表背景上色,但并非一直如此。它通过一个条件运算符(?:)来评估 lastSessionBar 变量是否为 true。如果是,运算符会返回一个透明的紫红色(color.fuchsia)作为背景色。否则,它会返回 na 值来禁用背景色。最终结果是,时段的最后一根K线会有一个紫红色的背景,而所有其他K线则没有背景。
在下方的图表上,该指标将15:45的K线高亮为时段的最后一根。这是因为,在一个15分钟的图表上,15:45开盘的K线正是11:00到16:00交易时段的最后一根。
被高亮的K线的时间戳并不总是与我们配置的时段相匹配。当图表和时段使用不同的时区时,就会发生这种情况。
比方说,时段使用的是GMT时区,而图表则使用UTC-5时区。这会导致高亮的背景比时段结束时间早5个小时出现。对于一个11:00-16:00的时段,(在15分钟图上)10:45的K线会被标记为时段的最后一根K线:
总结
IsLastBarSession()函数可以判断一根价格K线是否是特定时区内某个自定义时段的最后一根。- 当脚本在该最后一根K线上进行计算时,函数返回
true。对于时段内的其他K线以及时段外的K线,它都返回false。 IsLastBarSession()函数在基于价格的图表(如Renko和Line Break)上无效。- 当图表和时段使用不同的时区时,看起来函数可能识别了错误的K线,但这其实是由时区偏移引起的。






