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

Pine Script(214):三种止损写法 - 百分比、均线与高低价

#Pine Script入门教学

用基于百分比的止损退出亏损交易

止损单可以防止我们的策略遭受过大的亏损。TradingView本身支持基于点数(tick)和价格的止损单,但并未提供基于百分比的止损功能。让我们来看看如何通过编写代码来实现这一功能。

通过止损单,我们可以指定一个价格,当市场触及该价位时,我们希望平掉仓位。届时,TradingView(或我们的经纪商)会自动生成一个市价单来立即平仓。这样,我们就能通过避免更大的亏损来有效控制风险。

在代码中,我们通常使用 strategy.order()strategy.exit() 函数来提交止损单。虽然 strategy.exit() 函数非常灵活,但它只支持基于固定价格和固定点数的止损,无法直接为我们生成基于百分比的止损单。

然而,百分比止损非常有用。它能确保我们的止损位始终与开仓价保持一个固定的相对距离。这一点在长期的历史回测中尤其重要,因为在这期间,交易品种的价格可能已经发生了巨大的涨跌。在这种情况下,一个固定点数的止损有时会离现价太近,有时又太远,而百分比止损则能始终保持一个合理的相对距离。

幸运的是,我们只需编写一小段自定义代码,就能让我们的策略实现百分比止损。让我们看看具体怎么做。

要让我们的TradingView策略提交基于百分比的止损订单,我们需要执行以下步骤:

  1. (可选)创建输入选项:创建一个用户输入框,用于灵活配置止损的百分比。
  2. 计算止损价格:使用用户设定的百分比来计算出实际的止损价格。
  3. 提交止损订单:根据计算出的价格,提交具体的止损订单。

让我们来逐一审视这些步骤及其所需的代码。

步骤1:通过输入选项设置最大亏损百分比(可选)

创建一个输入选项,可以让我们在策略设置界面中方便地调整止损百分比,而无需每次都去修改策略的源代码。

为了获得最大的灵活性,我们将分别为多头和空头仓位创建输入选项:

// 通过输入选项设置止损水平(可选)
longLossPerc = input.float(1, title="多头止损 (%)",
     minval=0.0, step=0.1) * 0.01

shortLossPerc = input.float(1, title="空头止损 (%)",
     minval=0.0, step=0.1) * 0.01

我们使用 input.float() 函数创建了两个浮点数输入框。第一个名为”多头止损 (%)”,默认值为1(即1%),其最小值设为0以防意外输入负值。我们将这个输入框的当前值存储在 longLossPerc 变量中。

另一个输入框”空头止损 (%)”也同样默认从1%开始,且最小值也为0,以确保后续计算不会出错。它的值则由 shortLossPerc 变量来跟踪。

请注意,我们将每个输入框的值都乘以了 0.01。这是因为,虽然我们在界面上设置的是百分比(如3%或12%),但在第二步的计算中,使用小数形式(如0.03和0.12)会更加方便。因此,我们通过乘以0.01将百分比转换为了小数。(当然,除以100也能达到同样的效果。)

步骤2:使用百分比计算止损价格

知道了止损的百分比后,我们就可以计算出实际的止损价格了:

// 确定止损价格
longStopPrice  = strategy.position_avg_price * (1 - longLossPerc)
shortStopPrice = strategy.position_avg_price * (1 + shortLossPerc)

为了计算止损价格,我们使用了 strategy.position_avg_price 这个内置变量,它能返回当前持仓的平均开仓价格。

对于多头止损,我们用 strategy.position_avg_price 乘以 (1 - longLossPerc)。这里的 longLossPerc 就是上一步中定义的输入变量。我们用1减去这个亏损百分比,来计算出价格向下的目标位。(因为多头止损是设置在开仓价下方的。)

举个例子:假设开仓价是2,230.50,多头止损设为5%(即小数0.05)。那么 1 - 0.05 等于 0.95。用开仓价乘以 0.95,我们得到2,118.975。这个价格正好比我们的开仓价低5%,也就是我们多头止损应该设置的位置。

对于空头止损,计算方式类似,但方向相反。止损价位应该在开仓价上方某个百分比处。所以,我们用 strategy.position_avg_price 乘以 (1 + shortLossPerc)

我们将计算出的实际止损价格分别存储在 longStopPriceshortStopPrice 变量中,以备下一步使用。

注意:strategy.position_avg_price 有一个非常实用的特性。当策略进行加仓或减仓操作时,这个变量的值会自动更新,以反映最新的持仓平均成本。这样一来,我们的止损价格也会随之自动调整,从而确保止损位始终保持在相对于最新持仓成本的正确水平上,即使在多次进出场后也是如此。

