当你写脚本写多了,一定会遇到一个情况:某一段计算逻辑,比如“计算某个指标的金叉”或者“判断一个K线形态”,在代码的好几个地方都要用到。这时候,你是每次都复制粘贴一遍,还是有更聪明的办法?
答案就是创建自己的Pine脚本自定义函数。函数,说白了,就是把你常用的一段代码打包成一个可以重复使用的积木。而帮你完成这个打包动作的,就是函数声明运算符=>
。
为什么要费劲去创建函数?因为它能让你的编程水平产生质的飞跃,告别重复劳动,写一次,到处用。代码量大大减少。把复杂的逻辑封装进函数里,主流程代码会变得异常简洁,一目了然。修改维护超级方便,如果你的金叉算法要调整,只需要修改函数内部的一处代码,所有调用它的地方就全部自动更新了。想象一下,如果你是复制粘贴了10遍,那你得手动改10个地方,多容易出错!
单行函数
最简单的函数就是单行函数,它就像一个微型加工厂,接收几个原料(参数),经过一道工序(表达式),然后产出一个成品(返回值)。它的格式是:
函数名(参数1, 参数2) => 表达式
这里要特别提醒,函数声明用的=>
,千万别跟大于等于>=
搞混了,它俩长得像,但完全是两码事。
下面的实例展示了如何创建一个单行函数来计算EMA的动量。
//@version=6
indicator(title="函数声明 - 案例1")
// 1. 定义一个单行函数,用当前的EMA值减去barsBack根K线前的EMA值
momEMA(length, barsBack) => ta.ema(close, length) - ta.ema(close, length)[barsBack]
// 2. 调用函数
plot(momEMA(20, 10), color=color.blue, style=plot.style_histogram, linewidth=3)
plot(momEMA(40, 10), color=color.red, style=plot.style_histogram, linewidth=3)
// 3. 绘制零轴参考线
hline(0, color=color.gray, linestyle=hline.style_solid)
在这个例子里,我们把计算EMA动量的逻辑封装进了momEMA()
函数。之后想看任何周期组合的动量,只需要调用这个函数并传入不同的参数即可,非常方便。
将此示例指标添加到图表后,效果如下:
多行函数
如果你的“加工工序”比较复杂,一行代码写不完怎么办?那就用多行函数。它的结构像这样:
函数名(参数) =>
// 必须缩进的代码块(标准是4个空格)
变量1 = ...
变量2 = ...
最终的返回值
它的关键点有两个:一是=>
后面的所有代码都必须向右缩进(通常是4个空格),这样PineScript才知道这些代码都属于这个函数;二是函数体内的最后一行代码,就是这个函数的返回值,不需要写return
关键字。
下面的脚本演示了如何创建一个多行函数,用来判断价格是否上穿EMA。
//@version=6
indicator(title="函数声明 - 案例2", overlay=true)
// 1. 定义一个多行函数,判断“价格上穿EMA”
CrossAbove(price, length) =>
emaValue = ta.ema(price, length)
// “上穿”的定义:K线价格在均线之上,且上一根在均线之下
above = price > emaValue and price[1] < emaValue[1]
above
// 2. 调用自定义函数来标记信号
plotshape(CrossAbove(close, 10), style=shape.flag,
location=location.abovebar, color=color.red)
plotshape(CrossAbove(high, 30), style=shape.flag,
location=location.belowbar, color=color.blue)
// 3. 绘制EMA线
plot(ta.ema(close, 10), color=color.red, title="EMA(Close,10)")
plot(ta.ema(high, 30), color=color.blue, title="EMA(High,30)")
在这个例子里,我们把判断上穿的逻辑封装进了CrossAbove()
函数。以后无论你想判断收盘价上穿、最高价上穿,还是任何其他价格序列的上穿,都可以复用这个函数,而不需要重复写判断逻辑。
将此示例添加到图表后,效果如下:
总结
通过函数声明运算符=>
,我们可以创建可复用的单行函数和多行函数。创建函数时,依次是函数名
、括号()
里的参数列表
、然后是=>
运算符。对于单行函数,=>
后面是一个单独的表达式,其计算结果就是返回值。对于多行函数,=>
后面是多行代码,每一行都必须通过缩进(标准为4个空格)来表明其属于函数体。函数体内的最后一个表达式或变量,就是该函数的返回值。
当你开始习惯于将你策略里的各个部件(如入场条件、出场条件、风控计算)都封装成独立的函数时,你的编程水平和代码质量就上了一个大台阶。