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

Pine Script(270):策略函数限制、订单上限与自动化交易

#Pine Script入门教学

如何修复TradingView的”无法在学习脚本中使用策略功能”错误?

在TradingView中,我们能创建的脚本主要有两种:指标(indicators)和策略(strategies)。前者通常用于在图表上绘图和标记符号,而后者则可以模拟交易并回测交易思想。尽管两者共享大量的Pine Script代码,但某些专属于策略的代码元素是不能在指标中使用的。本文将探讨当我们在指标中误用策略代码时会触发何种错误,以及如何解决。

剖析TradingView的’can’t use strategy functions’错误

TradingView的指标和策略之所以易于上手,很大程度上是因为它们共享了许多通用的代码。大多数我们能为指标编写的功能同样也适用于策略。但某些函数和变量是特定脚本类型独有的。当我们试图混用时,就会遇到错误。

其中一个常见的错误就是’can’t use strategy functions in study script’(无法在研究脚本中使用策略函数)。当这个错误发生时,图表上首先会显示一个通用的无法编译脚本的提示:

这个提示本身帮助不大。幸运的是,Pine编辑器的控制台窗口中提供了更详细的信息,例如:

Processing script...
You can't use strategy functions (strategy.position_avg_price) in study script. Please replace 'study' with 'strategy'.
Script 'Error example' has been saved

(你不能在研究脚本中使用策略函数(strategy.position_avg_price)。请将’study’替换为’strategy’。)

这条错误信息非常明确:它不仅指出了错误的原因,还点名了我们试图误用的具体代码元素。

修复’can’t use strategy functions in study script’错误

‘can’t use strategy functions in study script’这个错误,发生在我们试图在指标脚本中使用专属于策略的变量或函数时。由于指标脚本的设计初衷不包含交易功能,TradingView会在我们尝试这么做时触发错误。

幸运的是,修复这个错误非常简单,因为错误信息已经给出了明确的指引。第一步,仔细阅读完整的错误信息,特别注意括号中提到的代码元素,例如 strategy.position_avg_price,这个变量或函数就是问题的根源。第二步,你需要决定如何处理这个不被允许的策略代码:如果你的脚本逻辑并不依赖于这个变量或函数,那么最简单的办法就是直接删除它并保存脚本,如果之后又出现了新的同类错误,只需重复此步骤即可;如果你确实需要使用这个变量或函数的功能,那么你就需要将整个脚本的类型从指标(indicator/study)更改为策略(strategy),这正是错误信息提示 Please replace 'study' with 'strategy' 的含义。

提示:虽然错误信息说的是策略函数,但实际上也有几个策略变量是无法在指标中使用的。因此,在编写指标时,也要留意不要误用这些策略独有的变量。

关于study script:在错误信息中,你可能会看到’study script’这个词。在这里,它只是指标(indicator)的另一个名字。在TradingView的语境中,study几乎总是指indicator。为了避免混淆,本文更倾向于使用指标和策略这两个更明确的术语。

接下来,让我们通过几个例子来看看如何修复这个错误。

错误示例1:在指标中绘制策略数据

一个常见的错误场景,是在指标脚本中尝试绘制策略的绩效数据。

例如,在一个指标中这样写:

//@version=5
indicator(title="错误示例", overlay=true)

plot(strategy.grossloss, color=color.blue, linewidth=2)
Processing script...
You can't use strategy functions (strategy.grossloss) in study script. Please replace 'study' with 'strategy'.
Script 'Error example' has been saved

这会引发错误,因为我们不能在指标中使用策略的总亏损变量(strategy.grossloss)。

正确的做法是将 plot() 函数从指标代码中移动到策略脚本内部。因为TradingView的策略脚本也具备绘图功能,我们完全可以在策略脚本中直接绘制其绩效数据,而无需创建独立的指标。修改后的策略脚本可能如下:

//@version=5
strategy(title="策略示例", overlay=false, pyramiding=10)

// ...交易逻辑...
if longCondition
    strategy.entry("Enter Long", strategy.long)
if shortCondition
    strategy.entry("Enter Short", strategy.short)

// 在策略脚本中直接绘制总亏损
plot(strategy.grossloss, color=color.blue, linewidth=2)

错误示例2:使用策略数据生成警报

