如何把TradingView警报变成交易策略
当一个指标的警报总能精准找出盈利机会时,我们自然会想:要是把它做成一个自动化交易策略,效果会怎样?可问题是,该怎么把一个指标及其警报,转化成一个功能完善的TradingView策略呢?下面就来一探究竟。
TradingView的警报功能,是接收交易信号和市场动态通知的好工具。有时我们手头的某个警报已经相当精准,能可靠地识别交易机会,这时难免会想:要是能回测这些信号,甚至让它自动交易就好了。
遗憾的是,截至本文撰写时,我们还无法在TradingView的“策略”脚本里直接用代码生成警报——所有由代码触发的警报都必须在“指标”脚本中实现,而指标脚本本身又无法提交订单或管理仓位。(如果你试图在指标脚本里使用策略类函数,TradingView会直接报错:can't use strategy functions in study script。)
因此,要想在警报触发的位置自动执行交易,唯一的途径就是把指标脚本改造成一个TradingView策略脚本。下面来看具体步骤。
三步把指标变策略
要在指标发出警报的位置进行交易,我们需要走以下三步:
- 新建策略并复制代码:在Pine编辑器中创建一个全新的“策略”脚本,把原有的指标代码完整复制过来。这样能保留原始代码,万一改坏了随时可以退回可用的初始版本。
- 精简代码:删掉从指标里复制过来、策略用不到的代码。由于策略无法创建警报,所有
alertcondition()调用都可以删掉;如果你不希望策略在图表上画指标线或改背景色,相关绘图代码也可一并移除。 - 改造代码,把指标变成策略:对清理后的代码做必要调整。先把开头的
indicator()换成strategy();再用strategy.entry()创建入场订单,入场逻辑沿用指标里原有的警报触发条件;最后基于指标原有的平仓警报条件创建出场订单,平仓有两种选择——市价平仓用strategy.close_all()或strategy.close(),限价或止损平仓则用strategy.exit()。
下面通过一个实例演练这三步。我们先做一个带多个警报条件的布林带指标,再把它的代码复制、改造成策略脚本,最后对比策略与指标在图表上的表现有何不同。
示例指标:触发布林带警报
下面这个示例指标会基于布林带(Bollinger Bands)的边界来触发警报。它用20周期的布林带生成警报:以20周期简单移动平均线(SMA)为中轨,上下轨分别是中轨加减2倍的20周期标准差。这个指标包含4种警报条件:
- 买入信号:当K线的最低价触及或跌破布林带下轨,但收盘价最终又顽强地收回到下轨之上时触发。可以理解为市场强势,因为价格在触及下轨后奋力反弹回带内。
- 多头平仓信号:当K线收盘价向下跌穿布林带中轨(即20周期SMA)时触发。逻辑是价格一度站上中轨表现强势,随后动能衰竭、再度跌破中轨。
- 做空信号:当K线最高价触及或突破布林带上轨,但收盘价最终无力地收回到上轨之下时触发。可以理解为市场疲软,因为价格没能收在上轨之外。
- 空头平仓信号:当价格从下方向上穿越布林带中轨时触发。逻辑是价格经历一段弱势后重新积聚力量,成功突破了中轨的压制。
该示例指标在图表上的效果如下:

以下是该指标的完整代码:
//@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线。条件满足时buySignal为true。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,警报条件成立,我们就会收到“应该做多”的提示;同理,第二个在shortSignal为true时触发“应该做空”。最后一个的触发条件基于sellSignal和coverSignal,由于用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)
和设置背景色类似,这里用了条件运算符?:(也叫三元运算符),根据sellSignal和coverSignal的值,决定arrowType是-1(向下箭头)、1(向上箭头)还是na(不画箭头)。然后把arrowType传给plotarrow(),它会按第一个参数画出不同方向的箭头,用colorup和colordown设置颜色,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)
然后是最关键的一步:用实际的交易指令替换掉警报条件,让策略在之前触发警报的地方自动下单。回顾一下指标的警报逻辑,它们由buySignal、shortSignal、sellSignal、coverSignal这四个布尔变量驱动。在指标里,buySignal和shortSignal用来触发做多、做空警报;在策略里,我们就用同样的变量调用strategy.entry()开立相应仓位。同样,sellSignal和coverSignal在指标里用于触发平仓警报,在策略里就用它们调用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(),因为策略本身无法创建警报;此外,任何你觉得策略用不到的绘图或标记代码(如plot、bgcolor等)也可一并删除。
第三步,改造。这是把指标“点石成金”为策略的核心步骤,需要做这些调整:用strategy()替换开头的indicator();用与原指标警报完全相同的逻辑条件来驱动策略的开仓与平仓——开仓用strategy.entry()建立多头或空头头寸,平仓若要以市价成交用strategy.close()或strategy.close_all(),若要以限价或止损方式成交则用strategy.exit()。