步骤3:提交实际的止损订单

现在,我们有了具体的止损价格,可以提交实际的订单了。我们使用 strategy.exit() 函数来实现:

// 根据计算出的止损价格提交平仓订单
if strategy.position_size > 0
    strategy.exit("XL STP", stop=longStopPrice)

if strategy.position_size < 0
    strategy.exit("XS STP", stop=shortStopPrice)

第一个 if 语句检查策略当前是否持有多头仓位(即 strategy.position_size > 0)。如果是,我们就调用 strategy.exit() 提交一个名为 “XL STP”(Exit Long Stop)的平仓订单,其止损价就是我们之前计算出的 longStopPrice

第二个 if 语句的逻辑类似。它检查策略是否持有空头仓位(strategy.position_size < 0)。如果是,就提交一个名为 “XS STP” 的订单,止损价为 shortStopPrice

有趣的是,strategy.exit() 函数本身并不直接支持百分比止损。但它提供了一个 stop 参数,可以接受一个基于具体价格的止损值。通过先计算出百分比止损对应的具体价格,我们巧妙地在TradingView中实现了百分比止损的功能。(你可以运用同样的原理,创造出各种自定义类型的止损。)

注意:我们也可以使用TradingView的 strategy.order() 函数来发送多空止损单。但需要注意的是,如果不加小心,这个函数可能会在平仓的同时开立一个反向的新仓位,并且我们还必须自己计算订单数量。为了避免不必要的复杂性,本文统一使用 strategy.exit() 函数。

示例策略:使用百分比止损进行交易

下面的策略整合了我们上面讨论的所有三个步骤。它使用20周期和60周期的简单移动平均线(SMA)交叉来产生交易信号。当快线上穿慢线时做多,下穿时则做空。

但我们不希望承担过大的风险,所以我们为多头和空头都设置了1%的止损。为了能在图表上直观地看到并跟踪这些止损位,我们还使用 plot() 函数将其以十字形标记绘制出来。

完整的策略代码如下:

//@version=5
strategy(title="Stop loss (% of instrument price)",
     overlay=true, pyramiding=3)

// 步骤 1:
// 通过输入选项设置止损水平(可选)
longLossPerc = input.float(1, title="多头止损 (%)",
     minval=0.0, step=0.1) * 0.01

shortLossPerc = input.float(1, title="空头止损 (%)",
     minval=0.0, step=0.1) * 0.01

// 计算移动平均线
fastSMA = ta.sma(close, 20)
slowSMA = ta.sma(close, 60)

// 计算交易条件
enterLong  = ta.crossover(fastSMA, slowSMA)
enterShort = ta.crossunder(fastSMA, slowSMA)

// 绘制移动平均线
plot(fastSMA, color=color.teal)
plot(slowSMA, color=color.orange)

// 步骤 2:
// 确定止损价格
longStopPrice  = strategy.position_avg_price * (1 - longLossPerc)
shortStopPrice = strategy.position_avg_price * (1 + shortLossPerc)

// 绘制止损位以供确认
plot(strategy.position_size > 0 ? longStopPrice : na,
     color=color.red, style=plot.style_cross,
     linewidth=2, title="多头止损位")

plot(strategy.position_size < 0 ? shortStopPrice : na,
     color=color.red, style=plot.style_cross,
     linewidth=2, title="空头止损位")

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

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

// 步骤 3:
// 根据计算出的止损价格提交平仓订单
if strategy.position_size > 0
    strategy.exit("XL STP", stop=longStopPrice)

if strategy.position_size < 0
    strategy.exit("XS STP", stop=shortStopPrice)

让我们看看策略的实际表现。下图标示了一笔标准普尔500 CFD的空头交易。该笔交易在2,805.6成交。不久之后,我们不幸在2,833.7被止损平仓,导致了28.2点的亏损,相当于开仓价的-1.005%:

在另一个例子中,我们将策略的止损设为3%。下图中,脚本在接近2,781.6的顶部位置做多。这笔交易并不顺利,几天后在2,698.1被止损。结果是亏损了83.5点,即-3.0019%。

编写移动平均线止损

一个优秀的止损应该能在趋势延续时紧随价格,而在趋势反转时及时平仓。这种方法能让我们最大化地从趋势中获利。接下来,让我们看看如何在TradingView中利用移动平均线来实现这种动态止损。