不幸的是,并非所有’can’t use strategy functions in study script’错误都能被完美解决。在本文写作之时,TradingView的策略脚本尚不支持创建警报,而指标脚本则可以。

那么,我们是否可以曲线救国,通过一个指标来读取策略的持仓信息并创建警报呢?例如:

//@version=5
indicator(title="错误示例", overlay=true)

smaValue = ta.sma(close, 50)
plot(smaValue, color=color.orange)

alert = close > smaValue and strategy.position_size != 0

alertcondition(condition=alert,
     message="价格在SMA上方且有持仓")
Processing script...
You can't use strategy functions (strategy.position_size) in study script. Please replace 'study' with 'strategy'.
Script 'Error example' has been saved

这个尝试同样会失败,因为指标脚本无法访问策略的持仓规模变量(strategy.position_size)。遗憾的是,由于策略脚本本身不能生成警报,这个问题目前是无解的。我们无法在TradingView中实现基于策略持仓来触发警报的功能。

总结

在TradingView中,脚本分为两种类型:指标和策略。指标通常用于绘制数据、标记图形符号和生成警报。而策略除了拥有指标的所有功能外,还可以提交订单和管理市场头寸。

尽管两者的编码过程非常相似,但它们并非完全相同。’can’t use strategy functions in study script’这个错误就揭示了它们的区别。当我们试图在指标脚本中使用专属于策略的函数或变量时,这个错误就会发生。

修复这个错误有两种方法:一是将有问题的策略代码从指标中移除;二是将整个脚本的类型从指标改为策略,从而获得访问这些策略专属功能的权限。

如何修复TradingView策略中的”订单限额已达”错误?

在回测策略时,会产生大量的订单活动:开仓、平仓以及加仓订单。这在通常情况下没有问题,但当我们执行的订单过多时,TradingView就会触发’order’s limit was reached’(达到订单数量上限)的错误。本文将探讨如何应对这个错误。

TradingView的’order’s limit reached’错误

TradingView的优势之一是其广泛的市场覆盖和丰富的数据。与其它平台相比,我们无需手动管理交易品种和下载数据,这使得在不同时间周期、时间段和市场条件下测试策略变得非常容易。

但一个包含大量历史数据的图表也可能带来一个意想不到的缺点:我们的策略可能会在这些K线上生成过多的订单。当这种情况发生时,TradingView便会触发其著名的’order’s limit was reached’错误。这个错误会出现在我们图表的顶部:

与其他TradingView错误相比,这个错误并不会在Pine编辑器的控制台窗口中显示任何消息。这意味着,图表上方的这条提示是我们能获得的全部线索。幸运的是,处理这个错误并不复杂。

处理已达到订单数量上限

这里有个坏消息:对于TradingView的’order’s limit was reached’错误,并没有真正的解决方案。这个错误仅仅是在我们的策略回测时提交了超过3,000个订单时便会发生。并且,这是一个TradingView平台的硬性限制,而非一个编程错误。

但我们可以通过对策略进行一些调整来处理这个错误。以下是当你遇到’order’s limit was reached’错误时可以尝试的一些方法。

首先,检查你的策略代码。是否存在某个错误,导致脚本发送了远超预期的订单?比如说,你本想交易一个30周期的EMA,却不小心写成了ta.ema(close, 3)而非ta.ema(close, 30)。修复这个错误是一个唾手可得的胜利,能大大降低遇到订单数量上限的可能性。

如果代码没有错误,那么你需要调整策略以减少其生成的订单数量。这里有一些值得尝试的事情:调低或完全禁用策略的pyramiding设置,这样每个多头或空头头寸就只有一个交易;添加一个时间过滤器,这样策略就不会回测图表上的所有价格K线(见下文示例);在更高的时间框架上运行策略,如果你在1分钟图上遇到了订单上限,可以考虑切换到3分钟或5分钟图;分别在只做多和只做空的回测中测试策略的表现,这样通常可以将策略的订单数量减少一半;让你的策略只在一天中的某个特定时间段内提交订单,如果你计划手动执行该策略,那么在半夜发生的信号可以安全地跳过。

如果以上几点都不起作用或不适合你的策略,那么你将不幸地需要进行重大的策略调整。这意味着你需要重新审视你最初的策略思想,并设计出一个交易活动更少的策略,以便TradingView能够对其进行回测。

