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

Pine Script(215):订单函数总览与strategy.entry()

#Pine Script入门教学

PineScript策略订单函数一览

在TradingView策略能够在图表上进行模拟交易之前,它的代码必须先生成交易指令。我们通过PineScript中一些特殊的函数——即所谓的订单函数来完成这项工作。

PineScript提供了多种订单函数以应对不同的需求。所有可用的函数如下:

函数 描述
strategy.entry() 专门用于开仓。可以生成市价单、停止单、限价单和停止-限价单。它也可以用于反手开仓。
strategy.exit() 专门用于保护性平仓。可以生成止盈单(限价)、止损单(停止)和追踪止损单。
strategy.order() 通用的订单函数。可以生成买入和卖出指令,用于开仓、平仓、加仓、减仓和反手。支持所有订单类型。
strategy.close() 按名称平仓。生成一个市价单,平掉所有具有特定ID的持仓。
strategy.close_all() 全部平仓。生成一个市价单,平掉策略当前所有的持仓,实现一键清仓。
strategy.cancel() 按名称撤单。取消一个特定ID的、尚未成交的挂单。
strategy.cancel_all() 全部撤单。取消策略当前所有尚未成交的挂单。

为了更好地理解这些函数,我们可以将它们分为三类:

  • 开仓函数:strategy.entry()、strategy.order()
  • 平仓函数:strategy.exit()、strategy.order()、strategy.close()、strategy.close_all()
  • 撤销挂单函数:strategy.cancel()、strategy.cancel_all()

下面,我们来逐一简要介绍每个订单函数。

开仓订单:strategy.entry()

strategy.entry() 函数专用于让策略开立多头或空头仓位。它支持市价单、停止单(stop)、限价单(limit)和停止-限价单(stop-limit)。

使用此函数,我们至少需要提供两个信息:一个订单ID(即订单名称)和交易方向(strategy.long 做多,strategy.short 做空)。

市价单:

// 当价格上穿20周期EMA时,以市价做多
if ta.crossover(close, ta.ema(close, 20))
    strategy.entry("Enter Long", strategy.long)

停止单,需额外使用 stop 参数指定触发价格:

// 当价格突破20周期最高点时,提交一个买入停止单
if close > ta.highest(high, 20)[1]
    strategy.entry("Enter Long", strategy.long, stop=high * 1.01)

限价单,需额外使用 limit 参数指定挂单价格:

// 当价格突破10周期最高点时,提交一个买入限价单
if high > ta.highest(high, 10)[1]
    strategy.entry("Enter Long", strategy.long, limit=high - 0.25)

停止-限价单,需同时使用 stop 和 limit 参数:

// 当价格上穿20周期SMA时,提交一个停止-限价订单
if ta.crossover(close, ta.sma(close, 20))
    strategy.entry("Enter Long", strategy.long, stop=high + 0.25, limit=close - 0.50)

保护性平仓订单:strategy.exit()

strategy.exit() 函数专用于为已有仓位设置保护性平仓,即止盈(profit target)、止损(stop-loss)和/或追踪止损(trailing stop)。

最佳实践是在提交入场订单的同时就提交 strategy.exit() 指令。这样,一旦入场单成交,仓位就能立刻受到保护。我们通过 from_entry 参数将这个平仓指令与特定的入场订单ID关联起来。

止盈单,可通过 profit(点数)或 limit(价格)设置:

// 入场做多的同时,设置一个200点的止盈目标
if ta.crossover(close, ta.ema(close, 20))
    strategy.entry("Enter Long", strategy.long)
    strategy.exit("Exit Long", from_entry="Enter Long", profit=200)

止损单,可通过 loss(点数)或 stop(价格)设置:

// 入场做多的同时,设置一个300点的止损
if high > ta.highest(high, 20)[1]
    strategy.entry("Enter Long", strategy.long)
    strategy.exit("Exit Long", from_entry="Enter Long", loss=300)

追踪止损单,需设置 trail_offset(追踪距离)和激活条件(trail_points 或 trail_price):

// 入场做多的同时,设置一个追踪止损
if ta.crossover(ta.rsi(close, 7), 30)
    strategy.entry("Enter Long", strategy.long)
    strategy.exit("Exit Long", from_entry="Enter Long", trail_points=5, trail_offset=20)