一些策略的止损是在价格跌至某个固定价位或亏损达到特定点数时平仓。另一些则根据价格的动态发展来平仓,例如基于百分比的追踪止损。但只有当我们基于移动平均线来平仓时,我们才真正拥有了一个趋势跟踪止损(trend-following stop)。

在TradingView中,有两个函数可以生成用于平仓的止损单:strategy.order()strategy.exit()。它们都是通过一个接受止损价格的参数来实现这一功能的。

幸运的是,这使得编写移动平均线止损的代码变得非常直接:我们只需计算出移动平均线的当前价格,然后提交一个以该价格为止损位的止损单即可。

要在我们的TradingView策略脚本中提交移动平均线止损,我们需要执行以下步骤:

  1. (可选)使用输入选项来配置移动平均线。
  2. 计算移动平均线本身。
  3. 为计算出的移动平均线价格提交一个止损订单。
  4. (可选)在图表上绘制出这个基于移动平均线的止损线。

让我们逐一分析这些步骤及其所需的代码。

步骤1:通过输入项设置移动平均线(可选)

通过输入选项,我们可以让移动平均线止损变得更易于配置和优化。这样,每当我们想调整移动平均线的参数时,就无需直接修改代码了。

为了配置移动平均线的参数,我们创建两个输入项:

// 通过输入选项配置移动平均线
priceData = input.source(close, title="价格数据")
maLength  = input.int(45, title="移动平均线周期", minval=2)

第一个选项”价格数据”,是一个源输入项,通过 input.source() 函数创建。它会在设置面板中生成一个下拉菜单,让用户可以选择不同的价格数据源(如收盘价、开盘价等)。我们默认使用收盘价(close),并用 priceData 变量来追踪用户当前的选择。

第二个输入项”移动平均线周期”,是一个通过 input.int() 函数创建的整数输入。它用于设定平均线的计算周期。我们默认设为45周期,最小值为2。后续代码中,我们将通过 maLength 变量来引用这个值。

步骤2:计算移动平均线

现在,我们需要计算移动平均线本身。下面是如何获取一个指数移动平均线(EMA)的值:

// 计算移动平均线
maValue = ta.ema(priceData, maLength)

我们调用TradingView的 ta.ema() 函数来计算EMA。我们传入的两个参数 priceDatamaLength,分别来自上一步创建的输入项,它们决定了EMA的计算基准和周期。计算出的平均线值被存储在 maValue 变量中,以供后续使用。

当然,除了EMA,TradingView还内置了许多其他类型的移动平均线:

函数 移动平均线类型
ta.sma() 简单移动平均线(SMA)
ta.ema() 指数移动平均线(EMA)
ta.wma() 加权移动平均线(WMA)
ta.rma() 修正指数移动平均线(RMA)
ta.swma() 对称加权移动平均线(SWMA)
ta.alma() Arnaud Legoux移动平均线(ALMA)
ta.vwma() 成交量加权移动平均线(VWMA)
ta.vwap() 成交量加权平均价格(VWAP)

要使用其他类型的平均线,只需将 ta.ema() 替换为上表中的相应函数即可。

步骤3:为移动平均线价格生成止损订单

计算出移动平均线的值后,我们就可以用这个价格来生成实际的止损订单了:

// 提交基于移动平均线的止损单
if strategy.position_size > 0
    strategy.exit("XL MA STP", stop=maValue)

if strategy.position_size < 0
    strategy.exit("XS MA STP", stop=maValue)

第一个 if 语句通过 strategy.position_size > 0 来判断策略当前是否持有多头仓位。如果是,我们就需要一个止损来保护这个仓位。

因此,我们执行 strategy.exit() 函数来创建止损单。通过其 stop 参数,我们将止损位设定为移动平均线的当前价格(maValue)。并通过第一个参数,我们将这个止损单命名为 “XL MA STP”(多头移动平均线止损的缩写)。

第二个 if 语句则通过 strategy.position_size < 0 来判断策略是否持有空头仓位。如果是,strategy.exit() 就会为 maValue 价格生成一个止损单,我们将其命名为 “XS MA STP”。

由于我们是在持有仓位的每一根K线上都执行这个逻辑,所以我们的仓位始终都会被一个动态更新的移动平均线止损所保护。

步骤4:在图表上显示移动平均线止损(可选)

为了方便观察和调试,我们可以在图表上将移动平均线止损位绘制出来。这不仅能让我们更直观地调整参数,还能验证仓位是否确实在移动平均线价格被平掉。

代码如下:

// 绘制止损价格以供确认
plot(strategy.position_size > 0 ? maValue : na,
     color=color.red, style=plot.style_circles, linewidth=3,
     title="多头止损")

plot(strategy.position_size < 0 ? maValue : na,
     color=color.red, style=plot.style_cross, linewidth=3,
     title="空头止损")

第一个 plot() 语句绘制了红色的实心圆点(style=plot.style_circles)来代表多头止损。第二个 plot() 语句则用红色的十字(style=plot.style_cross)来代表空头止损。

这两个绘图都只在特定条件下才显示。我们使用了条件运算符(?:):只有当策略持有多仓时(strategy.position_size > 0),才绘制 maValue 作为多头止损线;同理,只有当策略持有空仓时(strategy.position_size < 0),才绘制空头止损线。在其他情况下,我们传入 na 值来隐藏绘图。

通过这种方式,移动平均线止损位只在策略有持仓时才可见。并且,由于这里的显示条件与我们提交止损单的条件完全一致,所以只要你在图上看到了止损线,就意味着相应的止损订单也已经被策略提交了。

提示:我们推荐使用 strategy.exit() 函数来提交止损订单,因为它更简单直接。虽然 strategy.order() 也能发送止损订单,但它需要精确设定订单数量,如果设置不当,可能会意外地开立一个新仓位。相比之下,strategy.exit() 的使用更为安全便捷。

示例策略:使用移动平均线止损进行交易

下面这个完整的示例策略整合了以上所有步骤。该策略基于45周期的EMA进行交易:当一根K线完全位于EMA之上,并且连续两根K线收盘价上涨时,策略做多;反之,当K线完全位于EMA之下,并且连续两根K线收盘价下跌时,策略做空。

策略的平仓方式有两种:一是在出现反向信号时反手开仓;另一种就是我们讨论的,基于45周期EMA的移动止损。

策略的完整代码如下:

//@version=5
strategy(title="移动平均线止损", overlay=true)

// 步骤 1:通过输入选项配置移动平均线
priceData = input.source(close, title="价格数据")
maLength  = input.int(45, title="移动平均线周期", minval=2)

// 步骤 2:计算移动平均线
maValue = ta.ema(priceData, maLength)

// 在图表上显示移动平均线和止损位
plot(maValue, color=color.orange, title="移动平均线")
plot(strategy.position_size > 0 ? maValue : na,
     color=color.red, style=plot.style_circles, linewidth=3,
     title="多头止损")
plot(strategy.position_size < 0 ? maValue : na,
     color=color.red, style=plot.style_cross, linewidth=3,
     title="空头止损")

// 定义本策略的交易条件
isFlat = strategy.position_size == 0
enterLong = isFlat and low > maValue and close > close[1] and close[1] > close[2]
enterShort = isFlat and high < maValue and close < close[1] and close[1] < close[2]

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

// 步骤 4:提交基于移动平均线的止损单
if strategy.position_size > 0
    strategy.exit("XL MA STP", stop=maValue)
if strategy.position_size < 0
    strategy.exit("XS MA STP", stop=maValue)

让我们看看这个脚本在图表上的表现。下图中,欧元/美元经历了一轮强劲的下跌趋势。在此期间,移动平均线止损也跟随价格下移,保护了空头仓位的利润。

在图表周期的末尾,市场出现了一轮上涨。由于短期趋势上涨过快,而移动平均线未能及时跟上,价格最终触及了止损位,TradingView自动平掉了空头仓位。

下面这张图则展示了两个移动平均线止损被触发的例子。第一次,脚本平掉了一个空头仓位。第二次,策略平掉了一个多头交易。在这两种情况下,价格的反向运动都触发了移动平均线止损,但由于反弹/回调幅度不大,止损最终未能成为一个盈利的平仓点。

基于最高价和最低价的止损

一个交易品种近期的最高价和最低价定义了一个交易区间。一些趋势跟踪策略会选择在这些关键价位进行突破交易。但我们也可以反其道而行之,将这些价位用作止损位。这样,只有当价格明确突破近期区间时,我们的仓位才会被平掉。让我们来看看如何在TradingView中编写这样的逻辑。

当近期的某个高点或低点被突破时,趋势跟踪策略通常会将其视为一个信号,顺势开仓,以期价格能延续其运动。但反过来想,如果我们已经持有多头或空头仓位,而价格向着对我们不利的方向突破,那我们很可能就站错了队。通过设置一个基于近期最高价或最低价的止损,我们就能避免自己陷入这种尴尬的境地。