请注意,strategy.entry()strategy.exit()strategy.order()函数提交的都是订单(order)。但这与头寸(position)是不同的。毕竟,一个多头或空头头寸可能由多笔入场和/或出场订单构成。由于’order’s limit was reached’错误针对的是订单而非头寸,当我们的策略脚本为每个信号只使用一笔入场和一笔平仓订单时,它便能回测最多的信号。因此,如果我们为每个头寸使用5笔入场和5笔出场订单,我们只能回测200个信号。但如果只用一笔订单入场和出场,我们的策略便能测试1,000个信号。

现在,让我们探讨一些代码示例。每个示例都展示了我们如何能绕过’order’s limit was reached’错误。但请注意,每个策略、品种和时间框架都是独特的:对一个策略有效的方法,可能对另一个无效。

错误示例:由金字塔式加仓触发的订单上限

在TradingView中,编写一个进行金字塔式加仓的交易策略很容易:只需将pyramiding参数添加到strategy()函数中,或手动启用相应的策略选项。不幸的是,因此而触发’order’s limit was reached’错误也相当容易。

这里有一个例子:

//@version=5
strategy(title="错误示例", overlay=true, pyramiding=10)

// 计算数值
highestClose = ta.highest(close, 3)[1]
lowestClose  = ta.lowest(close, 3)[1]

// 交易条件
enterLong  = close > highestClose and close > open
enterShort = close < lowestClose and close < open

// 绘制数值
plot(highestClose, color=color.green)
plot(lowestClose, color=color.red)

// 提交订单
if enterLong
    strategy.entry("EL", strategy.long)

if enterShort
    strategy.entry("ES", strategy.short)

这个示例策略允许最多10次的金字塔式加仓。其开仓逻辑基于3周期内的最高或最低收盘价。这意味着策略的交易信号会非常频繁,产生的订单数量巨大,多到超出了TradingView平台的承受范围,因此会触发’order’s limit was reached’(达到订单数量上限)的错误。

然而,修复这个错误会更棘手一些。我们可以修改入场条件来降低交易频率,但这会改变我们策略的核心假设。我们也可以限制回测的时间窗口,但鉴于这个策略如此活跃,我们最终可能会得到一个因周期过短而缺乏统计意义的回测。

一个更实际的选择是暂时禁用金字塔式加仓。我们可能并不需要10次入场来仅仅验证一个初始信号是否有效。如果我们先在不加仓的情况下测试策略,若回测结果显示有潜力,我们随时可以再开启加仓功能,并在一个较小的时间窗口内进行更精细的测试。

因此,要修复’order’s limit was reached’错误,一个可行的方法是从 strategy() 函数中移除 pyramiding 参数。这样,示例中策略函数的声明(第2行)就变成了:

strategy(title="错误示例", overlay=true)

错误示例:通过时间过滤器修复订单限制错误

‘order’s limit was reached’错误的根源在于图表上的订单总数过多。但TradingView默认会在所有可用的历史数据上进行回测。由于我们无法在策略设置中直接配置回测的时间段,因此我们必须探索其他能以编程方式限制回测窗口的方法。

让我们通过下面这个会引发错误的策略脚本来看看如何着手:

//@version=5
strategy(title="错误示例", overlay=true)

// 计算数值
highestClose = ta.highest(close, 2)[1]
lowestClose  = ta.lowest(close, 2)[1]

// 交易条件
enterLong  = close > highestClose and close > open
enterShort = close < lowestClose and close < open

// 提交订单
if enterLong
    strategy.entry("EL", strategy.long)
if enterShort
    strategy.entry("ES", strategy.short)

这个策略所生成的’order’s limit was reached’错误,其中一个修复方法是使用一个程序化的时间过滤器。通过限制策略何时生成交易,我们便能限制它在整个回测期间的交易频率。

这个解决方案的挑战在于,如何设计一个好的时间过滤器。我们不想过度地限制我们的策略:如果只在一个很小的时间窗口上进行回测,我们便无法判断这个策略思想是否真的有效。我们也不能随意地排除任何时间段:如果我们最终将熊市行情排除在外,那么策略的回测结果也同样不可信。

