博客Blog /
让 Pine Script 警报不重绘、不重复的三个习惯
把 Pine Script 策略接到自动下单之前,我会先检查三件事。它们和策略好不好无关,只和“信号是否可靠”有关。
1. 只在 K 线收盘后发信号
盘中价格还在变动,条件可能这一秒成立、下一秒又不成立。如果警报在盘中触发,你可能已经下了单,图表上的信号却消失了。
最简单的办法,是在条件里加上 barstate.isconfirmed,或者在 alert() 里使用收盘频率:
//@version=6
indicator("Close-only alert", overlay = true)
longCond = ta.crossover(ta.sma(close, 10), ta.sma(close, 30))
if longCond and barstate.isconfirmed
alert("long signal", alert.freq_once_per_bar_close)
代价是信号会晚到一根 K 线收盘,但换来的是:图表上看到的信号,就是实际发出去的信号。
2. 跨周期取数,只用已经收盘的数据
在 1 小时图上引用日线数据时,很多人会写 request.security(syminfo.tickerid, "D", close)。在历史回测中,这可能会用到当天还没收盘的日线价格,回测结果因此偏好看。
常用的不重绘写法,是取前一根已经收盘的值,并配合 lookahead_on:
dailyClose = request.security(syminfo.tickerid, "D", close[1], lookahead = barmerge.lookahead_on)
这样回测和实盘拿到的都是同一个、已经确定的数字。
3. 每个信号带一个唯一编号
TradingView 的 webhook 偶尔会失败,网络重试也可能让同一条消息到达两次。执行端如果没有办法分辨,就可能重复下单。
我的做法是在消息里加上“品种 + 方向 + K 线时间”组成的编号:
signalId(side) => syminfo.ticker + "-" + side + "-" + str.tostring(time)
服务器收到消息后先查这个编号:没见过就执行,见过就丢弃并记录。之后每天对账,也用同一个编号把信号和券商订单对上。
小结
这三个习惯不会让策略更赚钱,但能让你相信:系统做的,就是你写的。下周我会写服务器端如何处理去重和断线。
本文仅讨论代码写法,不构成投资建议。