欢迎光临散文网 会员登陆 & 注册

发明者量化PINE语言入门教程-时间序列与脚本结构

2022-07-11 18:14 作者:发明者量化  | 我要投稿

时间序列

时间序列这个概念在Pine语言中非常重要,是我们学习Pine语言时必须要弄明白的一个概念。时间序列不是一种类型而是用于随时间存储变量的连续值的基本结构,我们知道Pine脚本是基于图表的,图表中展示的最基本的内容就是K线图。时间序列其中每个值都与一个K线Bar的时间戳关联。open是一个Pine语言的内置变量(built-in),其结构为储存每根K线Bar开盘价的时间序列。可以理解为open这个时间序列结构代表了当前K线图从开始的第一根Bar到当前脚本执行的这根Bar时所有K线Bar的开盘价。如果当前K线图是5分钟周期,那么我们在Pine策略代码中引用(或者使用)open时就是在使用策略代码当前执行时的K线Bar的开盘价。如果要引用时间序列中的历史值需要使用[]操作符。当Pine策略在某根K线Bar上执行时,使用open[1]表示引用open时间序列上当前脚本执行的这根K线Bar的前一根K线Bar的开盘价(即上一个K线周期的开盘价)。

  • 时间序列上的变量非常方便用于计算
    我们以内置函数ta.cum举例子:


测试代码:


有很多类似ta.cum这样的内置函数可以直接处理时间序列上的数据,例如ta.cum就是把传入的变量在每个K线Bar上对应的值累加起来,接下来我们使用一个图表来方便理解。


可以看到,其实v1、v2甚至bar_index都是时间序列结构,在每根Bar上都有对应的数据。这个测试代码不论用「实时价模型」还是「收盘价模型」区别仅仅为图表上是否显示实时Bar。为了回测速度我们使用「收盘价模型」回测测试。


因为v1这个变量在每一根Bar上都是1,ta.cum(v1)函数在第一根K线Bar上执行时由于只有第一根Bar,所以计算结果为1,赋值给变量v2。
ta.cum(v1)在第二根K线Bar上执行时,已经有2根K线Bar了(第一根对应的内置变量bar_index是0,第二根对应的内置变量bar_index是1),所以计算结果为2,赋值给变量v2,以此类推。实际上可以观察到v2就是图表中K线Bar的数量,由于K线的索引bar_index是从0开始递增,那么bar_index + 1实际上也就是K线Bar的数量。观察图表也可以看到线v2bar_index确实是重合的。


同样我也可以用ta.cum内置函数计算当前图表上所有Bar的收盘价之和,那么只用这样写就可以了:ta.cum(close),当策略运行到最右侧的实时Bar时ta.cum(close)计算出的结果就是图表上所有Bar的收盘价之和了(没有运行到最右侧时,只是累加到了当前Bar而已)。

时间序列上的变量也可以使用运算符进行运算,例如代码:ta.sma(high - low, 14),把内置变量high(K线Bar最高价)减去low(K线Bar最低价),最后使用ta.sma函数求平均值。

  • 函数调用结果也会在时间序列中留下值的痕迹

该测试代码在回测时测试运行,可以观察到v1v2的值是相同的,图表上画出的线也是完全重合的。函数调用计算出的结果在时间序列中会留下值的痕迹,例如代码ta.highest(high, 10)[1]其中的ta.highest(high, 10)函数调用计算出的结果也是可以用[1]来引用其历史值的。基于当前Bar的上一根Bar对应的ta.highest(high, 10)计算结果就是ta.highest(high[1], 10)。所以ta.highest(high[1], 10)ta.highest(high, 10)[1]完全等价。

使用另一种画图函数输出信息验证:

可以看到时间序列中变量a和变量b的值显示在对应的Bar的上方和下方。在学习过程中可以保留这个画图代码,因为在测试、试验时可能经常需要在图表上输出信息用于观察。

脚本结构

一般结构

在教程开始部分我们总结过一些FMZ上的Pine和Trading View上的Pine语言使用方面的不同点,FMZ上的Pine代码编写时可以省略版本号、indicator()strategy()、并且暂时不支持library()。当然为了兼容较早版本的Pine脚本,策略编写时写上诸如://@version=5indicator()strategy()也是可以的。一些策略设置也可以在strategy()函数中传参设置。

<version>版本控制信息可省略。

注释

Pine语言使用//作为单行注释符,由于Pine语言没有多行注释符。FMZ扩展了注释符/**/用于多行注释。

代码

脚本中不是注释或编译器指令的行是语句,它实现了脚本的算法。一个语句可以是这些内容之一。

  • 变量声明

  • 变量的重新赋值

  • 函数声明

  • 内置函数调用,用户定义的函数调用

  • ifforwhileswitch等结构

语句可以以多种方式排列

  • 有些语句可以用一行来表达,比如大多数变量声明、只包含一个函数调用的行或单行函数声明。其他的,像结构,总是需要多行,因为它们需要一个局部的块。

  • 脚本的全局范围内的语句(即不属于局部块的部分)不能以空格制表符(tab键)开始。它们的第一个字符也必须是该行的第一个字符。在行的第一个位置开始的行,根据定义成为脚本的全局范围的一部分。

  • 结构或多行函数声明总是需要一个local block。一个本地块必须缩进一个制表符或四个空格(否则,会被解析为上一行的串联代码,即被判定为上一行代码的连续内容),每个局部块定义了一个不同的局部范围。

  • 多个单行语句可以通过使用逗号(,)作为分隔符在一行中串联起来。

  • 一行中可以包含注释,也可以只是注释。

  • 行也可以被包起来(在多行上继续)。

例如,包括三个局部块,一个在自定义函数声明中,两个在变量声明中使用if结构,如下代码:

换行代码

长行可以被分割在多行上,或被 "包裹 "起来。被包裹的行必须缩进任何数量的空格,只要它不是4的倍数(这些边界用于缩进局部块)。

可以被包装成(注意每行缩进的空格数量都不是4的倍数):


一个长的plot()调用可以被包装成。

用户定义的函数声明中的语句也可以被包装。但是,由于局部块在语法上必须以缩进开始(4个空格或1个制表符),当把它分割到下一行时,语句的延续部分必须以一个以上的缩进开始(不等于4个空格的倍数)。比如说:

本章内容不难,基本都是Pine语言的概念,规则介绍。您学会了吗?

发明者量化PINE语言入门教程-时间序列与脚本结构的评论 (共 条)

分享到微博请遵守国家法律