但在现实中,一个时间过滤器有时必须排除大量的数据,才能防止TradingView的’order’s limit was reached’错误。前文的示例策略在1分钟图表上就非常活跃,以至于只有下面这样的时间过滤器才起作用:

// 交易条件
timeFilter = year == 2018 and 
     month >= 7 and 
     dayofmonth > 18

enterLong = close > highestClose and 
     close > open and 
     timeFilter

enterShort = close < lowestClose and 
     close < open and 
     timeFilter

我们在这里创建的timeFilter布尔变量,它只在K线的日期处于2018年7月19日及之后时才为true。我们将这个过滤器作为附加条件加入到enterLongenterShort变量中。这些变量正是策略用来确定是否应该发送订单的依据。

顺便提一下,在我编写这个例子时,日期是2018年7月26日。这意味着这个交易策略在1分钟的EUR/USD图表上是如此活跃,以至于它连一周的数据都无法完整回测,就会遇到’order’s limit was reached’的错误。

幸运的是,并非所有策略都如此活跃。因此在很多情况下,一个时间过滤器是有效的。这里有一些我们可以尝试的其他过滤器示例:year == 2018 and month >= 7,只从2018年7月开始回测;year == 2018,只回测整个2018年;(year == 2017 and month > 6) and (year == 2018 and month < 7),回测从2017年7月到2018年6月底的时间段。

错误示例:通过改变策略逻辑修复订单限制错误

有时,即便我们关闭了金字塔式加仓,并大刀阔斧地限制了策略的时间窗口,我们仍然会遇到’order’s limit was reached’的错误。这对于那些在市场上进行高频交易的策略尤其如此。

那么该怎么办?嗯,那么绕过这个错误的唯一方法,就是改变策略的逻辑(可能再结合一个时间过滤器)。这也是最极端的选项,所以你可能想先尝试其他所有方法。但如果别无他法,我们将不得不让我们的策略去适应TradingView平台(而不是反过来让平台适应我们)。

假设我们有这个示例脚本:

//@version=5
strategy(title="错误示例", overlay=true)

// 计算数值
highestClose = ta.highest(close, 3)[1]
lowestClose  = ta.lowest(close, 3)[1]

// 交易条件
enterLong  = close > highestClose and close > open
enterShort = close < lowestClose and close < open

// 提交订单
if enterLong
    strategy.entry("EL", strategy.long)

if enterShort
    strategy.entry("ES", strategy.short)

让TradingView快速触发’order’s limit was reached’错误的原因,是这个策略的交易活动性:它基于3周期的最高和最低值来进入头寸。

要修复该错误,我们需要让我们的策略不那么活跃。一种方法是增加它在开新仓前的观察周期。比如说,我们将最高和最低收盘价的周期从3根K线增加到5根,像这样:

// 计算数值
highestClose = ta.highest(close, 5)[1]
lowestClose  = ta.lowest(close, 5)[1]

这个策略之所以会迅速触发’order’s limit was reached’的错误,原因在于其交易逻辑过于活跃:它基于极短的3周期最高价和最低价来开立仓位。要修复这个错误,我们需要让策略的交易频率降低。一种方法是增加其开立新仓位前的回顾周期,比如将计算最高和最低收盘价的周期从3根K线延长到5根K线:

// 计算值
highestClose = ta.highest(close, 5)[1]
lowestClose  = ta.lowest(close, 5)[1]

对于我在1分钟EUR/USD图表上的测试,仅仅这个改动就足以规避’order’s limit was reached’的错误。虽然这确实意味着我修改了策略的原始逻辑,但至少它现在可以在平台上运行和评估了。

总结

当我们的TradingView策略生成的订单总数超过3,000个时,就会发生’order’s limit was reached’的错误。不幸的是,这个错误标志着一个TradingView平台的内在限制,这意味着我们需要主动地去规避它,而不是试图修复它。

有几种方法可以应对这个错误。最好的情况是,策略的过度交易是由一个简单的编码错误导致的。如果我们的策略代码是正确的,那么我们就需要考虑其他方法来处理这个错误。

我们可以禁用金字塔式加仓,这样策略仍然会响应相同的交易信号,但订单数量会大大减少。或者,我们可以添加一个时间过滤器,让策略不要在图表的整个历史数据上进行回测。另一个选项是在一个稍高的时间框架上进行回测。如果以上这些方法都没有真正的帮助,那我们就需要回到原点,重新思考如何能在降低交易频率的前提下,仍然有效地测试我们的策略思想。