通用订单指令:strategy.order()

strategy.order() 是一个非常灵活的万能函数,它只负责生成买入或卖出指令。这些指令具体会产生什么效果(开仓、平仓、加仓、减仓、反手),完全取决于策略当前的持仓状态和订单数量。它同样支持所有订单类型。

市价单:

// 提交一个市价买入指令
strategy.order("Buy (Market)", strategy.long)

限价单:

// 提交一个限价买入指令
strategy.order("Buy (Limit)", strategy.long, limit=low[1])

停止单:

// 提交一个停止买入指令
strategy.order("Buy (Stop)", strategy.long, stop=high[1])

停止-限价单:

// 提交一个停止-限价买入指令
strategy.order("Buy (Stop-Limit)", strategy.long, stop=close * 1.02, limit=high + 5 * syminfo.mintick)

按名称平仓:strategy.close()

strategy.close() 函数通过市价单平掉所有具有特定ID的持仓。它不在乎是多仓还是空仓,只要ID匹配就会被平掉。这个函数只能平仓,永远不会意外地开立反向仓位。

// 当价格下穿20周期SMA时,市价平掉所有ID为 "Enter Long" 的仓位
if ta.crossunder(close, ta.sma(close, 20))
	strategy.close("Enter Long")

全部平仓:strategy.close_all()

strategy.close_all() 函数通过一笔市价单平掉策略当前持有的所有仓位,实现一键清仓。该函数无需任何参数。

// 当价格下穿40周期EMA时,清空所有持仓
if ta.crossunder(close, ta.ema(close, 40))
	strategy.close_all()

按名称撤单:strategy.cancel()

strategy.cancel() 函数用于取消(删除)一个尚未成交的挂单。它需要一个参数:要取消的挂单的ID。

// 当价格上穿30周期EMA时,取消ID为 "Enter Long" 的挂单
if ta.crossover(close, ta.ema(close, 30))
	strategy.cancel("Enter Long")

全部撤单:strategy.cancel_all()

strategy.cancel_all() 函数用于取消策略当前所有尚未成交的挂单,无论其方向或类型。该函数无需任何参数。

// 当RSI下穿20时,取消所有挂单
if ta.crossunder(ta.rsi(close, 7), 20)
	strategy.cancel_all()

简单总结一下:TradingView策略通过PineScript的订单函数来开仓和平仓。开仓用 strategy.entry()(推荐)或 strategy.order();平仓用 strategy.exit()(保护性止损/止盈)、strategy.close()(按ID市价平仓)、strategy.close_all()(全部市价平仓)或 strategy.order()(通用);撤销挂单用 strategy.cancel()(按ID)或 strategy.cancel_all()(全部)。

用strategy.entry()开多头和空头交易

PineScript策略通过模拟交易来评估交易思路的表现,而 strategy.entry() 函数正是策略用来建立多头和空头仓位的核心工具。

更具体地说,strategy.entry() 函数能够通过以下四种订单类型来建立多头或空头仓位:市价单、止损单、限价单、止损限价单。

此外,strategy.entry() 还会与策略的当前持仓状态进行交互。基于这种交互,该函数可以实现开立一个新仓位、对现有仓位进行加仓,或是反转当前持仓。

可见 strategy.entry() 的功能十分强大。让我们首先来了解该函数的标准语法格式,然后再通过各种代码示例来深入学习这个重要的订单函数。

标准语法格式

strategy.entry() 函数包含以下参数:

strategy.entry(id, direction, qty, limit, stop, oca_name, oca_type, 
     comment, when, alert_message)
  • id:订单的标识符。这是一个必需的字符串参数,用于为订单命名。我们可以通过这个ID在之后修改或取消待处理的订单,或者在订单成交后对其进行平仓。这个ID也会显示在图表上以及策略测试器窗口的交易列表中。
  • direction:订单的市场方向。这个必需的参数只能是 strategy.long(多头开仓)或 strategy.short(空头开仓)。
  • qty:一个数字,指定要交易的合约、股票或单位的数量。如果不设置此参数或明确设为 na,策略将使用默认的订单大小。如果策略也未配置默认订单大小,则 strategy.entry() 会以数量 1 进行交易。
  • limit:订单的限价。这需要一个具体的价格,而不是一个点数偏移量。如果设置了该参数,strategy.entry() 会发送一个限价单或止损限价单;如果不设置(或设为 na),则不使用限价,此时订单将是市价单或止损单。
  • stop:订单的止损触发价。这也需要一个具体的价格,而不是点数数量。如果设置了该参数,strategy.entry() 会发送一个止损单或止损限价单;如果不设置(或设为 na),则不使用止损触发价,此时订单将是市价单或限价单。
  • oca_name:一个字符串,指定订单所属的订单组名称。TradingView通过这个名称来识别属于同一组的订单。
  • oca_type:设置订单组的类型。可选值有 strategy.oca.cancel(创建OCA订单组,其中一个成交,其他全部取消)、strategy.oca.reduce(创建ORO订单组,其中一个成交,其他订单数量相应减少)和 strategy.oca.none(默认值,不使用订单组)。
  • comment:一个字符串,用于为订单添加注释。这个注释会显示在图表上以及策略测试器的交易列表中。
  • when:一个布尔值(true 或 false),用于条件性地决定是否生成该订单。这是使用 if 语句来控制下单的另一种方式。
  • alert_message:一个字符串,用于设置订单的警报消息文本。当由 strategy.entry() 订单成交触发的警报中,{{strategy.order.alert_message}} 这个占位符会被替换为这里设置的文本。

这么多参数,看起来是不是有点复杂?但幸运的是,我们通常不需要同时使用所有这些参数。实际上,strategy.entry() 比它的参数列表所显示的要简单得多。让我们通过一些例子来深入了解。

四种订单类型

strategy.entry() 究竟会生成哪种订单,完全取决于我们如何组合使用 limit 和 stop 这两个参数。下表展示了这两个参数如何组合成四种订单类型:

入场订单类型 如何通过 strategy.entry() 创建
市价单 不使用 limit 和 stop 参数。
限价单 设置 limit 参数,但不设置 stop 参数。
止损单 设置 stop 参数,但不设置 limit 参数。
止损限价单 同时设置 limit 和 stop 参数。

现在,我们来为每一种订单编写具体的代码示例。

市价单入场

要让 strategy.entry() 发出一个市价单,我们只需通过第一个参数设置订单ID(例如 “Enter Long” 或 “Enter Short”),再通过第二个参数设置订单方向(strategy.long 或 strategy.short)。仅此而已。

如果需要,我们还可以通过以下可选参数来自定义市价单:用 qty 指定一个自定义的订单数量(否则订单将使用策略的默认订单大小)、用 comment 为订单添加一个自定义的描述、用 alert_message 定义一个在订单成交时触发的警报消息。strategy.entry() 的其他参数通常不与市价单一同使用。下面我们来看代码。

要通过市价单开立一个多头仓位,我们可以像这样使用 strategy.entry():

// 当价格上穿20周期EMA时,执行做多
if ta.crossover(close, ta.ema(close, 20))
	strategy.entry("Enter Long", strategy.long)

这个 if 语句判断K线的收盘价是否上穿了指数移动平均线。如果条件满足,strategy.entry() 就会执行,生成一个ID为 “Enter Long” 的多头(strategy.long)开仓订单。

如果我们还想指定订单数量,可以这样做:

// 当价格上穿20周期EMA时,执行做多
if ta.crossover(close, ta.ema(close, 20))
	strategy.entry("Enter Long", strategy.long, qty=10)

这段代码与上一个例子类似,但 qty 参数告诉 strategy.entry() 开仓10个合约。

如果我们使用了策略警报功能,并且希望在订单成交时发送自定义消息(替换 {{strategy.order.alert_message}} 占位符),则可以设置 alert_message 参数:

// 当价格上穿20周期EMA时,执行做多
if ta.crossover(close, ta.ema(close, 20))
	strategy.entry("Enter Long", strategy.long, qty=10,
		 alert_message="市价做多10手合约")

要通过市价单开立一个空头仓位,我们可以这样执行 strategy.entry():

// 当价格下穿20周期EMA时,执行做空
if ta.crossunder(close, ta.ema(close, 20))
    strategy.entry("Enter Short", strategy.short)

当价格下穿EMA时,strategy.entry() 会生成一个ID为 “Enter Short” 的空头(strategy.short)开仓订单。

