TradingView时间值与Unix时间
当你在TradingView中处理时间时,你可能已经在官方文档中注意到了UNIX time这个词,也可能见过TradingView time values(TradingView时间值)的说法。它们到底指什么?又是哪一种时间格式?让我们来一探究竟。
解析:TradingView所使用的时间格式
TradingView的指标和策略可以处理时间。例如,我们通过 time 和 time_close 变量来获取K线的时间。而要定义一个特定的时间点,我们则使用 timestamp() 函数。
所有这些时间都使用一种特定的格式。由于没有一个公认的贴切说法,我们姑且称之为TradingView时间值。这些值是基于所谓的Unix time。因此,要更好地理解时间在TradingView中是如何运作的,我们首先需要讨论一下Unix time。
Unix time:测量自1970年以来的总秒数
Unix time(也称为 epoch time 或 POSIX time)是一个用于描述时间点的系统,其原理是计算自协调世界时(UTC)1970年1月1日星期四00:00:00以来所经过的总秒数。这意味着,一个Unix时间戳就是某个特定日期时间与1970年1月1日0点之间的秒数差。
每过一秒,Unix time的值就增加一。经过完整的一天(24小时),Unix time会增加86,400。而经过一个月(30天),这个时间格式的值会增加2,592,000。
所以,这些时间值通常都很大。例如,当我在2019年12月17日18:47:39撰写本文初稿时,当前的Unix time是1,576,608,459。作为对比,在2019年1月1日00:00 UTC时,Unix time的值就已经达到了1,546,300,800。
由于Unix time只是简单地测量逝去的秒数,使用这种时间格式进行编程就相对直观。想知道从现在起12小时后的Unix time吗?只需简单地加上43,200(60秒 × 60分钟 × 12小时)即可。需要知道一周前的Unix time吗?只需从当前时间减去604,800即可。
注意事项
为求严谨,这里补充一点:Unix time也会对闰秒进行校正。之所以需要进行这些一秒钟的校正,是因为地球并非总能稳定地在86,400秒内完成一次完整的自转。
正因为闰秒的存在,严格来说,“Unix time测量了自1970年以来的所有秒数”这个说法是不准确的。然而,闰秒的影响非常有限:自1970年以来,总共只有27次一秒钟的校正,这大约相当于每年半秒钟的差异。因此,出于所有实际应用的目的,我们可以放心地认为Unix time就是测量自1970年以来的总秒数。
TradingView时间:测量自1970年以来的总毫秒数
现在我们来讨论TradingView指标和策略所使用的时间。这些时间值实际上是基于Unix time的。但它们并非测量秒数,而是报告自1970年1月1日00:00 UTC以来所经过的毫秒数。
因此,每过一秒,一个TradingView时间值就会增加1,000。一小时后,该时间值会增加3,600,000。而一天后,它会增加86,400,000。
有了这些数字,不难理解为何TradingView的时间值会随着时间的推移变得非常巨大:
- 一根在2019年12月17日9:30 UTC开盘的价格K线,其TradingView时间值为1,576,575,000,000。
- 1999年7月7日的日线价格K线,其TradingView时间值为931,354,200,000。
- 1972年7月25日的日线价格K线,其TradingView时间值为80,919,000,000。
- 而1968年1月10日的价格K线则有一个 -62,328,600,000的TradingView时间值。
最后一个值可能看起来有点奇怪。一个负的时间值表示某个特定的日期和时间发生在1970年1月1日之前的多少毫秒。
注意事项
官方文档把TradingView时间直接称作UNIX time。虽然这种说法相当准确,但并非完全正确:Unix time使用的是秒,而TradingView使用的是毫秒尺度。
因此,你编写的任何时间操作代码都必须考虑到一个1000倍的因子差异。不过,除此之外,TradingView时间和Unix time是相同的。
范例:使用TradingView时间值的代码
TradingView测量时间的方式在编程方面有几个非常有用的特性。
- 一个特性是,推算一个新的日期和时间非常容易。 比方说,我们想知道当前K线收盘后24小时的时间点。为此,我们只需简单地将86400000(一天中的毫秒数)加到
time_close变量上:// 获取当前K线收盘后 // 24小时的时间值 dayAfterClose = time_close + 86400000 - 类似地,要知道从当前时间起7天前的时间点,我们从
timenow变量中减去604800000即可:// 计算一周前的时间值 // (7个24小时的时间段) oneWeekAgo = timenow - 604800000 - 另一个不错的特性是:计算时间间隔非常直观。 假设我们想知道两根价格K线之间相隔了多少秒。为此,我们只需将两个时间值相减,然后除以我们目标时间单位(秒)所包含的毫秒数:
// 计算当前K线的开盘时间与 // 20根K线前的开盘时间之间经过了多少秒 secondsPassed = (time - time[20]) / 1000 - 而要查看两根K线之间相隔了多少分钟,我们则除以60000:
// 计算当前K线开盘时与 // 50根K线前的K线开盘时之间相差的分钟数 minuteDifference = (time - time[50]) / 60000 - 第三个特性是,我们可以直接对不同的时间进行比较。 由于TradingView的时间值只会随着时间的推移而增加,因此我们知道,更大的值总是在时间上发生得更晚,而更小的值则发生得更早。如果两个时间值相等,那么它们就发生在完全相同的时间点。(当然,这假设两个时间值都处于相同的时区。)
这个特性使得判断一根价格K线是否发生在某个特定时间点之后变得很容易,我们可以用 timestamp() 函数来定义这个时间点:
// 查看当前K线的时间是否在
// 2019年圣诞节第一天的午夜之后:
if time > timestamp(2019, 12, 25, 0, 0)
// 执行一些有用的操作
TradingView时间值的优缺点
TradingView测量时间的方式有几个优点:
- 无论你在哪个国家或地区,TradingView的时间值都可以是相同的。这是因为大多数变量和函数测量的是自一个基于UTC的时间点以来的毫秒数。所以如果你要绘制TradingView的当前UTC时间 (
timenow),你会看到和平台上其他人一样的值。 - 时间值使得比较时间变得容易。一个更大的值总是发生得更晚,而相同的值则发生在完全相同的时间。
- 一旦你熟悉了它们,使用TradingView的时间值进行计算会变得非常简单和快捷。
- 由于它们以毫秒尺度报告时间,TradingView的时间值有潜力做到非常精确。
但也有一些缺点:
- 自1970年以来的毫秒数会产生非常巨大的数值。例如,直接绘制一根K线的时间 (
time) 几乎没有意义:这些值太大了,以至于非常难以阅读和理解。 - 某些TradingView变量不使用基于UTC的时间值,而是报告图表交易品种所在的时区。这增加了混淆的可能性,也提高了出错的几率。
还有一点值得一提。尽管TradingView以毫秒尺度测量时间,但实际的值并没有毫秒级的精度。相反,时间值总是以1000毫秒(即一整秒)为单位递增。我猜想这在未来可能会改变,否则TradingView一开始可能就不会使用毫秒尺度了。
总结
- TradingView的时间值基于Unix time。但它并非报告自1970年1月1日00:00:00 UTC以来的秒数,而是测量自该时间点以来所经过的毫秒数。
- 这些值在编程时非常方便。要创建一个过去或未来的日期,我们只需在一个时间值上减去或加上一个毫秒数即可。例如,减去86,400,000毫秒,就能让我们在时间上回到24小时之前。
- TradingView的时间值也使得比较时间变得很容易。一个更大的时间值总是发生得更晚,而一个更小的时间值则发生在更远的过去。当两个时间值相同时,它们就发生在完全相同的时间点。
time与time_close:获取K线的开盘和收盘时间
大多数TradingView脚本处理的是价格数据和成交量。但我们的代码同样可以利用价格K线的时间戳进行工作。下面我们来看看如何实现。
在TradingView Pine中以编程方式访问K线时间
大多数TradingView指标和策略是基于价格和成交量来做出交易决策的。但时间同样是一项有用的信息。
例如,我们可能想判断一根K线是发生在某个特定时间点之前还是之后;或者计算自某个事件以来过去了多少分钟或小时;或者只是想知道一个隔夜跳空持续了多长时间。要在我们的脚本中实现这些行为,就需要访问K线的时间。让我们看看该怎么做。
TradingView有两个可以返回K线时间的变量:
time变量返回K线的开盘时间。- 而
time_close变量则给出K线的收盘时间。
让我们来深入探讨一下这些变量。
获取K线的开盘时间:time 变量
time 变量返回K线的开盘时间。该时间以UTC(协调世界时)时区进行报告。
与TradingView Pine中的任何其他时间值一样,time 也是使用UNIX time值来测量时间的。如果你不熟悉这个概念也没关系,我们可以在不了解其细节的情况下使用 time 并进行时间比较。(不过,当我们需要用时间进行计算时,了解UNIX time的基础知识还是必要的。)
获取当前K线的开盘时间
使用 time 的基本方式就是查找当前K线的开盘时间。要做到这一点,我们只需在代码的某个地方简单地使用 time 即可。例如:
// 获取当前K线的开盘时间
barOpenTime = time
当然,还有更实际的使用 time 的方法。如果我们想看看它的UNIX time值是什么样的,我们可以使用 plot() 函数将它们绘制在图表上:
// 绘制K线开盘的时间
plot(time, color=color.maroon,
title="Time of bar open")
获取历史K线的开盘时间
要知道某一根历史K线是在何时开盘的,我们可以将 time 变量与历史引用操作符([])结合使用。在方括号之间,我们放入一个整数,用以指明我们想回看多少根K线。
例如,time[1] 返回前一根K线的开盘时间:
// 获取前一根K线的开盘时间
prvOpenTime = time[1]
我们以同样的方式处理其他的历史K线:例如,time[5] 会返回5根K线之前的K线开盘时的UNIX time值。
计算两根K线之间的时间差
当我们获取了当前K线和某一根历史K线的时间后,就可以计算它们之间的时间差。为此,我们只需用当前K线的时间(time)减去一个历史时间(如 time[1])即可:
// 计算K线之间的时间差
timeDiff = time - time[1]
time 是使用UNIX time值来测量时间的。所以当我们对两个 time 值进行相减时,得到的结果也是一个UNIX值。在TradingView中,这些值测量的是自1970年以来的毫秒数。
因此,要计算K线之间的时间差,需要两个步骤。首先,我们将一个历史 time 值从另一个 time 值中减去;然后,我们将这个差值除以1000。例如:
// 获取当前K线与10根K线前
// 的开盘时间之间的总秒数
timeDifference = (time - time[10]) / 1000
这个代码片段计算了当前K线的开盘时间(time)和10根K线之前的开盘时间(time[10])之间相差的秒数。为了将这些UNIX值转换为实际的秒数,我们将其除以1000。
我们可以用 time 进行更多的计算。通过这个变量,我们可以计算隔夜交易时段的持续时间,或者计算一根价格K线的时间跨度。
TradingView time 变量的特性
time 变量具有以下特性:
- 对于某一根特定的K线,
time变量总是返回相同的开盘时间。因此,尽管time的值会随着K线的不同而改变,但在同一根K线内部,该变量的值是恒定的。这与其他变量的行为不同,例如,close(收盘价)在K线内的每次脚本计算中都可能有一个新值。 time变量以UNIX time值的形式返回当前K线的开盘时间。得益于这种时间测量方式,我们可以轻松地进行时间计算和比较。- 要访问历史K线的开盘时间,我们将
time与历史引用操作符([])结合使用。例如,time[3]可以告诉我们3根K线前的开盘时间。然而,这个特性不能反向使用:time[-1]会产生一个TradingView错误,而不会返回下一根K线的开盘时间。 time以UTC时区报告其值。这个时区与time_close和timenow变量所使用的时区相同。因此,我们可以轻松地对这三个变量进行比较,而无需进行时区转换。- 要将
time与一个非UTC时区进行比较,我们必须转换其中一个值,以确保两者使用相同的时区。通过timestamp()函数,我们可以为一个特定的时区定义一个时间点。 - 我们可以在任何类型的图表上使用
time。这似乎是理所当然的,但情况并非总是如此——正如我们接下来在讨论time_close变量时将了解到的。
获取K线的收盘时间:time_close 变量
time_close 变量返回K线的收盘时间。该值以UNIX time值的形式报告,并且始终采用UTC时区。让我们来仔细看看。
获取当前K线的收盘时间
当我们使用 time_close 变量时,我们会得到当前K线收盘时的时间戳。作为一个基础范例:
// 获取当前K线收盘的时间
barEndTime = time_close
当然,我们也可以做一些更实际的操作,比如在图表上绘制K线的收盘时间:
// 绘制K线收盘时的时间值
plot(time_close, color=color.blue,
title="Bar close time")
使用 time_close 还有更多的可能性。例如,通过这个变量,我们可以实现对实时K线收盘的倒计时功能。
获取历史K线的收盘时间
要知道某一根历史K线是在何时收盘的,我们可以将 time_close 变量与TradingView的历史引用操作符([])结合使用。在方括号内,我们指定要回看的K线数量。
例如,time_close[1] 可以告诉我们前一根K线的收盘时间:
// 获取上一根K线的收盘时间
prvCloseTime = time_close[1]
同样的过程也适用于其他的历史K线:time_close[3] 返回3根K线前的收盘时间,而 time_close[10] 则对10根K线前的情况做同样的操作。
计算收盘时间差
当我们获取了不同K线的收盘时间后,就可以计算它们之间的时间差。例如:
// 计算K线收盘时间之间的时间差
timeDiff = time_close - time_close[5]
这里,我们用当前K线的收盘时间(time_close)减去5根K线前的收盘时间(time_close[5])。由于 time_close 使用的是UNIX time值,这次减法的结果也是一个UNIX time值。
为了让这些UNIX time值更具实用性,我们会将其除以特定时间单位所包含的毫秒数。例如,要知道两根K线之间相隔的分钟数,我们就除以60000,因为一分钟里有60,000毫秒。
// 计算两根K线收盘时间之间的分钟数
timeDifference = (time_close - time_close[5]) / 60000
这个代码片段告诉我们两根K线的收盘时间之间相隔了多少分钟。
TradingView time_close 变量的特性
time_close 变量具有以下这些特性:
time_close只在基于时间的图表上有效;在基于价格的图表上(例如Renko图和Range图),该变量会返回na。其原因是,在基于价格的图表上,我们无法预知一根K线将在何时收盘。(即便是在已知该信息的历史K线上,time_close依然会返回na。)- 即使K线尚未收盘,
time_close也会返回该K线的预期收盘时间。这样,我们的脚本就可以预知当前K线何时结束。但这也意味着time_close的值在同一根K线期间是不会改变的(因此是恒定的)。 time_close以毫秒精度的UNIX时间格式报告其值。当我们需要用这些时间进行计算时,必须进行转换才能得到例如秒、分钟和小时数。time_close使用UTC时区,这与time和timenow变量使用的时区相同。因此,我们可以直接对这些变量进行比较,无需担心时区转换问题。- 要将
time_close与UTC以外的时区进行比较,我们需要手动转换时区,或者使用TradingView的timestamp()函数来创建一个特定于时区的时间点。
总结
- 有两个TradingView变量可以返回K线的时间。我们用
time获取K线的开盘时间,用time_close返回K线的收盘时间。后一个变量只在基于时间的图表上有效;在基于价格的图表(如Renko和Range)上,time_close会返回na值。 - 这两个变量都以UNIX time值的形式报告时间,并使用UTC时区。要查看历史K线的开盘或收盘时间,我们使用TradingView的历史引用操作符(
[])。但我们不能用[]来获取未来K线的时间。