在TradingView中,有两个订单函数可以用来生成平仓的止损单:strategy.order()strategy.exit()。它们都有一个 stop 参数,需要我们提供一个具体的止损价格。

因此,要使用近期的最高价和最低价来平仓,我们首先需要计算出这两个价格,然后再通过其中一个订单函数来提交实际的止损订单。下面我们来看看具体怎么做。

要让我们的TradingView策略提交基于近期最高价和最低价的止损订单,我们需要执行以下步骤:

  1. (可选)设置回看周期:通过输入选项来配置计算最高价和最低价的回看周期。
  2. 计算极值价格:计算出近期指定周期内的最高价和最低价。
  3. (可选)绘制止损位:在图表上将计算出的最高价和最低价止损位绘制出来,以便于验证和观察。
  4. 生成止损订单:当持有多头仓位时,为其设置一个基于近期最低价的止损;当持有空头仓位时,则为其设置一个基于近期最高价的止损。

接下来,我们来逐一探讨每个步骤及其所需的代码。

步骤1:通过输入选项设置回看周期(可选)

为了能够灵活地配置最高价和最低价的计算周期,我们可以创建两个输入选项。这样,每次想要调整止损的灵敏度时,就无需再修改策略的源代码了。

我们使用 input.int() 函数来创建这两个用户可配置的整数输入框:

// 为最高价和最低价的计算周期创建输入选项
hiLen = input.int(20, title="最高价回看周期", minval=2)
loLen = input.int(20, title="最低价回看周期", minval=2)

我们在这里创建了两个整数输入框(input.int())。第一个名为”最高价回看周期”,默认值为20,且最小值(minval)设为2,以确保至少有两根K线来计算最高价。我们用 hiLen 变量来跟踪这个选项的当前值。

另一个输入框”最低价回看周期”也同样默认从20开始,并要求至少2根K线。它的值则由 loLen 变量来跟踪。

步骤2:计算近期的最高价与最低价

有了回看周期的设置后,我们就可以利用这个周期长度来计算极值价格了。TradingView为此提供了两个非常方便的内置函数:ta.highest()ta.lowest()

所以,要获取近期的最高价和最低价,我们只需这样做:

// 计算近期的极值高点和低点
hiHighs = ta.highest(high, hiLen)[1]
loLows  = ta.lowest(low, loLen)[1]

为了获取周期最高价,我们调用 ta.highest() 函数,让它在K线的最高价(high)序列上进行计算,周期长度则使用我们上一步创建的输入变量 hiLen

类似地,我们用 ta.lowest() 函数来获取周期最低价,它作用于K线的最低价(low)序列,周期长度为 loLen

我们将计算出的近期最高价和最低价分别存入 hiHighsloLows 变量中,以备后用。

注意:这两个函数后面都跟着历史引用操作符 [1]。这确保了我们计算的是不包含当前K线在内的、过去一段时间的最高价和最低价。如果我们包含了当前K线的高低点,那么当前价格永远无法突破这个极值(因为极值本身就包含了当前K线的高低点),止损也就永远无法被触发。

步骤3:在图表上绘制极值高低点(可选)

将计算出的最高价和最低价绘制在图表上,可以让我们很方便地验证策略的止损逻辑是否按预期工作,并且能够快速地观察到调整回看周期对策略行为的影响。

要将这些价格点绘制在图表上,我们可以这样做:

// 绘制止损位以供直观验证
plot(strategy.position_size > 0 ? loLows : na,
     style=plot.style_circles, color=color.green, linewidth=3,
     title="最低价止损位")

plot(strategy.position_size < 0 ? hiHighs : na,
     style=plot.style_circles, color=color.red, linewidth=3,
     title="最高价止损位")

第一条 plot() 语句用于绘制 loLows 的值。它们会以绿色的(color.green)实心圆点(style=plot.style_circles)形式出现。通过将 linewidth 参数设为 3,这些圆点会比默认的更粗,更显眼。

第二条 plot() 语句的逻辑类似,它用红色的(color.red)实心圆点来显示 hiHighs 的值。

值得注意的是,这两个 plot() 语句并不会在每根K线上都进行绘制。相反,只有当策略持有多头仓位时(strategy.position_size > 0),才会显示最低价的止损位。而只有当策略持有空头仓位时(strategy.position_size < 0),才会显示最高价的止损位。

在没有持仓的时候,na 值会禁用绘图,这样可以最大程度地减少图表上的视觉干扰。

步骤4:提交基于最高价/最低价的止损订单