哪些服务可以自动化TradingView交易?

目前,TradingView本身并不支持自动交易。但随着自动交易和TradingView的流行,一些第三方公司加入进来,为TradingView提供自动交易功能。

它们是通过TradingView的警报实现的。当我们生成包含特定消息的警报时,第三方服务可以读取该警报信息,并用它来执行真实交易。

那么TradingView有哪些警报自动化服务呢?让我们来看看。

警报自动化服务列表(按字母排序)

这些第三方提供商提供在TradingView上实现交易自动化的工具和服务:3Commas、Aleeert、Alertatron、Altredo InteractiveBrokers插件、APIBridge、Autoview、Capitalise.ai、Cornix、Cryptohopper、Cryptowatch、Cwebhook、Gunbot、Mudrex、NextLevelbot、ProfitView、Quadency、SignalStack、Tickerly、Traderelay、TradersPost、TradingConnector、TradingView to MT4、TradingView.to、Wunderbit。

上面的列表包含了我经过广泛研究后找到的所有第三方,但仍然可能有所遗漏。如果你知道其中没有提到的服务,欢迎反馈,以便更新这篇文章供其他读者参考。

警报自动化服务提供的资产类别

并非所有上述提供商都覆盖所有类型的资产。事实上,大多数提供商只专注于加密货币。

以下是各家第三方提供的资产类别:

警报自动化服务 提供的资产类别
3Commas 加密货币现货、期货、保证金和期权市场。
Aleeert 加密货币。
Alertatron 加密货币。
Altredo InteractiveBrokers插件 股票、货币、期货、商品以及InteractiveBrokers支持的更多资产类别。
APIBridge InteractiveBrokers和各种印度经纪商。
Autoview 加密货币和外汇。此外,还可以通过OANDA的差价合约交易商品、指数和股票。
Capitalise.ai 多资产经纪商(如InteractiveBrokers)、差价合约经纪商(如Pepperstone和FXCM)以及加密货币(币安)。
Cornix 加密货币。
Cryptohopper 加密货币。
Cryptowatch 加密货币。
Cwebhook 任何提供cTrader软件的CFD经纪商所支持的品种。
Gunbot 加密货币。
Mudrex 加密货币现货和永续期货市场。
NextLevelbot 期货、股票、差价合约和加密货币(主要针对印度市场)。
ProfitView 加密货币现货、期货和保证金市场。此外,还可以通过OANDA的差价合约交易大宗商品、指数和股票。
Quadency 加密货币现货市场。
SignalStack 多资产经纪商(例如InteractiveBrokers和TradeStation)、CFD经纪商(例如OANDA)、期货经纪商(Optimus和NinjaTrader)以及加密货币(ByBit、Coinbase等)。
Tickerly 加密货币现货、期货和保证金市场。以及通过OANDA进行外汇、指数、商品、债券和加密货币交易。
Traderelay 通过币安交易加密货币现货、期货和保证金市场。此外,还可通过盈透证券交易股票、外汇、期货和差价合约。
TradersPost 股票、期权、ETF和加密货币。
TradingConnector 通过MetaTrader进行外汇、指数和商品交易。
TradingView to MT4 理论上MetaTrader经纪商支持的所有资产类别,但官方没有明确说明。
TradingView.to 加密货币现货、期货和保证金市场。此外,还有二元期权、外汇以及MetaTrader支持的其他资产类别。
Wunderbit 加密货币。

请注意,当你阅读本文时,一些提供商可能已经扩展了其服务范围。请查看那些看起来最有前景的提供商,以确认他们目前可以处理哪些资产类别和交易所。

上面的表格和列表中还缺少几个第三方。截至撰写本文时,他们的网站已经下线。

被排除的提供商包括:

警报自动化服务 提供资产类别吗?
Auto4Mex 未知;撰写本文时网站处于离线状态。
Signalbot 未知;撰写本文时网站处于离线状态。
Superorder 未知;撰写本文时网站处于离线状态。
赞(0)
未经允许不得转载:图道交易 » Pine Script(270):策略函数限制、订单上限与自动化交易
分享到

评论 抢沙发

登录

找回密码

注册