保持敬畏之心
交易是一场持久战

Pine Script(163):把TradingView警报变成交易策略

#Pine Script入门教学

如何把TradingView警报变成交易策略

当一个指标的警报总能精准找出盈利机会时,我们自然会想:要是把它做成一个自动化交易策略,效果会怎样?可问题是,该怎么把一个指标及其警报,转化成一个功能完善的TradingView策略呢?下面就来一探究竟。

TradingView的警报功能,是接收交易信号和市场动态通知的好工具。有时我们手头的某个警报已经相当精准,能可靠地识别交易机会,这时难免会想:要是能回测这些信号,甚至让它自动交易就好了。

遗憾的是,截至本文撰写时,我们还无法在TradingView的“策略”脚本里直接用代码生成警报——所有由代码触发的警报都必须在“指标”脚本中实现,而指标脚本本身又无法提交订单或管理仓位。(如果你试图在指标脚本里使用策略类函数,TradingView会直接报错:can't use strategy functions in study script。)

因此,要想在警报触发的位置自动执行交易,唯一的途径就是把指标脚本改造成一个TradingView策略脚本。下面来看具体步骤。

三步把指标变策略

要在指标发出警报的位置进行交易,我们需要走以下三步:

  1. 新建策略并复制代码:在Pine编辑器中创建一个全新的“策略”脚本,把原有的指标代码完整复制过来。这样能保留原始代码,万一改坏了随时可以退回可用的初始版本。
  2. 精简代码:删掉从指标里复制过来、策略用不到的代码。由于策略无法创建警报,所有alertcondition()调用都可以删掉;如果你不希望策略在图表上画指标线或改背景色,相关绘图代码也可一并移除。
  3. 改造代码,把指标变成策略:对清理后的代码做必要调整。先把开头的indicator()换成strategy();再用strategy.entry()创建入场订单,入场逻辑沿用指标里原有的警报触发条件;最后基于指标原有的平仓警报条件创建出场订单,平仓有两种选择——市价平仓用strategy.close_all()strategy.close(),限价或止损平仓则用strategy.exit()

下面通过一个实例演练这三步。我们先做一个带多个警报条件的布林带指标,再把它的代码复制、改造成策略脚本,最后对比策略与指标在图表上的表现有何不同。

示例指标:触发布林带警报

下面这个示例指标会基于布林带(Bollinger Bands)的边界来触发警报。它用20周期的布林带生成警报:以20周期简单移动平均线(SMA)为中轨,上下轨分别是中轨加减2倍的20周期标准差。这个指标包含4种警报条件:

  1. 买入信号:当K线的最低价触及或跌破布林带下轨,但收盘价最终又顽强地收回到下轨之上时触发。可以理解为市场强势,因为价格在触及下轨后奋力反弹回带内。
  2. 多头平仓信号:当K线收盘价向下跌穿布林带中轨(即20周期SMA)时触发。逻辑是价格一度站上中轨表现强势,随后动能衰竭、再度跌破中轨。
  3. 做空信号:当K线最高价触及或突破布林带上轨,但收盘价最终无力地收回到上轨之下时触发。可以理解为市场疲软,因为价格没能收在上轨之外。
  4. 空头平仓信号:当价格从下方向上穿越布林带中轨时触发。逻辑是价格经历一段弱势后重新积聚力量,成功突破了中轨的压制。

该示例指标在图表上的效果如下:

以下是该指标的完整代码:

//@version=5
indicator(title="布林带警报 [指标]", overlay=true)

// 输入选项
maLen  = input.int(20, title="均线周期")
stdLen = input.int(20, title="标准差周期")
offset = input.float(2.0, title="标准差倍数")

// 计算指标值
maValue = ta.sma(close, maLen)
stdValue = ta.stdev(close, stdLen)
upperBand = maValue + (stdValue * offset)
lowerBand = maValue - (stdValue * offset)

// 绘制指标线
plot(maValue, color=color.teal, title="中轨")
plot(upperBand, color=color.red, linewidth=2, title="上轨")
plot(lowerBand, color=color.green, linewidth=2, title="下轨")

// 确定警报条件
buySignal = low <= lowerBand and 
     close >= lowerBand
sellSignal = ta.crossunder(close, maValue)
shortSignal = high >= upperBand and 
     close <= upperBand
coverSignal = ta.crossover(close, maValue)

// 创建警报条件
alertcondition(condition=buySignal,
     message="触及布林带下轨;做多")
alertcondition(condition=shortSignal,
     message="触及布林带上轨;做空")
alertcondition(condition=sellSignal or coverSignal,
     message="若持有多单或空单,平掉当前仓位")

// 用背景色高亮买入/做空信号
backgroundColour = if buySignal
    color.new(color.green, 80)
else if shortSignal
    color.new(color.red, 80)
bgcolor(backgroundColour)

// 用箭头高亮平仓信号
arrowType = sellSignal ? -1 :
     coverSignal ? 1 :
     na
plotarrow(arrowType, colorup=color.teal,
     colordown=color.orange, maxheight=15, title="平仓箭头")

逐段解析一下。首先用indicator()定义指标属性,然后创建用户输入选项:

// 输入选项
maLen  = input.int(20, title="均线周期")
stdLen = input.int(20, title="标准差周期")
offset = input.float(2.0, title="标准差倍数")

这里创建了三个可供用户在指标设置中自定义的参数:均线周期(整数)、标准差周期(整数)和标准差倍数(浮点数),并给了常用默认值。把这些输入值分别存入独立变量,好处是后续代码只需通过变量名就能调用用户当前的设置。接着计算指标的核心数值:

// 计算指标值
maValue = ta.sma(close, maLen)
stdValue = ta.stdev(close, stdLen)
upperBand = maValue + (stdValue * offset)
lowerBand = maValue - (stdValue * offset)

我们用ta.sma()算收盘价的简单移动平均线(中轨),用ta.stdev()算收盘价的标准差,再用中轨加减指定倍数的标准差,得到布林带的上、下轨。算完后把这些轨道线画到图表上:

// 绘制指标线
plot(maValue, color=color.teal)
plot(upperBand, color=color.red, linewidth=2)
plot(lowerBand, color=color.green, linewidth=2)

中轨(maValue)画成蓝绿色,上轨(upperBand)和下轨(lowerBand)分别是红色和绿色。为了让上下轨更醒目,把线宽linewidth设为2。之后进入最核心的部分——把交易逻辑转化为布尔(真/假)变量:

// 确定警报条件
buySignal = low <= lowerBand and 
     close >= lowerBand
sellSignal = ta.crossunder(close, maValue)
shortSignal = high >= upperBand and 
     close <= upperBand
coverSignal = ta.crossover(close, maValue)

这里定义了四个布尔变量,分别代表四种交易信号:

  • buySignal(买入信号):寻找那些最低价一度触及或跌破下轨(low <= lowerBand),并且收盘时又收回到下轨之上(close >= lowerBand)的K线。条件满足时buySignaltrue
  • sellSignal(多头平仓信号):由ta.crossunder()决定,判断收盘价close是否从上向下穿越了中轨maValue,是则返回true
  • shortSignal(做空信号):描述最高价一度试探或突破上轨(high >= upperBand),但收盘时无力为继、又收回到上轨之下(close <= upperBand)的疲软形态。
  • coverSignal(空头平仓信号):由ta.crossover()决定,判断收盘价是否从下向上穿越了中轨,是则返回true

定义好这些布尔变量后,用alertcondition()创建警报就很直接了:

// 创建警报条件
alertcondition(condition=buySignal,
     message="触及布林带下轨;做多")

alertcondition(condition=shortSignal,
     message="触及布林带上轨;做空")

alertcondition(condition=sellSignal or coverSignal,
     message="若持有多单或空单,平掉当前仓位")

这里创建了三个警报。第一个直接用前面定义的buySignal,只要它在某次计算中为true,警报条件成立,我们就会收到“应该做多”的提示;同理,第二个在shortSignaltrue时触发“应该做空”。最后一个的触发条件基于sellSignalcoverSignal,由于用or连接,只要其中任意一个为true,就提示我们平仓。需要特别注意的是,这些警报能真正触发之前,我们必须手动到图表后台去启用和配置它们——alertcondition()只是创建了警报的“菜单选项”,它本身并不会自动发出任何警报。接下来,在图表上用不同背景色高亮这些信号:

// 用彩色背景高亮买入/做空信号
backgroundColour = if buySignal
    color.new(color.green, 80)
else if shortSignal
    color.new(color.red, 80)

bgcolor(backgroundColour)

我们创建了一个backgroundColour变量,用if...else if嵌套条件为它赋值:第一个if检查buySignal是否为true,是就用color.new()生成80%透明度的绿色;否则检查shortSignal,是就生成80%透明度的红色;两个都不满足时,这个if语句会隐式返回na,也就是不上色、保持背景原样。最后调用bgcolor()把这个颜色应用到图表背景上。再下面一段用箭头标记平仓信号:

// 用箭头高亮平仓信号
arrowType = sellSignal ? -1 :
     coverSignal ? 1 :
     na

plotarrow(arrowType, colorup=color.teal,
     colordown=color.orange, maxheight=15)

和设置背景色类似,这里用了条件运算符?:(也叫三元运算符),根据sellSignalcoverSignal的值,决定arrowType-1(向下箭头)、1(向上箭头)还是na(不画箭头)。然后把arrowType传给plotarrow(),它会按第一个参数画出不同方向的箭头,用colorupcolordown设置颜色,maxheight限制箭头尺寸,避免太大影响美观。

把示例指标改造成TradingView策略

现在按前面说的三步,把这个指标改造成一个功能完善的交易策略。

第一步:复制代码到新的策略脚本

先在Pine编辑器里新建一个策略脚本,把上面指标的完整代码原封不动粘贴进去。这样能留一份指标的原始代码,改坏了随时可以回头参考。

第二步:清理与精简代码

接下来删掉新策略里所有不适用于策略的指标代码,首当其冲的是alertcondition()。所以可以删掉这几行:

// 创建警报条件
alertcondition(condition=buySignal,
     message="触及布林带下轨;做多")
// ... (其余alertcondition行)

这一步清理到什么程度因人而异。比如你打算在同一张图上同时用这个新策略和原指标,为了避免图表元素重叠,可能还想把策略里所有绘图和标记的代码也删掉。也就是可以移除所有plot()语句:

// 绘制数值
plot(maValue, color=color.teal)
// ... (其余plot行)

以及所有用于高亮信号的bgcolor()plotarrow()代码:

// 用彩色背景高亮买入/做空信号
bgcolor(backgroundColour)
// 用箭头高亮退出警报
plotarrow(arrowType, ...)

第三步:进行必要的代码改造

现在对清理后的代码做核心改造,让它成为一个真正的策略。有几件事必须做。首先把脚本的“身份”声明从indicator()改成strategy(),也就是把这一行:

//@version=5
indicator(title="布林带警报 [指标]", overlay=true)

改为:

//@version=5
strategy(title="布林带 [策略]", overlay=true)

然后是最关键的一步:用实际的交易指令替换掉警报条件,让策略在之前触发警报的地方自动下单。回顾一下指标的警报逻辑,它们由buySignalshortSignalsellSignalcoverSignal这四个布尔变量驱动。在指标里,buySignalshortSignal用来触发做多、做空警报;在策略里,我们就用同样的变量调用strategy.entry()开立相应仓位。同样,sellSignalcoverSignal在指标里用于触发平仓警报,在策略里就用它们调用strategy.close()关闭相应仓位。于是把原本的alertcondition()语句替换成下面的策略代码:

// 提交入场订单
if buySignal
    strategy.entry("EL", strategy.long) // EL是订单ID,strategy.long代表做多

if shortSignal
    strategy.entry("ES", strategy.short) // ES是订单ID,strategy.short代表做空

// 提交出场订单
if sellSignal
    strategy.close("EL") // 根据订单ID'EL'平掉多头仓位

if coverSignal
    strategy.close("ES") // 根据订单ID'ES'平掉空头仓位

这段代码的逻辑是:buySignal为真时用strategy.entry()提交一个ID为“EL”的多头订单;shortSignal为真时提交一个ID为“ES”的空头订单;sellSignal为真时用strategy.close()平掉ID为“EL”的仓位;coverSignal为真时平掉ID为“ES”的仓位。

完整的策略代码

完成以上三步,我们就得到了一个完全基于原指标警报逻辑的交易策略。现在它能在警报条件满足时自动提交订单,并且借助策略的回测报告,我们可以量化地评估这些警报信号的盈利能力。完整代码如下:

//@version=5
strategy(title="布林带 [策略]", overlay=true)

// 输入选项
maLen  = input.int(20, title="均线周期")
stdLen = input.int(20, title="标准差周期")
offset = input.float(2.0, title="标准差倍数")

// 计算指标值
maValue = ta.sma(close, maLen)
stdValue = ta.stdev(close, stdLen)
upperBand = maValue + (stdValue * offset)
lowerBand = maValue - (stdValue * offset)

// 确定交易信号
buySignal = low <= lowerBand and 
     close >= lowerBand
sellSignal = ta.crossunder(close, maValue)
shortSignal = high >= upperBand and 
     close <= upperBand
coverSignal = ta.crossover(close, maValue)

// 提交入场订单
if buySignal
    strategy.entry("EL", strategy.long)
if shortSignal
    strategy.entry("ES", strategy.short)

// 提交出场订单
if sellSignal
    strategy.close("EL")
if coverSignal
    strategy.close("ES")

图表示例:用策略交易警报条件

现在看看策略是否真的按指标的信号在交易。首先,这是指标在图表上的样子:

图中绿色背景代表做多信号,红色背景代表做空信号;向上箭头是空头平仓信号,向下箭头是多头平仓信号。现在把策略脚本加到同一张图上:

可以看到,出现绿色背景后,策略用“EL”订单开了多头仓位;背景变红那根K线之后,策略在下一根K线的开盘价成交了一笔“ES”做空订单。持有多仓时,第一个向下箭头出现后策略平仓;持有空仓时,向上箭头出现后策略也相应平仓。这说明策略成功把指标识别出的警报信号转成了实际的交易行为。

重要提示

你可能已经从图上注意到,策略的订单成交总是比指标的信号标记晚一根K线。这是TradingView策略回测引擎的机制决定的:策略总是在历史K线收盘时计算,一旦决定生成订单,该订单最早也只能在下一根K线的开盘价成交。换句话说,一根K线已经收盘,我们就不可能再回到那根K线内部去交易,能成交的最快时机就是下一根K线的开始。指标则不同——它计算时可以立即在当前K线上用背景色标记,因为它不必等待成交这类市场行为发生。

再看一个例子,观察指标和策略的行为模式。下图是只加载了指标的图表:

现在把策略脚本加到同一张图上,效果如下:

这里看到了和之前一样的行为模式:出现绿色背景后策略做多,出现红色背景后策略开空,向下箭头出现时策略平掉多仓。你可能注意到图中的“EL”订单显示有2个合约,这是因为策略在做反转操作:其中1个合约用于平掉原有的空头仓位,另1个用于建立新的多头仓位。

小结

当一个指标的警报能有效发现有潜力的交易机会时,我们可以把它转化成交易策略,量化评估这些警报信号的实际表现。把TradingView指标转成策略,主要走三步。

第一步,复制。在Pine编辑器里新建一个策略脚本,把原指标的完整代码复制过来,留一份代码“快照”,后续改策略时万一出现难修的错误,总有一个可靠的原始版本可参照。

第二步,精简。从新的策略脚本里删掉所有策略不需要的指标功能,首当其冲是alertcondition(),因为策略本身无法创建警报;此外,任何你觉得策略用不到的绘图或标记代码(如plotbgcolor等)也可一并删除。

第三步,改造。这是把指标“点石成金”为策略的核心步骤,需要做这些调整:用strategy()替换开头的indicator();用与原指标警报完全相同的逻辑条件来驱动策略的开仓与平仓——开仓用strategy.entry()建立多头或空头头寸,平仓若要以市价成交用strategy.close()strategy.close_all(),若要以限价或止损方式成交则用strategy.exit()

赞(0)
未经允许不得转载:图道交易 » Pine Script(163):把TradingView警报变成交易策略
分享到

评论 抢沙发

登录

找回密码

注册