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

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)

停止-限价单,需同时使用 stoplimit 参数:

// 当价格上穿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_pointstrail_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:一个布尔值(truefalse),用于条件性地决定是否生成该订单。这是使用 if 语句来控制下单的另一种方式。
  • alert_message:一个字符串,用于设置订单的警报消息文本。当由 strategy.entry() 订单成交触发的警报中,{{strategy.order.alert_message}} 这个占位符会被替换为这里设置的文本。

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

四种订单类型

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

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

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

市价单入场

要让 strategy.entry() 发出一个市价单,我们只需通过第一个参数设置订单ID(例如 “Enter Long” 或 “Enter Short”),再通过第二个参数设置订单方向(strategy.longstrategy.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.longstrategy.short),再通过 stop 参数指定入场触发价。这需要一个具体的价格,而不是点数偏移。

此外,我们还可以通过以下可选参数来自定义止损单:用 qty 自定义订单数量、用 oca_nameoca_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 参数定义限价。这需要一个具体的价格,而不是点数偏移。我们也可以为其添加 qtyoca_nameoca_typecommentalert_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 参数定义止损触发价。limitstop 都需要一个具体的价格。

多头入场:

// 当价格上穿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.longstrategy.short)。通过组合使用 stoplimit 参数,它可以生成市价单、限价单、止损单和止损限价单。该函数的执行受到金字塔、风险管理和保证金等多种因素的制约,因此并不保证总能成功下单。

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

评论 抢沙发

登录

找回密码

注册