既然我们已经知道了最高价和最低价,就可以为这些价格提交止损订单了:

// 基于最高价和最低价提交止损单
if strategy.position_size > 0
    strategy.exit("XL HH", stop=loLows)

if strategy.position_size < 0
    strategy.exit("XS LL", stop=hiHighs)

第一个 if 语句检查策略是否持有多头仓位(strategy.position_size > 0)。如果是,strategy.exit() 函数就会提交一个止损订单。该订单的价格我们使用 loLows 变量,即我们计算出的周期最低价。我们将这个止损单命名为 “XL HH”(Exit Long Highest High)。

另一个 if 语句则检查策略是否持有空头仓位(strategy.position_size < 0)。如果是,strategy.exit() 就会为 hiHighs(周期最高价)生成一个止损。我们将这个平仓空头的订单命名为 “XS LL”。

请注意,我们是在策略持有多头或空头仓位的任何时候都发送这些止损单。这确保了我们的持仓始终受到止损的保护。因为一旦我们开仓,策略就会立即发送一个止损单,并且这个止损单会在整个持仓期间保持有效。

注意:策略也可以通过 strategy.order() 函数来生成止损单。但需要注意的是,如果我们不小心弄错了订单数量,这个函数可能会在平仓的同时开立一个反向的新仓位。strategy.exit() 函数则没有这个风险。因此,为了方便起见,本文统一使用 strategy.exit()

示例策略:使用最高价/最低价止损

上述所有步骤都整合在了下面的这个策略中。这个示例脚本在出现连续三个更高的收盘价时做多,在出现三个更低的收盘价时做空。并且,我们只在策略初始状态为空仓时才开仓。

所有交易都只通过止损订单来平仓。我们将多头仓位的止损设为20周期的最低价,空头仓位的止损设为20周期的最高价。为了方便观察这些止损位,我们用实心圆点将它们绘制在图表上。

策略的完整代码如下:

//@version=5
strategy(title="Highest high/lowest low stop", overlay=true)

// 步骤 1:
// 为最高价和最低价的计算周期创建输入选项
hiLen = input.int(20, title="最高价回看周期", minval=2)
loLen = input.int(20, title="最低价回看周期", minval=2)

// 步骤 2:
// 计算近期的极值高点和低点
hiHighs = ta.highest(high, hiLen)[1]
loLows  = ta.lowest(low, loLen)[1]

// 绘制止损位以供直观验证
plot(strategy.position_size > 0 ? loLows : na,
     style=plot.style_circles, color=color.green, linewidth=3,
     title="最低价止损位")

plot(strategy.position_size < 0 ? hiHighs : na,
     style=plot.style_circles, color=color.red, linewidth=3,
     title="最高价止损位")

// 此示例策略的交易条件
higherCloses = close > close[1] and
     close[1] > close[2] and 
     close[2] > close[3]

lowerCloses = close < close[1] and
     close[1] < close[2] and 
     close[2] < close[3]

isFlat = strategy.position_size == 0

// 提交开仓订单
if isFlat and higherCloses
    strategy.entry("EL", strategy.long)

if isFlat and lowerCloses
    strategy.entry("ES", strategy.short)

// 步骤 3:
// 基于最高价和最低价提交止损单
if strategy.position_size > 0
    strategy.exit("XL HH", stop=loLows)

if strategy.position_size < 0
    strategy.exit("XS LL", stop=hiHighs)

让我们看看这个脚本在图表上的表现。当市场处于一个长期趋势中时,使用近期最高价/最低价作为止损是一种非常有效的方法。

下面的比特币(BTC/USD)图表就是一个很好的例子。策略在大约$5,200的位置做多。由于在随后的上涨过程中,周期的最低价不断抬高,止损位也很好地跟随价格向上移动(移动止损)。一旦上涨趋势结束,价格回调触及止损位,策略便在大约$7,300的位置平仓。

如果我们缩短最高价和最低价的回看周期,止损位会更紧密地跟随仓位。这虽然能降低单笔交易的风险,但也会增加因正常波动而被过早止损出局的可能性。

下面的图表展示了使用10周期作为最高价/最低价止损的计算周期。止损位相当好地跟随了仓位。但当一根波动巨大的K线从最高价的计算窗口中移除时,极值高点止损位会急剧下降,这使得后续的K线很容易就能触及止损。

赞(0)
未经允许不得转载:图道交易 » Pine Script(214):三种止损写法 - 百分比、均线与高低价
分享到

评论 抢沙发

登录

找回密码

注册