要指定订单数量,可以添加 qty 参数:

// 当价格下穿20周期EMA时,执行做空
if ta.crossunder(close, ta.ema(close, 20))
    strategy.entry("Enter Short", strategy.short, qty=25)

这段代码将以25个合约、股票或单位的数量建立空头仓位。

同样,我们也可以为它设置一个自定义的警报消息:

// 当价格下穿20周期EMA时,执行做空
if ta.crossunder(close, ta.ema(close, 20))
    strategy.entry("Enter Short", strategy.short, qty=25,
		 alert_message="市价做空25手合约")

止损单入场

要让 strategy.entry() 通过止损单入场,我们需要设置订单ID、订单方向(strategy.long 或 strategy.short),再通过 stop 参数指定入场触发价。这需要一个具体的价格,而不是点数偏移。

此外,我们还可以通过以下可选参数来自定义止损单:用 qty 自定义订单数量、用 oca_name 和 oca_type 将订单加入订单组(例如OCA或ORO组)、用 comment 添加订单注释、用 alert_message 定义警报消息。

要生成一个多头入场的止损单,可以这样做:

// 当价格突破20周期最高价时,提交一个多头入场止损单
if close > ta.highest(high, 20)[1]
    strategy.entry("Enter Long", strategy.long, stop=high + 
         10 * syminfo.mintick)

当收盘价高于近期最高价时,strategy.entry() 会执行,生成一个ID为 “Enter Long” 的多头(strategy.long)订单。stop 参数将触发价设在了当前K线最高价上方10个最小变动单位(syminfo.mintick)的位置。

我们也可以指定订单数量和警报消息:

// ...
if close > ta.highest(high, 20)[1]
    strategy.entry("Enter Long", strategy.long, qty=50,
         stop=high + 10 * syminfo.mintick,
		 alert_message="止损单做多50手,价格 @ " + 
		 	 str.tostring(high + 10 * syminfo.mintick))

要将此订单加入一个OCA订单组,以实现一成交全取消的效果,可以这样做:

// ...
if close > ta.highest(high, 20)[1]
    strategy.entry("Enter Long", strategy.long, qty=50,
         stop=high + 10 * syminfo.mintick,
         oca_type=strategy.oca.cancel, oca_name="long-entries")

要生成一个空头入场的止损单,代码如下:

// 当价格跌破20周期最低价时,提交一个空头入场止损单
if close < ta.lowest(low, 20)[1]
    strategy.entry("Enter Short", strategy.short, stop=low - 
         10 * syminfo.mintick)

当收盘价低于近期最低价时,strategy.entry() 会生成一个ID为 “Enter Short” 的空头(strategy.short)订单,触发价设在当前K线最低价下方10个最小变动单位处。同样,我们也可以为其添加数量、警报消息和订单组等设置。

限价单入场

要让 strategy.entry() 通过限价单入场,我们需要设置订单ID、订单方向,再通过 limit 参数定义限价。这需要一个具体的价格,而不是点数偏移。我们也可以为其添加 qty、oca_name、oca_type、comment 和 alert_message 等可选参数。

要通过限价单开立一个多头仓位,代码如下:

// 当价格创下10周期新高时,在突破点下方挂一个多头限价单
if high > ta.highest(high, 10)[1]
    strategy.entry("Enter Long", strategy.long, limit=high - 
         15 * syminfo.mintick)

当价格突破近期高点时,strategy.entry() 会生成一个多头限价单,挂单价格设在当前K线最高价下方15个最小变动单位处,以期在回调时入场。

要通过限价单开立一个空头仓位,代码如下:

// 当价格创下10周期新低时,在突破点上方挂一个空头限价单
if low < ta.lowest(low, 10)[1]
    strategy.entry("Enter Short", strategy.short, limit=low +
         15 * syminfo.mintick)

当价格跌破近期低点时,strategy.entry() 会生成一个空头限价单,挂单价格设在当前K线最低价上方15个最小变动单位处。

止损限价单入场

要让 strategy.entry() 通过止损限价单入场,我们需要设置订单ID和订单方向,并同时通过 limit 参数指定限价、通过 stop 参数定义止损触发价。limit 和 stop 都需要一个具体的价格。

多头入场:

// 当价格上穿20周期SMA时,提交一个多头止损限价单
// 触发价为高点上方20点,限价为收盘价下方50点
if ta.crossover(close, ta.sma(close, 20))
    strategy.entry("Enter Long", strategy.long, stop=high + 
         20 * syminfo.mintick, limit=close - 50 * syminfo.mintick)

空头入场:

// 当价格下穿20周期SMA时,提交一个空头止损限价单
// 触发价为低点下方20点,限价为收盘价上方50点
if ta.crossunder(close, ta.sma(close, 20))
    strategy.entry("Enter Short", strategy.short, stop=low - 
         20 * syminfo.mintick, limit=close + 50 * syminfo.mintick)

strategy.entry()的行为特性

了解 strategy.entry() 如何生成订单后,我们再来看看它的一些重要行为特性。

除了开立新仓位,strategy.entry() 函数还可以自动反转一个已有的仓位,这无需我们进行任何额外配置。当策略持有多仓时,一个做空的 strategy.entry() 订单会自动将多头仓位反转为空头仓位;当策略持有空仓时,一个做多的 strategy.entry() 订单会自动将空头仓位反转为多头仓位。

这个过程是这样的:当策略有持仓时,如果 strategy.entry() 生成一个反向订单,TradingView会自动将这个新订单的数量加上当前持仓的数量。例如,如果我们持有多仓10手,而 strategy.entry() 生成一个5手的空单,TradingView实际上会发出一个15手的卖出订单。其中10手用于平掉多仓,另外5手用于建立新的空仓。

strategy.entry() 的具体行为取决于策略当前的持仓状态。对于一个做多的 strategy.entry() 订单:如果策略当前空仓,则开立一个新的多头仓位;如果当前持有多仓,则可以进行加仓(但受限于金字塔设置);如果当前持有空仓,则会反转为多头仓位。对于做空的订单,逻辑与此类似。

另外,PineScript的多个风险管理函数会限制 strategy.entry() 的行为。根据被触发的风险规则,strategy.entry() 可能会被限制只能单向交易,或者在某天内禁止交易,甚至完全无法再进行任何交易。

策略的金字塔(pyramiding)设置也会限制 strategy.entry() 在同一方向上可以开立的订单数量。一旦达到最大开仓次数,strategy.entry() 就无法再同向加仓,但仍然可以反转持仓。

我们可以通过两种方式来条件性地执行 strategy.entry()。第一种是使用 when 参数:

strategy.entry("Enter Long", strategy.long, when=ta.crossunder(low, ta.ema(hl2, 30)))

第二种是使用 if 语句(推荐):

if ta.crossunder(low, ta.ema(hl2, 30))
	strategy.entry("Enter Long", strategy.long)

两种写法的效果完全相同,但我个人更推荐使用 if 语句,因为它能让条件逻辑更突出,代码结构也更清晰易读。

调用函数时,我强烈建议除了前两个必需参数外,都使用关键字参数。先看不推荐的写法(位置参数):

strategy.entry("Enter Long", strategy.long, na, yesterdayClose, na, "", strategy.oca.none, "Yesterday Limit Entry")

这种写法容易出错且难以阅读。推荐的写法(关键字参数):

strategy.entry("Enter Long", strategy.long, limit=yesterdayClose, comment="Yesterday Limit Entry")

这样代码更简洁,也更清晰。

最后还有几点值得知道:与 strategy.order() 函数相比,strategy.entry() 是开仓交易更方便、更高效的方式,因为它受到了金字塔和风险管理规则的约束,更不容易出错。strategy.entry() 生成的所有订单都是模拟的,无法发送给真实的经纪商。调用 strategy.entry() 也不保证总能成功开仓,因为金字塔设置、风险管理规则和保证金要求都可能阻止订单的生成。

简单总结一下:strategy.entry() 函数用于模拟多头和空头的开仓交易,我们总是需要为其提供订单ID和交易方向(strategy.long 或 strategy.short)。通过组合使用 stop 和 limit 参数,它可以生成市价单、限价单、止损单和止损限价单。该函数的执行受到金字塔、风险管理和保证金等多种因素的制约,因此并不保证总能成功下单。

赞(0)
未经允许不得转载:图道交易 » Pine Script(215):订单函数总览与strategy.entry()
分享到

评论 抢沙发

登录

找回密码

注册