今天我们继续学习Pine语言的模型执行。在了解Pine语言时间序列基础上,你的交易逻辑是想基于实时价模型或者收盘价模型?收盘价模型对于趋势策略比较友好,而实时价模型更多的适用于震荡策略,当然这并没有固定的限制。但是如果你想更加准确的用Pine语言模拟你的交易思想,那么这部分内容你一定不要错过。
在入门学习Pine语言时,是非常有必要了解Pine语言脚本程序执行过程等相关概念的。Pine语言策略是基于图表运行的,可以理解为Pine语言策略为一系列的计算和操作,在图表上以时间序列的先后顺序从图表已经加载的最早数据开始执行。图表中加载的Bar有两个部分,策略开始前的历史Bar和策略开始后的实时Bar。
图表中历史Bar初始加载的数据量是有限的。实盘时通常这个数据量上限是基于交易所接口返回的最大数据量决定,回测时数据量上限是基于回测系统数据源提供的数据决定。
根据策略的设置不同,策略的模型执行方式也不同,分为收盘价模型和实时价模型。
收盘价模型 策略代码执行时,当前K线Bar的周期完全执行完成,K线闭合时即K线周期已经走完。此时执行一遍Pine策略逻辑,触发的交易信号将在下一根K线Bar开始时执行。
实时价模型 策略代码执行时,当前K线Bar不论是否闭合,每次行情变动就执行一遍Pine策略逻辑,触发的交易信号立即执行。
当Pine语言策略在图表上从左至右执行时,图表上的K线Bar是分为历史Bar和实时Bar的:
历史Bar 策略设置为「实盘价模型」开始执行时,图表上除了最右侧的那一根K线Bar之外所有K线Bar都是历史Bar。策略逻辑在每根历史Bar上仅执行一次。策略设置为「收盘价模型」开始执行时,图表上所有Bar都是历史Bar。策略逻辑在每根历史Bar上仅执行一次。 基于历史Bar的计算:策略代码在历史Bar收盘状态下执行一次,然后策略代码继续在下一个历史Bar执行,直到所有历史Bar都执行一次。
实时Bar 当策略执行到最右边的最后一根K线Bar上时,该Bar为实时Bar。当实时Bar闭合之后,这根Bar就变成了一个经过的实时Bar(变成了历史Bar)。图表最右侧会产生新的实时Bar。策略设置为「实时价模型」开始执行时,在实时Bar上每次行情变动都会执行一次策略逻辑。 策略设置为「收盘价模型」开始执行时,图表上不显示实时Bar。如果设置策略为「收盘价模型」图表不显示实时Bar,策略代码只在当前Bar收盘时执行一次。
如果设置策略为「实盘价模型」在实时Bar上的计算和历史Bar就完全不同了。例如内置变量high、low、close在历史Bar上是确定的,在实时Bar上可能每次行情变动时这些值是会发生变化的。所以基于这些值计算的指标等数据也是会实时变动的。在实时Bar上open是不变的,close始终代表当前最新价格,high和low始终代表自当前实时Bar开始以来达到的最高点和最低点。这些内置变量代表实时Bar最后一次更新时的最终值。
策略代码在历史Bar收盘状态下执行一次,然后策略代码继续在下一个历史Bar执行,直到所有历史Bar都执行一次。如果设置策略为「实盘价模型」在实时Bar上的计算和历史Bar就完全不同了,在实盘Bar上每次行情变动都会执行一次策略代码。
下面我们来举例说明下:
if open > close [1]
runtime.log("涨")
if open < close [1]
runtime.log("跌")
本策略以天为周期,打印出每个策略周期的涨跌值。当用收盘价为模型的时候,打印操作是在历史Bar收盘状态下执行的,所以以天为单位进行打印;而用实时价为模型,打印操作是在实时Bar上进行,每次行情变动都会打印一次。
在实时Bar执行时,策略的每次新迭代执行前重置用户定义的变量称为回滚。我们来用声明变量var和varip理解回滚机制,其中声明变量应该在赋值运算符处讲解,但是在不了解时间序列和模型执行的基础上,对于大家理解起来比较困难,因此放在这里讲解,并以此用来了解策略的回滚机制。
声明模式: 其实变量在命名的时候,在声明变量时最先写的就是「声明模式」,变量的声明模式有三种即: 1、使用关键字var。 2、使用关键字varip。 3、什么都不写。
var var 是用于分配和一次性初始化变量的关键字。通常,不包含关键字var的变量赋值语法会导致每次更新数据时都会覆盖变量的值。 与此相反,当使用关键字var分配变量时,尽管数据更新,它们仍可以“保持状态”。
varip varip(var intrabar persist)是用于分配和一次性初始化变量的关键词。它与var关键词相似,但是使用varip声明的变量在实时K线更新之间保留其值。
其实说起来解释还是比较晦涩,我们举例示范下。
strategy(overlay=true)
var i = 0
varip ii = 0
plotchar(true, title = 'i', char=str.tostring(i), location=location.abovebar, color=color.aqua)
plotchar(true, title = 'ii', char=str.tostring(ii), location=location.belowbar, color= color.blue)
i := i+1
ii := ii+1
我们看到在收盘价模型中, var 和 varip 没有区别,只是在策略周期更新时进行一次更新。由于收盘价模型是每根K线BAR走完时才执行一次策略逻辑。所以在收盘价模型时,历史K线阶段和实时K线阶段,var、varip声明的变量在以上例子中递增表现完全一致,都是每根K线BAR递增1。
当在实时价模型,历史K线阶段时var、varip声明的变量i、ii在策略代码每轮执行时都会执行递增操作。所以可以看到回测结果K线BAR上显示的数字逐个都是递增1的。当历史K线阶段结束,开始实时K线阶段。var、varip声明的变量则开始发生不同的变化。因为是实时价模型,在一根K线BAR内每次价格变动都会执行一遍策略代码,i := i + 1和ii := ii + 1都会执行一次。区别是ii每次都修改。i虽然每次也修改,但是下一轮执行策略逻辑时会恢复之前的值,就是回滚,直到当前K线BAR走完才更新确定i的值(即下一轮执行策略逻辑时不再恢复之前的值)。所以可以看到变量i依然是每根BAR增加1。但是变量ii每根BAR就累加了好几次。
转变执行方式为实时价模型,其实策略更新就是跟随者tick的数据,进行策略逻辑的运行。在收盘价模型里,我们策略的更新,是上一个周期的一整个k线bar。而在实时价模型,伴随每次行情变动进行策略的运行,其实就是对比交易所返回的tick数据。这里我们选择模拟级tick,就是每分钟根据k线图模拟四个左右的tick数据。回到图表里,我们看到不带有关键字的变量每次都是计算加1,然后在下一次tick数据返回时,返回到原来的值。带有关键字var在每个tick周期内,虽然每次都计算,但是在一个策略周期内,都会保留原有的值;直到下一次策略周期的更新。而带有关键字varip的变量的变动是伴随着tick周期的,每次tick变动,都会进行计算和保留。
在实时价模型中,有模拟级tick和实盘级tick的返回机制。
模拟级tick: 一分钟四个模拟tick,所以每分钟varip增加4个左右。
实盘级tick: 根据交易所反馈的信息,针对于螺纹钢品种(其他品种可能不一样),每秒两个tick,所以每分钟varip增加120个。
总体来说,这部分比较困难。因为理解起来比较晦涩,所以需要简单的代码例子进行详细的说明和解释。这部分内容需要在较好的理解“时间序列”概念上,理解策略背后运行的机制–模型执行。了解收盘价模型和实时价模型的区别,通过var和varip理解实时价模型背后的回滚机制。只有在此基础上,才能对策略模型的原理有一个清楚的理解。当然,这也对理解“偷价”和“未来函数”,这些策略背后的陷阱有一个清楚的认识。